/* ----------------------------------------------------------------------------
   Pas d'italique dans l'espace
   ----------------------------------------------------------------------------
   L'italique était employé huit fois, sur des mentions secondaires :
   « Chargement… », « aucune formule », « sans période ». Un ornement discret,
   et qui coûtait 39 Ko — la moitié du poids du serif — parce qu'il oblige le
   navigateur à télécharger un SECOND fichier de police, l'italique du
   Cormorant, en plus du romain.

   Trente-neuf kilo-octets, sur une 3G de montagne, c'est presque une seconde
   d'attente. Pour une inclinaison de lettres que personne n'avait remarquée.
   Le gris de ces mentions suffisait déjà à les mettre en retrait.
   -------------------------------------------------------------------------- */

/* ============================================================================
   Espace membre — reprend la charte du site
   ========================================================================== */

/* ----------------------------------------------------------------------------
   La palette
   ----------------------------------------------------------------------------
   L'espace n'a jamais eu 122 couleurs : il en a une, déclinée. Presque tous les
   gris — bordures, fonds, textes secondaires — sont la teinte du prune à des
   clartés différentes. Ils sont maintenant écrits comme tels : la teinte est
   une variable, la clarté reste dans la règle.

     hsl(var(--teinte) calc(var(--force) * 19%) 93%)

   Changer de palette, c'est donc tourner une teinte, pas remplacer 349
   valeurs. « --force » atténue la saturation quand une teinte tape plus fort
   à l'œil que le mauve, ce qui est le cas des bleus et des verts.

   Ce qui NE suit pas la palette : le vert de « réglé », l'ambre de « à faire »,
   le rouge d'une erreur, et les couleurs de familles de cours. Elles ne
   décorent pas, elles disent quelque chose — les teindre reviendrait à faire
   dépendre le sens de l'humeur graphique de l'association.
   -------------------------------------------------------------------------- */
:root {
  --teinte: 320;
  --force: 1;
}

/* Prune, la palette d'origine, redite ici pour qu'elle soit un choix parmi
   les autres et non le cas où l'on n'a rien choisi. */
/* Chaque palette tient en cinq valeurs : la teinte de la famille de gris, sa
   force, l'accent foncé, l'accent clair — celui des titres — et la couleur du
   geste, qui doit se détacher des deux autres pour qu'un bouton reste un
   bouton. Rien d'autre ne change. */
:root[data-palette="prune"] {
  --teinte: 320; --force: 1;
  --prune: #825574; --corail: #EC7069; --jaune: #FAB926; --orange: #F19953;
}
/* Rose et brun : les couleurs d'Agnès. Le brun porte, le rose parle — c'est
   l'inverse du prune, où l'accent foncé est le mauve et le clair un corail. */
:root[data-palette="bruyere"] {
  --teinte: 5; --force: .85;
  --prune: #7D5049; --corail: #C97F84; --jaune: #D9A05C; --orange: #C98A6A;
}

:root[data-palette="ardoise"] {
  --teinte: 212; --force: .78;
  --prune: #24557E; --corail: #4E86A8; --jaune: #E9A13B; --orange: #C98A4A;
}
:root[data-palette="foret"] {
  --teinte: 152; --force: .70;
  --prune: #2E6449; --corail: #5C9068; --jaune: #D98A3C; --orange: #C97C42;
}
:root[data-palette="ocean"] {
  --teinte: 194; --force: .72;
  --prune: #1F5F6B; --corail: #3D93A0; --jaune: #EDA13A; --orange: #DD8B4C;
}

/* « hidden » n'est appliqué par le navigateur que par une règle de très faible
   priorité : la moindre déclaration « display » la neutralise, et l'élément
   reste visible alors que le code le croit masqué. On l'impose donc ici, une
   fois pour toutes — c'est ce qui laissait apparaître « Se déconnecter » et une
   carte « Mon compte » vide à une visiteuse non connectée. */
[hidden] { display: none !important; }

.espace { background: hsl(var(--teinte) calc(var(--force) * 27.3%) 97.8%); min-height: 100vh; }

/* Le bandeau reste en haut quand on descend : le nom, le logo et « se
   déconnecter » ne s'attrapent plus en remontant tout l'écran.

   Il se resserre dès qu'on défile — logo plus petit, moins d'air — pour ne pas
   confisquer quatre-vingt-dix pixels de haut sur un téléphone où la barre
   d'onglets en prend déjà autant en bas. */
/* Deux barres collantes à « top: 0 » se recouvrent : la seconde glisse sous la
   première au défilement. Une seule enveloppe colle, et les deux s'empilent
   dedans — la hauteur peut alors varier sans qu'on ait à la calculer. */
.haut {
  position: sticky;
  top: 0;
  z-index: 30;
}

.espace__entete {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: 10px 16px;
  background: #fff;
  border-bottom: 1px solid hsl(var(--teinte) calc(var(--force) * 20%) 90.2%);
  transition: padding .18s ease, box-shadow .18s ease;
}
.espace__entete--collee { padding-top: 8px; padding-bottom: 8px; }
.haut:has(.espace__entete--collee) { box-shadow: 0 2px 12px rgba(42, 34, 40, .08); }
.espace__logo img { width: 42px; transition: width .18s ease; }
.espace__entete--collee .espace__logo img { width: 38px; }

@media (prefers-reduced-motion: reduce) {
  .espace__entete, .espace__logo img { transition: none; }
}
.espace__identite {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 10px;
  min-width: 0;
}
.espace__email { font-family: var(--font-titre); font-size: 15px; color: var(--prune); }

.lien-bouton {
  background: none;
  border: 0;
  padding: 0;
  font-family: var(--font-titre);
  font-size: 14px;
  color: var(--corail);
  text-decoration: underline;
  cursor: pointer;
}

.espace__corps { max-width: 900px; margin: 0 auto; padding: 30px 20px 80px; }

.espace h1, .espace h2 {
  font-family: var(--font-titre);
  color: var(--corail);
  line-height: 1.2em;
}
.espace h1 { font-size: 36px; margin: 0 0 12px; }
.espace h2 { font-size: 26px; margin: 0 0 16px; }
.espace h3 {
  font-family: var(--font-titre);
  font-size: 18px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 1px;
  color: var(--prune);
  margin: 0 0 10px;
}

.carte {
  background: #fff;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 20%) 90.2%);
  border-radius: 8px;
  padding: 30px;
  margin-bottom: 30px;
}

/* ---------------------------------------------------------------- formulaire */

#form-connexion { display: grid; gap: 10px; max-width: 420px; margin-top: 20px; }
#form-connexion input { width: 100%; min-width: 0; }
#form-connexion label { font-family: var(--font-titre); font-weight: 600; font-size: 15px; }
#form-connexion input {
  padding: 14px 20px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 20%) 90.2%);
  border-radius: 30px;
  font-family: var(--font-texte);
  font-size: 17px;
}
/* L'œil du mot de passe vit à l'intérieur du champ : il n'est pas un bouton
   du formulaire, et héritait pourtant du jaune pleine largeur de
   « Se connecter » — au point de recouvrir le champ entier. */
/* Le texte des boutons jaunes est brun très foncé, jamais blanc.
   ----------------------------------------------------------------------------
   Du blanc sur le jaune de la charte donne un contraste de 1,75 : 1 ; le minimum
   lisible est de 4,5. C'était le pire rapport de toute l'application — sur le
   bouton le plus touché, par des gens qui réservent dehors, au soleil, à bout de
   bras. Le brun le porte à 8,17 : 1.

   Le jaune ne bouge pas : c'est la couleur du geste dans cette maison. Seule
   l'encre change. */
#form-connexion button:not(.mdp__oeil), .bouton-reserver, .bouton-annuler {
  font-family: var(--font-titre);
  font-size: 14px;
  font-weight: 600;
  letter-spacing: .5px;
  text-transform: uppercase;
  border: 0;
  border-radius: 30px;
  padding: 12px 24px;
  cursor: pointer;
  color: #3A2708;
}
#form-connexion button:not(.mdp__oeil) {
  background: var(--jaune); justify-self: start; }
#form-connexion button:not(.mdp__oeil):hover { background: var(--orange); }

/* ------------------------------------------------------------------ messages */

/* Un message n'a que sa marge du haut : posé au-dessus d'un bouton, il le
   touchait — dans le formulaire d'invitation, celui d'un cours, d'une formule,
   partout où « .message » précède « .actions ». La marge vaut des deux côtés. */
.message {
  margin: 16px 0;
  padding: 12px 18px;
  border-radius: 20px;
  font-family: var(--font-titre);
  font-size: 15px;
  line-height: 1.4;
}
.message--succes { background: #E8F0EA; color: #2C5C3C; }
.message--erreur { background: #FBE7E6; color: #97302A; }
/* « break-all » coupait les mots français au milieu d'une syllabe. On ne casse
   plus que ce qui ne peut pas tenir autrement — un lien très long, à quoi
   cette règle était destinée. */
.message--info   { background: #FDF1DC; color: #7A5410; overflow-wrap: anywhere; }

/* --------------------------------------------------------------- abonnement */

.bandeau-abonnement {
  background: #fff;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 20%) 90.2%);
  border-left: 4px solid var(--jaune);
  border-radius: 0 8px 8px 0;
  padding: 16px 22px;
  margin-bottom: 24px;
  font-size: 18px;
}
.bandeau-abonnement--sans { border-left-color: var(--corail); }

/* ---------------------------------------------------------------- semaines */

/* Une ligne, deux chevrons, la date au milieu : cinquante pixels rendus à la
   grille. Le balayage horizontal fait la même chose, sans viser. */
.navigation-semaine {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 14px;
  padding: 5px 6px;
  background: #fff;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 12.9%) 87.8%);
  border-radius: 30px;
}
.navigation-semaine span {
  flex: 1 1 auto;
  text-align: center;
  font-family: var(--font-titre);
  font-weight: 600;
  font-size: 15px;
  color: var(--prune);
}
.navigation-semaine button {
  flex: 0 0 auto;
  width: 40px; height: 40px;
  border: 0;
  border-radius: 50%;
  background: hsl(var(--teinte) calc(var(--force) * 27.3%) 97.8%);
  color: var(--prune);
  font-family: var(--font-titre);
  font-size: 22px;
  font-weight: 600;
  line-height: 1;
  cursor: pointer;
}
.navigation-semaine button:hover { background: hsl(var(--teinte) calc(var(--force) * 21.1%) 92.5%); }

/* Le retour à la semaine en cours, dans la barre plutôt que sous elle.
   ----------------------------------------------------------------------------
   Il occupait sa propre ligne : cinquante-huit pixels pris à la grille dès
   qu'on s'éloignait. La barre avait la place — le libellé n'y tenait que deux
   cent cinquante pixels sur trois cent soixante.

   L'icône est dessinée et non écrite : le caractère « ↩ » se peignait en gros
   emoji bleu sur iOS, qui lui donne une présentation graphique par défaut. */
/* Elle hérite des flèches tout ce qui fait une pastille de cette barre — la
   taille, le fond, la forme. Réglée à part, elle mesurait quarante sur quarante
   quand les flèches font quarante sur quarante-quatre : quatre pixels de moins,
   et c'est tout ce qu'on voit quand trois ronds se suivent. */
.nav-retour { display: inline-flex; align-items: center; justify-content: center; padding: 0; }
.nav-retour svg {
  width: 18px; height: 18px;
  fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
}
/* Le libellé reste centré : un vide de la largeur d'une pastille lui répond de
   l'autre côté. Sans lui, la date glisse de vingt pixels vers la gauche. */
.navigation-semaine .nav-vide { flex: 0 0 auto; width: 40px; }

/* ---------------------------------------------------------------- tableaux */

.places { background: #E8F0EA; color: #2C5C3C; }
.places--basse { background: #FDF1DC; color: #7A5410; }
.places--nulle { background: hsl(var(--teinte) calc(var(--force) * 20%) 94.1%); color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%); }

/* Un lien déguisé en bouton. « bouton-reserver » donne la couleur, la forme
   et la police, mais pas ce qu'un <a> traîne avec lui : le soulignement, la
   ligne de texte, et l'absence de hauteur de pouce. Trois lignes suffisent —
   sans elles, « Envoyer par SMS » s'affichait souligné, en Cormorant, dans un
   rectangle serré à côté d'un vrai bouton. */
a.bouton-reserver, a.bouton-annuler {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  text-align: center;
  text-decoration: none;
}

.bouton-reserver { background: var(--jaune); }
.bouton-reserver:hover:not(:disabled) { background: var(--orange); }
.bouton-reserver:disabled { background: hsl(var(--teinte) calc(var(--force) * 12.9%) 87.8%); color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%); cursor: default; }
.bouton-annuler { background: #fff; color: var(--corail); border: 1px solid var(--corail); }
.bouton-annuler:hover { background: #FBE7E6; }

.chargement { color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%); }

/* La ligne discrète prend l'échelle du panneau qui l'accueille.
   ----------------------------------------------------------------------------
   « .chargement » ne fixe qu'une couleur : ni police, ni taille. Elle hérite
   donc de son conteneur, ce qui va très bien au milieu d'un écran — « Chargement… »
   y a la taille du texte courant. Dans un réglage, non : le titre y pèse 12 px,
   l'explication 14, le bouton 13, et « Aucune fermeture pour l'instant. » arrivait
   à 18 — quatre points de plus que le paragraphe juste au-dessus. La ligne la
   moins importante du bloc était la plus grosse. */
.reglage .chargement { font-size: 14px; line-height: 1.45; }

/* ------------------------------------------------- une semaine sans cours */

/* Le vide n'a pas à être vide : il dit pourquoi il n'y a rien, quand cela
   reprend, et offre le geste qui y mène. Une phrase en italique perdue en
   haut d'un écran blanc ne disait aucune des trois. */
.semaine-vide {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 6px;
  margin: 26px auto 0;
  padding: 34px 22px 30px;
  max-width: 420px;
  border-radius: 20px;
  background: linear-gradient(180deg, hsl(var(--teinte) calc(var(--force) * 40%) 98%) 0%, hsl(var(--teinte) calc(var(--force) * 46.7%) 97.1%) 100%);
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 28.2%) 92.4%);
}

/* Une semaine fermée. Elle garde la carte de la semaine vide, mais l'image y
   prend toute la largeur : bordée de blanc, elle aurait ressemblé à une
   vignette collée sur un message, alors qu'elle EST le message. */
.semaine-fermee { padding-top: 0; overflow: hidden; }
.semaine-fermee__image {
  margin: 0 -22px 18px;
  width: calc(100% + 44px);
}
.semaine-fermee__image img {
  display: block;
  width: 100%;
  /* Un format constant : une photo verticale mangerait l'écran, une panoramique
     ne dirait rien. Le recadrage se fait au centre, là où l'on cadre. */
  aspect-ratio: 16 / 10;
  object-fit: cover;
}
/* La date sous le titre : elle informe, elle n'annonce pas. En gras prune elle
   se battait avec le titre pour la même ligne de regard. */
.semaine-fermee__quand {
  margin: 0;
  font-family: var(--font-titre);
  font-size: 14px;
  font-weight: 500;
  letter-spacing: .01em;
  color: hsl(var(--teinte) calc(var(--force) * 7%) 44.7%);
}
/* Sans image, la coche remplace le point : une semaine fermée est une décision,
   pas un vide. */
.semaine-fermee .semaine-vide__marque svg .pleine { stroke: var(--prune); fill: none; }

.semaine-vide__marque {
  display: flex;
  width: 74px;
  height: 74px;
  margin-bottom: 6px;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: hsl(var(--teinte) calc(var(--force) * 33.3%) 94.1%);
}
.semaine-vide__marque svg {
  width: 38px;
  height: 38px;
  fill: none;
  stroke: var(--prune);
  stroke-width: 3.4;
  stroke-linecap: round;
  opacity: .72;
}
.semaine-vide__marque .pleine { fill: var(--corail); stroke: none; opacity: .85; }

.semaine-vide__titre {
  margin: 0;
  font-family: var(--font-titre);
  font-size: 21px;
  font-weight: 600;
  color: var(--prune);
  text-wrap: balance;
}
.semaine-vide__mot {
  margin: 0;
  max-width: 32ch;
  font-size: 16px;
  line-height: 1.5;
  color: hsl(var(--teinte) calc(var(--force) * 6.3%) 40.6%);
  text-wrap: pretty;
}

.semaine-vide__gestes {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px 16px;
  margin-top: 16px;
}
.semaine-vide__gestes > * { min-width: 0; }

/* Le retour en arrière existe, sans réclamer la même attention que la
   reprise : on regarde un planning pour ce qui vient. */
.semaine-vide__retour {
  padding: 6px 2px;
  border: 0;
  background: none;
  font-family: var(--font-titre);
  font-size: 15px;
  font-weight: 600;
  color: var(--corail);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: #EFC7C2;
  cursor: pointer;
}
.semaine-vide__retour:hover { text-decoration-color: var(--corail); }
.semaine-vide__retour:focus-visible { outline: 2px solid var(--corail); outline-offset: 2px; }

/* --------------------------------------------------------------- ma semaine */

.recap { margin-top: 40px; }

/* -------------------------------------------------------------------- admin */

/* Une aide se lit une fois et reste pour toujours : elle prend la taille du
   texte secondaire, pas celle du contenu. Dix-sept pixels de Cormorant sur
   trois lignes faisaient quatre-vingt-deux pixels en haut de chaque écran. */
.admin__aide {
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
  font-size: 15px;
  line-height: 1.4;
  margin: 0 0 14px;
  text-wrap: pretty;
}
#liste-membres select {
  padding: 8px 14px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 20%) 90.2%);
  border-radius: 20px;
  font-family: var(--font-titre);
  font-size: 14px;
  margin-right: 8px;
}

/* --------------------------------------------------------------- responsive */

@media (max-width: 640px) {
  .espace h1 { font-size: 28px; }

  /* La carte blanche à bords arrondis n'apporte rien sur un téléphone : le
     fond de la page est déjà d'une autre couleur, et il n'y a jamais qu'une
     carte à l'écran. Elle prenait vingt pixels de chaque côté — quarante sur
     trois cent quatre-vingt-dix, soit une colonne de planning. */
  .espace__corps > .carte {
    padding: 0;
    border: 0;
    border-radius: 0;
    background: none;
    box-shadow: none;
  }
  .espace__corps { padding: 20px 14px 60px; }
  .carte { padding: 20px; }
}

/* ---------------------------------------------------- gestion du planning */

.barre-saison {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
  margin: 18px 0 24px;
}
.barre-saison label {
  font-family: var(--font-titre);
  font-weight: 600;
  font-size: 15px;
  color: var(--prune);
}
/* ----------------------------------------------------------------------------
   Une commande sans couleur de texte prend celle du système
   ----------------------------------------------------------------------------
   Un bouton ou un champ dont la règle donne un fond mais pas de « color » n'est
   pas neutre : iOS y met SON bleu. C'est ainsi qu'un « Ajouter un cours » est
   apparu en bleu sur un bouton jaune, et le menu des périodes en bleu au milieu
   d'un écran prune. Le défaut ne se voit pas au développement — un navigateur
   de bureau met du noir — d'où la vérification qui balaie toute la feuille.
   -------------------------------------------------------------------------- */

/* La règle ne fixait aucune couleur : iOS peignait donc le menu de son bleu
   système, seule tache de bleu de tout l'espace. Et « inherit » lui donnait le
   serif du corps de texte, une police de lecture posée sur une commande. */
.barre-saison select {
  flex: 1 1 260px;
  padding: 8px 12px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 12.9%) 87.8%);
  border-radius: 8px;
  background: #fff;
  font-family: var(--font-titre);
  font-size: 16px;
  font-weight: 500;
  color: hsl(var(--teinte) calc(var(--force) * 7%) 27.1%);
}

/* Les dates de la période, sous le menu. Elles disent la même chose qu'avant
   mais en français, et le nombre de cours répond à la question qu'on se pose
   vraiment en changeant de période : « y a-t-il un planning là-dedans ? » */
.saison-dates {
  margin: -14px 0 24px;
  font-family: var(--font-titre);
  font-size: 14px;
  color: hsl(var(--teinte) calc(var(--force) * 6%) 45.1%);
}

/* Formulaire de saisie d'un cours ou d'une saison. Les champs se replient en
   une colonne sur téléphone : la grille suit la place disponible. */
.formulaire-bloc {
  background: hsl(var(--teinte) calc(var(--force) * 27.3%) 97.8%);
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 12.9%) 87.8%);
  border-radius: 12px;
  padding: 20px;
  margin: 20px 0;
}
.formulaire-bloc h3 { margin-top: 0; }

.champs {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 14px 12px;
  margin-bottom: 16px;
}

/* « min-width: 0 » est indispensable : un élément de grille a une largeur
   minimale automatique, et un champ de saisie possède une largeur propre
   supérieure à la colonne. Sans cela il élargit la colonne et déborde de la
   carte — c'est ce qui poussait « Nom » et « Ville » hors de l'écran. */
.champs label {
  display: block;
  min-width: 0;
  font-family: var(--font-titre);
  font-weight: 600;
  font-size: 13px;
  letter-spacing: .02em;
  color: var(--prune);
}
.champs .champ-large { grid-column: 1 / -1; }

/* Le libellé en bloc plutôt qu'en grille : « facultative » reste ainsi sur la
   même ligne que le nom du champ, au lieu d'occuper une rangée à elle seule. */
.champs input, .champs select, .champs textarea {
  display: block;
  width: 100%;
  min-width: 0;
  margin-top: 5px;
  padding: 10px 12px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 12.9%) 87.8%);
  border-radius: 8px;
  background: #fff;
  font-family: inherit;
  font-size: 16px;
  font-weight: 400;
  color: hsl(var(--teinte) calc(var(--force) * 10%) 15.7%);
}
.champs input:focus, .champs select:focus, .barre-saison select:focus {
  outline: 2px solid var(--jaune);
  outline-offset: 1px;
}

.actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
}
.actions button:not(.lien-bouton) {
  color: #3A2708;
  padding: 10px 22px;
  border: 0;
  border-radius: 30px;
  background: var(--jaune);
  font-family: var(--font-titre);
  font-weight: 600;
  font-size: 15px;
  cursor: pointer;
}
.actions button:not(.lien-bouton):hover { background: var(--orange); }
/* Éteint tant que le geste n'est pas possible : un bouton plein jaune promet
   un envoi, et le tenir allumé sur un champ vide, c'est promettre pour rien. */
.actions button:not(.lien-bouton):disabled {
  background: hsl(var(--teinte) calc(var(--force) * 12.9%) 87.8%);
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
  cursor: default;
}
.actions button:not(.lien-bouton):disabled:hover { background: hsl(var(--teinte) calc(var(--force) * 12.9%) 87.8%); }
.actions .bouton-annuler { background: #fff; }

/* ------------------------------------------------- exceptions ponctuelles */

/* Une étiquette dit pourquoi une séance sort de l'ordinaire : déplacée,
   exceptionnelle, ou le motif de son annulation. */
.etiquette { margin-left: 8px; background: #FDF1DC; color: #7A5410; }

.exception { padding: 18px; }
.exception .message { margin-top: 12px; }

/* ========================================================================
   Le planning de la semaine
   ------------------------------------------------------------------------
   Une colonne par jour, un bloc par cours : toute la semaine tient dans un
   écran de téléphone, sans défilement. Le tableau qu'il remplace demandait
   4 200 px de hauteur pour la même information.

   La couleur porte la discipline, l'état n'est écrit que lorsqu'il change la
   décision — « complet » et « 2 pl. » se lisent, « 11 places » est du bruit.
   ====================================================================== */

/* La semaine se lit en deux bandes : les matins, un filet, les après-midi.
   ----------------------------------------------------------------------------
   Les colonnes sont posées explicitement plutôt que coulées : chaque bande
   pose une cellule par jour, et un flux automatique les ferait glisser hors de
   leur colonne dès qu'une bande n'aurait pas le même compte que l'autre.

   Chaque rangée fait la hauteur de son jour le plus chargé — « align-items:
   start » —, et tous les après-midi partent donc du même trait. */
.grille-semaine {
  display: grid;
  grid-template-columns: repeat(var(--jours, 5), minmax(0, 1fr));
  gap: 5px;
  align-items: start;
}
/* Un ou deux jours seulement : on garde des blocs de taille normale, calés à
   gauche, plutôt qu'une colonne étirée sur tout l'écran. */
.grille-semaine[data-peu="1"] { grid-template-columns: minmax(0, 60%); justify-content: start; }
.grille-semaine[data-peu="2"] { grid-template-columns: repeat(2, minmax(0, 47%)); justify-content: start; }

/* Le filet qui sépare les deux demi-journées. Il traverse toute la grille :
   c'est une frontière commune, pas une bordure de colonne. */
/* Le corps de la grille : les colonnes des jours, sous la ligne des en-têtes.
   Il porte l'axe du temps, et sert de repère aux filets. */
.grille-semaine__corps {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: repeat(var(--jours, 5), minmax(0, 1fr));
  gap: 5px;
  position: relative;
}
.grille-semaine[data-peu="1"] .grille-semaine__corps { grid-template-columns: minmax(0, 60%); justify-content: start; }
.grille-semaine[data-peu="2"] .grille-semaine__corps { grid-template-columns: repeat(2, minmax(0, 47%)); justify-content: start; }

/* Un filet là où le temps a été replié : il dit qu'on a sauté des heures. */
.grille-semaine__filet {
  position: absolute;
  left: 0;
  right: 0;
  height: 1px;
  background: hsl(var(--teinte) calc(var(--force) * 18.9%) 92.7%);
}

/* Une colonne n'empile plus : elle porte l'axe du temps, et chaque cours s'y
   pose à la hauteur de son heure. C'est ce qui fait qu'une même heure est à la
   même hauteur d'un jour à l'autre — c'est la même coordonnée. */
.colonne-jour {
  position: relative;
  min-width: 0;
}
/* Le bloc occupe exactement sa tranche d'heure. Un nom trop long pour la
   place se coupe plutôt que de déborder sur le cours suivant — mais l'échelle
   est choisie pour que le plus court des cours tienne ses trois lignes. */
.colonne-jour .bloc-cours { position: absolute; left: 0; right: 0; overflow: hidden; }

.colonne-jour__entete {
  text-align: center;
  padding-bottom: 2px;
  font-family: var(--font-titre);
  line-height: 1.15;
}
.colonne-jour__lettre {
  display: block;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .08em;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
.colonne-jour__num {
  display: block;
  font-size: 16px;
  font-weight: 600;
  color: var(--prune);
  font-variant-numeric: tabular-nums;
}
.colonne-jour__vide {
  text-align: center;
  color: hsl(var(--teinte) calc(var(--force) * 12.5%) 81.2%);
  padding-top: 14px;
}

/* ------------------------------------------------------------ un cours -- */

.bloc-cours {
  /* Repère de la pastille « réservé », qui se pose dans le coin du bloc. */
  position: relative;
  border: 0;
  border-radius: 10px;
  /* Cinq pixels et non neuf, un d'interligne et non trois : le bloc passe de
     quatre-vingt-dix-neuf pixels à soixante-et-onze, et la grille d'une
     semaine perd quatre-vingt-quatre pixels — de quoi voir la fin de la
     journée sans faire défiler. */
  padding: 5px 5px;
  min-height: 56px;
  /* La hauteur dit la durée : au-delà d'une heure elle s'ajoute en ligne, ici
     c'est le plancher — celui du texte, qu'un cours plus court ne peut pas
     franchir sans perdre une ligne. */
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 1px;
  text-align: center;
  cursor: pointer;
  font-family: inherit;
  background: var(--fam-clair);
  color: var(--fam-fonce);
  /* « break-word » plutôt que « anywhere » : un mot ne se coupe que s'il ne
     tient pas, au lieu de « respiratio / n et posture ». La césure française
     prend le relais quand il le faut. */
  overflow-wrap: break-word;
  hyphens: auto;
}

.bloc-cours__heure {
  font-family: var(--font-titre);
  font-size: 11px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  opacity: .85;
}
/* La durée, à la suite de l'heure : plus petite et plus pâle, c'est un
   complément. Sur sa propre ligne elle coûtait seize pixels par bloc.
   Le point qui les sépare est dessiné, pas écrit : il ne doit pas se
   retrouver en tête de ligne quand la colonne est trop étroite. */
.bloc-cours__duree {
  font-size: 10px;
  font-weight: 600;
  opacity: .6;
  white-space: nowrap;
}
/* Le point appartient à l'heure de départ, pas à la durée : accroché à la
   durée, il ouvrait la seconde ligne — « 10h00 » puis « · 2h » — quand la
   colonne devenait trop étroite pour les tenir ensemble. */
.bloc-cours__depart { white-space: nowrap; }
.bloc-cours__depart::after { content: '·'; margin: 0 4px; opacity: .42; font-weight: 600; }
.bloc-cours__depart:only-child::after { content: none; }
.bloc-cours__nom { font-size: 14px; line-height: 1.15; }

/* Deux cours simultanés se partagent la colonne : à demi-largeur, le nom passe
   sur trois lignes et ne tient plus dans sa tranche d'heure. On resserre, et la
   jauge s'efface — le compteur dit déjà les places, et un trait de trois pixels
   ne se lit pas sur quarante de large. */
.bloc-cours.bloc-cours--etroit { padding-left: 3px; padding-right: 3px; }
.bloc-cours--etroit .bloc-cours__nom { font-size: 12px; line-height: 1.1; }
.bloc-cours--etroit .bloc-cours__heure { font-size: 10px; }
.bloc-cours--etroit .bloc-cours__jauge { display: none; }
/* À quarante-trois pixels de large, « 18h00 · 1h » passe lui-même sur deux
   lignes. La durée cède la place : elle reste dans la fiche, alors que les
   places libres sont ce qu'on regarde avant de choisir. */
.bloc-cours--etroit .bloc-cours__duree { display: none; }
/* Le point qui annonçait la durée n'a plus rien à annoncer. */
.bloc-cours--etroit .bloc-cours__depart::after { content: none; }
.bloc-cours__etat {
  font-family: var(--font-titre);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .03em;
}

/* Les places restantes sur la capacité, sur chaque cours. Discrètes tant
   qu'il en reste, elles se colorent quand la salle se remplit. */
.bloc-cours__places {
  font-family: var(--font-titre);
  font-size: 10px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  opacity: .75;
}
/* La jauge de remplissage, sous le titre.
   ----------------------------------------------------------------------------
   Elle existe pour lever l'ambiguïté du rapport : « 22/22 » se lit comme un
   score, donc comme complet, alors qu'il veut dire vingt-deux places libres.
   Barre vide, personne ; barre pleine, plus de place. Trois pixels suffisent —
   on ne la lit pas, on la voit.

   Sous le titre et non en bas de la tuile : là, elle jouxtait le trait de
   couleur du lieu, et deux règles empilées ne se distinguaient plus. */
.bloc-cours__jauge {
  /* Incompressible. Un bloc a maintenant la hauteur exacte de sa durée, et
     dans un cours de trois quarts d'heure le compte est juste : la barre, qui
     est un élément flexible de trois pixels, se laissait écraser jusqu'à
     disparaître. Elle s'effaçait donc sur le seul cours court de la semaine —
     et sur lui seul, ce qui rendait le défaut difficile à voir. */
  flex: 0 0 auto;
  display: block;
  height: 3px;
  margin: 3px 0 4px;
  border-radius: 999px;
  /* La transparence est DANS la couleur, pas sur l'élément.
     --------------------------------------------------------------------------
     « opacity » s'applique à tout le sous-arbre : posée sur la barre, elle
     éteignait aussi la portion remplie, qui porte la même couleur. Les deux
     tombaient donc à la même teinte et la jauge paraissait toujours vide, quel
     que soit le remplissage. Elle n'a jamais rien montré. */
  background: rgba(60, 40, 55, .13);
  background: color-mix(in oklab, currentColor 15%, transparent);
  overflow: hidden;
}
.bloc-cours__jauge__prise {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: currentColor;
  opacity: .6;
}
/* Pleine, la jauge cesse d'être un décor et devient l'information. */
.bloc-cours__jauge--pleine .bloc-cours__jauge__prise { opacity: .85; }

.bloc-cours__places--basse { color: #7A5410; opacity: 1; }
.bloc-cours__places--nulle { opacity: .5; }

.bloc-cours[aria-pressed="true"] {
  outline: 2px solid var(--fam-fonce);
  outline-offset: 1px;
}
/* Un stage, un atelier : ce qui n'a lieu qu'une fois.
   ----------------------------------------------------------------------------
   Le bloc perd son fond et devient un cadre. La distinction passe par la forme
   parce que la couleur est déjà prise deux fois — la teinte dit la discipline,
   le liseré du bas dit la salle — et qu'une troisième famille de couleurs
   rendrait la grille illisible.

   Le coin inférieur gauche reste vif quand les trois autres sont arrondis :
   le bloc ne s'inscrit plus tout à fait dans la trame, et cela se voit du coin
   de l'œil sans qu'on ait rien à lire. */
.bloc-cours--ponctuel {
  /* Le coin inférieur gauche est coupé net, à quarante-cinq degrés.
     ------------------------------------------------------------------------
     C'est une distinction de FORME, et c'est ce qui la rend utile : la couleur
     est déjà prise par la discipline, le liseré du bas par la salle, et le fond
     blanc par les cours qu'on a réservés. Il ne restait que la silhouette.

     Un bloc coupé ne s'inscrit plus tout à fait dans la trame — cela se voit du
     coin de l'œil, sans rien lire et sans légende à retenir.

     « clip-path » découpe aussi le liseré du bas, qui suit donc la coupe. On
     revient à un contour plein : un pointillé se serait fait trancher au milieu
     d'un tiret, et le trait aurait paru cassé plutôt que dessiné. */
  border-radius: 10px;
  clip-path: polygon(0 0, 100% 0, 100% 100%, 15px 100%, 0 calc(100% - 15px));
  box-shadow: inset 0 0 0 2px var(--fam);
}
/* Un stage qu'on a réservé : « à moi » prime, il passe au blanc comme les autres
   cours réservés, et garde sa coupe — les deux marques se cumulent sans se
   contredire. */
.bloc-cours--ponctuel.bloc-cours--mien { background: #fff; }

.bloc-cours--complet { opacity: .62; }
.bloc-cours--annule  { opacity: .5; }
.bloc-cours--annule .bloc-cours__nom { text-decoration: line-through; }
/* Réservé : le liseré, et une pastille cochée dans le coin.
   ----------------------------------------------------------------------------
   La couleur est déjà prise deux fois — la teinte dit la discipline, le liseré
   du bas dit la salle — et le fond pâle se garde tel quel : le planning reste
   calme, seuls les cours pris portent une marque.

   La pastille est POSÉE DANS le bloc et non à cheval dessus. Débordant du coin,
   elle mordait sur le bloc du dessus : les colonnes n'ont que cinq pixels
   d'écart, et deux cours qui se suivent dans la même journée se touchent
   presque. */
/* Fond blanc : dans une grille de blocs teintés, c'est la marque la plus forte
   dont on dispose une fois la couleur prise par la discipline et le liseré du
   bas par la salle. Elle n'est donnée qu'à un seul état — « vous y êtes » — ce
   qui la rend lisible sans légende. */
.bloc-cours--mien {
  background: #fff;
  box-shadow: inset 0 0 0 2px var(--fam);
}
.bloc-cours--mien::after {
  content: '✓';
  position: absolute;
  top: 3px;
  right: 4px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--fam);
  color: #fff;
  font-family: var(--font-titre);
  font-size: 10px;
  font-weight: 700;
  line-height: 16px;
  text-align: center;
}
/* La pastille occupe le coin haut-droit : l'heure, qui est centrée, recule
   d'autant pour ne pas venir la toucher. */
.bloc-cours--mien .bloc-cours__heure { padding-right: 16px; }

/* Une couleur par discipline, prise dans la charte du site. */
.bloc-cours--yoga,    .fiche-seance--yoga    { --fam: var(--prune); --fam-clair: hsl(var(--teinte) calc(var(--force) * 21.1%) 92.5%); --fam-fonce: #5E3B53; }
.bloc-cours--pilates, .fiche-seance--pilates { --fam: #EC7069; --fam-clair: #FCEAE9; --fam-fonce: #A8433D; }
.bloc-cours--paddle,  .fiche-seance--paddle  { --fam: #09354E; --fam-clair: #E3ECF1; --fam-fonce: #09354E; }
.bloc-cours--kids,    .fiche-seance--kids    { --fam: #F19953; --fam-clair: #FDF0E4; --fam-fonce: #8F5321; }
.bloc-cours--renfo,   .fiche-seance--renfo   { --fam: #FAB926; --fam-clair: #FDF3DE; --fam-fonce: #7A5410; }
.bloc-cours--autre,   .fiche-seance--autre   { --fam: var(--prune); --fam-clair: hsl(var(--teinte) calc(var(--force) * 20%) 94.1%); --fam-fonce: hsl(var(--teinte) calc(var(--force) * 7.1%) 32.9%); }

/* ----------------------------------------------- la fiche d'une séance -- */

.fiche-seance {
  margin-top: 14px;
  background: #fff;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 18.9%) 92.7%);
  border-left: 4px solid var(--fam, hsl(var(--teinte) calc(var(--force) * 12.9%) 87.8%));
  border-radius: 14px;
  padding: 14px 16px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  align-items: flex-start;
}

/* L'intitulé et les places sur une même ligne : la pastille occupait une
   ligne entière entre la date et le nom du cours. */
.fiche-seance__rang {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 4px 12px;
  width: 100%;
}
.fiche-seance__rang > * { min-width: 0; }

.fiche-invite {
  margin: 0;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
  text-align: center;
  width: 100%;
}

.fiche-seance__haut {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 10px 14px;
  width: 100%;
}
.fiche-seance__quand {
  font-family: var(--font-titre);
  font-size: 15px;
  font-weight: 600;
  color: var(--prune);
}
.fiche-seance__cours { margin: 0; font-size: 22px; line-height: 1.2; }
/* L'italique venait du serif, où il distinguait une phrase citée. En Jost,
   sur un nom de salle, il ne distingue plus rien : il penche, c'est tout. */
.fiche-seance__lieu  { margin: 0; color: hsl(var(--teinte) calc(var(--force) * 6.3%) 40.6%); }
.fiche-seance__motif {
  margin: 0;
  font-family: var(--font-titre);
  font-size: 14px;
  color: #97302A;
}
.fiche-seance__action { margin-top: 8px; }

.fiche-seance .exception {
  width: 100%;
  margin-top: 16px;
  padding: 16px 0 0;
  border-top: 1px solid hsl(var(--teinte) calc(var(--force) * 18.9%) 92.7%);
}

@media (max-width: 560px) {
  .grille-semaine { gap: 4px; }
  .bloc-cours { padding: 5px 3px; min-height: 52px; border-radius: 9px; }
  .bloc-cours__nom { font-size: 12.5px; }
  .fiche-seance { padding: 16px; }
  .fiche-seance__cours { font-size: 22px; }
  .fiche-seance__action { width: 100%; }
}

/* ========================================================================
   Mon compte
   ====================================================================== */

.compte { display: flex; flex-direction: column; gap: 16px; }

/* --------------------------------------------------------- la formule -- */

.formule {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 16px 18px;
  border-radius: 12px;
  background: hsl(var(--teinte) calc(var(--force) * 27.3%) 97.8%);
  border-left: 4px solid var(--prune);
}
.formule--sans { border-left-color: var(--corail); }
.formule--carte { border-left-color: var(--jaune); }
.formule--seance  { border-left-color: #09354E; }

/* ========================================================================
   Les membres, côté administration
   ====================================================================== */

.recherche { display: grid; gap: 6px; margin: 18px 0 22px; }
.recherche input {
  color: hsl(var(--teinte) calc(var(--force) * 7%) 27.1%);
  padding: 10px 14px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 12.9%) 87.8%);
  border-radius: 30px;
  background: #fff;
  font-family: inherit;
  font-size: 17px;
}
.recherche input:focus { outline: 2px solid var(--jaune); outline-offset: 1px; }

.membre {
  background: #fff;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 18.9%) 92.7%);
  border-radius: 14px;
  padding: 18px 20px;
  margin-bottom: 14px;
  display: flex;
  flex-direction: column;
  gap: 9px;
}

.membre__nom {
  margin: 0;
  font-family: var(--font-titre);
  font-size: 20px;
  font-weight: 600;
  color: var(--prune);
}
.membre__nom.manquant { color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%); }

.membre__formule {
  margin: 0;
  padding: 10px 14px;
  border-radius: 10px;
  background: hsl(var(--teinte) calc(var(--force) * 27.3%) 97.8%);
  border-left: 3px solid var(--prune);
  font-size: 17px;
}
.membre__formule--sans { border-left-color: hsl(var(--teinte) calc(var(--force) * 12.9%) 87.8%); color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%); }

.membre__actions { display: flex; flex-wrap: wrap; gap: 8px 18px; }

/* Panneau déplié sous une fiche membre : attribuer une formule, ou corriger
   les coordonnées. Un seul ouvert à la fois. */
.panneau {
  margin-top: 6px;
  padding-top: 16px;
  border-top: 1px solid hsl(var(--teinte) calc(var(--force) * 18.9%) 92.7%);
}
.panneau__aide {
  margin: 0 0 14px;
  color: hsl(var(--teinte) calc(var(--force) * 6.3%) 40.6%);
  font-size: 16px;
}
.panneau .message { margin-top: 12px; }

/* ---------------------------------------------------------- à encaisser */

.encaisser { margin-top: 34px; padding-top: 26px; border-top: 1px solid hsl(var(--teinte) calc(var(--force) * 12.9%) 87.8%); }
.encaisser h3 { margin-top: 0; }

/* Une séance à encaisser : qui, quoi, combien — et le geste au bout. */
.impaye {
  display: flex;
  align-items: center;
  /* « wrap » depuis que le choix du moyen se déplie sous la rangée : sans lui,
     les quatre boutons se glissaient entre le texte et « Annuler », et la
     rangée devenait illisible. */
  flex-wrap: wrap;
  gap: 12px;
  padding: 10px 0;
  border-bottom: 1px solid hsl(var(--teinte) calc(var(--force) * 18.9%) 92.7%);
}
.impaye__corps { flex: 1 1 auto; min-width: 0; }
.impaye__qui {
  display: block;
  font-family: var(--font-titre);
  font-weight: 600;
  font-size: 15px;
  color: var(--prune);
}
.impaye__quoi {
  margin: 1px 0 0;
  font-size: 14px;
  line-height: 1.35;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
.impaye__montant { font-family: var(--font-titre); font-weight: 600; color: hsl(var(--teinte) calc(var(--force) * 7.6%) 28.4%); }
.impaye__montant--flou { color: #8F5321; }

@media (max-width: 560px) {
  .compte__coordonnees { grid-template-columns: 1fr; gap: 2px; }
  .membre { padding: 16px; }
}

/* ========================================================================
   Connexion, première visite, invitation
   ====================================================================== */

#form-connexion input[type="password"] {
  color: hsl(var(--teinte) calc(var(--force) * 7%) 27.1%);
  padding: 12px 18px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 12.9%) 87.8%);
  border-radius: 30px;
  background: #fff;
  font-family: inherit;
  font-size: 17px;
}

.connexion__liens { margin-top: 14px; }

.connexion__aide {
  margin-top: 20px;
  padding-top: 16px;
  border-top: 1px solid hsl(var(--teinte) calc(var(--force) * 18.9%) 92.7%);
  font-size: 17px;
  color: hsl(var(--teinte) calc(var(--force) * 6.3%) 40.6%);
}
.connexion__aide a { color: var(--prune); }

/* Un libellé secondaire dans un champ : « facultative », « 8 caractères ». */
.champs label small {
  font-weight: 400;
  font-size: 12px;
  letter-spacing: 0;
  text-transform: none;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
.champs label small::before { content: " · "; }

#form-bienvenue .champs { margin-top: 18px; }

.inviter {
  background: hsl(var(--teinte) calc(var(--force) * 27.3%) 97.8%);
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 18.9%) 92.7%);
  border-radius: 14px;
  padding: 20px;
  margin: 18px 0 26px;
}
.inviter h3 { margin-top: 0; }

/* ---------------------------------------------------- données personnelles */

/* La phrase courte est là où les informations sont saisies ; le détail se
   déplie depuis le compte, sans encombrer la page de celles qui ne le
   cherchent pas. */
.mention-donnees {
  margin: 0 0 4px;
  padding: 14px 16px;
  border-radius: 10px;
  background: hsl(var(--teinte) calc(var(--force) * 27.3%) 97.8%);
  border-left: 3px solid var(--prune);
  font-size: 17px;
  color: hsl(var(--teinte) calc(var(--force) * 7.6%) 28.4%);
}

.donnees {
  margin-top: 8px;
  padding-top: 16px;
  border-top: 1px solid hsl(var(--teinte) calc(var(--force) * 18.9%) 92.7%);
}

.donnees > summary {
  cursor: pointer;
  font-family: var(--font-titre);
  font-size: 15px;
  font-weight: 600;
  color: var(--prune);
  list-style: none;
}
.donnees > summary::-webkit-details-marker { display: none; }
.donnees > summary::before {
  content: "▸ ";
  display: inline-block;
  transition: transform .15s;
}
.donnees[open] > summary::before { content: "▾ "; }
.donnees > summary:focus-visible { outline: 2px solid var(--prune); outline-offset: 3px; }

.donnees h3 {
  margin: 20px 0 6px;
  font-size: 15px;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
.donnees p, .donnees ul { margin: 0 0 10px; font-size: 17px; color: hsl(var(--teinte) calc(var(--force) * 7.6%) 28.4%); }
.donnees ul { padding-left: 20px; }
.donnees li { margin-bottom: 3px; }

@media (prefers-reduced-motion: reduce) {
  .donnees > summary::before { transition: none; }
}

/* ------------------------------------------------ règle d'un cours récurrent */

/* « Jour : Lundi » se lit comme « ce lundi-là ». Le formulaire dit donc en
   toutes lettres ce qu'il crée : un cours qui revient chaque semaine, et
   jusqu'à quand. */
.regle-recurrence {
  margin: 0 0 18px;
  padding: 12px 14px;
  border-radius: 10px;
  background: #fff;
  border-left: 3px solid var(--jaune);
  font-size: 17px;
  color: hsl(var(--teinte) calc(var(--force) * 7.6%) 28.4%);
}

/* L'heure de fin est déduite de la durée : on la montre pour confirmation,
   sans la faire saisir. */
.calcul-fin {
  margin: -4px 0 14px;
  font-family: var(--font-titre);
  font-size: 14px;
  font-weight: 600;
  color: var(--prune);
}
/* ========================================================================
   Gestion du planning sur téléphone
   ------------------------------------------------------------------------
   C'est depuis un téléphone que le planning se gère. Un tableau de six
   colonnes n'y tient pas : chaque cours est une fiche, groupée par jour.
   ====================================================================== */

.bloc-gestion { margin-bottom: 30px; }
.bloc-gestion h3 { margin-bottom: 4px; }

.gestion__jour {
  margin: 22px 0 8px;
  font-family: var(--font-titre);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}

/* Les deux outils d'administration, sous la fiche d'une séance. */
/* Trois libellés en toutes lettres débordaient sur deux lignes. Une icône
   au-dessus d'un mot tient sur une seule, et les trois gestes se partagent la
   largeur à parts égales. */
/* Trois gestes qu'on emploie une fois par mois — déplacer une date, prévenir
   les inscrits, supprimer une séance — occupaient cent trente pixels en tuiles
   verticales, au-dessus de la liste des inscrits qu'on vient réellement lire.
   Ils passent en une rangée de pastilles : quatre-vingt-deux pixels ramenés à
   cinquante-cinq.

   « cette date », qui les allongeait, est dit là où il compte — dans la
   confirmation, qui nomme le cours et la date, et dont le bouton porte
   « Supprimer cette date ». Une étiquette qui prévient trois semaines à
   l'avance vaut moins qu'une question posée la main sur le bouton. */
.fiche-seance__outils {
  display: flex;
  gap: 6px;
  width: 100%;
  margin-top: 8px;
  padding-top: 10px;
  border-top: 1px solid hsl(var(--teinte) calc(var(--force) * 18.9%) 92.7%);
}

/* Ces règles ne valent QUE pour les outils d'une séance : « .outil » sert aussi
   aux gestes d'une fiche adhérent, où la disposition en tuile est la bonne. */
.fiche-seance__outils .outil {
  flex-direction: row;
  justify-content: center;
  gap: 6px;
  min-height: 38px;
  padding: 7px 8px;
  border-radius: 999px;
}
.fiche-seance__outils .outil svg { width: 16px; height: 16px; }
.fiche-seance__outils .outil__mot { font-size: 12.5px; }


.outil {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  min-height: 56px;
  padding: 9px 4px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 21.7%) 91%);
  border-radius: 11px;
  background: hsl(var(--teinte) calc(var(--force) * 33.3%) 97.6%);
  color: var(--prune);
  cursor: pointer;
}
.outil svg {
  width: 20px;
  height: 20px;
  flex: 0 0 auto;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.outil__mot {
  max-width: 100%;
  font-family: var(--font-titre);
  font-size: 12px;
  font-weight: 600;
  line-height: 1.2;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.outil:hover { background: hsl(var(--teinte) calc(var(--force) * 33.3%) 92.9%); border-color: hsl(var(--teinte) calc(var(--force) * 24.1%) 82.9%); }
.outil:focus-visible { outline: 2px solid var(--prune); outline-offset: 2px; }

/* Ce qui retire quelque chose se signale sans crier : la couleur dit la nature
   du geste, pas son urgence. */
.outil--rouge { color: #A8535E; border-color: #F0DDDF; background: #FDF6F6; }
.outil--rouge:hover { background: #F8E7E8; border-color: #E4C2C6; }

/* Raccourcir « Déplacer cette séance » en « Déplacer » effacerait la portée du
   geste. Elle se lit sous le verbe, dans le bouton : trois lignes de phrase en
   dessous des deux boutons disaient la même chose, et il fallait les relire
   pour savoir lequel elles qualifiaient. */
.outil__portee {
  display: block;
  margin-top: 1px;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .02em;
  opacity: .72;
}

/* ------------------------------------------------------ points de contact */

/* Un numéro ou une adresse se touchent pour appeler ou écrire. Ils doivent
   donc se voir comme des liens, et offrir une cible confortable au doigt. */
.contact {
  color: var(--prune);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
  text-decoration-color: hsl(var(--teinte) calc(var(--force) * 18.4%) 79.8%);
  overflow-wrap: anywhere;
}
.contact:hover { text-decoration-color: var(--prune); }
.contact:focus-visible { outline: 2px solid var(--prune); outline-offset: 2px; }

.membre__coordonnees .contact,

/* ---------------------------------------------------- prévenir les inscrites */

.prevenir {
  margin: 4px 0 16px;
  padding: 14px 16px;
  border-radius: 10px;
  background: #FDF1DC;
}

.case {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  cursor: pointer;
  font-family: var(--font-titre);
  font-size: 15px;
  font-weight: 600;
  color: #7A5410;
}
.case input { width: 20px; height: 20px; margin: 1px 0 0; accent-color: var(--prune); flex: 0 0 auto; }

.prevenir .champ-large { margin-top: 12px; display: grid; gap: 5px; }
.prevenir textarea {
  padding: 9px 12px;
  border: 1px solid #E9D9BC;
  border-radius: 8px;
  background: #fff;
  font-family: inherit;
  font-size: 16px;
  resize: vertical;
}
.prevenir textarea:focus { outline: 2px solid var(--jaune); outline-offset: 1px; }

/* ------------------------------------------- inscrites à une séance, historique */

.inscriptions {
  width: 100%;
  margin-top: 12px;
  padding-top: 14px;
  border-top: 1px solid hsl(var(--teinte) calc(var(--force) * 18.9%) 92.7%);
}
.inscriptions__titre {
  margin: 0 0 10px;
  font-family: var(--font-titre);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}

/* Le titre de la liste d'attente vient juste après la dernière inscrite : sans
   un peu d'air, les deux listes n'en font plus qu'une. Le premier titre n'en a
   pas besoin, un trait le précède déjà. */
.inscrit + .inscriptions__titre { margin-top: 18px; }

/* Ce que le titre ne dit pas : que la place se transmet sans qu'on la donne.
   Sous le titre plutôt que dans les rangées — une mention par personne les
   faisait passer à la ligne dès que le nom était long. */
.inscriptions__note {
  margin: -6px 0 10px;
  font-size: 13px;
  line-height: 1.35;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}

/* Une ligne, une personne : le nom prend la place, les trois gestes tiennent
   dans trois pastilles. Écrits en toutes lettres, « Appeler » et « Écrire »
   faisaient d'une liste de quinze personnes un écran de défilement. */
.inscrit {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 0;
  border-bottom: 1px solid hsl(var(--teinte) calc(var(--force) * 23.8%) 95.9%);
}
.inscrit__nom {
  flex: 1 1 auto;
  font-family: var(--font-titre);
  font-weight: 600;
  font-size: 16px;
  line-height: 1.25;
}
.inscrit__actions { display: flex; flex: 0 0 auto; gap: 6px; }

/* Le nom fait l'appel. Il garde exactement l'allure d'un nom : un bouton
   dessiné comme tel aurait ajouté un cadre à chaque rangée, et vingt cadres
   sur une liste de vingt ne se lisent plus. C'est le résultat qui se voit —
   le nom barré — pas l'outil.

   « text-align: left » et « padding: 0 » parce qu'un <button> centre son
   libellé et se réserve une marge que le <span> n'avait pas : sans ces deux
   lignes, tous les noms se décalaient. */
.inscrit__appel {
  padding: 0;
  border: 0;
  background: none;
  text-align: left;
  color: inherit;
  cursor: pointer;
}
.inscrit--absent .inscrit__nom {
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
  text-decoration: line-through;
  text-decoration-thickness: 1px;
}

/* Les accompagnants, sous la ligne de l'inscrit. Tant que personne n'est
   amené, un seul mot discret : la liste ne s'alourdit que quand il le faut. */
.accomp { padding: 0 0 9px; border-bottom: 1px solid hsl(var(--teinte) calc(var(--force) * 23.8%) 95.9%); }
.accomp--ouverte {
  margin: 2px 0 9px;
  padding: 10px 12px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 28.6%) 91.8%);
  border-radius: 10px;
  background: hsl(var(--teinte) calc(var(--force) * 33.3%) 97.6%);
}
.accomp__entete {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 6px;
  font-family: var(--font-titre);
  font-size: 13px;
  font-weight: 600;
  color: var(--prune);
}
.accomp__entete > * { min-width: 0; }
.accomp__rang {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 3px 0;
}
.accomp__rang > * { min-width: 0; }
.accomp__quoi { font-size: 15px; color: hsl(var(--teinte) calc(var(--force) * 6.3%) 40.6%); }

.accomp__compteur {
  display: flex;
  align-items: center;
  flex: 0 0 auto;
  gap: 2px;
  padding: 2px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 21.7%) 91%);
  border-radius: 20px;
  background: hsl(var(--teinte) calc(var(--force) * 33.3%) 97.6%);
}
.accomp__pas {
  /* Le rond dessiné reste petit — il vit dans une pastille étroite — mais la
     zone qui répond au doigt fait la taille d'un pouce. On agrandit la cible,
     pas le dessin : c'est ce qui se règle sans rien changer à l'écran. */
  width: 28px;
  height: 28px;
  min-width: 44px;
  min-height: 44px;
  background-clip: content-box;
  padding: 8px;
  flex: 0 0 auto;
  border: 0;
  border-radius: 50%;
  background: none;
  font-family: var(--font-titre);
  font-size: 17px;
  font-weight: 600;
  line-height: 1;
  color: var(--prune);
  cursor: pointer;
}
.accomp__pas:hover { background: hsl(var(--teinte) calc(var(--force) * 31.7%) 92%); }
.accomp__pas:focus-visible { outline: 2px solid var(--prune); outline-offset: 1px; }
.accomp__nombre {
  padding: 0 6px;
  font-family: var(--font-titre);
  font-size: 14px;
  font-weight: 600;
  color: var(--prune);
  white-space: nowrap;
}

.accomp__pas[disabled] { opacity: .3; pointer-events: none; }

/* Côté élève : dire seulement combien on vient. Le sort de chaque place
   revient au coach — offrir un essai est sa décision, pas une règle. */

/* Ce que coûtent les places accompagnées, dit avant de réserver plutôt qu'au
   moment de payer sur place. */
/* Le compteur d'accompagnants, sur une place déjà prise.
   ----------------------------------------------------------------------------
   Il se tenait dans la rangée du bouton « Réserver », avant de l'avoir touché,
   et se lisait comme une étape à franchir. Il n'apparaît plus qu'après, dans
   une phrase : une phrase ne se prend pas pour un formulaire. */
.venir-avec-apres { margin-top: 14px; }
.venir-avec__phrase {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0;
  font-size: 15px;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
/* « personne » ou « personnes » : le mot suit le nombre et ne s'en sépare pas
   quand la phrase se replie. */
.venir-avec__unite { white-space: nowrap; }

.venir-avec__prix {
  margin: 6px 0 0;
  font-size: 14px;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
  text-wrap: pretty;
}

.accomp__du {
  flex: 0 0 auto;
  font-family: var(--font-titre);
  font-size: 14px;
  font-weight: 600;
  color: #7A5410;
}

.pastille {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  flex: 0 0 auto;
  padding: 0;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 21.7%) 91%);
  border-radius: 50%;
  background: hsl(var(--teinte) calc(var(--force) * 33.3%) 97.6%);
  color: var(--prune);
  cursor: pointer;
  text-decoration: none;
}
.pastille svg { width: 19px; height: 19px; fill: currentColor; }
.pastille:hover { background: hsl(var(--teinte) calc(var(--force) * 33.3%) 92.9%); border-color: hsl(var(--teinte) calc(var(--force) * 24.1%) 82.9%); }
.pastille:focus-visible { outline: 2px solid var(--prune); outline-offset: 2px; }
.pastille--retirer { color: #A8535E; border-color: #F0DDDF; background: #FDF6F6; }
.pastille--retirer:hover { background: #F8E7E8; border-color: #E4C2C6; }
.pastille[disabled] { opacity: .45; pointer-events: none; }

/* Ajouter quelqu'un venu sans réserver : un champ, puis les noms qu'il
   trouve. En colonne et non en ligne — les propositions se posent sous le
   champ, là où le pouce vient de frapper. */
.inscrit-ajout { margin-top: 14px; }
.inscrit-ajout__champ {
  width: 100%;
  padding: 11px 14px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 12.9%) 87.8%);
  border-radius: 10px;
  background: #fff;
  font-family: inherit;
  /* Seize pixels : en dessous, iOS agrandit la page au premier toucher dans
     un champ, et l'écran saute. */
  font-size: 16px;
}
.inscrit-ajout__champ:focus {
  outline: 2px solid var(--jaune);
  outline-offset: 1px;
}

.inscrit-ajout__trouves { display: flex; flex-direction: column; gap: 4px; }
.inscrit-ajout__trouves:not(:empty) { margin-top: 8px; }

/* Chaque proposition est pleine largeur et haute d'un pouce : on la touche
   sans viser, et c'est ce toucher qui inscrit — il n'y a pas de bouton
   « Ajouter » derrière. */
.inscrit-ajout__trouve {
  display: block;
  width: 100%;
  min-height: 44px;
  padding: 10px 14px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 21.7%) 91%);
  border-radius: 10px;
  background: hsl(var(--teinte) calc(var(--force) * 33.3%) 97.6%);
  font-family: var(--font-titre);
  font-size: 16px;
  font-weight: 600;
  text-align: left;
  color: var(--prune);
  cursor: pointer;
}
.inscrit-ajout__trouve:hover { background: hsl(var(--teinte) calc(var(--force) * 31.3%) 93.7%); }
.inscrit-ajout__trouve:disabled { opacity: .5; }
.inscrit-ajout .chargement { margin: 8px 0 0; }

.historique { margin-top: 10px; }
.historique__total {
  margin: 0 0 12px;
  font-family: var(--font-titre);
  font-size: 15px;
  font-weight: 600;
  color: var(--prune);
}
/* Un en-tête par mois, avec le compte à droite : on retrouve une période sans
   lire chaque ligne. */
.historique__mois {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  margin: 16px 0 4px;
  padding-bottom: 4px;
  border-bottom: 1px solid hsl(var(--teinte) calc(var(--force) * 18.9%) 92.7%);
  font-family: var(--font-titre);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
.historique__compte { color: var(--prune); letter-spacing: 0; font-size: 13px; }

/* Une ligne par séance : trente-six pixels au lieu de cent quatre-vingt-dix. */
.historique__ligne {
  display: grid;
  grid-template-columns: 52px 44px 1fr auto;
  align-items: baseline;
  gap: 10px;
  padding: 7px 0;
}
.historique__ligne--sans-effet { opacity: .5; }
.historique__ligne--sans-effet .historique__cours { text-decoration: line-through; }

.historique__jour {
  font-family: var(--font-titre);
  font-size: 12px;
  font-weight: 600;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
.historique__heure {
  font-family: var(--font-titre);
  font-size: 13px;
  font-weight: 600;
  color: var(--prune);
  font-variant-numeric: tabular-nums;
}
.historique__cours {
  font-size: 16px;
  line-height: 1.25;
  overflow-wrap: anywhere;
}
.historique__etat {
  font-family: var(--font-titre);
  font-size: 10px;
  font-weight: 600;
  padding: 2px 8px;
  border-radius: 20px;
  white-space: nowrap;
}
.historique__etat--gris  { background: hsl(var(--teinte) calc(var(--force) * 20%) 94.1%); color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%); }
.historique__etat--ambre { background: #FDF1DC; color: #7A5410; }

/* -------------------------------------------------- le solde d'une carte */

/* C'est ce que la personne vient vérifier en se connectant : le nombre doit
   se lire sans être cherché dans une phrase. */
.solde { display: inline-flex; align-items: baseline; gap: 6px; }

/* ------------------------------------------------------ le catalogue d'offres */

.offre {
  background: #fff;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 18.9%) 92.7%);
  border-left: 4px solid var(--jaune);
  border-radius: 12px;
  padding: 14px 16px;
  margin-bottom: 10px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

/* -------------------------------------------------------------- ateliers */

/* Un atelier ne se range dans aucune discipline : sa couleur lui est propre,
   parce que ce qui le distingue n'est pas ce qu'on y fait mais qu'il se paie
   à part. Le violet de la charte n'était pas encore employé. */
.bloc-cours--atelier,
.fiche-seance--atelier,

.bloc-cours--atelier { box-shadow: inset 0 0 0 1.5px #D9B9E0; }
.bloc-cours--atelier .bloc-cours__etat { font-size: 11px; }

.fiche-seance__atelier {
  margin: 0;
  padding: 10px 12px;
  border-radius: 8px;
  background: #F3E8F5;
  color: #5B2465;
  font-size: 16px;
}

/* Case à cocher tenant toute la largeur d'un formulaire. */
/* La règle posait « flex-direction » sans jamais poser « display » : le
   libellé restait le « block » de « .champs label », la case tombait seule sur
   sa ligne et la phrase commençait dessous.

   « !important » comme les quatre déclarations voisines : « .champs label »
   pèse un élément de plus que « .case-champ » et l'emporte sans cela. */
.case-champ {
  display: flex !important;
  flex-direction: row;
  align-items: flex-start;
  gap: 10px;
  font-weight: 400 !important;
  color: hsl(var(--teinte) calc(var(--force) * 7.6%) 28.4%) !important;
  text-transform: none !important;
  font-size: 16px !important;
  cursor: pointer;
}
.case-champ input { width: 20px; height: 20px; margin: 2px 0 0; accent-color: var(--prune); flex: 0 0 auto; }
/* La phrase prend la place qui reste et se replie dedans, au lieu de pousser
   la case hors de la ligne. */
.case-champ span { flex: 1 1 auto; min-width: 0; line-height: 1.35; }

/* ------------------------------------------------------------- paiements */

.paiements { margin-top: 10px; }

/* Un simple filet ne séparait pas deux périodes : leurs faits, leurs
   versements et leur formulaire se suivaient au même niveau, et l'on ne
   voyait plus où l'une finissait. Chacune devient une carte. */
.paiements__abonnement {
  margin: 8px 0;
  padding: 12px 14px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 18.9%) 92.7%);
  border-radius: 12px;
  background: #fff;
}
.paiements__abonnement--en-cours { border-color: hsl(var(--teinte) calc(var(--force) * 28%) 85.3%); box-shadow: 0 1px 0 hsl(var(--teinte) calc(var(--force) * 30.8%) 94.9%); }

.paiements__entete {
  display: grid;
  gap: 5px;
  justify-items: start;
}
.paiements__puces { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.paiements__nom {
  font-family: var(--font-titre);
  font-size: 16px;
  font-weight: 600;
  color: var(--prune);
}
/* La pastille du solde prend l'habit commun : elle était en 14 px quand sa
   voisine était en 12, ce qui donnait deux pastilles de hauteurs différentes
   sur la même ligne. Seules ses couleurs lui appartiennent encore. */
.paiements__solde--ok { background: #E8F0EA; color: #2C5C3C; }
.paiements__solde--du { background: #FDF1DC; color: #7A5410; }

.paiements__total {
  margin: 2px 0 8px;
  padding-bottom: 8px;
  border-bottom: 1px solid hsl(var(--teinte) calc(var(--force) * 23.8%) 95.9%);
  font-size: 14px;
  color: hsl(var(--teinte) calc(var(--force) * 6.3%) 40.6%);
}

/* Un versement : son montant et sa date en titre, son moyen en description,
   et le geste rare au bout. Rien ne se replie d'une ligne à l'autre. */
.versement {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 9px 0;
  border-bottom: 1px solid hsl(var(--teinte) calc(var(--force) * 23.8%) 95.9%);
}
.versement__corps { flex: 1 1 auto; min-width: 0; }
.versement__titre {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 2px 10px;
}
.versement__montant {
  font-family: var(--font-titre);
  font-size: 17px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.versement__date {
  font-family: var(--font-titre);
  font-size: 13px;
  font-weight: 500;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
.versement__moyen {
  margin: 1px 0 0;
  font-size: 15px;
  color: hsl(var(--teinte) calc(var(--force) * 6.3%) 40.6%);
  line-height: 1.35;
}
.versement__moyen:empty { display: none; }
.versement__effacer {
  flex: 0 0 auto;
  padding: 2px 0;
  min-height: 0;
  font-size: 13px;
}

/* Ajouter un versement est un geste ponctuel : le formulaire se déplie, il ne
   trône pas ouvert sous chaque période. */

.versement-ajout {
  margin-top: 8px;
  padding: 12px;
  border-radius: 10px;
  background: hsl(var(--teinte) calc(var(--force) * 27.3%) 97.8%);
  display: grid;
  gap: 8px;
}
.versement-ajout .actions { margin: 0; }
.versement-ajout .actions button { padding: 9px 20px; font-size: 14px; }

/* ========================================================================
   La barre de navigation
   ------------------------------------------------------------------------
   Posée en bas : c'est là que le pouce arrive sans effort, et elle reste
   atteignable sans remonter la page. Un écran à la fois, plutôt qu'une page
   de plusieurs milliers de pixels où l'on cherche où l'on est.
   ====================================================================== */

.barre {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 20;
  display: flex;
  background: #fff;
  border-top: 1px solid hsl(var(--teinte) calc(var(--force) * 12.9%) 87.8%);
  /* Laisse la place à la barre d'accueil des téléphones sans bouton. */
  padding-bottom: env(safe-area-inset-bottom, 0);
  box-shadow: 0 -2px 12px rgba(42, 34, 40, .06);
}

.barre__onglet {
  flex: 1 1 0;
  min-width: 0;
  border: 0;
  background: none;
  padding: 9px 2px 8px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  cursor: pointer;
  font-family: var(--font-titre);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .01em;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
  /* 44 px de haut : la taille minimale d'une cible tactile confortable. */
  min-height: 52px;
}

.barre__onglet svg {
  width: 22px; height: 22px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.barre__onglet span {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* L'onglet ouvert ne se distinguait que par sa teinte — prune contre gris —
   et sur un écran au soleil, deux gris se ressemblent. Il porte maintenant une
   pastille derrière son icône, comme les sous-onglets de la Gestion : une
   forme se voit là où une nuance se devine.

   La pastille est derrière l'icône seule, pas derrière l'ensemble : elle
   marquerait sinon un pavé de la hauteur de la barre, et « Mon compte » ferait
   deux fois la largeur d'« Infos ». */
.barre__onglet--actif { color: var(--prune); }
.barre__onglet--actif svg { stroke-width: 2; }
.barre__onglet svg {
  padding: 4px 14px;
  border-radius: 999px;
  box-sizing: content-box;
  transition: background-color .15s ease;
}
.barre__onglet--actif svg { background: hsl(var(--teinte) calc(var(--force) * 31.3%) 93.7%); }
@media (prefers-reduced-motion: reduce) { .barre__onglet svg { transition: none; } }
.barre__onglet:focus-visible { outline: 2px solid var(--prune); outline-offset: -3px; }

/* La barre recouvre le bas de la page : on lui réserve sa hauteur. */
body.avec-barre .espace__corps { padding-bottom: 96px; }

@media (max-width: 380px) {
  .barre__onglet { font-size: 10px; }
  .barre__onglet svg { width: 20px; height: 20px; }
}

/* ===================================================== les informations */

.info {
  padding: 20px 0;
  border-bottom: 1px solid hsl(var(--teinte) calc(var(--force) * 18.9%) 92.7%);
}
.info:last-of-type { border-bottom: 0; }
.info--masquee { opacity: .55; }

.info__date {
  margin: 0 0 4px;
  font-family: var(--font-titre);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
.info__titre {
  margin: 0 0 10px;
  font-family: var(--font-titre);
  font-size: 22px;
  font-weight: 600;
  color: var(--corail);
  text-transform: none;
  letter-spacing: 0;
}
.info__image {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 12px;
  margin: 0 0 12px;
}
.info__texte { margin: 0 0 10px; font-size: 18px; line-height: 1.55; }
.info__actions { display: flex; flex-wrap: wrap; gap: 6px 18px; margin-top: 10px; }

#form-info textarea {
  padding: 10px 12px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 12.9%) 87.8%);
  border-radius: 8px;
  background: #fff;
  font-family: inherit;
  font-size: 17px;
  font-weight: 400;
  color: hsl(var(--teinte) calc(var(--force) * 10%) 15.7%);
  resize: vertical;
}
#form-info textarea:focus { outline: 2px solid var(--jaune); outline-offset: 1px; }
/* Un sélecteur de fichier porte un bouton natif et un libellé qui, ensemble,
   dépassent la largeur d'une colonne. On réduit le tout et on borne la boîte. */
#form-info input[type="file"] {
  font-family: inherit;
  font-size: 14px;
  font-weight: 400;
  padding: 8px;
}
#form-info input[type="file"]::file-selector-button {
  margin-right: 10px;
  padding: 7px 14px;
  border: 0;
  border-radius: 20px;
  background: hsl(var(--teinte) calc(var(--force) * 21.1%) 92.5%);
  color: var(--prune);
  font-family: var(--font-titre);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}

/* Choisir une photo dans une feuille. Le champ natif reste dans le document —
   c'est lui qui ouvre la pellicule — mais il est masqué sous une zone dessinée :
   le label l'enveloppe, donc le clic lui parvient sans script. */
/* Le sélecteur masqué doit l'emporter sur « .feuille__champ input », qui donne
   100 % de large à tout champ d'une feuille — et qui est plus spécifique qu'une
   simple classe. Sans le sélecteur composé ci-dessous, l'input reprenait la
   largeur de l'écran, sortait du panneau (il est en position absolue, sans
   ancêtre positionné) et faisait glisser toute la feuille latéralement au
   doigt. Rien ne se voyait : l'élément est invisible, seul son encombrement
   agissait. */
.champ-photo { position: relative; }
.champ-photo input.champ-photo__entree,
.feuille__champ input.champ-photo__entree,
.champ-photo__entree {
  position: absolute;
  width: 1px;
  height: 1px;
  min-width: 0;
  padding: 0;
  margin: -1px;
  border: 0;
  clip-path: inset(50%);
  overflow: hidden;
}
.champ-photo__zone {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  margin-top: 3px;
  padding: 15px 12px;
  /* Pointillés : la zone se propose, elle ne réclame pas comme un champ à
     remplir. La photo est facultative et doit le rester à l'œil. */
  border: 1px dashed hsl(var(--teinte) calc(var(--force) * 15.7%) 83.7%);
  border-radius: 10px;
  background: hsl(var(--teinte) calc(var(--force) * 25%) 98.4%);
  cursor: pointer;
}
.champ-photo__zone svg {
  width: 20px;
  height: 20px;
  flex: none;
  fill: none;
  stroke: var(--prune);
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.champ-photo__mot {
  font-family: var(--font-titre);
  font-size: 15px;
  font-weight: 500;
  color: var(--prune);
}
@media (hover: hover) {
  .champ-photo:hover .champ-photo__zone { border-color: var(--prune); background: hsl(var(--teinte) calc(var(--force) * 37.5%) 96.9%); }
}
.champ-photo__entree:focus-visible + .champ-photo__zone,
.champ-photo:focus-within .champ-photo__zone { outline: 2px solid var(--prune); outline-offset: 2px; }

/* L'aperçu de la photo d'une fermeture. Il montre le cadrage réel — 16/10,
   recadré au centre — pour qu'on ne découvre pas sur le planning d'un adhérent
   qu'une photo verticale a perdu la tête du groupe. */
.apercu-fermeture {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
  margin: 0;
}
.apercu-fermeture img {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  border-radius: 10px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 12.9%) 87.8%);
}
.apercu-fermeture__retirer {
  padding: 0;
  border: 0;
  background: none;
  font-family: var(--font-titre);
  font-size: 14px;
  color: #B4553F;
  text-decoration: underline;
  cursor: pointer;
}

#apercu-image {
  margin-bottom: 16px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
}
#apercu-image img {
  width: 100%;
  max-width: 340px;
  height: auto;
  border-radius: 10px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 12.9%) 87.8%);
}

/* ========================================================================
   Les membres : une liste pour trouver, une fiche pour agir
   ------------------------------------------------------------------------
   Une fiche par membre occupait 230 px et n'en montrait qu'un seul. Une
   ligne en occupe 56, et huit tiennent à l'écran : on balaye au lieu de lire.
   ====================================================================== */

.barre-recherche {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 18px 0 14px;
}
.barre-recherche input {
  color: hsl(var(--teinte) calc(var(--force) * 7%) 27.1%);
  flex: 1 1 auto;
  min-width: 0;
  padding: 11px 16px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 12.9%) 87.8%);
  border-radius: 30px;
  background: #fff;
  font-family: inherit;
  font-size: 17px;
}
.barre-recherche input:focus { outline: 2px solid var(--jaune); outline-offset: 1px; }

.bouton-plus {
  flex: 0 0 auto;
  width: 44px; height: 44px;
  border: 0; border-radius: 50%;
  background: var(--jaune);
  color: #3A2708;
  font-family: var(--font-titre);
  font-size: 26px; font-weight: 600; line-height: 1;
  cursor: pointer;
}
.bouton-plus:hover { background: var(--orange); }

/* Les filtres tiennent en une ligne : ce qu'on regarde à gauche, de quoi en
   changer à droite. Le choix s'ouvre dessous, en grand, et se referme dès
   qu'on a choisi. */
.filtres { margin-bottom: 14px; }
.filtres__rang { display: flex; align-items: center; gap: 10px; }
.filtres__dit {
  flex: 1;
  min-width: 0;
  font-family: var(--font-titre);
  font-size: 14.5px;
  line-height: 1.3;
  color: var(--prune);
}
.filtres__dit b { font-weight: 600; }
.filtres__appoint { color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%); }

.filtres__bouton {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  max-width: 62%;
  padding: 9px 15px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 15%) 88%);
  border-radius: 99px;
  background: #fff;
  font-family: var(--font-titre);
  font-size: 14.5px;
  font-weight: 600;
  color: var(--prune);
  cursor: pointer;
}
.filtres__bouton > span:first-child {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Un filtre posé se voit sans qu'on ouvre : le bouton porte alors la couleur
   pleine, comme la pastille active qu'il remplace. */
.filtres__bouton--pose { background: var(--prune); border-color: var(--prune); color: #fff; }
.filtres__chevron { flex: none; font-size: 11px; opacity: .7; }

/* Défaire les filtres, à côté du bouton. « Tout enlever » prenait une ligne
   entière au pied du panneau — dans un panneau qu'on venait de ramener de
   338 px à 175. Ici il ne coûte aucune hauteur : la ligne existe déjà. */
.filtres__remise {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  padding: 0;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 15%) 88%);
  border-radius: 50%;
  background: #fff;
  color: hsl(var(--teinte) calc(var(--force) * 6.3%) 40.6%);
  cursor: pointer;
}
.filtres__remise svg {
  width: 15px; height: 15px;
  fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round;
}
.filtres__remise:focus-visible { outline: 2px solid var(--prune); outline-offset: 2px; }

.filtres__panneau {
  margin-top: 10px;
  padding: 11px 12px 12px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 15%) 88%);
  border-radius: 16px;
  background: #fff;
}
/* L'intertitre se tient à gauche de sa rangée. Posé dessus, il coûtait une
   ligne entière par groupe pour un mot de cinq lettres. */
.filtres__groupe {
  display: flex;
  align-items: center;
  gap: 9px;
  min-width: 0;
}
.filtres__groupe + .filtres__groupe { margin-top: 8px; }
.filtres__titre {
  flex: 0 0 auto;
  width: 48px;
  font-family: var(--font-titre);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  line-height: 1.15;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
/* Une ligne qui défile, et non des rangées qui s'empilent.
   ----------------------------------------------------------------------------
   Le panneau prenait 338 px sur un écran de 664 — la moitié — et poussait le
   premier adhérent dehors : on filtrait à l'aveugle, puis on refermait pour
   voir. La cause n'était pas le nombre de filtres mais la longueur des noms :
   « Formule spéciale cours privés · 2 » fait 265 px, occupe une rangée entière
   et en laisse 25 vides.

   Sur une ligne, la hauteur ne dépend plus du nombre de formules. Et les noms
   restent ENTIERS : c'est la place horizontale qui manquait, et elle ne manque
   plus. Abréger « Carte de 10 séances » en « Carte 10 » aurait coûté la
   justesse pour un problème qui n'est plus le nôtre.

   Le dégradé du bord dit qu'il y a une suite — et disparaît quand il n'y en a
   plus, faute de quoi il mentirait et rognerait le dernier jeton pour rien. */
.filtres__jetons {
  display: flex;
  gap: 7px;
  flex: 1 1 auto;
  min-width: 0;
  flex-wrap: nowrap;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  /* La barre est masquée mais le défilement reste : au doigt c'est naturel, et
     à la souris la molette horizontale et le clavier fonctionnent. */
  scrollbar-width: none;
  /* Le jeton ne doit pas coller au bord quand on arrive au bout. */
  padding-right: 2px;
}
.filtres__jetons::-webkit-scrollbar { display: none; }
.filtres__jetons--suite {
  -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 34px), transparent);
          mask-image: linear-gradient(90deg, #000 calc(100% - 34px), transparent);
}
.filtres__jetons--avant.filtres__jetons--suite {
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 20px,
                                      #000 calc(100% - 34px), transparent);
          mask-image: linear-gradient(90deg, transparent, #000 20px,
                                      #000 calc(100% - 34px), transparent);
}
.filtres__jetons--avant:not(.filtres__jetons--suite) {
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 20px);
          mask-image: linear-gradient(90deg, transparent, #000 20px);
}
/* Le contour de focus d'un jeton se ferait rogner par le dépassement caché :
   on lui laisse de quoi se dessiner. */
.filtres__jetons .filtre { flex: 0 0 auto; scroll-margin: 0 16px; }



.filtre {
  padding: 6px 13px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 12.9%) 87.8%);
  border-radius: 20px;
  background: #fff;
  font-family: var(--font-titre);
  font-size: 12px; font-weight: 600;
  color: hsl(var(--teinte) calc(var(--force) * 6.3%) 40.6%);
  cursor: pointer;
}
.filtre--actif { background: var(--prune); border-color: var(--prune); color: #fff; }

/* ------------------------------------------------------------- la liste -- */

/* « overflow: hidden » servait à couper les coins des première et dernière
   rangées. Mais il fait de la liste le conteneur de référence du
   positionnement collant : les bandeaux d'initiale s'y calaient à soixante-cinq
   pixels du haut de la liste au lieu du haut de la fenêtre, et se posaient donc
   par-dessus la deuxième rangée. Les coins se coupent maintenant sur les
   rangées elles-mêmes. */
.liste-membres {
  background: #fff;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 18.9%) 92.7%);
  border-radius: 14px;
}
/* Les coins se coupent sur ce qui se trouve aux extrémités — une rangée quand
   la liste est à la file, un bandeau ou la dernière rangée d'un paquet quand
   elle est rangée par initiale. */
.liste-membres > .ligne-membre:first-child,
.liste-membres__paquet:first-child > .liste-membres__lettre {
  border-top-left-radius: 13px;
  border-top-right-radius: 13px;
}
.liste-membres > .ligne-membre:last-child,
.liste-membres__paquet:last-child > .ligne-membre:last-child {
  border-bottom-left-radius: 13px;
  border-bottom-right-radius: 13px;
  border-bottom: 0;
}

/* La rangée est une boîte : elle porte le bouton qui ouvre la fiche et, pour
   une demande, celui qui valide. Un bouton ne peut pas en contenir un autre. */
.ligne-membre {
  display: flex;
  align-items: stretch;
  gap: 8px;
  width: 100%;
  padding: 0 14px 0 0;
  border-bottom: 1px solid hsl(var(--teinte) calc(var(--force) * 23.8%) 95.9%);
}
.ligne-membre__ouvrir {
  flex: 1 1 auto;
  min-width: 0;
  display: grid;
  grid-template-columns: 38px 1fr auto;
  align-items: center;
  gap: 2px 12px;
  padding: 11px 0 11px 14px;
  border: 0;
  background: none;
  text-align: left;
  cursor: pointer;
  font-family: inherit;
  color: inherit;
  /* 60 px de haut : une cible tactile confortable, sans effort de visée. */
  min-height: 60px;
}
.ligne-membre:last-child { border-bottom: 0; }
.ligne-membre--ouvert { background: hsl(var(--teinte) calc(var(--force) * 27.3%) 97.8%); }
.ligne-membre__ouvrir:focus-visible { outline: 2px solid var(--prune); outline-offset: -2px; }

/* Valider est le geste de la rentrée : vingt fois de suite, il doit tomber
   sous le pouce sans ouvrir quoi que ce soit. */
/* Deux formes de petit bouton, une seule hauteur
   ---------------------------------------------------------------------------
   « Valider » était une pastille de 34 px, « Nouveau lieu » un rectangle en
   pointillés de 44, « + Ajouter un versement » le même en 38, « Réglé » une
   pastille de 34 : cinq hauteurs et quatre formes pour des gestes de même
   importance.

   La pastille agit sur la rangée où elle se trouve ; le rectangle en
   pointillés ajoute un élément au bas d'une liste. */
.ligne-membre__valider, .impaye__regle {
  flex: 0 0 auto;
  align-self: center;
  padding: 6px 14px;
  min-height: 44px;
  border: 1px solid #EFDCB6;
  border-radius: 999px;
  background: #FDF1DC;
  font-family: var(--font-titre);
  font-size: 13px; font-weight: 600;
  color: #7A5410;
  cursor: pointer;
}
.ligne-membre__valider:hover:not(:disabled),
.impaye__regle:hover:not(:disabled) {
  background: var(--jaune); border-color: var(--jaune); color: #4A3208;
}
.ligne-membre__valider:disabled, .impaye__regle:disabled { opacity: .6; }
.ligne-membre__valider:focus-visible { outline: 2px solid var(--prune); outline-offset: 2px; }

.ligne-membre__initiales {
  grid-column: 1;
  grid-row: 1 / 3;
  width: 38px; height: 38px;
  border-radius: 50%;
  display: grid; place-items: center;
  background: hsl(var(--teinte) calc(var(--force) * 21.1%) 92.5%);
  color: var(--prune);
  font-family: var(--font-titre);
  font-size: 14px; font-weight: 600;
}
.ligne-membre__nom {
  grid-column: 2;
  grid-row: 1;
  font-family: var(--font-titre);
  font-size: 16px; font-weight: 600;
  line-height: 1.2;
}
/* La ligne de détail tenait sur deux lignes dès que la phrase dépassait la
   largeur : les vingt-quatre rangées mesurées le faisaient, ce qui portait
   chacune à soixante-douze pixels au lieu de cinquante-six. Sur trois cents
   adhérents, cela fait sept écrans de défilement pour une information
   secondaire — la fiche la porte en entier. Elle se coupe donc plutôt que de
   déborder. */
.ligne-membre__detail {
  grid-column: 2;
  grid-row: 2;
  min-width: 0;
  font-size: 14px;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
  line-height: 1.25;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ligne-membre__etat { grid-column: 3; grid-row: 1 / 3; text-align: right; }

/* Une seule pastille, trois tons
   ---------------------------------------------------------------------------
   « Association », « À VENIR », « 27 / 30 places », « atelier », « +2 » :
   cinq pastilles pour le même métier — dire un état en un mot — avec quatre
   tailles de texte et deux arrondis. L'œil apprenait une règle puis en
   rencontrait une autre.

   Vert : c'est réglé. Ambre : il reste à faire. Gris : c'est passé, ou neutre.
   Une taille, un arrondi, une hauteur. */
/* « inline-flex » et non « inline-block » : le texte se centre alors dans la
   pastille quelle que soit sa casse. En capitales, les lettres remplissent la
   hauteur ; en bas de casse, elles s'appuient sur la ligne de base — deux
   pastilles côte à côte n'avaient donc pas leur texte à la même hauteur. */
.puce, .etat-abo, .places, .etiquette, .paiements__solde {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  line-height: 1.35;
  padding: 3px 9px;
  border-radius: 999px;
  background: hsl(var(--teinte) calc(var(--force) * 15.2%) 93.5%);
  color: hsl(var(--teinte) calc(var(--force) * 5.9%) 39.6%);
  font-family: var(--font-titre);
  font-size: 12px; font-weight: 600;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  vertical-align: middle;
}
.puce {
  background: #E8F0EA;
  color: #2C5C3C;
}
.puce--ambre { background: #FDF1DC; color: #7A5410; }
.puce--gris  { background: hsl(var(--teinte) calc(var(--force) * 20%) 94.1%); color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%); }

/* -------------------------------------------------------------- la fiche -- */

.fiche-membre {
  margin-top: 16px;
  background: #fff;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 18.9%) 92.7%);
  border-top: 3px solid var(--prune);
  border-radius: 14px;
  padding: 18px;
}
/* La formule tient la première ligne : c'est ce qu'on vient lire, et le nom
   est déjà au bandeau de la feuille. */
.fiche-membre__formule {
  margin: 0 0 3px;
  font-family: var(--font-titre);
  font-size: 19px; font-weight: 600;
  color: var(--prune);
  line-height: 1.25;
}
.fiche-membre__formule--sans { color: #8F5321; }
.fiche-membre__contact { margin: 0; font-size: 15px; color: hsl(var(--teinte) calc(var(--force) * 6.3%) 40.6%); line-height: 1.4; }

/* La fiche d'un groupe, elle, porte bien un nom : le sien. */
.fiche-membre__nom {
  margin: 0 0 3px;
  font-family: var(--font-titre);
  font-size: 21px; font-weight: 600;
  color: var(--prune);
}
.fiche-membre__resume { margin: 0; font-size: 16px; color: hsl(var(--teinte) calc(var(--force) * 6.3%) 40.6%); line-height: 1.4; }

/* Le nom prend la place, les deux façons de joindre tiennent en deux
   pastilles. « Appeler » et « Écrire » en pavés pleine largeur occupaient le
   haut de la carte pour deux gestes qu'on fait rarement. */
.fiche-membre__haut { display: flex; align-items: flex-start; gap: 10px; }
.fiche-membre__identite { flex: 1 1 auto; min-width: 0; }
.fiche-membre__joindre { display: flex; flex: 0 0 auto; gap: 6px; }

/* Une adhésion en attente passe avant l'argent : tant qu'elle n'est pas
   validée, la personne ne peut pas réserver. */
.fiche-membre__appel {
  margin-top: 14px;
  padding: 13px 14px;
  border-radius: 12px;
  background: #FDF6E9;
  border: 1px solid #F3E2C4;
}
.fiche-membre__appel-mot {
  margin: 0 0 10px;
  font-family: var(--font-titre);
  font-size: 15px;
  font-weight: 600;
  color: #7A5410;
}
.fiche-membre__appel .bouton-reserver { width: 100%; }

/* ------------------------------------------------------ le solde et la caisse */

/* La fiche s'ouvre sur l'argent : c'est pour lui qu'on l'ouvre neuf fois sur
   dix, et la plupart des gens règlent en plusieurs fois. */
.solde-membre { margin-top: 14px; }
.solde-membre__corps {
  padding: 13px 14px 14px;
  border-radius: 12px;
  background: hsl(var(--teinte) calc(var(--force) * 33.3%) 97.6%);
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 28.6%) 91.8%);
}
.solde-membre__rang { display: flex; align-items: baseline; gap: 10px; }
.solde-membre__rang > * { min-width: 0; }
.solde-membre__chiffre {
  font-family: var(--font-titre);
  font-size: 27px;
  font-weight: 600;
  line-height: 1.1;
  color: var(--prune);
}
.solde-membre__chiffre small {
  display: block;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
.solde-membre__chiffre--ok { color: #2C5C3C; }
.solde-membre__quoi { margin: 6px 0 0; font-size: 15px; color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%); }
.solde-membre__corps .jauge { margin-top: 11px; }

.solde-membre--vide .solde-membre__rien {
  margin: 0;
  padding: 12px 14px;
  border-radius: 12px;
  background: hsl(var(--teinte) calc(var(--force) * 23.1%) 97.5%);
  border: 1px dashed hsl(var(--teinte) calc(var(--force) * 22.6%) 87.8%);
  font-size: 15px;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
.solde-membre__cta { width: 100%; margin-top: 12px; }

.caisse[hidden] { display: none; }
.caisse__corps { margin-top: 12px; display: flex; flex-direction: column; gap: 9px; }
.caisse__duo { display: flex; gap: 8px; }
.caisse__duo > * { flex: 1 1 0; min-width: 0; }
.caisse__champ { display: block; }
.caisse__champ > span {
  display: block;
  font-family: var(--font-titre);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
.caisse__champ input,
.caisse__note {
  display: block;
  width: 100%;
  min-width: 0;
  margin-top: 3px;
  padding: 10px 11px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 12.9%) 87.8%);
  border-radius: 9px;
  background: #fff;
  font-family: var(--font-titre);
  font-size: 16px;
  color: hsl(var(--teinte) calc(var(--force) * 7.2%) 27.1%);
  appearance: none;
  -webkit-appearance: none;
}

/* Le moyen de paiement se choisit dans une liste : cinq pastilles se
   repliaient sur deux lignes, et l'on croyait la liste incomplète. */
.caisse__champ select {
  display: block;
  width: 100%;
  min-width: 0;
  margin-top: 3px;
  padding: 10px 11px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 12.9%) 87.8%);
  border-radius: 9px;
  background-color: #fff;
  font-family: var(--font-titre);
  font-size: 16px;
  color: hsl(var(--teinte) calc(var(--force) * 7.2%) 27.1%);
}

/* ------------------------------------------------------------- les volets */

.volets {
  display: flex;
  gap: 3px;
  margin: 16px 0 2px;
  padding: 3px;
  border-radius: 22px;
  background: hsl(var(--teinte) calc(var(--force) * 26.7%) 94.1%);
}
.volet {
  flex: 1 1 0;
  min-width: 0;
  padding: 9px 6px;
  border: 0;
  border-radius: 20px;
  background: none;
  font-family: var(--font-titre);
  font-size: 15px;
  font-weight: 600;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
  cursor: pointer;
}
.volet[aria-selected="true"] {
  background: #fff;
  color: var(--prune);
  box-shadow: 0 1px 3px rgba(130, 85, 116, .16);
}
.volet:focus-visible { outline: 2px solid var(--prune); outline-offset: 2px; }

.action-ligne--rouge { color: #A8535E; }
.action-ligne--du .action-ligne__appoint { color: #7A5410; font-weight: 600; }

/* Une respiration au-dessus des actions.
   ----------------------------------------------------------------------------
   Le bouton « Encaisser un versement » les touchait : son bord venait se poser
   exactement sur le filet de « Ses séances », et les deux se lisaient comme un
   seul bloc. La marge se pose ICI plutôt que sous le bouton — ainsi elle vaut
   quel que soit ce qui précède, et ne s'ajoute pas au formulaire d'encaissement
   quand il se déplie. */
.fiche-membre__actions { display: flex; flex-direction: column; margin-top: 18px; }

/* Une action par ligne, pleine largeur : on vise sans effort, et on lit ce
   que chacune contient avant de l'ouvrir. */
.action-ligne {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  min-height: 48px;
  padding: 12px 2px;
  border: 0;
  border-top: 1px solid hsl(var(--teinte) calc(var(--force) * 18.9%) 92.7%);
  background: none;
  text-align: left;
  cursor: pointer;
  font-family: var(--font-titre);
  font-size: 15px; font-weight: 500;
  color: hsl(var(--teinte) calc(var(--force) * 10%) 15.7%);
}
.action-ligne:hover { color: var(--prune); }
.action-ligne:focus-visible { outline: 2px solid var(--prune); outline-offset: -2px; }
.action-ligne__appoint {
  font-size: 13px;
  font-weight: 600;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
  text-align: right;
}

/* ------------------------------------------------------------ inscription */

/* Champ piège : invisible pour une personne, rempli par les robots. Ni
   « display:none » ni « hidden », que certains robots savent repérer. */
.piege {
  position: absolute;
  left: -9999px;
  width: 1px; height: 1px;
  overflow: hidden;
}

#ecran-inscription .champs { margin-top: 20px; }
#ecran-inscription h1 { margin-bottom: 6px; }
#ecran-inscription select,
#ecran-inscription input {
  font-weight: 400;
}

/* ========================================================================
   Mon compte : la réponse d'abord
   ------------------------------------------------------------------------
   Quinze blocs empilés où l'essentiel arrivait en cinquième position. Le
   solde et le prochain cours passent en tête ; le reste se replie.
   ====================================================================== */

.compte { gap: 12px; }

.resume {
  background: #fff;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 18.9%) 92.7%);
  border-left: 4px solid var(--prune);
  border-radius: 14px;
  padding: 18px 20px;
  display: flex;
  flex-direction: column;
  gap: 5px;
}
.resume--carte  { border-left-color: var(--jaune); }
.resume--seance { border-left-color: #09354E; }
.resume--sans   { border-left-color: var(--corail); font-size: 18px; }

.resume__offre {
  font-family: var(--font-titre);
  font-size: 12px; font-weight: 600;
  letter-spacing: .12em; text-transform: uppercase;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
.resume__chiffre { margin: 2px 0 4px; font-size: 19px; line-height: 1.2; }
.resume__chiffre b {
  font-family: var(--font-titre);
  font-size: 40px; font-weight: 600; line-height: 1;
  color: var(--prune);
  font-variant-numeric: tabular-nums;
  margin-right: 6px;
}
.resume__chiffre--texte { font-size: 18px; color: hsl(var(--teinte) calc(var(--force) * 7.6%) 28.4%); }
.resume__note { font-size: 15px; color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%); }
.resume__argent {
  font-family: var(--font-titre);
  font-size: 14px; font-weight: 600;
  color: #2C5C3C;
}
.resume__argent--du { color: #7A5410; }

/* La jauge donne l'état d'un solde sans qu'on lise un chiffre. */
.jauge {
  height: 8px;
  border-radius: 6px;
  background: hsl(var(--teinte) calc(var(--force) * 22%) 92%);
  overflow: hidden;
  margin: 2px 0 6px;
}
.jauge i { display: block; height: 100%; background: var(--prune); border-radius: 6px; }
.jauge--basse i { background: var(--jaune); }

.prochain {
  background: #fff;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 18.9%) 92.7%);
  /* Prune et non corail : la carte du dessus porte un liseré prune, et deux
     accents empilés faisaient de celle-ci une pièce rapportée. */
  border-left: 4px solid var(--prune);
  border-radius: 14px;
  padding: 14px 16px;
  display: block;
}
/* L'heure en colonne, le reste à droite — la forme de la fiche d'une séance. */
.prochain__tete { display: flex; align-items: flex-start; gap: 14px; }
.prochain__heure {
  flex: 0 0 auto;
  padding-right: 14px;
  text-align: center;
  border-right: 1px solid hsl(var(--teinte) calc(var(--force) * 19%) 93%);
}
.prochain__hh {
  display: block;
  font-family: var(--font-titre);
  font-size: 24px;
  font-weight: 700;
  line-height: 1;
  color: var(--prune);
  font-variant-numeric: tabular-nums;
}
.prochain__jj {
  display: block;
  margin-top: 4px;
  font-family: var(--font-titre);
  font-size: 13px;
  white-space: nowrap;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
.prochain__droite { flex: 1 1 auto; min-width: 0; }

/* L'étiquette murmure, comme toutes les autres de l'espace. */
.prochain__quand {
  display: block;
  font-family: var(--font-titre);
  font-size: 11px; font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
.prochain__nom {
  margin: 3px 0 0;
  font-family: var(--font-titre);
  font-size: 18px;
  font-weight: 600;
  line-height: 1.2;
  color: hsl(var(--teinte) calc(var(--force) * 7%) 27.1%);
}
/* Le nom du cours prend la police d'interface, comme tous les intitulés de
   l'espace. Il héritait du serif du corps de texte : dans une carte dont la
   date, les replis et la barre du bas sont en Jost, c'était la seule ligne
   d'une autre famille — et c'était justement la plus regardée. */
.prochain__quoi {
  margin: 2px 0 0;
  font-family: var(--font-titre);
  font-size: 15px;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}

/* La salle du prochain cours mène à la carte. Souligné et non encadré : la
   phrase reste une phrase — « Full body — Salle des fêtes de Bolquère » — et
   c'est le nom du lieu qui se donne à toucher, pas un bouton posé à côté. */
.prochain__lieu {
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  text-decoration: underline;
  text-decoration-color: rgba(130, 85, 116, .45);
  text-underline-offset: 3px;
  cursor: pointer;
}
.prochain__lieu:hover { text-decoration-color: var(--prune); }
.prochain__lieu:focus-visible { outline: 2px solid var(--prune); outline-offset: 2px; }

/* -------------------------------------------------------------- les replis */

.replis,
/* La liste des réglages emprunte l'habit des replis de « Mon compte » : c'est
   le même geste — une liste de sections, on en ouvre une — et deux dessins
   pour un même geste s'apprennent deux fois. */
.reglages-menu {
  background: #fff;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 18.9%) 92.7%);
  border-radius: 14px;
  overflow: hidden;
}
.reglages-retour { margin-bottom: 10px; }

.repli {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  min-height: 50px;
  padding: 13px 18px;
  border: 0;
  border-bottom: 1px solid hsl(var(--teinte) calc(var(--force) * 18.9%) 92.7%);
  background: none;
  text-align: left;
  cursor: pointer;
  font-family: var(--font-titre);
  font-size: 15px; font-weight: 500;
  color: hsl(var(--teinte) calc(var(--force) * 10%) 15.7%);
}
.repli:last-child { border-bottom: 0; }
.repli--ouvert { background: hsl(var(--teinte) calc(var(--force) * 27.3%) 97.8%); color: var(--prune); }
.repli:focus-visible { outline: 2px solid var(--prune); outline-offset: -2px; }
.repli__appoint {
  font-size: 13px; font-weight: 600;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
  white-space: nowrap;
}

#compte-panneau:not(:empty) {
  background: #fff;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 18.9%) 92.7%);
  border-radius: 14px;
  padding: 18px;
}

.donnees-texte h4 {
  margin: 16px 0 5px;
  font-family: var(--font-titre);
  font-size: 13px; font-weight: 600;
  letter-spacing: .06em; text-transform: uppercase;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
.donnees-texte h4:first-child { margin-top: 0; }
.donnees-texte p { margin: 0; font-size: 17px; color: hsl(var(--teinte) calc(var(--force) * 7.6%) 28.4%); }
.donnees-texte a { display: inline-block; margin-top: 16px; }

/* --------------------------------------------------- groupes d'un formulaire */

/* Onze champs d'affilée se lisent comme une corvée. Trois groupes nommés
   donnent une progression : qui, où, quoi. */
.groupe {
  margin: 22px 0 10px;
  padding-bottom: 7px;
  border-bottom: 1px solid hsl(var(--teinte) calc(var(--force) * 18.9%) 92.7%);
  font-family: var(--font-titre);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
.groupe:first-of-type { margin-top: 24px; }

/* ---------------------------------------------------------- filet de sécurité */

/* Un champ de saisie a une largeur propre — vingt caractères par défaut, plus
   pour un sélecteur de date ou de fichier. Placé dans une grille ou un bloc
   étroit, il élargit son conteneur au lieu de se contraindre, et déborde de
   l'écran. Cette règle vaut pour tous les champs de l'espace, y compris ceux
   qui seront ajoutés plus tard. */
.espace input,
.espace select,
.espace textarea {
  max-width: 100%;
  min-width: 0;
}

/* ========================================================================
   Rien ne dépasse
   ------------------------------------------------------------------------
   Dans une grille ou une boîte flexible, un enfant a pour largeur minimale
   celle de son contenu : il élargit sa colonne plutôt que de se contraindre,
   et pousse la page hors de l'écran. C'est la cause unique de tous les
   débordements constatés — champs de saisie, libellés d'action, noms de
   formules. On la traite une fois, pour toutes les lignes de l'espace.
   ====================================================================== */

.ligne-membre__ouvrir > *,
.action-ligne > *,
.historique__ligne > *,
.versement > *,
.impaye > *,
.repli > *,
.cours-fiche__haut > *,
.fiche-seance__haut > *,
.paiements__entete > *,
.compte__coordonnees > *,
.membre__coordonnees > *,
.barre-recherche > *,
.inscrit > * {
  min-width: 0;
}

/* Ce qui n'a pas d'espace où se couper — une adresse, un nom de formule —
   se coupe quand même plutôt que de déborder. */
.ligne-membre__nom,
.action-ligne > span,
.historique__cours,
.versement__moyen,
.impaye__quoi,
.fiche-membre__contact,
.fiche-membre__resume,
.compte__coordonnees dd,
.membre__coordonnees span,
.inscrit__nom {
  overflow-wrap: anywhere;
}

/* Le complément d'une ligne d'action se réduit avant le libellé : c'est le
   libellé qui dit ce que fait le bouton. */
.action-ligne__appoint,
.repli__appoint {
  flex: 0 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.action-ligne > span:first-child,
.repli > span:first-child { flex: 1 1 auto; }

/* Dernier rempart : si un élément échappait encore, il ne fera pas défiler la
   page entière de côté. Le corps de l'espace ne déborde jamais. */
.espace__corps { overflow-x: clip; }

/* ------------------------------------------------------------ sous-onglets */

/* Membres et formules sont deux faces de l'administration : un lien donnait
   l'impression de quitter l'écran, deux onglets disent qu'on y reste. */
/* L'engrenage rejoint la barre des sous-onglets. Le titre « Administration »
   qu'il accompagnait était écrit cinq fois, au-dessus d'onglets qui disent
   déjà où l'on est et sous une barre du bas où « Gestion » est allumé : il ne
   renseignait personne et prenait quarante pixels par écran. */
/* La pilule des onglets et l'engrenage sur une même ligne. */
.barre-gestion {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 18px;
}
.barre-gestion .sous-onglets { flex: 1 1 auto; min-width: 0; margin: 0; }
.sous-onglets__reglages {
  flex: 0 0 auto;
  width: 40px; height: 40px;
}
.sous-onglets__reglages svg { width: 18px; height: 18px; }

.sous-onglets {
  display: flex;
  gap: 6px;
  margin: 4px 0 20px;
  padding: 4px;
  background: hsl(var(--teinte) calc(var(--force) * 18.5%) 94.7%);
  border-radius: 30px;
}
.sous-onglet {
  flex: 1 1 0;
  min-width: 0;
  padding: 9px 10px;
  border: 0;
  border-radius: 24px;
  background: none;
  cursor: pointer;
  font-family: var(--font-titre);
  font-weight: 600;
  color: hsl(var(--teinte) calc(var(--force) * 6.3%) 40.6%);

  /* Une icône au-dessus du mot, comme la barre du bas : quatre mots seuls se
     coupaient en « Memb… » et « Formu… ». */
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  padding: 7px 3px 6px;
}
.sous-onglet svg {
  width: 20px;
  height: 20px;
  flex: 0 0 auto;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.sous-onglet__mot {
  max-width: 100%;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .01em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* À cinq sous-onglets — c'est-à-dire quand les groupes sont allumés — chacun
   tombe à cinquante-six pixels et « Adhérents » se coupait en « Adhéren… ». Le
   mot perd un point et son rembourrage latéral : il tient alors entier, et les
   quatre autres n'y perdent rien de lisible. On se règle sur la classe que
   porte déjà la racine, et non sur le rang du bouton : l'onglet des groupes
   reste dans la page quand il est éteint, et le compter le ferait rétrécir
   les quatre autres pour rien. */
html:not(.sans-groupes) .sous-onglet {
  padding-left: 1px;
  padding-right: 1px;
}
html:not(.sans-groupes) .sous-onglet__mot {
  font-size: 10px;
  letter-spacing: 0;
}
.sous-onglet--actif { background: #fff; color: var(--prune); box-shadow: 0 1px 3px rgba(42,34,40,.08); }
.sous-onglet:focus-visible { outline: 2px solid var(--prune); outline-offset: -2px; }

/* ------------------------------------------------- basculer d'affichage */

/* Les deux gestes rares du bandeau : ils descendent en menu plutôt que
   d'occuper une ligne entière sur tous les écrans. */
.espace__liens {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 40;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 2px;
  min-width: 210px;
  padding: 6px;
  background: #fff;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 20%) 90.2%);
  border-radius: 12px;
  box-shadow: 0 12px 30px -12px rgba(46, 37, 48, .38);
}
/* Les entrées du menu : de l'encre, pas du corail.
   ----------------------------------------------------------------------------
   Elles étaient toutes corail et soulignées — six liens de la même couleur vive,
   sans hiérarchie, dans un menu où l'on cherche une chose précise. Le corail est
   la couleur des titres de section, pas celle d'une liste de commandes.

   Les entrées passent en encre, comme dans toute liste de l'espace. Seul
   « Se déconnecter » garde une couleur, parce que c'est le seul geste qu'on ne
   veut pas faire par erreur. */
.espace__liens .lien-bouton {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  text-align: left;
  min-height: 44px;
  padding: 0 12px;
  border-radius: 8px;
  font-size: 15px;
  font-weight: 500;
  color: hsl(var(--teinte) calc(var(--force) * 7%) 27.1%);
  text-decoration: none;
}
.espace__liens .lien-bouton:hover { background: hsl(var(--teinte) calc(var(--force) * 33.3%) 97.6%); }
.espace__liens .lien-bouton--partir { color: #A8535E; }
/* « Revenir à mon profil » est une entrée de menu, pas une pastille.
   ----------------------------------------------------------------------------
   La classe « --actif » sert ailleurs à marquer une pastille pleine, prune sur
   blanc. Reprise ici, elle posait un fond prune ET ma couleur de texte prune
   par-dessus : un bloc plein dont on ne lisait rien.

   Dans le menu, elle ne garde que ce qui la distingue — la couleur d'accent et
   la graisse — et rend le fond. */
.espace__liens .lien-bouton--actif {
  padding: 0 12px;
  border-radius: 8px;
  background: none;
  color: var(--prune);
  font-weight: 600;
}

/* Un titre par groupe : « Regarder comme », « Aide ». Sans eux, six entrées se
   suivaient sans qu'on sache laquelle appartenait à quoi. */
.menu__titre {
  display: block;
  padding: 12px 12px 4px;
  font-family: var(--font-titre);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: hsl(var(--teinte) calc(var(--force) * 6%) 55%);
}
.menu__titre:first-child { padding-top: 4px; }
/* Un filet entre les groupes, plutôt qu'un simple écart : il dit que la liste
   change de sujet. */
.espace__liens .vues + .menu__titre {
  margin-top: 4px;
  border-top: 1px solid hsl(var(--teinte) calc(var(--force) * 19%) 93%);
  padding-top: 10px;
}

/* Le bouton qui les ouvre : trois points, à la taille d'un pouce. */
.espace__menu {
  flex: 0 0 auto;
  width: 44px; height: 44px;
  padding: 0;
  display: grid; place-items: center;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 20%) 90.2%);
  border-radius: 50%;
  background: #fff;
  color: hsl(var(--teinte) calc(var(--force) * 6.3%) 40.6%);
  cursor: pointer;
}
.espace__menu svg { width: 20px; height: 20px; fill: currentColor; }
.espace__menu:hover { color: var(--prune); border-color: var(--prune); }
.espace__menu:focus-visible { outline: 2px solid var(--prune); outline-offset: 2px; }

/* Quand l'affichage est en retrait, le bouton du retour se voit : on ne doit
   pas se demander pourquoi les écrans d'administration ont disparu. */
.lien-bouton--actif {
  padding: 3px 11px;
  border-radius: 20px;
  background: var(--prune);
  color: #fff;
  text-decoration: none;
}

/* ---------------------------------------------------------- champ figé */

/* Une information qu'on doit voir sans pouvoir la modifier soi-même. */
.champ-fige {
  display: grid;
  gap: 2px;
  margin: 0 0 18px;
  padding: 12px 14px;
  border-radius: 10px;
  background: hsl(var(--teinte) calc(var(--force) * 27.3%) 97.8%);
}
.champ-fige__nom {
  font-family: var(--font-titre);
  font-size: 13px;
  font-weight: 600;
  color: var(--prune);
}
.champ-fige__valeur { font-size: 17px; overflow-wrap: anywhere; }
.champ-fige__note { font-size: 14px; color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%); }

/* ------------------------------------------------- en-tête d'écran + action */

.entete-ecran {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  margin-bottom: 18px;
}
.entete-ecran h2 { margin: 0; }

/* Chaque information devient une fiche : un simple filet ne la distinguait
   pas du texte d'aide qui la précédait. */
.info {
  background: #fff;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 18.9%) 92.7%);
  border-left: 4px solid var(--corail);
  border-radius: 14px;
  padding: 18px 20px;
  margin-bottom: 12px;
}
.info--masquee { opacity: .55; border-left-color: hsl(var(--teinte) calc(var(--force) * 12.9%) 87.8%); }
.info:last-of-type { border-bottom: 1px solid hsl(var(--teinte) calc(var(--force) * 18.9%) 92.7%); }

/* ------------------------------------------------------ couleur d'un cours */

.teintes { display: block; }
.teintes__nom {
  display: block;
  font-family: var(--font-titre);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .02em;
  color: var(--prune);
}
.teintes__choix { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 8px; }

/* On choisit une couleur en la voyant, pas en lisant son nom. */
.teinte {
  width: 36px; height: 36px;
  border: 2px solid transparent;
  border-radius: 50%;
  background: var(--fam-clair);
  box-shadow: inset 0 0 0 2px var(--fam);
  cursor: pointer;
}
.teinte--choisie { border-color: var(--prune); background: var(--fam); }
.teinte:focus-visible { outline: 2px solid var(--prune); outline-offset: 2px; }

.teinte--yoga    { --fam: var(--prune); --fam-clair: hsl(var(--teinte) calc(var(--force) * 21.1%) 92.5%); }
.teinte--pilates { --fam: #EC7069; --fam-clair: #FCEAE9; }
.teinte--renfo   { --fam: #FAB926; --fam-clair: #FDF3DE; }
.teinte--kids    { --fam: #F19953; --fam-clair: #FDF0E4; }
.teinte--paddle  { --fam: #09354E; --fam-clair: #E3ECF1; }
.teinte--atelier { --fam: #7F348B; --fam-clair: #F3E8F5; }
.teinte--autre   { --fam: hsl(var(--teinte) calc(var(--force) * 6.4%) 51%); --fam-clair: hsl(var(--teinte) calc(var(--force) * 20%) 94.1%); }

/* ------------------------------------------------------- dates et heures */

/* Un champ de date ou d'heure conserve une largeur native que « width: 100% »
   ne contraint pas : il dépassait de la carte. Retirer l'apparence native la
   lui fait respecter — et aligne son contenu à gauche, comme les autres
   champs, au lieu de le centrer. */
.espace input[type="date"],
.espace input[type="time"] {
  -webkit-appearance: none;
  appearance: none;
  text-align: left;
  /* L'apparence retirée, la hauteur naturelle disparaît aussi : on la rend,
     pour garder une cible confortable au doigt. */
  min-height: 44px;
}

/* ------------------------------------------------------- un lien à copier */

/* Le site n'envoie pas d'e-mail : les liens de connexion s'affichent pour
   être transmis à la main. Ils doivent donc être lisibles et sélectionnables. */
.lien-a-copier {
  margin: 12px 0;
  padding: 12px 14px;
  border-radius: 8px;
  background: hsl(var(--teinte) calc(var(--force) * 27.3%) 97.8%);
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 12.9%) 87.8%);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 13px;
  line-height: 1.5;
  color: hsl(var(--teinte) calc(var(--force) * 7.6%) 28.4%);
  overflow-wrap: anywhere;
  user-select: all;
}

/* Prévenir ne se fait plus par e-mail : on ouvre la liste des inscrits. */
.prevenir__mot {
  margin: 0 0 12px;
  font-family: var(--font-titre);
  font-size: 15px;
  font-weight: 600;
  color: #7A5410;
}
.prevenir .bouton-reserver { padding: 9px 20px; font-size: 14px; }

/* ------------------------------------------------------ listes déroulantes */

/* Comme un champ de date, une liste déroulante garde une largeur native tirée
   de sa plus longue option : « Année 2026-2027 — 2 cours/semaine · 300 € »
   débordait de la carte. Retirer l'apparence native la contraint — on redessine
   donc le chevron, que le navigateur ne fournit plus. */
.espace select {
  color: hsl(var(--teinte) calc(var(--force) * 7%) 27.1%);
  -webkit-appearance: none;
  appearance: none;
  padding-right: 34px;
  min-height: 44px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' fill='none' stroke='%23825574' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 13px center;
  background-size: 12px 8px;
  text-overflow: ellipsis;
}

/* Les périodes terminées se rangent en historique, sous leur propre en-tête,
   plutôt que mêlées à celle qui court. */
.paiements__groupe {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  margin: 18px 0 2px;
  padding-bottom: 5px;
  border-bottom: 1px solid hsl(var(--teinte) calc(var(--force) * 18.9%) 92.7%);
  font-family: var(--font-titre);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
.paiements__groupe:first-child { margin-top: 4px; }
/* Les dates, les droits et les séances prises sur une seule ligne. */
.paiements__faits {
  margin: 4px 0 0;
  font-size: 14px;
  line-height: 1.4;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}

/* Un seul cumul, en tête, et il porte sur tout le parcours. Un total par
   groupe se posait au-dessus d'une période qui n'avait rien reçu. */
.paiements__recap {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 10px;
  padding: 12px 14px;
  border-radius: 12px;
  background: hsl(var(--teinte) calc(var(--force) * 33.3%) 97.6%);
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 28.6%) 91.8%);
}
.paiements__recap > * { min-width: 0; }
.paiements__recap-verse {
  font-family: var(--font-titre);
  font-size: 19px;
  font-weight: 600;
  color: var(--prune);
}
.paiements__recap-du { font-size: 15px; font-weight: 600; color: #7A5410; }
.paiements__recap-quoi { flex: 1 1 100%; font-size: 14px; color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%); }

/* Ce à quoi la période donne droit, et ce qu'elle a servi à prendre. */

/* Une période passée reste lisible, mais cesse de réclamer l'attention. */
.paiements__abonnement--termine { opacity: .78; }

.etat-abo { letter-spacing: .06em; text-transform: uppercase; }
.etat-abo--en-cours { background: #E8F0EA; color: #2C5C3C; }
.etat-abo--a-venir  { background: #EAEFF6; color: #33507A; }
.etat-abo--termine  { background: hsl(var(--teinte) calc(var(--force) * 15.2%) 93.5%); color: hsl(var(--teinte) calc(var(--force) * 5.9%) 39.6%); }

/* ------------------------------------------------------ le lieu d'un cours */

/* Le fond dit la discipline, le liséré du bas dit le lieu : deux canaux
   distincts, lisibles ensemble. La légende ne s'affiche que s'il y a plus
   d'un lieu dans la semaine — sinon elle n'apprend rien. */
.legende-lieux {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 16px;
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid hsl(var(--teinte) calc(var(--force) * 18.9%) 92.7%);
}
.legende-lieux__item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-titre);
  font-size: 12px;
  font-weight: 600;
  color: hsl(var(--teinte) calc(var(--force) * 6.3%) 40.6%);
}
.legende-lieux__item i {
  width: 14px;
  height: 4px;
  border-radius: 2px;
  display: inline-block;
}

/* ============================================================== la caisse == */

/* La fiche membre répond à « où en est Léa ». Cet écran répond à l'autre
   question : où en est la saison — combien est rentré, et qui n'a pas réglé. */

/* Les deux questions d'argent, côte à côte. Empilées, chacune avec son titre
   en capitales et son gros chiffre, elles poussaient le premier versement à
   quatre cent vingt pixels du haut — sur un écran qui en compte huit cents. */
.caisse-tete {
  display: flex;
  gap: 14px;
  align-items: flex-start;
  margin-top: 14px;
}
.caisse-tete__part { flex: 1 1 0; min-width: 0; }
.caisse-tete__part--saison {
  padding-left: 14px;
  border-left: 1px solid hsl(var(--teinte) calc(var(--force) * 18.9%) 92.7%);
}
.caisse-tete__mot {
  display: block;
  font-family: var(--font-titre);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
.caisse-tete__chiffre {
  display: block;
  margin-top: 1px;
  font-family: var(--font-titre);
  /* Deux colonnes sur un téléphone : le chiffre suit la largeur plutôt que
     d'être fixe, sinon « 12 345 € » se casse en deux au milieu. */
  font-size: clamp(22px, 7.2vw, 28px);
  font-weight: 600;
  line-height: 1.1;
  color: var(--prune);
}
.caisse-tete__quoi {
  display: block;
  margin-top: 4px;
  font-family: var(--font-titre);
  font-size: 13.5px;
  line-height: 1.35;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
.caisse-tete__manque { font-weight: 600; color: #7A5410; }

/* Les colonnes. Une case sans versement garde la sienne, réduite à un trait :
   on voit qu'elle a été comptée plutôt qu'oubliée. */
.caisse-colonnes {
  display: flex;
  align-items: flex-end;
  gap: 5px;
  /* Cent-trente-deux pixels de tige et trente-six de légendes, pour comparer
     deux ou trois barres : la hauteur ne servait pas la lecture, elle servait
     l'effet. Soixante-dix suffisent à voir laquelle dépasse. */
  height: 70px;
  margin: 16px 0 4px;
  padding-bottom: 32px;
}
.caisse-colonne {
  flex: 1 1 0;
  min-width: 0;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  position: relative;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
}
.caisse-colonne i {
  display: block;
  border-radius: 6px 6px 3px 3px;
  background: hsl(var(--teinte) calc(var(--force) * 23.3%) 85.7%);
}
.caisse-colonne--vive i { background: var(--prune); }
@media (hover: hover) {
  .caisse-colonne:hover i { background: var(--corail); }
}
.caisse-colonne span,
.caisse-colonne em {
  position: absolute;
  left: 0;
  right: 0;
  text-align: center;
  font-family: var(--font-titre);
  font-style: normal;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.caisse-colonne span { bottom: -19px; font-size: 12px; font-weight: 600; color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%); }
.caisse-colonne em   { bottom: -34px; font-size: 11px; font-weight: 500; color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%); }
.caisse-colonne--vive span { color: var(--prune); }
.caisse-colonne--vive em { color: var(--prune); font-weight: 600; }
.caisse-colonne:focus-visible { outline: 2px solid var(--prune); outline-offset: 3px; border-radius: 6px; }

/* La part reçue se pose sur le fond ocre du reste : deux couleurs, deux états,
   et la frontière entre elles est le seul repère qui compte. */
.caisse-bilan__barre {
  margin-top: 8px;
  height: 8px;
  border-radius: 99px;
  overflow: hidden;
  background: #E2D3B8;
}
.caisse-bilan__part { height: 100%; background: #3E7150; }

.caisse-titre {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  margin: 22px 0 2px;
  padding-bottom: 5px;
  border-bottom: 1px solid hsl(var(--teinte) calc(var(--force) * 18.9%) 92.7%);
  font-family: var(--font-titre);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
.caisse-titre > * { min-width: 0; }
.caisse-titre__appoint { letter-spacing: 0; text-transform: none; font-size: 13px; }
/* Un geste posé sur le titre : il ne prend pas de ligne à lui, et le haut de
   la caisse reste ce qu'il est. */
.caisse-titre__geste { flex: none; letter-spacing: 0; text-transform: none; font-size: 13px; }
.recette-ajout:not(:empty) { margin: 10px 0 4px; }

/* Chaque ligne mène à la fiche, où le bouton d'encaissement attend. De « qui
   n'a pas payé » à « c'est encaissé » : trois touchers. */
.ligne-du {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 10px 0;
  border: 0;
  border-bottom: 1px solid hsl(var(--teinte) calc(var(--force) * 23.8%) 95.9%);
  background: none;
  text-align: left;
  cursor: pointer;
}
.ligne-du > * { min-width: 0; }
.ligne-du:hover { background: hsl(var(--teinte) calc(var(--force) * 33.3%) 98.2%); }
.ligne-du:focus-visible { outline: 2px solid var(--prune); outline-offset: -2px; }
.ligne-du__rond {
  flex: 0 0 auto;
  width: 34px;
  height: 34px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: hsl(var(--teinte) calc(var(--force) * 28.2%) 92.4%);
  color: var(--prune);
  font-family: var(--font-titre);
  font-size: 12px;
  font-weight: 600;
}
.ligne-du__milieu { flex: 1 1 auto; display: flex; flex-direction: column; }
.ligne-du__nom {
  font-family: var(--font-titre);
  font-size: 16px;
  font-weight: 600;
  color: hsl(var(--teinte) calc(var(--force) * 7.2%) 27.1%);
  overflow-wrap: anywhere;
}
.ligne-du__sous { font-size: 14px; color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%); overflow-wrap: anywhere; }
.ligne-du__montant {
  flex: 0 0 auto;
  font-family: var(--font-titre);
  font-size: 16px;
  font-weight: 600;
  color: #7A5410;
}

/* Une recette se distingue d'une dette : le rond et le montant passent au
   vert, l'ambre reste réservé à ce qui manque. */
.ligne-du__rond--recette { background: #E8F0EA; color: #2C5C3C; }
.ligne-du__montant--recette { color: #2C5C3C; }

.caisse-quitte {
  margin: 22px 0 0;
  padding: 16px;
  border-radius: 12px;
  background: #EEF5F0;
  border: 1px solid #D9E8DE;
  text-align: center;
  font-family: var(--font-titre);
  font-size: 16px;
  font-weight: 600;
  color: #2C5C3C;
}

/* Ce qui retire quelque chose se signale, sans crier : le rouge dit la nature
   du geste, pas son urgence. */
.lien-bouton--rouge { color: #A8535E; }

/* ============================================================ les groupes == */

/* Qui voit un cours. Aucun groupe coché : il s'adresse à tout le monde, et la
   case « cacher aux autres » n'a pas lieu d'être. */
.visibilite { margin-top: 4px; }
.cases-groupes { display: flex; flex-direction: column; gap: 3px; margin-top: 6px; }
.case-groupe {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  padding: 9px 11px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 12.9%) 87.8%);
  border-radius: 9px;
  background: #fff;
  text-align: left;
  font-family: var(--font-titre);
  font-size: 15px;
  color: hsl(var(--teinte) calc(var(--force) * 6.3%) 40.6%);
  cursor: pointer;
}
.case-groupe > * { min-width: 0; }
.case-groupe[aria-checked="true"] {
  border-color: var(--prune);
  background: hsl(var(--teinte) calc(var(--force) * 42.9%) 97.3%);
  color: var(--prune);
  font-weight: 600;
}
.case-groupe i {
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  border-radius: 5px;
  border: 1.5px solid hsl(var(--teinte) calc(var(--force) * 18.3%) 81.8%);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-style: normal;
  font-size: 12px;
  color: #fff;
}
.case-groupe[aria-checked="true"] i { background: var(--prune); border-color: var(--prune); }
.case-groupe span { flex: 1 1 auto; overflow-wrap: anywhere; }
.case-groupe em {
  flex: 0 0 auto;
  font-style: normal;
  font-size: 13px;
  font-weight: 500;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
.case-groupe:focus-visible { outline: 2px solid var(--prune); outline-offset: 2px; }

/* Un cours réservé se montre quand même, fermé : le planning en ligne reste
   celui de l'affiche. Un liseré suffit à le dire dans la grille. */
.bloc-cours--reserve { box-shadow: inset 0 0 0 1.5px rgba(130, 85, 116, .35); }
.bloc-cours--ferme { opacity: .62; }

.fiche-seance__reserve {
  margin: 8px 0 0;
  padding: 10px 12px;
  border-radius: 10px;
  background: hsl(var(--teinte) calc(var(--force) * 28%) 95.1%);
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 22.6%) 87.8%);
  font-size: 15px;
  color: #6C4B7C;
}
.fiche-seance__reserve--mien { background: #EEF5F0; border-color: #D9E8DE; color: #2C5C3C; }

/* Les ronds d'un groupe prennent sa teinte, comme les cours au planning. */
.teinte-fond--yoga    { background: hsl(var(--teinte) calc(var(--force) * 21.1%) 92.5%); color: var(--prune); }
.teinte-fond--pilates { background: #FCEAE9; color: #B84B44; }
.teinte-fond--renfo   { background: #FDF3DE; color: #7A5410; }
.teinte-fond--kids    { background: #FDF0E4; color: #8A5A1A; }
.teinte-fond--paddle  { background: #E4EDF3; color: #2C5070; }
.teinte-fond--atelier { background: #F1E8F4; color: #6C3E7C; }
.teinte-fond--autre   { background: hsl(var(--teinte) calc(var(--force) * 13.5%) 92.7%); color: hsl(var(--teinte) calc(var(--force) * 6.3%) 40.6%); }

.puce--groupe { background: hsl(var(--teinte) calc(var(--force) * 28.2%) 92.4%); color: #6C4B7C; }

/* --------------------------------------------------- composer un groupe -- */

/* Soixante-dix adhérents : les prendre un par un dans un menu déroulant
   demanderait autant de touchers que de personnes. Une liste cochable, avec
   recherche et filtre, laisse composer un groupe d'une traite. */
.composer { margin-top: 14px; }
.composer__recherche {
  width: 100%;
  min-width: 0;
  padding: 11px 13px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 12.9%) 87.8%);
  border-radius: 22px;
  background: #fff;
  font-family: var(--font-titre);
  font-size: 16px;
  color: hsl(var(--teinte) calc(var(--force) * 7.2%) 27.1%);
  appearance: none;
  -webkit-appearance: none;
}
/* Une rangée qui se replie sur deux lignes double la hauteur de l'en-tête,
   juste au-dessus d'une liste qu'on vient parcourir. Elle reste sur une ligne
   et défile de côté si jamais un jour elle déborde. */
.composer__filtres {
  display: flex;
  flex-wrap: nowrap;
  gap: 6px;
  margin: 10px 0 4px;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
  padding-bottom: 2px;
}
.composer__filtres::-webkit-scrollbar { display: none; }
.composer__filtres .filtre { flex: 0 0 auto; }

/* La liste défile dans son cadre : la page, elle, ne s'allonge pas de
   soixante-dix lignes, et les filtres restent sous la main. */
.composer__liste {
  max-height: 46vh;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 18.9%) 92.7%);
  border-radius: 12px;
}
.composer__ligne {
  display: flex;
  align-items: center;
  gap: 11px;
  width: 100%;
  padding: 10px 12px;
  border: 0;
  border-bottom: 1px solid hsl(var(--teinte) calc(var(--force) * 23.8%) 95.9%);
  background: none;
  text-align: left;
  cursor: pointer;
}
.composer__ligne > * { min-width: 0; }
.composer__ligne:last-child { border-bottom: 0; }
.composer__ligne[aria-checked="true"] { background: hsl(var(--teinte) calc(var(--force) * 42.9%) 97.3%); }
.composer__ligne:focus-visible { outline: 2px solid var(--prune); outline-offset: -2px; }
.composer__ligne--attente { opacity: .5; pointer-events: none; }

.composer__case {
  flex: 0 0 auto;
  width: 22px;
  height: 22px;
  border-radius: 6px;
  border: 1.5px solid hsl(var(--teinte) calc(var(--force) * 18.3%) 81.8%);
  background: #fff;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-style: normal;
  font-size: 13px;
  font-weight: 700;
  color: #fff;
}
.composer__ligne[aria-checked="true"] .composer__case {
  background: var(--prune);
  border-color: var(--prune);
}
.composer__milieu { flex: 1 1 auto; display: flex; flex-direction: column; }
.composer__nom {
  font-family: var(--font-titre);
  font-size: 16px;
  font-weight: 600;
  color: hsl(var(--teinte) calc(var(--force) * 7.2%) 27.1%);
  overflow-wrap: anywhere;
}
.composer__ligne[aria-checked="true"] .composer__nom { color: var(--prune); }
.composer__sous { font-size: 14px; color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%); overflow-wrap: anywhere; }

/* ------------------------------------------------------------- l'aperçu -- */

/* Un aperçu qui montrerait tout ne servirait à rien : le serveur répond comme
   à une élève, et l'on choisit de quel groupe on fait partie. Le bandeau dit
   sans ambiguïté qu'on n'est plus dans sa propre vue. */
.apercu {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 12px;
  padding: 9px 20px;
  background: #FDF1DC;
  border-bottom: 1px solid #F0DFBE;
}
.apercu > * { min-width: 0; }
.apercu__mot {
  font-family: var(--font-titre);
  font-size: 14px;
  font-weight: 600;
  color: #7A5410;
  white-space: nowrap;
}
.apercu__groupe {
  flex: 1 1 160px;
  min-width: 0;
  padding: 7px 11px;
  border: 1px solid #E4CFA6;
  border-radius: 8px;
  background-color: #fff;
  font-family: var(--font-titre);
  font-size: 15px;
  color: hsl(var(--teinte) calc(var(--force) * 6.3%) 40.6%);
}

/* Deux gris de la charte tombaient à 4,04:1 et 2,83:1 sur blanc, sous le seuil
   de lisibilité. Ils passent à 4,97:1. La hiérarchie n'y perd rien : elle tient
   à la taille et à la graisse, qui ne s'effacent pas au soleil. */

/* ======================================== réglages propres au téléphone == */

/* Ce bloc rassemble ce qui ne se voit qu'au doigt, et qui se corrigeait
   jusqu'ici cas par cas. Agnès travaille au pouce : c'est la situation
   ordinaire, pas un cas limite. */

/* iOS gonfle le texte en paysage si on ne l'en empêche pas. */
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }

/* Le pavé gris-mauve qui apparaissait sous « Appeler » et « Écrire » au
   toucher, c'était la surbrillance native : elle déborde du texte et donne
   l'impression d'un bouton mal dessiné. On la remplace par une teinte de la
   charte, à peine visible. */
.espace a,
.espace button,
.espace select,
.espace label,
.espace [role="checkbox"] {
  -webkit-tap-highlight-color: rgba(130, 85, 116, .12);
}

/* Un bouton n'est pas du texte : le toucher long ne doit pas en sélectionner
   le libellé, et « manipulation » supprime l'attente du double-toucher. */
.espace button,
.espace .filtre,
.espace .volet,
.espace .sous-onglet,
.espace .barre__onglet,
.espace .pastille {
  touch-action: manipulation;
  -webkit-user-select: none;
  user-select: none;
}

/* Une liste qui défile dans son cadre ne doit pas entraîner la page derrière
   elle quand on arrive au bout. */
.composer__liste,
.grille-semaine { overscroll-behavior: contain; }

/* Deux champs côte à côte dans trois cents pixels donnent des colonnes de
   cent quarante : une date n'y tient pas. Sous cette largeur, un champ par
   ligne — c'est plus long à parcourir, mais lisible. */
@media (max-width: 430px) {
  .champs { grid-template-columns: 1fr; }
  /* Sauf les couples qui se lisent ensemble : une heure et une durée, un
     montant et sa date, se comprennent mieux côte à côte que l'un sous
     l'autre. */
  .caisse__duo { display: flex; }
}

/* La barre du bas mesure sa hauteur plus l'encoche du téléphone : réserver
   quatre-vingt-seize pixels fixes laissait la dernière ligne dessous. */
body.avec-barre .espace__corps {
  padding-bottom: calc(96px + env(safe-area-inset-bottom, 0px));
}

/* ------------------------------------------------ ce qui se touche du pouce */

/* Quarante-quatre pixels, c'est la pulpe d'un pouce. En dessous, on vise. */
.espace button:not(.lien-bouton):not(.teinte):not(.pastille):not(.accomp__pas):not(.barre__onglet):not(.sous-onglet):not(.ligne-membre__valider):not(.inscrit__avec):not(.impaye__regle):not(.paiements__ajout):not(.reglage__ajout):not(.mdp__oeil):not(.reglette__lettre):not(.puce--geste):not(.site-inter) {
  min-height: 44px;
}
/* « Valider » fait exception : posé sur une rangée de soixante pixels qu'il
   partage avec le bouton qui ouvre la fiche, un pavé de quarante-quatre
   pixels tirait l'œil plus que le nom de la personne. Trente-quatre suffisent
   ici — rien d'autre ne se touche à côté. */
.ligne-membre__valider { min-height: 34px; }
.pastille { width: 40px; height: 40px; }
.pastille svg { width: 20px; height: 20px; }
.accomp__pas { width: 36px; height: 36px; }
.filtre { min-height: 38px; }
.case-groupe, .composer__ligne { min-height: 46px; }
.volet { min-height: 42px; }
.teinte { width: 40px; height: 40px; }

/* Un menu déroulant sous seize pixels fait zoomer Safari à la mise au point,
   et l'on se retrouve à faire défiler la page de côté pour en sortir. */
#liste-membres select,
#form-info input[type="file"] { font-size: 16px; }

/* -------------------------------------------- l'action principale, au pouce */

/* Sur un téléphone, l'action principale d'un formulaire mérite toute la
   largeur : c'est la seule chose qu'on vient y faire, et un bouton calé à
   gauche se vise au lieu de s'atteindre. Le lien secondaire passe dessous,
   centré, où il ne se touche pas par mégarde. */
@media (max-width: 560px) {
  .actions {
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
  }
  .actions button:not(.lien-bouton) { width: 100%; }
  .actions .lien-bouton { align-self: center; padding: 10px 6px; }

  #form-connexion button:not(.mdp__oeil) { width: 100%; justify-self: stretch; }
  .connexion__liens { display: flex; justify-content: center; }
  .connexion__liens .lien-bouton,
  .connexion__aide .lien-bouton { padding: 10px 6px; }
  .connexion__aide { text-align: center; }

  /* Le formulaire d'un cours, d'une formule ou d'un groupe se termine de la
     même façon : le bouton d'enregistrement prend la largeur. */
  .formulaire-bloc .actions button:not(.lien-bouton) { width: 100%; }
}

/* Un lien-bouton fait la hauteur de son texte : douze pixels de haut, on le
   rate une fois sur trois. Il garde son air de lien, avec de quoi le viser. */
.lien-bouton { padding: 8px 2px; min-height: 40px; }
.espace__liens .lien-bouton { min-height: 36px; }

/* Pendant qu'on écrit, la barre du bas ne sert à rien et prend soixante
   pixels sur les trois cents que laisse le clavier. Elle se retire. */
body.clavier .barre { transform: translateY(110%); }
.barre { transition: transform .16s ease; }
body.clavier.avec-barre .espace__corps { padding-bottom: 24px; }
@media (prefers-reduced-motion: reduce) { .barre { transition: none; } }

/* ------------------------------------------------ hiérarchie des actions -- */

/* Deux boutons jaunes côte à côte disent que les deux gestes se valent.
   Ajouter un cours se fait chaque rentrée, une séance exceptionnelle deux fois
   l'an : le second se dessine en creux. */
.bouton-second {
  background: #fff !important;
  color: var(--prune) !important;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 12.9%) 87.8%) !important;
}
.bouton-second:hover { background: hsl(var(--teinte) calc(var(--force) * 42.9%) 97.3%) !important; }

/* La barre de saison entassait un menu et trois liens sur une ligne. Le menu
   prend la largeur, les gestes se rangent dessous — et « Supprimer » cesse de
   ressembler à « Modifier ». */
@media (max-width: 560px) {
  /* Le menu prend sa ligne, les trois gestes coulent sur la suivante : en
     colonne, chacun devenait un pavé pleine largeur et la barre mesurait la
     moitié de l'écran. */
  .barre-saison { row-gap: 6px; column-gap: 16px; }
  .barre-saison label { flex: 0 0 auto; }
  .barre-saison select { flex: 1 1 100%; width: 100%; }
}

/* Un cours qu'on ne peut pas prendre doit se voir d'un regard. Une simple
   transparence à 62 % ne disait rien : on lisait un cours ordinaire, avec ses
   places libres, et l'on découvrait le refus en le touchant.

   Il perd donc sa couleur, se raye légèrement, et remplace son compte de
   places par le nom du groupe — la question n'est pas « reste-t-il de la
   place » mais « à qui s'adresse-t-il ». */
.bloc-cours--ferme {
  filter: saturate(.18);
  opacity: .9;
  background-image: repeating-linear-gradient(
    135deg,
    rgba(110, 97, 105, .07) 0 5px,
    transparent 5px 10px
  );
  box-shadow: inset 0 0 0 1px rgba(110, 97, 105, .18);
}
.bloc-cours--ferme .bloc-cours__nom,
.bloc-cours--ferme .bloc-cours__heure { color: hsl(var(--teinte) calc(var(--force) * 5.9%) 39.6%); }

/* Un cadenas plutôt que le nom du groupe : celui-ci ne change jamais et
   s'écrivait neuf fois dans la grille. Le dessin dit « pas pour vous » sans
   occuper de largeur ; la fiche dit pourquoi. */
.bloc-cours__ferme {
  display: flex;
  justify-content: center;
  color: hsl(var(--teinte) calc(var(--force) * 5.9%) 39.6%);
}
.bloc-cours__ferme svg {
  width: 15px;
  height: 15px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* L'appartenance aux groupes se pose à la main : elle se lit donc sous le nom.
   Sans groupe, une personne validée voit le planning sans pouvoir rien
   réserver, et rien d'autre ne le signalerait. */
.fiche-membre__groupes { display: flex; flex-wrap: wrap; gap: 5px; margin: 7px 0 0; }
/* La validité de la formule et l'état du certificat : deux mentions, sur une
   même ligne qui se replie si l'écran est trop étroit. */
.fiche-membre__mentions { display: flex; flex-wrap: wrap; gap: 5px; margin: 7px 0 0; }

/* La date d'une information, et à qui elle s'adresse. */
.info__date { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; }
.info__date > * { min-width: 0; }

/* ------------------------------------------------- complétion d'adresse -- */

/* La liste des rues proposées. Elle flotte sous le champ plutôt que de pousser
   le formulaire : sur un téléphone, un contenu qui grandit sous le doigt fait
   manquer la ligne qu'on visait. */
.suggestions {
  position: absolute;
  left: 0;
  right: 0;
  z-index: 40;
  margin-top: 2px;
  max-height: 46vh;
  overflow-y: auto;
  overscroll-behavior: contain;
  background: #fff;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 12.9%) 87.8%);
  border-radius: 12px;
  box-shadow: 0 10px 28px -14px rgba(42, 34, 40, .35);
}
.champs label { position: relative; }

.suggestion {
  display: flex;
  flex-direction: column;
  gap: 1px;
  width: 100%;
  min-height: 46px;
  padding: 9px 13px;
  border: 0;
  border-bottom: 1px solid hsl(var(--teinte) calc(var(--force) * 23.8%) 95.9%);
  background: none;
  text-align: left;
  cursor: pointer;
}
.suggestion:last-child { border-bottom: 0; }
.suggestion:hover, .suggestion:focus-visible { background: hsl(var(--teinte) calc(var(--force) * 42.9%) 97.3%); outline: 0; }
.suggestion__rue {
  font-family: var(--font-titre);
  font-size: 15px;
  font-weight: 600;
  color: hsl(var(--teinte) calc(var(--force) * 7.2%) 27.1%);
  overflow-wrap: anywhere;
}
.suggestion__ou { font-size: 14px; color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%); }

/* ================================================================ la carte */

/* Écrite à la main plutôt qu'empruntée : une bibliothèque de cartographie
   pèserait cent soixante kilo-octets et ferait entrer un script étranger dans
   une page qui n'en accepte aucun. */
.carte-cadre {
  position: relative;
  height: 260px;
  margin: 12px 0;
  border-radius: 12px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 12.9%) 87.8%);
  overflow: hidden;
  background: hsl(var(--teinte) calc(var(--force) * 13.5%) 92.7%);
}
.carte-cadre--grande { height: 58vh; min-height: 300px; }

/* ============================================================== les signes */

/* Douze cartes, une par signe, du signe du jour au précédent. Le glyphe
   astronomique fait le repère — Agnès reconnaît ♌ avant de lire « Lion ». Un
   signe sans personne reste, plus discret : sa place dans l'ordre est ce
   qui dit où l'on en est de l'année. */
.signes { display: flex; flex-direction: column; gap: 10px; margin-top: 4px; }
.signe {
  background: #fff;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 18.9%) 92.7%);
  border-radius: 14px;
  overflow: hidden;
}
.signe--en-cours { border-color: var(--corail); }
.signe--vide { opacity: .62; }
.signe__tete {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  background: hsl(var(--teinte) calc(var(--force) * 27.3%) 97.8%);
}
.signe__glyphe {
  flex: 0 0 auto;
  width: 38px; height: 38px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--prune);
  color: #fff;
  font-size: 21px;
  line-height: 1;
}
.signe--en-cours .signe__glyphe { background: var(--corail); }
.signe__titre { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.signe__nom { font-family: var(--font-titre); font-size: 16px; font-weight: 600; color: var(--prune); }
.signe__dates { font-size: 13px; color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%); }
.signe__nombre {
  font-family: var(--font-titre);
  font-size: 15px; font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
.signe__personne {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  min-height: 50px;
  padding: 9px 16px;
  border: 0;
  border-top: 1px solid hsl(var(--teinte) calc(var(--force) * 18.9%) 92.7%);
  background: none;
  text-align: left;
  cursor: pointer;
  font-family: var(--font-titre);
  color: hsl(var(--teinte) calc(var(--force) * 10%) 15.7%);
}
.signe__personne:focus-visible { outline: 2px solid var(--prune); outline-offset: -2px; }
.signe__initiales {
  flex: 0 0 auto;
  width: 30px; height: 30px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: hsl(var(--teinte) calc(var(--force) * 13.5%) 92.7%);
  font-size: 12px; font-weight: 600;
  color: var(--prune);
}
.signe__qui { flex: 1 1 auto; min-width: 0; font-size: 15px; font-weight: 500; overflow-wrap: anywhere; }
.signe__quand {
  flex: 0 0 auto;
  font-size: 13px;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
  white-space: nowrap;
}
.signes__reste { margin: 8px 2px 0; }

.carte__plan {
  position: absolute;
  inset: 0;
  cursor: grab;
  touch-action: none;
}
.carte__plan:active { cursor: grabbing; }

.carte__tuile {
  position: absolute;
  width: 256px;
  height: 256px;
  user-select: none;
  -webkit-user-drag: none;
  pointer-events: none;
}

/* Un point porte les initiales : sur une carte de village, deux membres de la
   même rue se distinguent mieux par leurs lettres que par leur position. */
.carte__point {
  position: absolute;
  width: 30px;
  height: 30px;
  margin: -15px 0 0 -15px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 2px solid #fff;
  border-radius: 50%;
  background: var(--prune);
  color: #fff;
  font-family: var(--font-titre);
  font-size: 11px;
  font-weight: 700;
  cursor: pointer;
  box-shadow: 0 2px 6px rgba(42, 34, 40, .35);
}
.carte__point:focus-visible { outline: 3px solid var(--corail); outline-offset: 1px; }

.carte__nom {
  position: absolute;
  left: 10px;
  right: 60px;
  bottom: 10px;
  padding: 9px 12px;
  border-radius: 10px;
  background: rgba(255, 255, 255, .95);
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 12.9%) 87.8%);
  font-family: var(--font-titre);
  font-size: 14px;
  font-weight: 600;
  color: hsl(var(--teinte) calc(var(--force) * 7.2%) 27.1%);
  overflow-wrap: anywhere;
}

.carte__zoom {
  position: absolute;
  top: 10px;
  right: 10px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.carte__bouton {
  width: 40px;
  height: 40px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 12.9%) 87.8%);
  border-radius: 9px;
  background: rgba(255, 255, 255, .95);
  font-family: var(--font-titre);
  font-size: 20px;
  font-weight: 600;
  line-height: 1;
  color: var(--prune);
  cursor: pointer;
}
.carte__bouton:hover { background: #fff; }

/* OpenStreetMap fournit le fond gratuitement et demande en retour d'être
   citée. C'est la moindre des choses. */
.carte__credit {
  position: absolute;
  right: 0;
  bottom: 0;
  padding: 2px 7px;
  border-radius: 6px 0 0 0;
  background: rgba(255, 255, 255, .82);
  font-family: var(--font-titre);
  font-size: 10px;
}
.carte__credit a { color: hsl(var(--teinte) calc(var(--force) * 5.9%) 39.6%); text-decoration: none; }

.carte__rien {
  margin: 0;
  padding: 26px 20px;
  text-align: center;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}

/* ============================== la semaine type, et sa feuille du bas == */

/* Une carte de cent quatre-vingts pixels par cours, deux liens de douze à
   viser, et un formulaire posé après toute la liste sans rien pour y mener :
   corriger un horaire du lundi demandait six écrans de descente.

   Une ligne, toute la largeur, et le formulaire monte du bas — toujours au
   même endroit, sous le pouce, quel que soit le cours touché. */
.cours-ligne {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  min-height: 52px;
  padding: 8px 10px;
  border: 0;
  border-left: 3px solid var(--fam, hsl(var(--teinte) calc(var(--force) * 12.9%) 87.8%));
  border-bottom: 1px solid hsl(var(--teinte) calc(var(--force) * 23.8%) 95.9%);
  background: none;
  text-align: left;
  cursor: pointer;
  font-family: var(--font-texte);
}
.cours-ligne > * { min-width: 0; }
.cours-ligne:hover { background: hsl(var(--teinte) calc(var(--force) * 33.3%) 98.2%); }
.cours-ligne--ouvert { background: hsl(var(--teinte) calc(var(--force) * 42.9%) 97.3%); }
.cours-ligne--retire { opacity: .55; }
.cours-ligne:focus-visible { outline: 2px solid var(--prune); outline-offset: -2px; }

.cours-ligne__heure {
  flex: 0 0 auto;
  font-family: var(--font-titre);
  font-size: 14px;
  font-weight: 700;
  color: var(--prune);
  font-variant-numeric: tabular-nums;
}
.cours-ligne__milieu { flex: 1 1 auto; display: flex; flex-direction: column; }
.cours-ligne__nom {
  font-family: var(--font-titre);
  font-size: 15px;
  font-weight: 600;
  color: hsl(var(--teinte) calc(var(--force) * 7.2%) 27.1%);
  overflow-wrap: anywhere;
}
.cours-ligne__sous { font-size: 14px; color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%); overflow-wrap: anywhere; }
.cours-ligne__places {
  flex: 0 0 auto;
  font-family: var(--font-titre);
  font-size: 12px;
  font-weight: 600;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}

/* Les teintes des disciplines, comme au planning. */
.cours-ligne--yoga    { --fam: var(--prune); }
.cours-ligne--pilates { --fam: #EC7069; }
.cours-ligne--renfo   { --fam: #FAB926; }
.cours-ligne--kids    { --fam: #F19953; }
.cours-ligne--paddle  { --fam: #09354E; }
.cours-ligne--atelier { --fam: #7F348B; }
.cours-ligne--autre   { --fam: hsl(var(--teinte) calc(var(--force) * 10.8%) 69.2%); }

/* ------------------------------------------------------ la feuille du bas */

.voile-bas {
  position: fixed;
  inset: 0;
  z-index: 50;
  background: rgba(46, 37, 48, .34);
}
body.feuille-ouverte { overflow: hidden; }

/* Le clavier d'iOS ne réduit pas la hauteur que connaît le CSS : « vh » et
   même « dvh » continuent de mesurer l'écran entier. Une feuille haute se
   retrouvait donc à cheval — son bas caché derrière le clavier, son haut poussé
   au-dessus de l'écran, hors d'atteinte : on ne pouvait plus remonter à ses
   premiers champs. « --vue-hauteur » et « --vue-bas » portent ce que mesure
   « visualViewport », mis à jour à l'ouverture du clavier ; sans lui — ou sur
   un navigateur qui l'ignore — on retombe sur l'ancien calcul. */
.feuille {
  position: fixed;
  left: 0;
  right: 0;
  bottom: var(--vue-bas, 0px);
  z-index: 51;
  max-height: min(88vh, calc(var(--vue-hauteur, 88vh) - 10px));
  overflow-y: auto;
  /* Une feuille ne glisse jamais de côté. « overflow-y: auto » suffit à rendre
     l'axe horizontal défilable aussi — c'est la règle du CSS dès qu'un des deux
     axes n'est plus « visible » — et le moindre élément trop large se met alors
     à emporter tout le panneau sous le doigt. On ferme la porte ici, en plus de
     corriger ce qui déborde. */
  overflow-x: hidden;
  overscroll-behavior: contain;
  padding: 8px 16px calc(18px + env(safe-area-inset-bottom, 0px));
  background: #fff;
  border-radius: 20px 20px 0 0;
  box-shadow: 0 -10px 34px -16px rgba(46, 37, 48, .5);
  transform: translateY(100%);
  transition: transform .22s cubic-bezier(.2, .8, .3, 1);
}
.feuille--montee { transform: translateY(0); }
@media (prefers-reduced-motion: reduce) { .feuille { transition: none; } }
@media (min-width: 640px) {
  .feuille { left: 50%; right: auto; width: 460px; transform: translate(-50%, 100%); }
  .feuille--montee { transform: translate(-50%, 0); }
}

/* Sur un écran large tenu à la souris, la feuille cessait d'être une feuille.
   Collée au bas de la fenêtre, coins carrés en bas, elle avait l'air rognée
   par le bord de l'écran plutôt que posée dessus — et le regard, qui se tient
   au milieu d'un grand écran, devait descendre la chercher.

   Elle devient alors un panneau centré : arrondi sur ses quatre côtés, à
   distance des bords, et elle apparaît en montant de quelques pixels au lieu
   de surgir du bas. Le tri se fait sur le pointeur, pas sur la largeur : une
   tablette tactile large garde la feuille du bas, parce que le geste qui la
   referme — tirer la poignée — n'existe qu'au doigt. */
@media (min-width: 640px) and (hover: hover) and (pointer: fine) {
  .feuille {
    top: 50%;
    bottom: auto;
    max-height: min(84vh, calc(var(--vue-hauteur, 84vh) - 60px));
    padding: 18px 22px 22px;
    border-radius: 18px;
    box-shadow: 0 24px 60px -24px rgba(46, 37, 48, .45);
    transform: translate(-50%, calc(-50% + 14px));
    opacity: 0;
    transition: transform .2s cubic-bezier(.2, .8, .3, 1), opacity .2s ease;
  }
  .feuille--montee { transform: translate(-50%, -50%); opacity: 1; }

  /* La poignée ne sert qu'au doigt : sans elle, le titre remonte. */
  .feuille__poignee { display: none; }
}

/* Une poignée qu'on peut saisir : glisser vers le bas referme, c'est le geste
   qu'on essaie d'instinct devant un panneau qui monte.
   ----------------------------------------------------------------------------
   `touch-action: none` confisquait TOUT glissé parti de là. Vers le bas, très
   bien : c'est la fermeture. Mais vers le haut — le geste de « voir la suite »
   — il ne se passait rien du tout, et l'on croyait la feuille bloquée. Comme la
   poignée est la première chose sous le pouce quand la feuille s'ouvre, c'est
   souvent de là qu'on part.

   `pan-y` rend le défilement au navigateur ; la fermeture reste possible parce
   que le gestionnaire ne prend la main QUE lorsque la feuille est déjà en haut
   et que le doigt descend — il n'y a alors rien à faire défiler. */
.feuille__poignee {
  width: 44px;
  height: 5px;
  margin: 2px auto 12px;
  border-radius: 5px;
  background: hsl(var(--teinte) calc(var(--force) * 12.9%) 87.8%);
  touch-action: pan-y;
  cursor: grab;
}

/* La zone qu'on saisit est plus large que le trait qu'on voit : cinq pixels de
   haut ne s'attrapent pas au pouce. */
.feuille__poignee::after {
  content: '';
  position: absolute;
  left: 0; right: 0;
  margin-top: -14px;
  height: 34px;
}
.feuille__poignee { position: relative; }
.feuille__titre {
  margin: 0 0 12px;
  font-family: var(--font-titre);
  font-size: 17px;
  font-weight: 600;
  color: var(--prune);
  text-wrap: balance;
}
.feuille__champs { display: flex; flex-direction: column; gap: 10px; }
.feuille__duo { display: flex; gap: 8px; }
.feuille__duo > * { flex: 1 1 0; min-width: 0; }
.feuille__champ { display: block; }
/* L'étiquette. En capitales, elle se lit moins vite qu'en bas-de-casse — et
   l'appoint qui la suit (« pour qui ne la voit pas ») devenait une seconde
   ligne de capitales, aussi voyante que l'étiquette elle-même alors qu'il n'est
   qu'une précision. */
.feuille__champ > span {
  display: block;
  font-family: var(--font-titre);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
.feuille__champ > span small {
  text-transform: none;
  letter-spacing: 0;
  font-weight: 400;
  font-size: 12px;
  opacity: .85;
}
/* `textarea` MANQUAIT à cette liste, et le manque ne se voyait pas d'un coup
   d'œil — il fallait mesurer.
   ----------------------------------------------------------------------------
   Une zone de texte sans style prend la largeur que le navigateur lui donne
   d'après son attribut `cols` : 170 pixels sur les 358 des autres champs, soit
   moins de la moitié. Et surtout elle gardait la taille de caractère par défaut
   d'un navigateur, 13,3 px — sous les 16 px, **iOS zoome la page** dès qu'on
   touche le champ, puis il faut la repincer pour revoir le bouton
   « Enregistrer ». C'est ce qui rendait la saisie des textes pénible, bien plus
   que la disposition. */
.feuille__champ input,
.feuille__champ textarea,
.feuille__champ select {
  display: block;
  width: 100%;
  min-width: 0;
  margin-top: 3px;
  padding: 11px 12px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 12.9%) 87.8%);
  border-radius: 10px;
  background-color: #fff;
  font-family: var(--font-titre);
  /* Jamais moins de 16 px : c'est le seuil sous lequel iOS zoome. */
  font-size: 16px;
  color: hsl(var(--teinte) calc(var(--force) * 7.2%) 27.1%);
}

/* Un texte se relit autant qu'il s'écrit : on lui donne de l'interligne, et une
   hauteur qui SUIT ce qu'on tape. Écrire trois paragraphes de présentation par
   un hublot de quatre lignes, en faisant défiler à l'intérieur d'un champ qui
   défile lui-même dans une feuille qui défile, est la meilleure façon de
   renoncer à corriger une virgule. */
.feuille__champ textarea {
  line-height: 1.5;
  min-height: 96px;
  resize: vertical;
  overflow: hidden;
}

.feuille__champ input:focus-visible,
.feuille__champ textarea:focus-visible,
.feuille__champ select:focus-visible {
  outline: 2px solid var(--prune);
  outline-offset: 1px;
}

/* L'enregistrement prend la largeur ; ce qu'on fait rarement se range
   dessous, et « Retirer » y est rouge. */
.feuille__gestes {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 16px;
  margin-top: 14px;
}
.feuille__gestes > * { min-width: 0; }
.feuille__gestes .bouton-reserver { flex: 1 1 100%; }

/* Ce que le choix des groupes entraîne, dit sous les cases du panneau. */
.feuille__mot {
  margin: 7px 0 0;
  font-size: 15px;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
  text-wrap: pretty;
}

/* La feuille accueille aussi le déplacement d'une séance : sa phrase
   d'avertissement et le rappel de prévenir les inscrits. */
.feuille > .feuille__mot { margin: -4px 0 12px; }
.feuille .prevenir { margin-top: 14px; }
.feuille .prevenir .bouton-reserver { width: 100%; margin-top: 8px; }

/* Un formulaire déplacé dans la feuille du bas : il perd son cadre, la feuille
   en fournit un, et son titre ferait doublon avec celui du panneau. */
.formulaire-bloc--feuille {
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
}
.formulaire-bloc--feuille > h3 { display: none; }
.formulaire-bloc--feuille .actions { margin-top: 16px; }

/* Un panneau de fiche membre posé dans la feuille du bas : la feuille fournit
   déjà le cadre et le titre. */
.hote-panneau > .panneau {
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
}
.hote-panneau .panneau__aide:first-child { margin-top: 0; }

/* La fiche d'un membre vit dans la feuille du bas ; ses panneaux la
   remplacent, avec une flèche qui ramène. */
.hote-fiche > .fiche-membre {
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
}
/* Le retour vers la fiche : un lien rouge de la taille de son texte se
   ratait une fois sur trois. Il prend la forme d'un bouton discret — cerné,
   à hauteur de pouce — puisque c'est le geste qu'on fait en sortant. */
.feuille__retour {
  display: inline-flex;
  align-items: center;
  margin: -2px 0 12px;
  padding: 8px 14px 8px 11px;
  min-height: 40px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 20%) 90.2%);
  border-radius: 999px;
  background: hsl(var(--teinte) calc(var(--force) * 33.3%) 97.6%);
  font-family: var(--font-titre);
  font-size: 14px;
  font-weight: 600;
  color: var(--prune);
  cursor: pointer;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.feuille__retour:hover { background: hsl(var(--teinte) calc(var(--force) * 31.3%) 93.7%); border-color: var(--prune); }
.feuille__retour:focus-visible { outline: 2px solid var(--prune); outline-offset: 2px; }

/* ------------------------------------------------------------ les alertes */

/* Un changement de dernière minute, en tête de l'espace, pour les seules
   personnes inscrites à la séance concernée. Rouge, parce qu'il annonce que
   quelque chose ne se passera pas comme prévu. */
.alertes { display: flex; flex-direction: column; gap: 8px; margin-bottom: 14px; }

/* Une alerte est une carte blanche ; la couleur tient dans la pastille.
   ----------------------------------------------------------------------------
   Toutes les alertes étaient roses, avec un triangle d'avertissement — le rose
   des messages d'erreur. Or un changement de salle n'est pas un incident, c'est
   une nouvelle : le peindre en rouge use l'alarme pour le jour où elle servira,
   et trois alertes empilées faisaient virer tout le haut de l'écran.

   Le fond redevient blanc. La nature de l'alerte se lit dans un rond de
   trente-quatre pixels — prune pour un changement, rouge pour une annulation,
   corail pour un message — si bien que trois natures peuvent se suivre sans que
   la page prenne parti. */
.alerte {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 12px 14px;
  border-radius: 12px;
  background: #fff;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 16%) 89%);
}
.alerte > * { min-width: 0; }

/* Une alerte qui mène quelque part est un bouton : elle doit s'aligner comme
   les autres et ne pas centrer son texte, ce qu'un <button> fait d'office. */
.alerte--menant {
  width: 100%;
  text-align: left;
  font: inherit;
  cursor: pointer;
}
.alerte--menant:hover { background: hsl(var(--teinte) calc(var(--force) * 27%) 98%); }

.alerte__icone {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: 50%;
}
.alerte__icone svg {
  width: 18px;
  height: 18px;
  fill: none;
  stroke: #fff;
  stroke-width: 1.9;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.alerte--changement .alerte__icone { background: var(--prune); }
.alerte--annulee    .alerte__icone { background: #A8535E; }
.alerte--message    .alerte__icone { background: var(--corail); }

.alerte__corps { flex: 1 1 auto; }
/* Le titre reprend l'encre du texte : la couleur est déjà dans la pastille, la
   redire ici donnait une ligne rouge en haut de chaque carte. */
.alerte__quoi {
  margin: 0 0 2px;
  font-family: var(--font-titre);
  font-size: 13px;
  font-weight: 700;
  color: hsl(var(--teinte) calc(var(--force) * 7%) 27.1%);
  overflow-wrap: anywhere;
}
.alerte__mot { margin: 0; font-size: 17px; color: hsl(var(--teinte) calc(var(--force) * 7.2%) 27.1%); text-wrap: pretty; }

/* Le panneau des notifications : du texte, un bouton, une réserve. */
.notifs__mot { margin: 0 0 12px; font-size: 16px; color: hsl(var(--teinte) calc(var(--force) * 7.2%) 27.1%); text-wrap: pretty; }
.notifs__note {
  margin: 14px 0 0;
  padding-top: 12px;
  border-top: 1px solid hsl(var(--teinte) calc(var(--force) * 18.9%) 92.7%);
  font-size: 14px;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
  text-wrap: pretty;
}
.notifs .actions { margin-top: 4px; }
.notifs .bouton-reserver { width: 100%; }

/* Le bloc « prévenir », dans la feuille de déplacement. */
.prevenir { margin-top: 14px; }
.prevenir__mot { margin: 0 0 9px; font-size: 15px; color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%); text-wrap: pretty; }

/* Deux boutons côte à côte tant que la ligne le permet, l'un sous l'autre
   sinon : « Copier pour WhatsApp » est long, et sur un petit téléphone les
   deux serrés devenaient deux pavés illisibles. */
.prevenir__gestes { display: flex; flex-wrap: wrap; gap: 8px; }
.prevenir__gestes button { flex: 1 1 auto; }

/* ------------------------------------------------- supprimer un compte -- */

/* Un geste sans retour se dessine comme tel : ce qui va disparaître est
   énuméré, l'argent est signalé à part, et le bouton demande un mot tapé. */
.perte__titre {
  margin: 14px 0 6px;
  font-family: var(--font-titre);
  font-size: 14px;
  font-weight: 600;
  color: hsl(var(--teinte) calc(var(--force) * 7.2%) 27.1%);
  overflow-wrap: anywhere;
}
.perte {
  margin: 0;
  padding-left: 20px;
  font-size: 16px;
  color: hsl(var(--teinte) calc(var(--force) * 6.3%) 40.6%);
}
.perte li { margin-bottom: 3px; }

.perte__argent {
  margin-top: 12px;
  padding: 12px 14px;
  border-radius: 11px;
  background: #FDF3E2;
  border: 1px solid rgba(122, 84, 16, .24);
}
.perte__argent p {
  margin: 0;
  font-size: 16px;
  color: #7A5410;
  text-wrap: pretty;
}
.perte__argent p + p { margin-top: 7px; }

.bouton-supprimer {
  flex: 1 1 100%;
  min-height: 44px;
  padding: 12px 20px;
  border: 0;
  border-radius: 30px;
  background: #A8535E;
  color: #fff;
  font-family: var(--font-titre);
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
}
.bouton-supprimer:hover:not(:disabled) { background: #93454F; }
.bouton-supprimer:disabled { background: hsl(var(--teinte) calc(var(--force) * 12.9%) 87.8%); color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%); cursor: default; }

/* ------------------------------------------------- voir son mot de passe -- */

/* L'œil se pose dans le champ, à droite, sans en changer la forme : le champ
   de connexion est une pilule de trente pixels de rayon, celui d'un formulaire
   un rectangle arrondi. On ne touche qu'à la place réservée au bouton. */
.mdp { position: relative; display: block; }
.mdp > input { width: 100%; padding-right: 48px; }

.mdp__oeil {
  position: absolute;
  top: 50%;
  right: 6px;
  transform: translateY(-50%);
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: 50%;
  background: none;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
  cursor: pointer;
}
.mdp__oeil svg {
  width: 21px;
  height: 21px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.mdp__oeil:hover { color: var(--prune); background: hsl(var(--teinte) calc(var(--force) * 42.9%) 97.3%); }
.mdp__oeil[aria-pressed="true"] { color: var(--prune); }
.mdp__oeil:focus-visible { outline: 2px solid var(--prune); outline-offset: 1px; }

/* Le champ de connexion vit dans une grille : l'enveloppe doit en prendre la
   place, sinon elle se réduit à la largeur du champ. */
#form-connexion .mdp { width: 100%; }

/* --------------------------------------------------------------- réglages */

/* L'engrenage, à droite du titre « Administration ». Discret : il ouvre ce
   qu'on règle deux fois l'an, pas ce qu'on vient faire. */
.bouton-reglages {
  flex: 0 0 auto;
  width: 44px; height: 44px;
  padding: 0;
  display: grid; place-items: center;
  background: none;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 18.9%) 92.7%);
  border-radius: 50%;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
  cursor: pointer;
}
.bouton-reglages svg { width: 19px; height: 19px; fill: none; stroke: currentColor; stroke-width: 1.7; }
.bouton-reglages:hover { color: var(--prune); border-color: var(--prune); }
.bouton-reglages:focus-visible { outline: 2px solid var(--prune); outline-offset: 2px; }

/* Trois niveaux, sinon rien ne se distingue : le titre de la feuille, un
   intertitre discret par section, et le reste en gris. Écrits du même poids,
   « Réglages », « Les saisons » et « Les groupes » se lisaient comme trois
   titres concurrents.

   Restait un défaut plus sourd : la séparation entre deux sections et celle
   entre deux lignes d'une même section étaient le même filet d'un pixel. Deux
   séparations de sens opposé, dessinées à l'identique — la feuille se lisait
   comme une seule longue liste. Le filet reste aux lignes ; une section
   s'ouvre maintenant par un bandeau teinté, sur toute la largeur, qui la
   nomme. Il tient en haut pendant qu'on fait défiler : la liste des lieux est
   longue, et l'on veut savoir en permanence dans quelle partie on se trouve. */
#bloc-reglages { margin: 0 -16px; }

/* L'indentation vient du rembourrage de la section, pas des marges de ses
   enfants : « .reglage__mot » porte un « margin: 0 » qui écrasait toute règle
   de même poids, et les phrases grises se collaient au bord de l'écran. Seul
   le bandeau ressort, par une marge négative. */
.reglage { padding: 0 16px 18px; }
.reglage:last-child { padding-bottom: 4px; }

.reglage__titre {
  position: sticky;
  top: -8px;
  z-index: 1;
  margin: 0 -16px 12px;
  padding: 9px 16px;
  background: hsl(var(--teinte) calc(var(--force) * 25%) 95.3%);
  border-top: 1px solid hsl(var(--teinte) calc(var(--force) * 21.7%) 91%);
  border-bottom: 1px solid hsl(var(--teinte) calc(var(--force) * 21.7%) 91%);
  font-family: var(--font-titre);
  font-size: 12px; font-weight: 600;
  letter-spacing: .12em; text-transform: uppercase;
  color: hsl(var(--teinte) calc(var(--force) * 7.3%) 40.2%);
}
.reglage:first-child > .reglage__titre { border-top: none; }
.reglage__mot {
  margin: 0;
  font-size: 14px;
  line-height: 1.45;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
.reglage__titre + .reglage__mot { margin-top: -3px; margin-bottom: 10px; }
/* Une explication puis d'autres champs : sans respiration, le libellé qui suit
   se lit comme la suite du paragraphe. */
.feuille__champs + .reglage__mot { margin-top: 10px; }
.reglage__mot + .feuille__champs { margin-top: 14px; }

/* L'interrupteur : le nom à gauche, la case à droite, comme partout ailleurs
   sur un téléphone. La phrase qui explique vit dessous, en gris — elle disait
   la même chose que l'étiquette, et les deux se répétaient. */
.reglage__bascule {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  min-height: 46px;
  cursor: pointer;
}
.reglage__nom {
  font-family: var(--font-titre);
  font-size: 15px; font-weight: 500;
  color: hsl(var(--teinte) calc(var(--force) * 10%) 15.7%);
}
.reglage__bascule input {
  flex: 0 0 auto;
  width: 22px; height: 22px;
  margin: 0;
  accent-color: var(--prune);
}

/* Créer une saison est rare : un lien encadré, pas le bouton jaune qui appelle
   au geste principal. */
.reglage__ajout, .paiements__ajout {
  width: 100%;
  margin-top: 10px;
  padding: 9px;
  min-height: 38px;
  border: 1px dashed hsl(var(--teinte) calc(var(--force) * 15.7%) 83.7%);
  border-radius: 10px;
  background: none;
  font-family: var(--font-titre);
  font-size: 13px; font-weight: 500;
  color: var(--prune);
  cursor: pointer;
}
.reglage__ajout:hover, .paiements__ajout:hover { background: hsl(var(--teinte) calc(var(--force) * 33.3%) 97.6%); border-color: var(--prune); }
.reglage__ajout:focus-visible, .paiements__ajout:focus-visible {
  outline: 2px solid var(--prune); outline-offset: 2px;
}

/* Une saison par rangée : son nom, ses dates, et les deux gestes rares. */
.saison-ligne {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 11px 0;
  border-top: 1px solid hsl(var(--teinte) calc(var(--force) * 18.9%) 92.7%);
}
.saison-ligne__milieu { flex: 1 1 auto; min-width: 0; display: grid; gap: 2px; }
.saison-ligne__nom { font-family: var(--font-titre); font-size: 15px; font-weight: 600; }
.saison-ligne__quand { font-size: 13px; color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%); }
.saison-ligne__gestes { flex: 0 0 auto; display: flex; gap: 4px; }
.saison-ligne__gestes .lien-bouton { padding: 6px 6px; font-size: 0.85rem; }

/* Groupes éteints : tout ce qui les nomme quitte l'écran. Rien n'est effacé
   côté serveur — les rallumer restitue chaque case à sa place. */
:root.sans-groupes [data-groupes] { display: none !important; }

/* Le bandeau d'une feuille : son titre, et la place d'un geste rare à droite. */
.feuille__bandeau {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 12px;
}
.feuille__bandeau .feuille__titre { margin: 0; flex: 1 1 auto; min-width: 0; }
.feuille__geste { flex: 0 0 auto; min-height: 34px; }
.bouton-reglages--feuille { width: 34px; height: 34px; }
.bouton-reglages--feuille svg { width: 17px; height: 17px; }

/* --------------------------------------------- les chiffres de son compte */

/* Ce qu'on ouvre son compte pour savoir : à combien de séances on est venu,
   ce qu'on doit encore, et sur une carte ce qu'il reste dessus. Trois blocs
   au plus, alignés, lisibles sans lire. */
.chiffres {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  width: 100%;
  margin: 4px 0 2px;
}
.chiffres__un {
  flex: 1 1 96px;
  min-width: 0;
  padding: 12px 14px;
  border-radius: 12px;
  background: rgba(255, 255, 255, .68);
  border: 1px solid rgba(130, 85, 116, .12);
}
.chiffres__valeur {
  display: block;
  font-family: var(--font-titre);
  font-size: 26px; font-weight: 600;
  line-height: 1.1;
  color: var(--prune);
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}
.chiffres__mot {
  display: block;
  margin-top: 3px;
  font-family: var(--font-titre);
  font-size: 12px; font-weight: 500;
  letter-spacing: .04em;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
.chiffres__un--ok .chiffres__valeur { color: #2C5C3C; }
.chiffres__un--du {
  background: #FDF6E9;
  border-color: #EFDCB6;
}
.chiffres__un--du .chiffres__valeur { color: #8F5321; }
.chiffres__un--du .chiffres__mot { color: #8F5321; }

/* ------------------------------------------------------ la liste des offres */

/* Sept formules en cartes détaillées faisaient trois écrans. Une rangée : le
   nom et le tarif sur une ligne, ce qui la caractérise sur la suivante. Tout
   le détail — et les gestes — vit dans la feuille qu'un toucher fait monter. */
/* Le même bandeau que dans les réglages, et pour la même raison : il faut
   distinguer « nouvelle partie » de « ligne suivante », que le filet d'un
   pixel confondait. Il tient en haut pendant le défilement — sept offres
   réparties sur trois périodes tiennent plus d'un écran. */
.offres__titre {
  position: sticky;
  top: 0;
  z-index: 1;
  margin: 18px -16px 0;
  padding: 8px 16px;
  background: hsl(var(--teinte) calc(var(--force) * 25%) 95.3%);
  border-top: 1px solid hsl(var(--teinte) calc(var(--force) * 21.7%) 91%);
  border-bottom: 1px solid hsl(var(--teinte) calc(var(--force) * 21.7%) 91%);
}
#liste-formules > .offres__titre:first-child { margin-top: 0; border-top: none; }

.offre-ligne {
  display: block;
  width: 100%;
  padding: 10px 4px;
  border: 0;
  border-top: 1px solid hsl(var(--teinte) calc(var(--force) * 18.9%) 92.7%);
  background: none;
  text-align: left;
  cursor: pointer;
}
/* Sous un bandeau, le filet ferait doublon avec la bordure de celui-ci. */
.offres__titre + .offre-ligne { border-top: 0; }
#liste-formules .offre-ligne:first-child { border-top: 0; }
.offre-ligne:hover { background: hsl(var(--teinte) calc(var(--force) * 33.3%) 97.6%); }
.offre-ligne:focus-visible { outline: 2px solid var(--prune); outline-offset: -2px; }
.offre-ligne--retiree { opacity: .6; }

/* Ranger le catalogue à la main. La rangée cesse d'être touchable en entier —
   sinon on ouvrirait la formule à chaque fois qu'on rate une flèche — et les
   deux flèches se posent à droite, à l'écart l'une de l'autre pour qu'un pouce
   ne les confonde pas. */
.offres__barre { display: flex; justify-content: flex-end; margin-bottom: 2px; }
/* Ranger n'est pas défaire : le corail du lien-bouton annonce ailleurs un
   geste qu'on regrette. Celui-ci porte la couleur de la maison. */
.offres__ranger { font-size: 14px; color: var(--prune); }

/* La rangée devient un div : elle perd la police que le navigateur donne aux
   boutons, et la ligne de détail repassait en serif au milieu de la liste. */
.offre-ligne--rangement {
  font-family: var(--font-titre);
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 4px 12px;
  cursor: default;
}
.offre-ligne--rangement:hover { background: none; }
.offre-ligne--rangement .offre-ligne__haut { grid-column: 1; }
.offre-ligne--rangement .offre-ligne__quoi { grid-column: 1; }
.offre-ligne__fleches {
  grid-column: 2;
  grid-row: 1 / span 2;
  display: flex;
  gap: 6px;
}
.offre-fleche {
  width: 40px;
  min-height: 40px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 15%) 88%);
  border-radius: 11px;
  background: #fff;
  font-size: 13px;
  color: var(--prune);
  cursor: pointer;
}
.offre-fleche:disabled { opacity: .3; cursor: default; }

.offre-ligne__haut {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}
.offre-ligne__nom {
  font-family: var(--font-titre);
  font-size: 16px; font-weight: 600;
  color: var(--prune);
  min-width: 0;
}
.offre-ligne__montant {
  flex: 0 0 auto;
  font-family: var(--font-titre);
  font-size: 16px; font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.offre-ligne__quoi {
  display: block;
  margin-top: 1px;
  font-size: 13px;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
  line-height: 1.3;
}

/* Les gestes rares au pied d'une feuille, séparés de ce qu'on y règle. */
.feuille__gestes {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 16px;
  width: 100%;
  margin-top: 6px;
  padding-top: 10px;
  border-top: 1px solid hsl(var(--teinte) calc(var(--force) * 18.9%) 92.7%);
}

/* ------------------------------------------------ la liste des inscrits */

/* Une séance peut compter trente personnes. Deux lignes chacune — le nom, puis
   « + accompagnant » — faisaient six écrans à parcourir pour savoir qui vient.
   Une rangée, et le détail des accompagnants seulement pour qui en a. */
.inscrit {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 5px 0;
  border-bottom: 1px solid hsl(var(--teinte) calc(var(--force) * 23.8%) 95.9%);
}
.inscrit__gauche {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 3px 8px;
}
.inscrit__actions { flex: 0 0 auto; display: flex; gap: 4px; }

/* Le nom se serre pour laisser le chiffre à côté de lui, et non à la ligne. */
.inscrit__gauche .inscrit__nom {
  flex: 0 1 auto;
  min-width: 0;
  font-size: 15px;
  overflow-wrap: anywhere;
}

/* Ce que coûtent les accompagnants, et rien d'autre : le NOMBRE est passé sur
   le bouton « + », qui sert justement à en ajouter un.

   « +1 · 12 € » mêlait un décompte, qui ne demande rien, et une dette, qui
   demande d'encaisser — et le tout ne tenait pas à côté du nom sur un
   téléphone. La pastille passait à la ligne : la seule rangée portant une
   information de plus était celle qui se lisait le moins bien, parce qu'elle
   rompait l'alignement de toutes les autres. */
/* La seule pastille qui se touche : elle garde son cerne pour le dire. */
.inscrit__avec {
  flex: 0 0 auto;
  padding: 3px 9px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 22.6%) 87.8%);
  border-radius: 999px;
  background: hsl(var(--teinte) calc(var(--force) * 33.3%) 97.6%);
  font-family: var(--font-titre);
  font-size: 12px; font-weight: 600;
  color: var(--prune);
  cursor: pointer;
  min-height: 0;
}
.inscrit__avec--du { background: #FDF1DC; border-color: #EFDCB6; color: #7A5410; }
.inscrit__avec:focus-visible { outline: 2px solid var(--prune); outline-offset: 2px; }

.pastille--menue { width: 32px; height: 32px; }
.pastille--menue svg { width: 16px; height: 16px; }
.pastille--plus {
  font-family: var(--font-titre);
  font-size: 19px; font-weight: 600;
  line-height: 1;
  color: var(--prune);
}

/* Le nombre d'invités, posé sur le bouton qui sert à en ajouter. Il déborde du
   cercle : à l'intérieur il aurait fallu rétrécir le « + », qui est la cible
   qu'on vise. Le débordement est donc assumé, et la rangée lui laisse la place
   par son interligne — aucune hauteur de plus. */
.pastille--porte { position: relative; overflow: visible; }
.pastille__nombre {
  position: absolute;
  top: -3px; right: -3px;
  min-width: 16px; height: 16px;
  padding: 0 4px;
  border-radius: 999px;
  background: var(--prune);
  color: #fff;
  font-family: var(--font-titre);
  font-size: 10px; font-weight: 700;
  line-height: 16px;
  text-align: center;
}
/* Ambre quand il reste à encaisser : la même couleur que la pastille du
   montant, pour qu'on lise les deux comme une seule information. */
.pastille__nombre--du { background: #C8A24B; color: #3a2a12; }
/* ------------------------------------------------------------- où c'est */

/* Le nom d'une salle ne dit rien à qui n'y est jamais allé. Quand on connaît
   son adresse, il devient un bouton — et se donne l'air d'en être un. */
.fiche-seance__lieu--situe {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 4px 10px;
  width: 100%;
  padding: 4px 0;
  border: 0;
  background: none;
  text-align: left;
  cursor: pointer;
  font-family: inherit;
  font-size: inherit;
  color: hsl(var(--teinte) calc(var(--force) * 6.3%) 40.6%);
}
.fiche-seance__ou {
  font-family: var(--font-titre);
  font-size: 12px; font-weight: 600;
  font-style: normal;
  letter-spacing: .04em;
  color: var(--prune);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.fiche-seance__lieu--situe:hover .fiche-seance__ou { color: var(--corail); }
.fiche-seance__lieu--situe:focus-visible { outline: 2px solid var(--prune); outline-offset: 2px; }

.lieu__adresse {
  margin: 0 0 10px;
  font-size: 16px;
  color: hsl(var(--teinte) calc(var(--force) * 6.3%) 40.6%);
  text-wrap: pretty;
}
/* Le cadre vient de « carte-cadre » : on n'en règle ici que la hauteur. */
.lieu__carte { height: 230px; margin: 0; }

/* L'itinéraire s'ouvre dans l'application du téléphone : c'est elle qui sait
   où l'on est. Celle qui correspond à l'appareil vient en premier. */
.lieu__gestes {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  width: 100%;
  margin: 0 0 12px;
}
.lieu__geste {
  flex: 1 1 auto;
  padding: 11px 14px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 18.9%) 92.7%);
  border-radius: 10px;
  background: #fff;
  font-family: var(--font-titre);
  font-size: 14px; font-weight: 600;
  color: var(--prune);
  text-align: center;
  text-decoration: none;
}
.lieu__geste--premier {
  flex: 1 1 100%;
  padding: 14px;
  font-size: 15px;
  background: var(--jaune);
  border-color: var(--jaune);
  color: #4A3208;
}
.lieu__geste:hover { border-color: var(--prune); }

/* Une salle sans position ne montre ni carte ni itinéraire : on le signale là
   où l'on peut y remédier, plutôt que de laisser la découverte à l'usage. */
.saison-ligne__quand .puce { margin-left: 8px; vertical-align: middle; }

/* Les gestes d'un compte : ce qui agit plutôt que ce qui se lit. Sept rangées
   du même poids ne distinguaient pas « Coordonnées », qu'on vient consulter,
   de « Supprimer ce compte », qui efface tout. Quatre tuiles à la fin, dans la
   forme que les outils d'une séance ont déjà. */
.compte-gestes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(76px, 1fr));
  gap: 6px;
  width: 100%;
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid hsl(var(--teinte) calc(var(--force) * 18.9%) 92.7%);
}
.compte-gestes .outil { flex: none; }

/* La croix qui referme une feuille : toujours à la même place, toujours
   visible, et à la taille d'un pouce. Le seul geste visible était un
   « Fermer » en petit rouge tout en bas, qu'il fallait aller chercher. */
.feuille__fermer {
  flex: 0 0 auto;
  width: 44px; height: 44px;
  margin: -3px -4px 0 0;
  padding: 0;
  display: grid; place-items: center;
  border: 0;
  border-radius: 50%;
  background: hsl(var(--teinte) calc(var(--force) * 18.5%) 94.7%);
  color: hsl(var(--teinte) calc(var(--force) * 6.3%) 40.6%);
  cursor: pointer;
}
.feuille__fermer svg {
  width: 19px; height: 19px;
  fill: none; stroke: currentColor;
  stroke-width: 2; stroke-linecap: round;
}
.feuille__fermer:hover { background: hsl(var(--teinte) calc(var(--force) * 20%) 90.2%); color: var(--prune); }
.feuille__fermer:focus-visible { outline: 2px solid var(--prune); outline-offset: 2px; }

/* ------------------------------------------------------- demander, prévenir */

/* La boîte du navigateur ouvrait un rectangle gris hors charte, avec « OK »
   en bleu système. Une question qui engage quatre cent quinze euros mérite
   d'être posée dans la langue du site. */
.demande-voile {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: rgba(42, 34, 40, .42);
  backdrop-filter: blur(2px);
}
.demande {
  position: fixed;
  z-index: 61;
  left: 50%;
  top: 50%;
  width: min(420px, calc(100vw - 36px));
  max-height: 84vh;
  overflow-y: auto;
  padding: 20px 20px 16px;
  background: #fff;
  border-radius: 18px;
  box-shadow: 0 24px 60px -20px rgba(46, 37, 48, .55);
  transform: translate(-50%, -50%) scale(.96);
  opacity: 0;
  transition: transform .16s cubic-bezier(.2,.8,.3,1), opacity .16s ease;
}
.demande--montee { transform: translate(-50%, -50%) scale(1); opacity: 1; }
@media (prefers-reduced-motion: reduce) { .demande { transition: none; } }

/* Une question ne se pose pas en capitales : la règle générale des « h3 » les
   imposait, et « VALIDER L'ADHÉSION DE MARC BATAILLE ? » criait. */
.demande .demande__titre {
  margin: 0 0 10px;
  font-family: var(--font-titre);
  font-size: 19px; font-weight: 600;
  line-height: 1.25;
  letter-spacing: 0;
  text-transform: none;
  color: var(--prune);
  text-wrap: balance;
}
.demande__texte {
  margin: 0 0 10px;
  font-size: 17px;
  line-height: 1.45;
  color: hsl(var(--teinte) calc(var(--force) * 7.6%) 28.4%);
  text-wrap: pretty;
}
.demande__texte:last-of-type { margin-bottom: 16px; }

.demande__gestes {
  display: flex;
  flex-direction: column-reverse;
  gap: 8px;
}
.demande__bouton {
  width: 100%;
  min-height: 46px;
  padding: 12px 18px;
  border: 0;
  border-radius: 12px;
  background: var(--jaune);
  font-family: var(--font-titre);
  font-size: 15px; font-weight: 600;
  color: #4A3208;
  cursor: pointer;
}
.demande__bouton--second {
  background: none;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 20%) 90.2%);
  color: hsl(var(--teinte) calc(var(--force) * 6.3%) 40.6%);
}
.demande__bouton--rouge { background: #A8535E; color: #fff; }
.demande__bouton:focus-visible { outline: 2px solid var(--prune); outline-offset: 2px; }

/* ------------------------------------------- ce qui attend d'être validé */

/* Une demande d'adhésion attendait en silence : rien, dans le site, ne disait
   qu'il y en avait. La pastille se voit depuis n'importe quel écran, et son
   nombre dit s'il faut s'y mettre maintenant ou ce soir. */
.barre__onglet { position: relative; }
.barre__pastille {
  position: absolute;
  top: 2px;
  left: 50%;
  margin-left: 4px;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  display: grid;
  place-items: center;
  border-radius: 999px;
  background: var(--corail);
  color: #fff;
  font-family: var(--font-titre);
  font-size: 11px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  box-shadow: 0 0 0 2px #fff;
  pointer-events: none;
}

/* Une étiquette que l'œil n'a pas besoin de lire — le contenu du champ la dit
   déjà — mais qu'un lecteur d'écran doit entendre. */
.visuellement-cache {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ------------------------------------------------------ demander son adhésion */

/* Sur l'écran d'entrée, la plupart des gens n'ont pas encore de compte : c'est
   le geste le plus fréquent, et il tenait dans un lien de deux mots au bas de
   la page, sous « Mot de passe oublié ». Il prend la forme d'un bouton, à la
   largeur des autres — mais cerné et non jaune : se connecter reste le geste
   principal pour qui revient. */
/* Le bloc se détache sur un fond teinté : cerné d'un simple filet, il se
   lisait comme la fin de l'écran de connexion plutôt que comme une seconde
   proposition — or c'est ici que tout commence pour qui n'a pas de compte. */
.connexion__adhesion {
  margin-top: 24px;
  padding: 18px 16px 16px;
  border-radius: 16px;
  background: hsl(var(--teinte) calc(var(--force) * 46.7%) 97.1%);
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 27.7%) 90.8%);
  text-align: center;
}
.connexion__adhesion-mot {
  margin: 0 0 12px;
  font-family: var(--font-titre);
  font-size: 16px;
  font-weight: 600;
  color: hsl(var(--teinte) calc(var(--force) * 9.4%) 20.8%);
}

/* Blanc sur un fond presque blanc, ce bouton ne se lisait pas comme un
   bouton. Il se remplit — mais de prune, pas du jaune de « Se connecter » :
   deux gestes de même couleur se seraient lus comme le même geste, alors
   qu'ils s'adressent à deux personnes différentes. */
.espace .connexion__adhesion-bouton {
  width: 100%;
  min-height: 50px;
  padding: 14px 20px;
  border-radius: 30px;
  background: var(--prune) !important;
  color: #fff !important;
  border: none !important;
  box-shadow: 0 3px 10px -4px rgba(130, 85, 116, .65);
  font-family: var(--font-titre);
  font-size: 16px;
  font-weight: 600;
  letter-spacing: .3px;
  cursor: pointer;
}
.espace .connexion__adhesion-bouton:hover { background: #6F4763 !important; }
.espace .connexion__adhesion-bouton:focus-visible {
  outline: 2px solid var(--prune); outline-offset: 3px;
}
.connexion__adhesion-note {
  margin: 12px 0 0;
  font-size: 14px;
  color: hsl(var(--teinte) calc(var(--force) * 7.3%) 40.2%);
  text-wrap: pretty;
}
.connexion__adhesion-note a {
  color: var(--prune);
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* Ce qui manque à une demande, dans sa ligne de détail : la colonne de droite
   est prise par « Valider », et une pastille de plus y étranglait le nom. */
.ligne-membre__manque { color: #8F5321; font-weight: 600; }

/* Le bloc de gestes garde son air : posé après un message ou un champ, il ne
   doit pas s'y coller. */
.actions { margin-top: 4px; }
.message + .actions { margin-top: 0; }

/* Jusqu'à quand une place peut être rendue : dit sous le bouton, avant de
   réserver — pas au moment où il est trop tard. */
.fiche-seance__delai {
  margin: 6px 0 0;
  width: 100%;
  font-size: 14px;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
  text-wrap: pretty;
}

/* Le compte Instagram, au pied de l'espace : discret, mais présent partout —
   c'est là que vivent les nouvelles entre deux cours. */
.pied-instagram {
  margin: 26px 0 0;
  text-align: center;
}
.pied-instagram a {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 18px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 20%) 90.2%);
  border-radius: 999px;
  background: #fff;
  font-family: var(--font-titre);
  font-size: 14px;
  font-weight: 500;
  color: var(--prune);
  text-decoration: none;
}
.pied-instagram svg {
  width: 18px; height: 18px;
  fill: none; stroke: currentColor; stroke-width: 1.7;
}
.pied-instagram a:hover { border-color: var(--prune); background: hsl(var(--teinte) calc(var(--force) * 33.3%) 97.6%); }

/* ------------------------------------------- ce qui a été pris, en un coup d'œil

   La caisse disait ce qui était rentré sans jamais dire d'où ça venait : deux
   cents euros ne se lisent pas de la même façon selon qu'ils viennent d'un
   illimité ou de quatre cartes. Une barre partagée donne la forme — laquelle
   domine, laquelle est marginale — et les lignes donnent le chiffre, qu'une
   barre ne sait pas dire. */
.repartition { margin-top: 26px; }

.repartition__barre {
  display: flex;
  gap: 2px;
  height: 12px;
  margin: 4px 0 14px;
  border-radius: 6px;
  overflow: hidden;
}
.repartition__part {
  flex-basis: 0;
  /* Une part d'un seul abonnement reste visible à côté d'une part de trente. */
  min-width: 6px;
}

.repartition__ligne {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding: 8px 0;
  border-top: 1px solid hsl(var(--teinte) calc(var(--force) * 22.6%) 93.9%);
}
.repartition__quoi {
  display: flex;
  align-items: baseline;
  gap: 9px;
  min-width: 0;
}
.repartition__pastille {
  flex: 0 0 auto;
  width: 9px; height: 9px;
  border-radius: 3px;
  transform: translateY(-1px);
}
.repartition__nom {
  font-family: var(--font-titre);
  font-size: 15px; font-weight: 500;
  color: hsl(var(--teinte) calc(var(--force) * 10%) 15.7%);
}
.repartition__periode {
  display: block;
  font-size: 12px;
  font-style: normal;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
.repartition__chiffres {
  flex: 0 0 auto;
  display: flex;
  align-items: baseline;
  gap: 8px;
}
.repartition__nombre {
  font-family: var(--font-titre);
  font-size: 17px; font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--prune);
}
.repartition__part-mot {
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
  min-width: 34px;
  text-align: right;
}
.repartition__mot {
  margin: 12px 0 0;
  font-size: 14px;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}

/* Six tons tirés de la palette, du prune au sable : ils se distinguent les uns
   des autres sans qu'aucun crie plus fort que le reste de l'écran. */
.repartition__part--0, .repartition__pastille--0 { background: var(--prune); }
.repartition__part--1, .repartition__pastille--1 { background: #EC7069; }
.repartition__part--2, .repartition__pastille--2 { background: #FAB926; }
.repartition__part--3, .repartition__pastille--3 { background: #6E8FA8; }
.repartition__part--4, .repartition__pastille--4 { background: #B98BA6; }
.repartition__part--5, .repartition__pastille--5 { background: #C9A87C; }

/* ------------------------------------------ trouver quelqu'un parmi trois cents

   Une liste à la file cesse d'être navigable au-delà d'une trentaine de noms :
   à trois cents adhérents elle mesure trente-deux écrans. Rangée par initiale,
   avec un bandeau qui tient en haut et une réglette au bord droit, elle
   s'atteint d'un geste — celui des contacts d'un téléphone, que personne n'a
   besoin d'apprendre. */
#liste-membres { position: relative; }

.liste-membres__lettre {
  position: sticky;
  /* Sous l'entête, jamais dessous au sens propre : « .haut » colle à zéro avec
     un rang supérieur, et un bandeau calé au même endroit disparaîtrait
     derrière lui. La hauteur est mesurée, car elle varie. */
  top: var(--haut-hauteur, 56px);
  z-index: 2;
  margin: 0;
  padding: 5px 16px;
  background: hsl(var(--teinte) calc(var(--force) * 25%) 95.3%);
  border-top: 1px solid hsl(var(--teinte) calc(var(--force) * 21.7%) 91%);
  border-bottom: 1px solid hsl(var(--teinte) calc(var(--force) * 21.7%) 91%);
  font-family: var(--font-titre);
  font-size: 12px; font-weight: 700;
  letter-spacing: .12em;
  color: hsl(var(--teinte) calc(var(--force) * 7.3%) 40.2%);
}
.liste-membres__lettre:first-child { border-top: none; }

/* La réglette longe le bord droit, à hauteur du pouce. Elle ne défile pas avec
   la liste : on doit pouvoir sauter de A à V sans d'abord chercher la
   réglette. */
.reglette {
  position: fixed;
  right: 2px;
  top: 50%;
  transform: translateY(-50%);
  z-index: 20;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  padding: 6px 3px;
  border-radius: 999px;
  background: rgba(255, 255, 255, .82);
  backdrop-filter: blur(6px);
  box-shadow: 0 2px 10px -4px rgba(46, 37, 48, .35);
}
.reglette__lettre {
  /* Vingt-sept lettres à quarante-quatre pixels — la hauteur que la feuille
     impose à tout bouton — donnaient une réglette de mille cent quatre-vingts
     pixels sur un écran qui en fait six cent soixante : les extrémités étaient
     hors d'atteinte. Dix-huit pixels tiennent l'alphabet entier dans la
     hauteur disponible. C'est en deçà du seuil tactile habituel, et c'est
     assumé : une réglette d'index se parcourt du pouce le long du bord, elle
     ne se vise pas lettre à lettre. */
  width: 22px;
  height: 18px;
  padding: 0;
  border: 0;
  background: none;
  font-family: var(--font-titre);
  font-size: 10px;
  font-weight: 700;
  line-height: 18px;
  color: var(--prune);
  cursor: pointer;
}
.reglette__lettre:active { color: var(--corail); }
.reglette__lettre:focus-visible { outline: 2px solid var(--prune); outline-offset: 1px; }

/* La réglette recouvrirait la colonne de droite d'une rangée — les pastilles,
   le bouton « Valider ». On lui réserve sa gouttière.

   Le bloc des filtres, au-dessus, en avait besoin lui aussi : posée en fixe et
   centrée sur la hauteur, la réglette couvre le tiers médian de l'écran, et le
   bouton « Filtrer » passait à moitié dessous. */
#liste-membres .ligne-membre { padding-right: 26px; }
.filtres--reglette { padding-right: 26px; }

/* ------------------------------------------------------------- les profils

   Trois choix, chacun disant ce qu'il accorde. Une bascule à deux états
   suffisait quand il n'y avait que « adhérente » et « administration » ; à
   trois, il faut nommer et décrire, sinon on choisit à l'aveugle. */
.profil {
  display: block;
  width: 100%;
  margin-top: 8px;
  padding: 12px 14px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 20%) 90.2%);
  border-radius: 12px;
  background: #fff;
  text-align: left;
  cursor: pointer;
}
/* Le survol ne vaut qu'à la souris : sur un écran tactile, il reste collé
   après un toucher, et deux cartes paraissaient alors choisies — celle qu'on
   venait d'effleurer et le profil actuel. C'est ce qui rendait la liste
   illisible. */
@media (hover: hover) {
  .profil:hover { border-color: var(--prune); background: hsl(var(--teinte) calc(var(--force) * 33.3%) 97.6%); }
}

/* Le profil actuel n'est pas un choix : il se dessine comme un état. Un bord
   épais à gauche, un fond plein, et le nom en capitales — trois signes plutôt
   qu'une nuance de rose, parce qu'une nuance ne se voit pas au soleil. */
.profil--actuel {
  /* Trois côtés pâles et un bord épais à gauche : un cadre prune tout autour
     ne se distinguait pas d'un cadre gris au premier coup d'œil. */
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 23.3%) 85.7%);
  border-left: 5px solid var(--prune);
  background: hsl(var(--teinte) calc(var(--force) * 31.3%) 93.7%);
  cursor: default;
}
/* Le bouton est « disabled » — il n'y a rien à choisir sur son propre profil —
   et le navigateur grise alors le texte de sa propre autorité, chip comprise.
   On lui rend ses couleurs : ici, « désactivé » veut dire « c'est déjà le
   cas », pas « indisponible ». */
.profil--actuel:disabled { opacity: 1; -webkit-text-fill-color: currentColor; }
.profil--actuel .profil__nom {
  color: var(--prune);
  letter-spacing: .04em;
  text-transform: uppercase;
}
.profil--actuel .profil__quoi { color: hsl(var(--teinte) calc(var(--force) * 7.1%) 32.9%); }
.profil--actuel .profil__marque { -webkit-text-fill-color: #fff; }

/* Les autres sont des gestes : le chevron le dit, comme partout ailleurs dans
   l'application. */
.profil__aller {
  float: right;
  margin-left: 10px;
  font-family: var(--font-titre);
  font-size: 17px;
  font-weight: 600;
  color: hsl(var(--teinte) calc(var(--force) * 11.4%) 69%);
}
.profil:hover .profil__aller { color: var(--prune); }
.profil__nom {
  display: block;
  font-family: var(--font-titre);
  font-size: 15px; font-weight: 600;
  color: var(--prune);
}
.profil__quoi {
  display: block;
  margin-top: 2px;
  font-size: 14px;
  line-height: 1.35;
  color: hsl(var(--teinte) calc(var(--force) * 7.3%) 40.2%);
}
/* « Profil actuel » devient une étiquette pleine plutôt qu'une ligne grise :
   grise et en bas de carte, elle se lisait comme une note de pied de page. */
.profil__marque {
  display: inline-block;
  margin-top: 8px;
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--prune);
  color: #fff;
  font-family: var(--font-titre);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
}

/* ------------------------------------------------------- qui accède à quoi

   Une colonne par profil, une ligne par partie : le tableau se lit dans les
   deux sens — ce que ce profil ouvre, et qui ouvre cette partie. Une liste de
   cases par profil aurait demandé de comparer deux listes de mémoire. */
.droits {
  display: flex;
  flex-direction: column;
  margin-top: 4px;
}
.droits__ligne {
  display: grid;
  /* Trois colonnes de profils dans une feuille de 358 pixels : cinquante-deux
     chacune suffisent à une case de vingt et un, et laissent au nom de la
     partie de quoi tenir sur une ligne. */
  grid-template-columns: 1fr 52px 52px 52px;
  align-items: center;
  min-height: 42px;
  border-top: 1px solid hsl(var(--teinte) calc(var(--force) * 22.6%) 93.9%);
}
.droits__ligne--entete {
  min-height: 0;
  padding-bottom: 4px;
  border-top: 0;
}
.droits__quoi {
  font-family: var(--font-titre);
  font-size: 15px;
  font-weight: 500;
  color: hsl(var(--teinte) calc(var(--force) * 10%) 15.7%);
}
.droits__profil {
  font-family: var(--font-titre);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
  text-align: center;
}
.droits__case {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 42px;
  cursor: pointer;
}
.droits__case input {
  width: 21px; height: 21px;
  margin: 0;
  accent-color: var(--prune);
}
/* Une case qu'on ne peut pas décocher doit se voir comme telle, sans devenir
   illisible : c'est une règle, pas une panne. */
.droits__case input:disabled { opacity: .45; cursor: not-allowed; }

/* ------------------------------------------------------ écrire à sa coach

   Un fil, pas un chat : rien ne se rafraîchit tout seul, et les bulles se
   lisent de haut en bas comme une conversation qu'on relit. Ce qu'on a écrit
   soi-même se cale à droite — c'est la convention que tout le monde connaît,
   et elle évite d'avoir à nommer l'auteur de chaque ligne. */
.fil {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin: 4px 0 16px;
}
/* ----------------------------------------------------------------------------
   Une discussion se lit à la voix, pas au texte
   ----------------------------------------------------------------------------
   Les deux bulles étaient deux nuances du même rose pâle, dans la police de
   lecture : l'œil ne distinguait pas les voix, et l'écran paraissait fade parce
   qu'il ne racontait rien.

   Ce qu'on écrit prend l'accent de l'association, plein, en blanc. Ce qu'on
   reçoit reste blanc, cerclé, précédé de l'initiale de qui parle. C'est la
   convention que tout le monde a déjà dans l'œil, et elle se lit sans qu'on
   ait rien à apprendre.

   Les couleurs viennent de la palette : changer de palette change la
   discussion, comme le reste de l'espace. */
.fil { gap: 4px; }

.fil__rangee {
  display: flex;
  align-items: flex-end;
  gap: 8px;
  max-width: 100%;
}
.fil__rangee--moi { justify-content: flex-end; }

/* L'initiale de qui parle : on reconnaît la voix avant d'avoir lu. */
.fil__qui {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  margin-bottom: 2px;
  border-radius: 50%;
  background: var(--corail);
  color: #fff;
  font-family: var(--font-titre);
  font-size: 12px;
  font-weight: 700;
}

.fil__jour {
  margin: 12px 0 6px;
  text-align: center;
  font-family: var(--font-titre);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
.fil__jour:first-child { margin-top: 0; }

.fil__mot {
  max-width: 82%;
  padding: 10px 13px;
  border-radius: 16px 16px 16px 4px;
  background: #fff;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 16%) 89%);
}
.fil__mot--moi {
  border-radius: 16px 16px 4px 16px;
  background: var(--prune);
  border: 0;
}
.fil__texte {
  margin: 0;
  font-family: var(--font-titre);
  font-size: 15px;
  line-height: 1.45;
  color: hsl(var(--teinte) calc(var(--force) * 10%) 15.7%);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.fil__mot--moi .fil__texte { color: #fff; }
.fil__quand {
  display: block;
  margin-top: 4px;
  font-family: var(--font-titre);
  font-size: 11px;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
.fil__mot--moi .fil__quand { text-align: right; color: rgba(255, 255, 255, .72); }

/* « ✓ lu » se pose après l'heure, sur la même ligne : une ligne de plus sous
   chaque bulle aurait allongé le fil d'un tiers pour deux caractères. Il est
   plus pâle que l'heure — c'est une confirmation, pas une information qu'on
   vient chercher. */
.fil__vu {
  margin-left: 8px;
  color: var(--prune);
  opacity: .75;
  white-space: nowrap;
}
/* Sur fond plein, la coche se lit en blanc atténué : le prune sur prune la
   faisait disparaître. */
.fil__mot--moi .fil__vu { color: rgba(255, 255, 255, .9); opacity: 1; }
/* « pas encore lu » : plus discret que la coche, c'est une attente, pas une
   confirmation. */
.fil__mot--moi .fil__vu--attente { color: rgba(255, 255, 255, .7); font-style: italic; }

#form-message textarea {
  width: 100%;
  padding: 11px 12px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 12.9%) 87.8%);
  border-radius: 12px;
  /* Sous seize pixels, Safari zoome à la mise au point et l'on ne ressort du
     champ qu'en faisant défiler la page de côté. */
  font-size: 16px;
  font-family: inherit;
  line-height: 1.4;
  resize: vertical;
}
#form-message textarea:focus-visible {
  outline: 2px solid var(--prune);
  outline-offset: 1px;
}

/* ------------------------------------------- une puce qui est aussi un geste

   Le certificat se note d'un toucher plutôt qu'en traversant l'engrenage, le
   panneau des coordonnées et un champ de date. La puce dit l'état et le change
   — elle doit donc se voir comme touchable, sans devenir un bouton de plus
   dans un écran qui en compte déjà. */
.puce--geste {
  border: 1px solid transparent;
  cursor: pointer;
  font: inherit;
  font-family: var(--font-titre);
  font-size: 12px;
  font-weight: 600;
  /* La règle générale impose quarante-quatre pixels à tout bouton : une puce
     n'en veut pas, elle vit dans une ligne de texte. */
  min-height: 0;
}
.puce--geste:hover { border-color: currentColor; }
.puce--geste:focus-visible { outline: 2px solid var(--prune); outline-offset: 2px; }
.puce--geste:disabled { opacity: .5; cursor: wait; }

.puce--vert {
  background: #EDF5F1;
  color: #2E6B52;
}

/* La liste d'attente, sous les inscrits : les mêmes rangées, en plus discret —
   ce ne sont pas des places prises, mais des places espérées. */
.inscrit--attente { opacity: .8; }

/* Le rang tient sa largeur : sans cela il se serrait, et le nom passait
   dessous. L'écart vient de la rangée, pas d'une marge qui s'y ajoutait. */
.inscrit__rang {
  flex: 0 0 auto;
  display: inline-grid;
  place-items: center;
  width: 20px; height: 20px;
  border-radius: 50%;
  background: hsl(var(--teinte) calc(var(--force) * 18.5%) 94.7%);
  font-family: var(--font-titre);
  font-size: 11px; font-weight: 700;
  color: var(--prune);
}

/* ============================================================================
   L'apparence de l'association
   ----------------------------------------------------------------------------
   Le nom à côté du logo, le logo lui-même, et le choix des couleurs. Les
   pastilles de palette portent leurs couleurs en dur, dans l'attribut « style »
   : ce sont des échantillons, elles doivent montrer les cinq accords côte à
   côte quelle que soit la palette en cours — une pastille qui suivrait le thème
   ne montrerait que le thème.
   ========================================================================== */

.espace__nom {
  flex: 0 1 auto;
  min-width: 0;
  margin-left: -10px;
  font-family: var(--font-titre);
  font-size: 16px;
  font-weight: 600;
  color: var(--prune);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Sur un écran étroit, le bandeau porte déjà le logo, l'adresse et le menu.
   Le nom est le seul des quatre qu'on peut lire ailleurs — il cède la place. */
@media (max-width: 430px) { .espace__nom { display: none; } }

.apercu-logo {
  display: flex;
  align-items: center;
  gap: 14px;
  margin: 10px 0 0;
}
.apercu-logo img {
  width: 56px;
  height: 56px;
  object-fit: contain;
  padding: 6px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 13%) 88.2%);
  border-radius: 12px;
  background: #fff;
}

.palettes { margin-top: 18px; }
.palettes__titre {
  display: block;
  margin-bottom: 8px;
  font-family: var(--font-titre);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: hsl(var(--teinte) calc(var(--force) * 6%) 45.1%);
}
.palettes__grille {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(96px, 1fr));
  gap: 8px;
}
.palette {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 7px;
  padding: 8px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 13%) 88.2%);
  border-radius: 12px;
  background: #fff;
  cursor: pointer;
}
/* Choisie : un liseré plein, pas seulement une bordure un peu plus foncée.
   Une sélection qui ne se voit qu'en comparant deux bordures ne se voit pas. */
.palette--choisie {
  border-color: var(--prune);
  box-shadow: 0 0 0 1.5px var(--prune);
}
.palette__bandes {
  display: flex;
  height: 26px;
  border-radius: 7px;
  overflow: hidden;
}
.palette__bande { flex: 1; }
/* Le geste occupe moins de place que les deux accents : c'est sa proportion
   sur un écran, et l'échantillon ment moins ainsi. */
.palette__bande:last-child { flex: .55; }
.palette__nom {
  font-family: var(--font-titre);
  font-size: 13px;
  font-weight: 600;
  color: hsl(var(--teinte) calc(var(--force) * 7%) 27.1%);
}

/* La confirmation : une pastille à côté du bouton, jamais une ligne de texte
   nue qui écarte ce qui l'entoure. Elle s'efface d'elle-même — c'est pourquoi
   elle est posée dans la rangée des gestes, où sa disparition ne remonte rien.
   L'erreur porte les mêmes formes mais reste : on doit pouvoir la relire. */
.reglage__mot--ok,
.reglage__mot--erreur {
  margin: 0;
  padding: 6px 12px;
  border-radius: 999px;
  font-family: var(--font-titre);
  font-size: 13px;
  font-weight: 600;
  transition: opacity .35s ease;
}
.reglage__mot--ok {
  background: #E8F0EA;
  color: #2C5C3C;
}
.reglage__mot--ok::before { content: '✓ '; }
.reglage__mot--erreur {
  background: #FBE7E6;
  color: #97302A;
  /* Une erreur peut être longue : elle prend la ligne plutôt que de serrer le
     bouton contre le bord. */
  flex: 1 1 100%;
}
.reglage__mot--part { opacity: 0; }
@media (prefers-reduced-motion: reduce) { .reglage__mot--ok { transition: none; } }

/* ============================================================================
   Les places tenues pour des externes
   ----------------------------------------------------------------------------
   Elles vivent sous la liste des inscrits, mais ne lui ressemblent pas : ce ne
   sont pas des personnes, ce sont des places. Un liseré en pointillés le dit —
   la même convention que la zone « choisir une photo » : quelque chose qui
   occupe la place sans être encore rempli.
   ========================================================================== */
.externes {
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px solid hsl(var(--teinte) calc(var(--force) * 19%) 93%);
}
.externe {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 9px 12px;
  margin-bottom: 6px;
  border: 1px dashed hsl(var(--teinte) calc(var(--force) * 16%) 84%);
  border-radius: 10px;
  background: hsl(var(--teinte) calc(var(--force) * 27%) 98%);
}
.externe__gauche { display: flex; flex-direction: column; min-width: 0; }
.externe__nombre {
  font-family: var(--font-titre);
  font-size: 15px;
  font-weight: 600;
  color: var(--prune);
}
.externe__mot {
  font-family: var(--font-titre);
  font-size: 13px;
  color: hsl(var(--teinte) calc(var(--force) * 6%) 45%);
}
.externe__rendre {
  flex: none;
  padding: 6px 12px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 16%) 84%);
  border-radius: 999px;
  background: #fff;
  font-family: var(--font-titre);
  font-size: 13px;
  font-weight: 600;
  color: #A8535E;
  cursor: pointer;
}
.externe__tenir {
  width: 100%;
  margin-top: 4px;
  padding: 10px;
  border: 1px dashed hsl(var(--teinte) calc(var(--force) * 16%) 84%);
  border-radius: 10px;
  background: #fff;
  font-family: var(--font-titre);
  font-size: 14px;
  font-weight: 600;
  color: var(--prune);
  cursor: pointer;
}
.externe__tenir:disabled {
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
  cursor: default;
}

/* Les vues, dans le menu du compte : une par profil. Elles s'empilent comme
   les autres liens du menu, mais leur groupe se détache — ce ne sont pas des
   destinations, ce sont des lunettes qu'on chausse. */
.vues { display: flex; flex-direction: column; }

/* ============================================================================
   Plusieurs dates dans un même formulaire
   ----------------------------------------------------------------------------
   Chaque ligne est une séance de plus : une date, une heure, une croix pour la
   retirer. Elles s'alignent sous la première paire, dont elles sont la suite —
   d'où le retrait à gauche, qui les rattache visuellement à ce qui précède.
   ========================================================================== */
.dates-plus { display: flex; flex-direction: column; gap: 8px; }
.date-plus {
  display: flex;
  align-items: center;
  gap: 8px;
  padding-left: 14px;
  border-left: 2px solid hsl(var(--teinte) calc(var(--force) * 19%) 93%);
}
.date-plus input {
  flex: 1 1 0;
  min-width: 0;
  padding: 9px 10px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 12.9%) 87.8%);
  border-radius: 8px;
  background: #fff;
  font-family: var(--font-titre);
  font-size: 15px;
  color: hsl(var(--teinte) calc(var(--force) * 7%) 27.1%);
}
.date-plus__oter {
  flex: none;
  width: 32px;
  height: 32px;
  border: 0;
  border-radius: 50%;
  background: none;
  font-family: var(--font-titre);
  font-size: 20px;
  line-height: 1;
  color: hsl(var(--teinte) calc(var(--force) * 6%) 45.1%);
  cursor: pointer;
}
.date-plus__oter:hover { background: hsl(var(--teinte) calc(var(--force) * 19%) 93%); }
.date-plus__ajouter {
  align-self: flex-start;
  padding: 7px 0;
  border: 0;
  background: none;
  font-family: var(--font-titre);
  font-size: 14px;
  font-weight: 600;
  color: var(--prune);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}

/* Qui anime la séance, sous le lieu. Le serveur ne l'envoie qu'à partir de
   deux coachs dans l'association : avec une seule, ce serait neuf fois la même
   information sur un planning de neuf lignes. */
.fiche-seance__coach {
  margin: 2px 0 0;
  font-family: var(--font-titre);
  font-size: 14px;
  color: hsl(var(--teinte) calc(var(--force) * 6%) 45.1%);
}

/* À la place du bouton, sur son propre cours. Un vide se confondrait avec un
   cours qu'on ne peut pas réserver ; un mot dit ce qui se passe. */
.fiche-seance__anime {
  margin: 14px 0 0;
  padding: 11px 14px;
  border-radius: 10px;
  background: hsl(var(--teinte) calc(var(--force) * 19%) 93%);
  font-family: var(--font-titre);
  font-size: 15px;
  font-weight: 600;
  color: var(--prune);
  text-align: center;
}

/* La liste des coachs, dans les réglages. Une ligne par personne : son nom,
   son profil, et combien de cours elle anime — le seul chiffre qui compte
   avant de lui retirer l'encadrement. */
.coach {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  padding: 11px 12px;
  margin-bottom: 6px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 12.9%) 87.8%);
  border-radius: 10px;
  background: #fff;
  text-align: left;
  cursor: pointer;
}
.coach:hover { background: hsl(var(--teinte) calc(var(--force) * 27%) 98%); }
.coach:focus-visible { outline: 2px solid var(--prune); outline-offset: 2px; }
.coach__gauche { display: flex; flex-direction: column; min-width: 0; }
.coach__nom {
  font-family: var(--font-titre);
  font-size: 15px;
  font-weight: 600;
  color: hsl(var(--teinte) calc(var(--force) * 7%) 27.1%);
}
.coach__mot {
  font-family: var(--font-titre);
  font-size: 13px;
  color: hsl(var(--teinte) calc(var(--force) * 6%) 45.1%);
}
.coach__fleche {
  flex: none;
  font-family: var(--font-titre);
  font-size: 20px;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}

/* Le champ de désignation prend un peu d'air : il suit une liste, il n'en
   fait pas partie. */
#ajout-coach { margin-top: 14px; }

/* ============================================================================
   Le calendrier de plage
   ----------------------------------------------------------------------------
   Sept colonnes égales, des cases carrées, et la plage colorée d'un bout à
   l'autre. Les deux extrémités sont pleines, ce qu'il y a entre elles est
   teinté : on lit la durée d'un regard sans compter les jours.

   Les cases font quarante pixels de côté au minimum — c'est la taille d'un
   pouce, et c'est le seul chiffre qui compte sur un calendrier qu'on touche.
   ========================================================================== */
.calendrier {
  margin-top: 4px;
  padding: 10px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 12.9%) 87.8%);
  border-radius: 14px;
  background: #fff;
}
.calendrier__tete {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 8px;
}
.calendrier__mois {
  font-family: var(--font-titre);
  font-size: 16px;
  font-weight: 600;
  color: var(--prune);
}
.calendrier__tourner {
  width: 38px;
  height: 38px;
  flex: none;
  border: 0;
  border-radius: 50%;
  background: none;
  font-family: var(--font-titre);
  font-size: 22px;
  line-height: 1;
  color: var(--prune);
  cursor: pointer;
}
.calendrier__tourner:hover { background: hsl(var(--teinte) calc(var(--force) * 19%) 93%); }
.calendrier__tourner:focus-visible { outline: 2px solid var(--prune); outline-offset: 1px; }

.calendrier__grille {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 2px 0;
}
.calendrier__jour-nom {
  padding: 4px 0 6px;
  text-align: center;
  font-family: var(--font-titre);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .04em;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
.calendrier__vide { min-height: 40px; }
.calendrier__jour {
  min-height: 40px;
  border: 0;
  background: none;
  font-family: var(--font-titre);
  font-size: 15px;
  color: hsl(var(--teinte) calc(var(--force) * 7%) 27.1%);
  cursor: pointer;
}
.calendrier__jour:focus-visible { outline: 2px solid var(--prune); outline-offset: -2px; }
/* Aujourd'hui : un point sous le chiffre, pas un cercle — un cercle se
   confondrait avec une extrémité de plage. */
.calendrier__jour--aujourdhui { font-weight: 700; text-decoration: underline; text-underline-offset: 3px; }

.calendrier__jour--dedans { background: hsl(var(--teinte) calc(var(--force) * 31%) 94%); }
.calendrier__jour--bout {
  background: var(--prune);
  color: #fff;
  font-weight: 600;
}
/* Les coins arrondis n'existent qu'aux extrémités : la plage se lit alors
   comme un ruban, et non comme une suite de pastilles. */
.calendrier__jour--premier { border-radius: 20px 0 0 20px; }
.calendrier__jour--dernier { border-radius: 0 20px 20px 0; }
.calendrier__jour--seul    { border-radius: 20px; }
/* Hors de portée — avant aujourd'hui, après la fin de saison : le chiffre
   pâlit et ne répond pas. Grisé ici, il serait refusé par le serveur. */
.calendrier__jour:disabled {
  color: hsl(var(--teinte) calc(var(--force) * 6%) 76%);
  cursor: default;
}

/* Le calendrier d'un seul jour.
   Le champ natif reste, caché — mais pas par « display: none », qui l'ôterait
   du clavier et des lecteurs d'écran : il porte la valeur, et un navigateur
   sans JavaScript le garde. Un seul mois est dessiné, et son nom vit dans le
   bandeau : celui de la grille ferait doublon. */
.espace input.calendrier__valeur {
  position: absolute;
  width: 1px; height: 1px; min-height: 0;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  border: 0;
}
.calendrier--jour .calendrier__mois-nom { display: none; }
.calendrier--jour .calendrier__jour { min-height: 42px; }

/* Replié : un bouton qui a l'air d'un champ et qui dit le jour — « mardi 7
   septembre 2026 » — avec un petit calendrier à droite pour qu'on sache qu'il
   s'ouvre. Il prend exactement la place du champ natif qu'il remplace,
   dans les deux familles de formulaires. */
.calendrier__bouton {
  position: relative;
  display: block;
  width: 100%;
  min-width: 0;
  margin-top: 5px;
  padding: 10px 40px 10px 12px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 12.9%) 87.8%);
  border-radius: 8px;
  background: #fff;
  font-family: var(--font-titre);
  font-size: 16px;
  font-weight: 400;
  text-align: left;
  line-height: 1.3;
  color: hsl(var(--teinte) calc(var(--force) * 10%) 15.7%);
  cursor: pointer;
}
/* L'icône est un masque teinté par la charte : un dessin figé dans l'image
   garderait le prune sur les thèmes brun et bleu. */
.calendrier__bouton::after,
.calendrier__liste-coque::after {
  --calendrier-icone: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 20 20' fill='none' stroke='black' stroke-width='1.6' stroke-linecap='round'><rect x='2.5' y='4' width='15' height='13' rx='2.5'/><path d='M2.5 8.5h15M6.5 2.5v3M13.5 2.5v3'/></svg>");
  --chevron-icone: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'><path d='M1 1l4 4 4-4' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round'/></svg>");
}
.calendrier__bouton::after {
  content: '';
  position: absolute;
  right: 12px; top: 50%;
  width: 20px; height: 20px;
  margin-top: -10px;
  background: var(--prune);
  -webkit-mask: var(--calendrier-icone) no-repeat center / 20px 20px;
  mask: var(--calendrier-icone) no-repeat center / 20px 20px;
}
.calendrier__bouton--vide { color: hsl(var(--teinte) calc(var(--force) * 6%) 55%); }
.calendrier__bouton:focus-visible { outline: 2px solid var(--jaune); outline-offset: 1px; }
.calendrier__bouton[aria-expanded="true"] { border-color: var(--prune); }
.feuille__champ .calendrier__bouton { margin-top: 3px; padding-top: 11px; padding-bottom: 11px; border-radius: 10px; }
.caisse__champ .calendrier__bouton { margin-top: 3px; padding: 10px 34px 10px 11px; border-radius: 9px; }
.caisse__champ .calendrier__bouton::after { right: 9px; }
.feuille__champ .calendrier__bouton:focus-visible { outline-color: var(--prune); }
.calendrier__coque .calendrier,
.feuille__duo + .calendrier--jour,
.caisse__duo + .calendrier--jour,
.date-plus + .calendrier--jour { margin-top: 6px; }
/* Sur un écran large, la grille des champs a deux colonnes : un calendrier
   ouvert prend la ligne entière plutôt que de se serrer dans la sienne. */
.champs label:has(.calendrier--jour:not([hidden])) { grid-column: 1 / -1; }
/* Dans une ligne « date · heure · retirer », le bouton prend la part du champ
   qu'il remplace. */
.date-plus .calendrier__coque { flex: 1 1 0; min-width: 0; }
.date-plus .calendrier__bouton { margin-top: 0; padding: 9px 34px 9px 10px; font-size: 15px; }
.date-plus .calendrier__bouton::after { right: 8px; }

/* La tête en listes : le mois et l'année se choisissent d'un coup, pour les
   dates qu'on n'atteint pas flèche par flèche. Les listes gardent l'air du
   titre — même police, même couleur — avec juste un petit chevron. */
.calendrier__mois--listes { display: flex; gap: 4px; }
/* Le sélecteur pèse plus que « .champs select » et « .feuille__champ select »,
   qui habillent les listes d'un formulaire en champs bordés : ici la liste
   est un titre. */
.espace select.calendrier__liste {
  -webkit-appearance: none;
  appearance: none;
  display: inline-block;
  width: auto;
  margin: 0;
  border: 0;
  border-radius: 8px;
  padding: 6px 20px 6px 8px;
  background: transparent;
  font-family: var(--font-titre);
  font-size: 16px;
  font-weight: 600;
  color: var(--prune);
  min-height: 0;
}
/* Un « select » ne porte pas de pseudo-élément : le chevron se pose sur la
   coque qui l'entoure, et ne gêne pas le toucher. */
.calendrier__liste-coque { position: relative; display: inline-block; }
.calendrier__liste-coque::after {
  content: '';
  position: absolute;
  right: 4px; top: 50%;
  width: 10px; height: 6px;
  margin-top: -3px;
  pointer-events: none;
  background: var(--prune);
  -webkit-mask: var(--chevron-icone) no-repeat center / 10px 6px;
  mask: var(--chevron-icone) no-repeat center / 10px 6px;
}
.espace select.calendrier__liste:focus { outline: 2px solid var(--prune); outline-offset: 1px; }
@media (hover: hover) {
  .calendrier__jour:hover:not(.calendrier__jour--bout) {
    background: hsl(var(--teinte) calc(var(--force) * 27%) 96%);
  }
}

/* Deux mois l'un sous l'autre : le nom de chacun au-dessus de sa grille, le
   bandeau du haut portant la paire. Sans ce rappel, on ne saurait plus lequel
   des deux on regarde en descendant. */
.calendrier__mois-bloc + .calendrier__mois-bloc { margin-top: 14px; }
.calendrier__mois-nom {
  display: block;
  margin-bottom: 2px;
  font-family: var(--font-titre);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
.calendrier__mois { font-size: 15px; }

/* La phrase sous le calendrier : elle dit où l'on en est du geste — premier
   jour touché, plage complète — et combien de jours cela fait. */
.reglage__mot--plage {
  margin: 8px 0 0;
  font-family: var(--font-titre);
  font-size: 14px;
  font-weight: 500;
  color: var(--prune);
}

/* ============================================================================
   La règle des deux polices
   ----------------------------------------------------------------------------
   L'espace en emploie deux, et jusqu'ici sans règle : le corps de page est en
   Cormorant, si bien que TOUT ce dont la feuille ne disait rien y retombait —
   « 67 % » au milieu d'un écran de caisse, « Salle des fêtes d'Odeillo » sous un
   intitulé en Jost. Le serif n'était presque jamais choisi ; il était hérité.

   La règle, désormais :

     Jost        pour ce qui se manipule ou se compte — intitulés, chiffres,
                 étiquettes, boutons, lignes de liste.
     Cormorant   pour ce qui se lit — les phrases, les explications, les mots
                 qu'Agnès écrit aux adhérents.

   Ce qui suit rattrape les endroits où le serif s'était installé par défaut. Un
   élément qui porte une donnée y figure ; un élément qui porte une phrase, non.
   ========================================================================== */

/* Des données, pas des phrases : elles se scannent, elles ne se lisent pas. */
.bloc-cours__nom,
.fiche-seance__lieu,
.outil__portee,
.venir-avec__mot,
.ligne-membre__detail,
.cours-ligne__sous,
.ligne-du__sous,
.caisse-bilan__legende,
.caisse-tete__quoi,
.repartition__mot,
.repartition__part-mot,
.resume__note {
  font-family: var(--font-titre);
}

/* Les chiffres qui se comparent d'une ligne à l'autre s'alignent en colonne :
   sans cela, « 1 170 € » et « 415 € » ne tombent pas l'un sous l'autre. */
.repartition__part-mot,
.ligne-du__sous,
.caisse-tete__quoi {
  font-variant-numeric: tabular-nums;
}

/* Restent en serif, et c'est voulu : ce sont des phrases.
   .admin__aide · .semaine-vide__mot · .resume__chiffre · .chargement */

/* ============================================================================
   La fiche d'une séance : l'heure en vedette
   ----------------------------------------------------------------------------
   Elle tenait sur cinq lignes empilées — date, intitulé, salle, coach, « Je
   viens accompagné(e) » — dont chacune disait peu et prenait autant de place
   que les autres.

   L'heure passe à gauche, en gros : c'est ce qu'on cherche quand on hésite
   entre deux cours. Le reste se range à sa droite, sur deux lignes. Le
   compteur d'accompagnants rejoint le bouton.
   ========================================================================== */
.fiche-seance__corps {
  display: flex;
  align-items: flex-start;
  gap: 14px;
}
.fiche-seance__quand {
  flex: 0 0 auto;
  padding-right: 14px;
  border-right: 1px solid hsl(var(--teinte) calc(var(--force) * 19%) 93%);
  text-align: center;
}
.fiche-seance__heure {
  display: block;
  font-family: var(--font-titre);
  font-size: 24px;
  font-weight: 700;
  line-height: 1;
  color: var(--prune);
  font-variant-numeric: tabular-nums;
}
.fiche-seance__jour {
  display: block;
  margin-top: 4px;
  font-family: var(--font-titre);
  font-size: 13px;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
  white-space: nowrap;
}
/* La colonne de droite doit pouvoir se rétrécir : sans « min-width: 0 », un
   nom de salle long — « Salle des fêtes de La Cabanasse » — pousserait la
   carte hors de l'écran au lieu de passer à la ligne. */
.fiche-seance__droite { flex: 1 1 auto; min-width: 0; }

/* La salle et le coach sur une seule ligne. Le nom de la classe évite
   « fiche-seance__ou », qui servait déjà au lien « où est-ce ? » — deux règles
   sous le même nom soulignaient tout le paragraphe. */
.fiche-seance__contexte {
  margin: 3px 0 0;
  font-family: var(--font-titre);
  font-size: 15px;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
  text-wrap: pretty;
}
.fiche-seance__contexte .fiche-seance__lieu {
  display: inline;
  font-size: inherit;
  padding: 0;
}
/* Seul le nom de la salle est souligné : ce qui suit n'est pas touchable. */
.fiche-seance__avec { color: inherit; text-decoration: none; }

/* L'intitulé et les places sur la même ligne : l'intitulé se rétrécit et passe
   à la ligne s'il le faut, la pastille garde sa place à droite. */
.fiche-seance__rang { align-items: flex-start; }
.fiche-seance__rang .fiche-seance__cours { flex: 1 1 auto; min-width: 0; }
.fiche-seance__rang .places { flex: 0 0 auto; }

/* Le nom de la salle, devenu le seul repère touchable de sa ligne, porte
   lui-même le soulignement — c'est ce qui disait « on peut me toucher », et
   qui vivait jusqu'ici sur le « où est-ce ? » que la ligne a perdu. */
.fiche-seance__contexte .fiche-seance__lieu--situe {
  display: inline;
  width: auto;
  padding: 0;
  text-decoration: underline;
  text-decoration-color: rgba(130, 85, 116, .45);
  text-underline-offset: 3px;
}
.fiche-seance__contexte .fiche-seance__lieu--situe:hover {
  text-decoration-color: var(--prune);
}

/* L'intitulé garde la pastille à sa droite : sans « nowrap » sur la rangée,
   un titre long la renvoyait seule à la ligne suivante, et la fiche gagnait
   une ligne pour rien. */
.fiche-seance__corps .fiche-seance__rang {
  flex-wrap: nowrap;
  align-items: baseline;
  gap: 10px;
}
.fiche-seance__corps .fiche-seance__cours { overflow-wrap: anywhere; }

/* L'intitulé dans la colonne de droite : dix-neuf pixels et non vingt-deux.
   La colonne a perdu la largeur de l'heure ; à vingt-deux, « Yoga mobilité »
   passait à la ligne et rendait la fiche plus haute qu'avant le resserrage. */
.fiche-seance__corps .fiche-seance__cours { font-size: 19px; }

/* Le survol laisse une pastille grise sur un écran tactile, où le doigt « reste
   au-dessus » après avoir touché. On ne l'allume que là où un vrai pointeur
   existe. */

/* ============================================================================
   L'annonce d'un atelier, dans le fil des informations
   ----------------------------------------------------------------------------
   Deux formes pour une même carte, choisies sur ce qu'on a et non sur un
   réglage : avec photo c'est une affiche, l'image en tête ; sans photo c'est
   une carte à date, la date en colonne comme dans le planning.
   ========================================================================== */
.info--annonce {
  padding: 0;
  overflow: hidden;
  border-left: 0;
}
.annonce__image {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
}
.annonce__corps { padding: 14px 16px 16px; }

.annonce__tete { display: flex; align-items: flex-start; gap: 14px; }
.annonce__droite { flex: 1 1 auto; min-width: 0; }

/* La colonne de date, quand il n'y a pas de photo. */
.annonce__date {
  flex: 0 0 auto;
  padding-right: 14px;
  text-align: center;
  border-right: 1px solid hsl(var(--teinte) calc(var(--force) * 19%) 93%);
}
.annonce__j {
  display: block;
  font-family: var(--font-titre);
  font-size: 24px;
  font-weight: 700;
  line-height: 1;
  color: var(--prune);
}
.annonce__m {
  display: block;
  margin-top: 3px;
  font-family: var(--font-titre);
  font-size: 13px;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}

/* L'étiquette dit la nature avant qu'on lise le titre : c'est ce qui distingue
   une invitation d'une nouvelle ordinaire. */
.annonce__marque {
  /* « flex » et non « inline-flex ».
     --------------------------------------------------------------------------
     Une boîte en ligne s'assied sur une ligne de base et porte son interligne
     au-dessus d'elle : l'étiquette descendait de quelques pixels et ne
     s'alignait plus avec le « 17 » de la colonne d'à côté, alors que les deux
     partent du même bord. En bloc, elle commence là où commence sa colonne.
     « max-content » l'empêche de s'étirer sur toute la largeur. */
  display: flex;
  width: max-content;
  max-width: 100%;
  align-items: center;
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--prune);
  color: #fff;
  font-family: var(--font-titre);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
}
/* « .espace .annonce__titre » et non « .annonce__titre » seul.
   ----------------------------------------------------------------------------
   « .espace h3 » pèse (0,1,1) et l'emportait sur (0,1,0) : la marge écrite ici
   n'a jamais rien fait, et c'est « margin: 0 0 10px » qui s'appliquait. Le
   titre venait donc coller le pourtour de l'étiquette au-dessus de lui. Une
   classe de plus reprend la main. */
.espace .annonce__titre {
  margin: 12px 0 3px;
  font-family: var(--font-titre);
  font-size: 20px;
  font-weight: 700;
  line-height: 1.2;
  color: var(--prune);
  text-wrap: balance;
}
.annonce__quand {
  margin: 0;
  font-family: var(--font-titre);
  font-size: 15px;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
  text-wrap: pretty;
}
.annonce__texte {
  margin: 12px 0 0;
  font-size: 17px;
  color: hsl(var(--teinte) calc(var(--force) * 7.2%) 27.1%);
  text-wrap: pretty;
}

/* Le geste, et ce qu'il reste de places à côté. */
.annonce__geste {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 14px;
}
.annonce__geste .bouton-reserver {
  flex: 1 1 auto;
  min-width: 0;
  height: 46px;
  white-space: nowrap;
}
.annonce__reste {
  flex: 0 0 auto;
  font-family: var(--font-titre);
  font-size: 14px;
  white-space: nowrap;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
.info--annonce .info__actions { padding: 0 16px 14px; }

/* ============================================================================
   Le champ de saisie reste au bas de l'écran
   ----------------------------------------------------------------------------
   Dans une discussion, on écrit après avoir lu : le champ doit être là où le
   pouce l'attend, pas à la fin d'un fil qu'il faut d'abord dérouler. C'est la
   convention de toutes les messageries, et son absence se remarque.

   « sticky » et non « fixed » : le champ reste dans le flux, donc il ne
   recouvre rien tant que la page tient à l'écran, et il ne sort pas de la
   largeur de la carte. Il se cale au-dessus de la barre d'onglets, dont on
   reprend la hauteur.
   ========================================================================== */
/* Le champ de saisie est ancré au bas de l'écran, comme dans toute messagerie.
   ----------------------------------------------------------------------------
   « sticky » avait été mon premier réflexe : il ne colle qu'à l'intérieur de son
   conteneur, et tant que la carte s'arrêtait au-dessus du bas de l'écran, le
   champ n'avait rien à quoi se coller. Étirer la carte à la hauteur de la vue
   marchait presque — mais la hauteur du bandeau varie quand on défile, et le
   calcul restait approximatif de quelques dizaines de pixels.

   « fixed » ne dépend de rien : il se pose au-dessus de la barre d'onglets, un
   point c'est tout. Le prix à payer est de réserver la place sous le fil pour
   que la dernière bulle ne passe pas dessous — cette hauteur est MESURÉE au
   chargement, pas devinée. */
#form-message {
  position: fixed;
  left: 0;
  right: 0;
  bottom: calc(64px + env(safe-area-inset-bottom, 0px));
  z-index: 15;
  margin: 0;
  padding: 12px 20px 14px;
  background: #fff;
  border-top: 1px solid hsl(var(--teinte) calc(var(--force) * 19%) 93%);
}
/* Sur un écran large, la barre traverse toute la fenêtre — c'est ce qui lui
   donne son fond blanc d'un bord à l'autre — mais son contenu reste dans la
   colonne du texte.
   ----------------------------------------------------------------------------
   Deux erreurs se cumulaient, et l'on ne les voyait que sur un ordinateur.
   D'abord la règle visait `> button`, alors que le bouton vit dans un
   `div.actions` : elle ne l'atteignait donc jamais, et il restait collé au bord
   gauche de la fenêtre, à un mètre de la zone de texte. Ensuite la zone de texte
   est un `inline-block` : sur un élément de ce type, `margin: auto` ne centre
   rien, il retombe à zéro — elle était centrée en apparence sur un téléphone
   seulement parce qu'elle y occupe toute la largeur.

   On passe donc par une colonne flexible, qui centre ses enfants quel que soit
   leur mode d'affichage. Sur un téléphone, la largeur maximale ne mord pas et
   rien ne bouge. */
#form-message {
  display: flex;
  flex-direction: column;
  align-items: center;
}
/* 860 et non 900 : c'est la largeur RÉELLE de la carte au-dessus
   (`.espace__corps` fait 900 moins ses 20 px de marge de chaque côté). À 900,
   la barre débordait de vingt pixels de part et d'autre — assez peu pour ne pas
   sauter aux yeux, assez pour que la colonne paraisse de travers. */
#form-message > textarea,
#form-message > .actions {
  width: 100%;
  max-width: 860px;
}

/* Sur un téléphone, le corps de la page se serre à 14 px de marge : la barre
   d'envoi doit suivre, sinon la zone de texte est en retrait de six pixels sur
   le fil qu'elle prolonge.
   ----------------------------------------------------------------------------
   Cette règle doit vivre ICI, après celle qui pose le rembourrage général, et
   non dans le bloc « téléphone » du haut du fichier : à poids égal, c'est la
   dernière écrite qui l'emporte, et l'autre était donc sans effet. */
@media (max-width: 640px) {
  #form-message { padding-left: 14px; padding-right: 14px; }
}

/* La place réservée sous le fil, écrite par le script d'après la hauteur réelle
   du champ — il grandit avec le texte qu'on écrit. */
#fil-messages { padding-bottom: var(--hauteur-saisie, 170px); }

/* ------------------------------ les changements de salle et d'horaire */
/* Les bascules déjà posées, empilées dans leur feuille. Chacune se lit en une
   ligne — la date d'abord, puisque c'est elle qu'on cherche — et porte son
   propre geste d'annulation à droite. */
.changements {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 16px;
}
.changement {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 12px;
  border-radius: 12px;
  background: hsl(var(--teinte) calc(var(--force) * 30%) 97%);
}
.changement__texte {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.changement__date {
  font-weight: 600;
  font-size: 15px;
}
.changement__quoi {
  font-size: 14px;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
.changement .lien-bouton { flex: none; }

/* Une liste vide le dit, plutôt que de laisser un trou. */
.feuille__vide {
  margin: 0 0 16px;
  font-size: 15px;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}

/* ============================================================================
   Ce qui a été versé, ce qui reste
   ----------------------------------------------------------------------------
   Deux nombres à égalité — on ne calcule rien, on lit. Le dû part en ambre :
   c'est ce qui reste à faire, comme partout ailleurs dans l'application.
   ========================================================================== */
.versements__tete { display: flex; gap: 10px; margin: 4px 0 12px; }
.versements__chiffre {
  flex: 1 1 0;
  min-width: 0;
  padding: 12px 14px;
  border-radius: 14px;
  background: hsl(var(--teinte) calc(var(--force) * 30%) 97.5%);
}
.versements__chiffre--du { background: #FDF1DC; }
.versements__chiffre--ok { background: #E8F0EA; }
.versements__valeur {
  display: block;
  font-family: var(--font-titre);
  font-size: 21px;
  font-weight: 700;
  line-height: 1.15;
  color: var(--prune);
  font-variant-numeric: tabular-nums;
}
.versements__chiffre--du .versements__valeur { color: #7A5410; }
.versements__chiffre--ok .versements__valeur { color: #2C5C3C; }
.versements__mot {
  display: block;
  margin-top: 2px;
  font-family: var(--font-titre);
  font-size: 13px;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}

/* La même jauge que sur le planning : on ne la lit pas, on la voit. */
.versements__jauge {
  height: 6px;
  margin: -4px 0 14px;
  border-radius: 999px;
  background: hsl(var(--teinte) calc(var(--force) * 20%) 92%);
  overflow: hidden;
}
.versements__jauge__part {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: var(--prune);
}

/* L'en-tête d'une période, quand la personne en a plusieurs : ses dates à
   gauche, son solde à droite. Le nom de la formule n'y est pas — on vient de le
   lire sur la fiche d'où l'on arrive. */
.versements__periode {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 4px 10px;
  margin: 18px 0 6px;
  padding-top: 12px;
  border-top: 1px solid hsl(var(--teinte) calc(var(--force) * 23.8%) 95.9%);
}
.versements__periode:first-of-type { margin-top: 10px; border-top: 0; padding-top: 0; }
.versements__periode-quand {
  font-family: var(--font-titre);
  font-size: 14px;
  font-weight: 600;
  color: hsl(var(--teinte) calc(var(--force) * 7.2%) 27.1%);
}

/* ============================================================================
   Les règlements annoncés par l'adhérent
   ----------------------------------------------------------------------------
   Le liseré en pointillés dit ce qu'ils sont : quelque chose de posé, pas
   encore acquis — la même convention que « Tenir des places » ou « Choisir une
   photo ». Une écriture pleine les ferait passer pour de l'argent reçu, et
   c'est exactement l'erreur que cette page existe pour éviter.
   ========================================================================== */
.annonces {
  margin: 4px 0 16px;
  padding: 12px 14px 8px;
  border: 1px dashed #EFDCB6;
  border-radius: 14px;
  background: #FDF9F0;
}
.annonces__titre {
  margin: 0 0 8px;
  font-family: var(--font-titre);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: #7A5410;
}
.annonce-reglement {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 6px 12px;
  padding: 8px 0;
  border-top: 1px solid #F3E6CC;
}
.annonce-reglement:first-of-type { border-top: 0; }
.annonce-reglement__gestes {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: none;
}
/* Le bouton d'encaissement reprend la pastille ambre de « Valider » : c'est le
   même métier — un geste de rentrée, répété, qui doit tomber sous le pouce. */
.annonce-reglement .ligne-membre__valider { min-height: 38px; padding: 5px 14px; }
/* La phrase qui accompagne une annonce : elle dit ce que l'annonce N'EST PAS. */
.annonces__mot {
  margin: 0 0 10px;
  font-size: 15px;
  line-height: 1.45;
  color: #7A5410;
  text-wrap: pretty;
}
.versement-ajout .annonces__mot { margin-bottom: 12px; }
/* Le formulaire de correction se déplie sous l'annonce qu'il corrige, et prend
   la largeur : trois champs serrés à droite des boutons seraient illisibles. */
.annonce-reglement__forme { flex: 1 1 100%; margin-top: 8px; }

/* La case du dû, quand elle porte le geste d'annoncer un règlement. Elle reste
   un chiffre — c'est ce qu'on vient lire — et gagne le mot qui dit qu'on peut
   la toucher. Le contour ambre suffit à l'annoncer sans en faire un bouton de
   plus dans un écran qui en compte déjà. */
.chiffres__un--geste {
  border: 1px solid #EFDCB6;
  text-align: left;
  cursor: pointer;
  font: inherit;
}
.chiffres__un--geste:hover { background: #FBEED4; }
.chiffres__un--geste:focus-visible { outline: 2px solid var(--prune); outline-offset: 2px; }
.chiffres__geste {
  display: block;
  margin-top: 5px;
  font-family: var(--font-titre);
  font-size: 13px;
  font-weight: 600;
  color: #7A5410;
  text-decoration: underline;
}

/* Ce qui a été annoncé et attend d'être confirmé. En ambre comme le dû : c'est
   du même ordre — quelque chose qui n'est pas encore réglé. */
.resume__annonce {
  display: block;
  margin-top: 6px;
  font-family: var(--font-titre);
  font-size: 14px;
  font-weight: 500;
  color: #7A5410;
  text-wrap: pretty;
}

/* ============================================================================
   La croix qui vide un champ de recherche
   ----------------------------------------------------------------------------
   iOS n'en pose aucune sur un « type=search » — c'est un usage de navigateur de
   bureau. Sans elle, effacer un nom se fait lettre à lettre, clavier ouvert,
   alors qu'on cherche justement à revenir à la liste entière.

   Elle mesure trente-six pixels, posée dans le champ : la cible reste
   confortable sans manger la place du texte, que la marge intérieure droite
   réserve.
   ========================================================================== */
.champ-chercher {
  position: relative;
  display: flex;
  flex: 1 1 auto;
  min-width: 0;
}
.champ-chercher input { padding-right: 46px; }
/* La croix du navigateur ferait doublon avec la nôtre là où elle existe. */
.champ-chercher input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }
/* Une croix nue plutôt qu'une pastille grise.
   ----------------------------------------------------------------------------
   Elle pesait presque autant que le bouton « + » d'à côté — même diamètre,
   même présence — pour un geste bien moins important : ajouter quelqu'un se
   décide, effacer trois lettres se répare tout seul. Le fond disparaît donc,
   et il ne reste que le signe, dans le gris des libellés.

   La cible du pouce, elle, ne bouge pas : « .espace button » lui garde ses
   quarante-quatre pixels. C'est l'encre qui maigrit, pas la surface qu'on
   vise. Et le « × » de texte devient un vrai dessin : le caractère n'a ni la
   même épaisseur ni le même centrage selon la police qui le rend. */
.champ-chercher__vider {
  position: absolute;
  right: 4px;
  top: 50%;
  transform: translateY(-50%);
  width: 44px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  background: none;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 52%);
  cursor: pointer;
}
.champ-chercher__vider svg { width: 15px; height: 15px; display: block; }
.champ-chercher__vider:hover,
.champ-chercher__vider:active { color: var(--prune); }
.champ-chercher__vider:focus-visible { outline: 2px solid var(--prune); outline-offset: 2px; }

/* La part qui ne se règle pas par versement : séances hors forfait, ateliers,
   accompagnants. Ambre, comme tout ce qui reste à faire — et le total dessous,
   parce que le grand chiffre au-dessus n'est qu'une des deux dettes. */
.solde-membre__seances {
  margin: 8px 0 0;
  padding: 8px 12px 9px;
  border-radius: 11px;
  background: #FDF1DC;
}
.solde-membre__seances-quoi {
  margin: 0;
  font-family: var(--font-titre);
  font-size: 14px;
  line-height: 1.4;
  color: #7A5410;
  text-wrap: pretty;
}
.solde-membre__seances-quoi b { font-weight: 700; }
.solde-membre__total {
  margin: 4px 0 0;
  font-family: var(--font-titre);
  font-size: 15px;
  font-weight: 700;
  color: #7A5410;
  font-variant-numeric: tabular-nums;
}

/* Le liseré de la rangée : qui doit encore, qui est à jour.
   ----------------------------------------------------------------------------
   « inset » plutôt qu'une bordure : une bordure gauche décalerait tout le
   contenu de quatre pixels, et la liste se remettrait en place à chaque
   règlement. L'ombre intérieure ne prend pas de place.

   Ambre et vert sont les deux tons que l'application emploie déjà partout pour
   « il reste à faire » et « c'est réglé » — l'œil n'apprend rien de nouveau. */
.ligne-membre--doit  { box-shadow: inset 4px 0 0 #EFC15E; }
.ligne-membre--ajour { box-shadow: inset 4px 0 0 #9CC5A8; }

/* Les quatre moyens, sous la séance qu'on règle. Ils prennent la largeur : un
   rang de petits boutons serrés à droite se viserait mal, et c'est un geste
   qu'on fait debout, à la fin d'un cours. */
.impaye__moyens {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  flex: 1 1 100%;
  margin-top: 8px;
}
.impaye__moyens[hidden] { display: none; }
.impaye__moyen {
  flex: 1 1 auto;
  min-height: 40px;
  padding: 6px 12px;
  border: 1px solid #EFDCB6;
  border-radius: 999px;
  background: #FDF1DC;
  font-family: var(--font-titre);
  font-size: 13px;
  font-weight: 600;
  color: #7A5410;
  cursor: pointer;
}
.impaye__moyen:hover:not(:disabled) { background: var(--jaune); border-color: var(--jaune); color: #4A3208; }
.impaye__moyen:disabled { opacity: .5; }

/* ============================================================================
   Le relevé d'un adhérent
   ----------------------------------------------------------------------------
   Deux blocs empilés plutôt que deux colonnes côte à côte : sur trois cent
   quatre-vingt-dix pixels, deux colonnes de montants donneraient des lignes de
   quatre mots qui passent à la ligne. Empilés, chaque bloc garde toute la
   largeur — le libellé à gauche, la somme à droite, alignée sur ses chiffres.
   ========================================================================== */
.releve { margin: 14px 0 4px; }
.releve__colonne {
  padding: 10px 12px 8px;
  border-radius: 12px;
  background: hsl(var(--teinte) calc(var(--force) * 30%) 97.5%);
}
.releve__colonne + .releve__colonne { margin-top: 8px; }
.releve__colonne--verse { background: #EEF4EF; }
.releve__tete {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 6px;
}
.releve__titre {
  font-family: var(--font-titre);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
.releve__colonne--verse .releve__titre { color: #2C5C3C; }
.releve__total {
  font-family: var(--font-titre);
  font-size: 17px;
  font-weight: 700;
  color: var(--prune);
  font-variant-numeric: tabular-nums;
}
.releve__colonne--verse .releve__total { color: #2C5C3C; }
.releve__ligne {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  padding: 3px 0;
}
.releve__quoi {
  font-size: 15px;
  line-height: 1.35;
  color: hsl(var(--teinte) calc(var(--force) * 7.2%) 27.1%);
  min-width: 0;
}
.releve__combien {
  flex: none;
  font-family: var(--font-titre);
  font-size: 14px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
.releve__rien {
  margin: 0;
  font-size: 15px;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
/* L'écart entre les deux blocs : c'est lui qu'on vient chercher. */
.releve__pied {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-top: 10px;
  padding: 9px 12px;
  border-radius: 12px;
  background: #E8F0EA;
  font-family: var(--font-titre);
  font-size: 15px;
  font-weight: 600;
  color: #2C5C3C;
}
.releve__pied--du { background: #FDF1DC; color: #7A5410; }
.releve__pied b { font-size: 18px; font-weight: 700; font-variant-numeric: tabular-nums; }
/* Le geste au bout d'une ligne de relevé : discret, mais à portée. */
.releve__geste { flex: none; font-size: 13px; }
.releve__ajout { margin-top: 10px; }
/* ============================================================================
   Le RIB de l'association
   ----------------------------------------------------------------------------
   Trois cadres et trois gros boutons pour une information qu'on lit une fois,
   et jamais quand on paie en espèces : le bloc se replie derrière une ligne.
   Ouvert, l'IBAN prend la taille et le contraste — c'est la seule chose qu'on
   vient chercher ; le titulaire et le BIC tiennent la ligne du dessous.
   ========================================================================== */
.rib { margin: 12px 0 0; }

.rib__ouvrir {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 12px 14px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 15%) 88%);
  border-radius: 14px;
  background: #fff;
  cursor: pointer;
  text-align: left;
}
.rib--ouvert .rib__ouvrir { border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
.rib__ouvrir__mot {
  flex: 1;
  font-family: var(--font-titre);
  font-size: 15px;
  font-weight: 600;
  color: var(--prune);
}
.rib__ouvrir__quoi {
  font-size: 13px;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
/* Le chevron pivote vers le bas quand le bloc s'ouvre : le seul indice qu'il
   reste quelque chose dessous. */
.rib__ouvrir__chevron {
  font-size: 18px;
  line-height: 1;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
  transition: transform .18s ease;
}
.rib--ouvert .rib__ouvrir__chevron { transform: rotate(90deg); }
@media (prefers-reduced-motion: reduce) { .rib__ouvrir__chevron { transition: none; } }

.rib__dedans {
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 15%) 88%);
  border-top: 0;
  border-radius: 0 0 14px 14px;
  background: #fff;
  padding: 2px 14px 8px;
}

/* Chaque ligne se touche en entier : l'icône n'est qu'un repère, pas une cible
   à viser au pouce. */
.rib__ligne {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px 0;
  border: 0;
  background: none;
  cursor: pointer;
  text-align: left;
}
.rib__ligne--appoint { border-top: 1px solid hsl(var(--teinte) calc(var(--force) * 23.8%) 95.9%); }

.rib__valeur {
  flex: 1;
  min-width: 0;
  font-family: var(--font-titre);
  /* L'IBAN fait trente-trois caractères avec ses espaces : la taille suit la
     largeur plutôt que d'être fixe, pour qu'il tienne d'un trait même sur les
     320 pixels des plus étroits. */
  font-size: clamp(12.5px, 4vw, 16px);
  font-weight: 600;
  letter-spacing: .01em;
  color: var(--prune);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Le titulaire et le BIC partagent une ligne, mais pas au prix d'un BIC coupé
   en son milieu : c'est un code qu'on recopie, il se lit en entier ou pas du
   tout. La ligne passe donc à deux quand il le faut. */
.rib__ligne--appoint .rib__valeur {
  font-size: 13.5px;
  font-weight: 400;
  line-height: 1.35;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
  white-space: normal;
  overflow: visible;
  text-overflow: clip;
}

.rib__marque {
  flex: none;
  display: inline-flex;
  align-items: center;
  font-family: var(--font-titre);
  font-size: 13px;
  font-weight: 600;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
.rib__marque svg { width: 17px; height: 17px; }
.rib__ligne--iban .rib__marque { color: var(--prune); }
.rib__marque--dit { color: #2C5C3C; }

/* Ce qui vient d'être encaissé : une ligne verte, le temps de la lire. */
.solde-membre__fait {
  margin: 0 0 10px;
  padding: 9px 13px;
  border-radius: 11px;
  background: #E8F0EA;
  font-family: var(--font-titre);
  font-size: 15px;
  font-weight: 600;
  color: #2C5C3C;
  transition: opacity .35s ease;
}
.solde-membre__fait--part { opacity: 0; }
@media (prefers-reduced-motion: reduce) { .solde-membre__fait { transition: none; } }

/* Une séance qu'on vient de régler : elle reste en place, marquée, avec de quoi
   revenir dessus. Elle disparaîtra à la prochaine venue sur l'écran. */
.impaye--regle { opacity: .75; }
.impaye__fait {
  font-family: var(--font-titre);
  font-size: 13.5px;
  font-weight: 600;
  color: #2C5C3C;
  background: #E8F0EA;
  padding: 5px 11px;
  border-radius: 999px;
}

/* ============================================================================
   Choisir sa formule, après la séance d'essai
   ----------------------------------------------------------------------------
   Trois ou quatre rangées, chacune un engagement : le nom et le prix sur une
   ligne, ce que la formule donne sur la suivante. Rien de plus — on choisit
   entre des offres, pas entre des fiches techniques.
   ========================================================================== */
.choix-formule__mot {
  margin: 0 0 12px;
  font-family: var(--font-titre);
  font-size: 15px;
  line-height: 1.4;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
.choix-formule__ligne {
  display: block;
  width: 100%;
  margin-bottom: 8px;
  padding: 12px 14px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 15%) 88%);
  border-radius: 14px;
  background: #fff;
  text-align: left;
  cursor: pointer;
}
.choix-formule__ligne:disabled { opacity: .5; cursor: default; }
.choix-formule__ligne:focus-visible { outline: 2px solid var(--prune); outline-offset: 2px; }
.choix-formule__haut {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}
.choix-formule__nom {
  font-family: var(--font-titre);
  font-size: 16px;
  font-weight: 600;
  color: var(--prune);
}
.choix-formule__prix {
  flex: none;
  font-family: var(--font-titre);
  font-size: 16px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--prune);
}
.choix-formule__quoi {
  display: block;
  margin-top: 2px;
  font-family: var(--font-titre);
  font-size: 13.5px;
  line-height: 1.35;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}

/* ============================================================================
   Les dépenses
   ----------------------------------------------------------------------------
   Une rangée par sortie, dans les mêmes proportions que les versements de la
   caisse : les deux écrans se lisent l'un contre l'autre, et un œil qui passe
   de l'un à l'autre ne doit pas réapprendre à lire.
   ========================================================================== */
.caisse-tete__chiffre--bon     { color: #2C5C3C; }
.caisse-tete__chiffre--mauvais { color: #8C3A32; }
.caisse-tete__rentre { font-weight: 600; color: #2C5C3C; }
.caisse-tete__sorti  { font-weight: 600; color: #8C3A32; }

.depense-ajout { margin-top: 16px; }

.depense {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 0;
  border-bottom: 1px solid hsl(var(--teinte) calc(var(--force) * 23.8%) 95.9%);
}
.depense__quoi { flex: 1; min-width: 0; }
.depense__libelle {
  display: block;
  font-family: var(--font-titre);
  font-size: 15.5px;
  font-weight: 600;
  color: hsl(var(--teinte) calc(var(--force) * 7.2%) 27.1%);
  overflow-wrap: anywhere;
}
.depense__detail {
  display: block;
  font-family: var(--font-titre);
  font-size: 13.5px;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
/* Le montant d'une sortie porte son signe : dans une colonne de chiffres, rien
   ne distingue autrement 280 € reçus de 280 € payés. */
.depense__montant {
  flex: none;
  font-family: var(--font-titre);
  font-size: 15.5px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: #8C3A32;
}
.depense__geste { flex: none; font-size: 13px; }

/* Les postes, en jetons qui s'enroulent : douze mots qu'on touche, au lieu
   d'un libellé à taper. Le titre reprend l'habit des étiquettes de champ. */
.d-postes__mot {
  display: block;
  font-family: var(--font-titre);
  font-weight: 600;
  font-size: 13px;
  letter-spacing: .02em;
  color: var(--prune);
  margin-bottom: 7px;
}
.postes { display: flex; flex-wrap: wrap; gap: 8px; }
.poste { font-size: 13px; }

/* Un abonnement : sa ligne, l'histoire de ses tarifs, ses gestes. Arrêté,
   il s'efface un peu — il reste lisible, il ne compte plus. */
.abonnement { border-bottom: 1px solid hsl(var(--teinte) calc(var(--force) * 23.8%) 95.9%); }
.abonnement .depense { border-bottom: 0; padding-bottom: 4px; }
.abonnement--arrete .depense__libelle,
.abonnement--arrete .depense__montant { color: hsl(var(--teinte) calc(var(--force) * 6.1%) 55%); }
.abonnement__tarifs {
  margin: 0 0 6px;
  font-family: var(--font-titre);
  font-size: 13px;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
.abonnement__tarif { padding: 1px 0; }
.abonnement__tarif b { font-weight: 600; font-variant-numeric: tabular-nums; }
.abonnement__annuler { margin-left: 8px; font-size: 12.5px; }
.abonnement__gestes { display: flex; flex-wrap: wrap; gap: 6px 16px; padding: 2px 0 10px; font-size: 13px; }
.abonnement__form { margin: 0 0 10px; }
.abonnement__explication {
  margin: 8px 0 0;
  font-family: var(--font-titre);
  font-size: 13px;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
/* Le compte de résultat : deux colonnes de lignes et un total, avec le
   résultat en tête. Il emprunte l'habit de la caisse — on passe de l'un à
   l'autre en un geste, on ne doit pas réapprendre à lire. */
.exercice-debut { display: flex; gap: 8px; }
.exercice-debut select { flex: 1; min-width: 0; }
.resultat-choix { margin-bottom: 12px; }
.resultat-quand {
  margin: 0 0 14px;
  font-family: var(--font-titre);
  font-size: 13.5px;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
.resultat-tete { margin-bottom: 18px; }
.resultat-part { margin-bottom: 18px; }
.resultat-ligne {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  padding: 7px 0;
  border-bottom: 1px solid hsl(var(--teinte) calc(var(--force) * 23.8%) 95.9%);
}
.resultat-ligne__mot {
  font-family: var(--font-titre);
  font-size: 14.5px;
  color: hsl(var(--teinte) calc(var(--force) * 7.2%) 27.1%);
  overflow-wrap: anywhere;
}
.resultat-ligne__nombre {
  display: block;
  font-size: 12.5px;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
.resultat-ligne__montant {
  flex: none;
  font-family: var(--font-titre);
  font-size: 14.5px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.resultat-ligne--total {
  border-bottom: 0;
  border-top: 2px solid hsl(var(--teinte) calc(var(--force) * 23.8%) 90%);
}
.resultat-ligne--total .resultat-ligne__mot { font-weight: 600; }
.resultat-note {
  margin: 0;
  font-family: var(--font-titre);
  font-size: 13.5px;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}

/* Une recette saisie à la main porte son geste : la ligne garde sa forme, le
   bouton se pose au bout. */
.ligne-du-recette { display: flex; align-items: center; gap: 10px; }
.ligne-du-recette .ligne-du { flex: 1; min-width: 0; }

/* Le bilan : ce que l'association possède, sous le résultat. L'écart entre la
   trésorerie et le résultat se signale — il dit qu'une écriture manque. */
.bilan .resultat-note { margin-top: 10px; }
.resultat-note--alerte { color: #8C3A32; }

/* Le total par poste : une ligne par poste, le plus lourd en tête. */
.postes-totaux {
  margin: 0 0 10px;
  padding: 10px 12px;
  border-radius: 10px;
  background: hsl(var(--teinte) calc(var(--force) * 27.3%) 97.8%);
}
.postes-totaux__ligne {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding: 3px 0;
  font-family: var(--font-titre);
  font-size: 13.5px;
  color: hsl(var(--teinte) calc(var(--force) * 6.3%) 40.6%);
}
.postes-totaux__montant { font-weight: 600; font-variant-numeric: tabular-nums; }

/* ============================================================================
   Les statistiques
   ----------------------------------------------------------------------------
   Des barres proportionnelles au plus grand : la comparaison se fait d'un coup
   d'œil, sans lire les nombres. Le nom garde une largeur fixe pour que toutes
   les barres partent du même bord — sinon l'œil compare des longueurs qui ne
   commencent pas au même endroit.
   ========================================================================== */
.stat-barres { margin-top: 8px; }
.stat-ligne { display: flex; align-items: center; gap: 10px; padding: 5px 0; }
.stat-nom {
  flex: 0 0 40%;
  max-width: 150px;
  font-family: var(--font-titre);
  font-size: 13.5px;
  color: hsl(var(--teinte) calc(var(--force) * 7.2%) 27.1%);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.stat-jauge {
  flex: 1;
  min-width: 0;
  height: 9px;
  border-radius: 99px;
  overflow: hidden;
  background: hsl(var(--teinte) calc(var(--force) * 18.9%) 92.7%);
}
.stat-jauge i { display: block; height: 100%; background: var(--prune); opacity: .72; }
/* Un cours qui se remplit à moins de quarante pour cent : c'est celui dont on
   se demande s'il faut le garder. La couleur pose la question. */
.stat-jauge i.stat-jauge--basse { background: #C08A2E; opacity: .85; }
.stat-n {
  flex: 0 0 auto;
  min-width: 38px;
  text-align: right;
  font-family: var(--font-titre);
  font-size: 13.5px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--prune);
}

.stat-alerte {
  margin-top: 14px;
  padding: 11px 13px;
  border-radius: 12px;
  background: #FDF1DC;
}
.stat-alerte b { font-family: var(--font-titre); font-size: 15px; color: #7A5410; }
.stat-alerte p {
  margin: 2px 0 0;
  font-family: var(--font-titre);
  font-size: 13.5px;
  line-height: 1.4;
  color: #7A5410;
}

.stat-mot,
.stat-vide {
  margin: 9px 0 0;
  font-family: var(--font-titre);
  font-size: 13.5px;
  line-height: 1.45;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
.stat-vide {
  padding: 12px 13px;
  border: 1px dashed hsl(var(--teinte) calc(var(--force) * 19%) 85%);
  border-radius: 12px;
}

/* Une rangée par personne qui se désiste. Le taux à droite, le détail dessous :
   on lit la colonne, puis on s'arrête sur qui interroge. */
.stat-fiab {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 0;
  border-bottom: 1px solid hsl(var(--teinte) calc(var(--force) * 23.8%) 95.9%);
}
.stat-fiab__quoi { flex: 1; min-width: 0; }
.stat-fiab__nom {
  display: block;
  font-family: var(--font-titre);
  font-size: 15.5px;
  font-weight: 600;
  color: hsl(var(--teinte) calc(var(--force) * 7.2%) 27.1%);
}
.stat-fiab__detail {
  display: block;
  font-family: var(--font-titre);
  font-size: 13px;
  line-height: 1.35;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
.stat-fiab__taux {
  flex: none;
  font-family: var(--font-titre);
  font-size: 16px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
/* Beaucoup d'annulations ET un préavis court : c'est la combinaison qui coûte
   une place. L'une sans l'autre ne se marque pas. */
.stat-fiab__taux--vive { color: #8C3A32; }

/* Les familles du menu des réglages.
   ----------------------------------------------------------------------------
   Treize lignes à plat se cherchaient une à une. Cinq familles courtes se
   parcourent d'un regard — et le premier titre, « À consulter », reconnaît que
   deux d'entre elles ne sont pas des réglages du tout.

   Le titre est léger : c'est un repère pour l'œil qui parcourt, pas une
   section à lire. */
.reglages-menu__titre {
  display: block;
  margin: 16px 0 5px;
  padding: 0 2px;
  font-family: var(--font-titre);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 52%);
}
.reglages-menu__titre:first-child { margin-top: 2px; }

/* Chaque famille dans son cadre : les lignes s'y touchent, et l'on voit où
   l'une s'arrête sans avoir à lire les titres. */
.reglages-menu__famille {
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 15%) 90%);
  border-radius: 14px;
  overflow: hidden;
  background: #fff;
}
.reglages-menu__famille .repli { border-radius: 0; }
.reglages-menu__famille .repli:last-child { border-bottom: 0; }

/* Une recette qui n'appartient à personne — une place tenue pour des externes.
   Elle ne mène à aucune fiche : le curseur le dit, et rien d'autre ne change.
   La griser l'aurait fait passer pour annulée. */
.ligne-du--sans-fiche { cursor: default; }

/* ============================================================================
   L'éditeur du site public
   ----------------------------------------------------------------------------
   Une liste de sections. Chacune dit son nom, ce qu'elle contient, et porte ses
   deux flèches et son interrupteur. Éteinte, elle pâlit sans disparaître : son
   contenu attend, et c'est ce qui permet d'essayer sans craindre.
   ========================================================================== */
.site__mot {
  margin: 0 0 14px;
  font-family: var(--font-titre);
  font-size: 14px;
  line-height: 1.45;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}

.site-liste { border-top: 1px solid hsl(var(--teinte) calc(var(--force) * 23.8%) 95.9%); }
.site-ligne {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 0;
  border-bottom: 1px solid hsl(var(--teinte) calc(var(--force) * 23.8%) 95.9%);
}
.site-ligne--eteinte .site-ligne__nom,
.site-ligne--eteinte .site-ligne__resume { opacity: .5; }

.site-ligne__quoi {
  flex: 1;
  min-width: 0;
  padding: 0;
  border: 0;
  background: none;
  text-align: left;
  cursor: pointer;
  font: inherit;
}
.site-ligne__quoi:not(button) { cursor: default; }
.site-ligne__nom {
  display: block;
  font-family: var(--font-titre);
  font-size: 15.5px;
  font-weight: 600;
  color: hsl(var(--teinte) calc(var(--force) * 7.2%) 27.1%);
}
.site-ligne__resume {
  display: block;
  font-family: var(--font-titre);
  font-size: 13px;
  line-height: 1.35;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
  overflow-wrap: anywhere;
}
.site-ligne__fleches { flex: none; display: flex; gap: 5px; }

/* L'interrupteur : la forme dit l'état sans qu'on lise un mot. */
/* Hors de la règle des quarante-quatre pixels : un interrupteur a des
   proportions reconnues — cinquante et un sur trente et un — et forcé au carré
   il se dessinait en rond, méconnaissable. Sa largeur reste au-dessus de la
   pulpe d'un pouce. */
.site-inter {
  flex: none;
  position: relative;
  width: 51px;
  height: 31px;
  padding: 0;
  border: 0;
  border-radius: 99px;
  background: hsl(var(--teinte) calc(var(--force) * 18.9%) 90%);
  cursor: pointer;
  transition: background .18s ease;
}
.site-inter::after {
  content: '';
  position: absolute;
  top: 3px;
  left: 3px;
  width: 25px;
  height: 25px;
  border-radius: 50%;
  background: #fff;
  transition: left .18s ease;
}
.site-inter--on { background: var(--prune); }
.site-inter--on::after { left: 23px; }
.site-inter:disabled { opacity: .45; cursor: default; }
@media (prefers-reduced-motion: reduce) {
  .site-inter, .site-inter::after { transition: none; }
}

/* Ce qui n'est pas encore posé : on ne propose que ce qui manque. */
.site-ajouts { display: flex; flex-direction: column; gap: 7px; margin-top: 10px; }
.site-ajout {
  display: block;
  width: 100%;
  padding: 11px 13px;
  border: 1px dashed hsl(var(--teinte) calc(var(--force) * 19%) 84%);
  border-radius: 12px;
  background: none;
  text-align: left;
  cursor: pointer;
}
.site-ajout__nom {
  display: block;
  font-family: var(--font-titre);
  font-size: 15px;
  font-weight: 600;
  color: var(--prune);
}
.site-ajout__quoi {
  display: block;
  font-family: var(--font-titre);
  font-size: 13px;
  line-height: 1.35;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}

/* Les entrées répétées d'une section : les photos d'une galerie, les activités
   qu'on propose. Numérotées, parce qu'on parle d'elles par leur rang. */
.site-entrees { margin-top: 16px; }
.site-entrees__titre {
  margin: 0 0 8px;
  font-family: var(--font-titre);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}
.site-entree {
  margin-bottom: 10px;
  padding: 11px 13px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 15%) 90%);
  border-radius: 12px;
}
.site-entree__haut {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 4px;
}
.site-entree__n {
  font-family: var(--font-titre);
  font-size: 12px;
  font-weight: 600;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}

/* ------------------------------------------------ les demandes venues du site

   Elles vivent dans la messagerie, avec les messages des adhérentes, et doivent
   pourtant se distinguer au premier regard : elles viennent de quelqu'un qui
   n'a pas de compte, à qui l'on ne peut pas répondre dans l'application, et qui
   ne saura jamais si son message s'est perdu.

   La marque est une enveloppe à la place des initiales, dessinée en creux
   plutôt que remplie. Une pastille verte signale l'exception qui change tout :
   l'adresse est celle d'une adhérente déjà inscrite. */

.ligne-membre__initiales--site {
  background: transparent;
  border: 1.5px dashed hsl(var(--teinte) calc(var(--force) * 26%) 78%);
}
.ligne-membre__initiales--site svg {
  width: 19px; height: 19px;
  fill: none;
  stroke: var(--prune);
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* La feuille d'une demande : le texte tel qu'il a été écrit, puis les deux
   gestes qui servent — appeler, écrire. */
.feuille__corps { padding: 0 4px 8px; }

.demande__marque {
  margin: 0 0 12px;
  padding: 10px 12px;
  border-radius: 10px;
  background: #E8F3EC;
  color: #2F5C42;
  font-size: 14px;
  line-height: 1.45;
}

/* Le geste qui range la demande : la même pastille jaune que partout ailleurs
   quand un écran n'a qu'une chose à faire. */
.demande__ranger {
  width: 100%;
  min-height: 48px;
  color: #3A2708;
  padding: 12px 22px;
  border: 0;
  border-radius: 30px;
  background: var(--jaune);
  font-family: var(--font-titre);
  font-weight: 600;
  font-size: 15px;
  cursor: pointer;
}
.demande__ranger:hover:not(:disabled) { background: var(--orange); }
.demande__ranger:disabled { opacity: .6; cursor: wait; }
.demande__ranger:focus-visible { outline: 2px solid var(--prune); outline-offset: 2px; }

.demande__texte {
  margin: 0 0 10px;
  white-space: pre-wrap;
  font-size: 16px;
  line-height: 1.55;
}

.demande__quand {
  margin: 0 0 18px;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
  font-size: 13px;
}

.demande__gestes {
  display: flex;
  gap: 10px;
  margin-bottom: 18px;
}

/* Deux cibles larges, côte à côte : on les touche au pouce, en marchant. */
.demande__geste {
  flex: 1 1 0;
  min-height: 56px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 2px;
  padding: 8px 12px;
  border-radius: 12px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 22%) 88%);
  background: hsl(var(--teinte) calc(var(--force) * 20%) 97%);
  text-decoration: none;
  color: inherit;
}
.demande__geste:focus-visible { outline: 2px solid var(--prune); outline-offset: 2px; }
.demande__geste__mot {
  flex: 0 0 auto;
  font-family: var(--font-titre);
  font-size: 15px; font-weight: 600;
  line-height: 1.35;
  color: var(--prune);
}

/* `flex: 0 0 auto` n'est pas un détail : sans lui, les deux lignes se
   laissaient comprimer pour tenir dans les 56 px du cadre, et l'`overflow`
   coupait l'adresse en deux dans le sens de la hauteur — on lisait le haut des
   lettres et rien d'autre. Le minimum du cadre est un PLANCHER, pas un
   plafond : ce sont les enfants qui décident de sa hauteur.

   L'`overflow` reste, mais pour l'autre sens : une adresse trop longue se
   termine par des points de suspension plutôt que de déborder. */
.demande__geste__quoi {
  flex: 0 0 auto;
  font-size: 12px;
  line-height: 1.45;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* --------------------------------------------------------- le champ « photo »

   Une photo ne se tape pas, elle se choisit. Le champ montre celle qui est
   posée, ce qu'on sait d'elle, et ouvre la galerie de l'association — la même
   que l'écran « Les photos », atteinte depuis un champ au lieu du menu. */

.photo-ligne {
  display: flex; align-items: center; gap: 10px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 20%) 88%);
  border-radius: 12px;
  padding: 8px;
}

.photo-vignette {
  flex: 0 0 auto;
  width: 54px; height: 54px;
  border-radius: 8px;
  overflow: hidden;
  background: hsl(var(--teinte) calc(var(--force) * 18%) 94%);
  display: grid; place-items: center;
}
.photo-vignette img { width: 100%; height: 100%; object-fit: cover; display: block; }
.photo-vignette--vide {
  color: hsl(var(--teinte) calc(var(--force) * 8%) 62%);
  font-size: 20px;
  border: 1.5px dashed hsl(var(--teinte) calc(var(--force) * 22%) 82%);
  background: none;
}

.photo-ligne__quoi { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.photo-ligne__nom {
  font-family: var(--font-titre);
  font-size: 14px; font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.photo-ligne__sous {
  font-size: 12px;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.photo-changer {
  flex: 0 0 auto;
  min-height: 36px;
  font-family: var(--font-titre);
  font-size: 13px; font-weight: 600;
  color: var(--prune);
  background: hsl(var(--teinte) calc(var(--force) * 20%) 95%);
  border: 0; border-radius: 999px;
  padding: 8px 14px;
  cursor: pointer;
}
.photo-changer:hover { background: hsl(var(--teinte) calc(var(--force) * 24%) 91%); }
.photo-changer:focus-visible { outline: 2px solid var(--prune); outline-offset: 2px; }

/* Le tiroir. Il s'ouvre SOUS le champ plutôt que par-dessus l'écran : on garde
   sous les yeux la carte qu'on est en train de composer, et l'on voit la
   vignette changer au moment où l'on touche une photo. */
.photo-tiroir {
  margin-top: 10px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 20%) 88%);
  border-top: 3px solid var(--prune);
  border-radius: 14px;
  padding: 12px;
  background: hsl(var(--teinte) calc(var(--force) * 20%) 97%);
}

.photo-galerie__mot {
  margin: 0 0 9px;
  font-family: var(--font-titre);
  font-size: 12px; font-weight: 600;
  letter-spacing: .06em; text-transform: uppercase;
  color: var(--prune);
}

.photo-grille {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(84px, 1fr));
  gap: 7px;
}

.photo-case {
  aspect-ratio: 1;
  padding: 0; border: 0; border-radius: 9px;
  overflow: hidden;
  background: hsl(var(--teinte) calc(var(--force) * 18%) 92%);
  cursor: pointer;
}
.photo-case img { width: 100%; height: 100%; object-fit: cover; display: block; }
.photo-case--choisie { outline: 3px solid var(--prune); outline-offset: -3px; }
.photo-case:focus-visible { outline: 3px solid var(--prune); outline-offset: 2px; }

/* Le « + » ouvre la pellicule du téléphone. C'est un `label` : le champ de
   fichier qu'il porte est caché, mais il reste atteignable au clavier. */
.photo-ajout {
  aspect-ratio: 1;
  display: grid; place-items: center; gap: 2px;
  border: 1.5px dashed var(--prune);
  border-radius: 9px;
  color: var(--prune);
  font-family: var(--font-titre);
  font-size: 12px; font-weight: 600;
  text-align: center;
  cursor: pointer;
}
.photo-ajout__plus { font-size: 22px; line-height: 1; }
.photo-ajout:hover { background: hsl(var(--teinte) calc(var(--force) * 22%) 94%); }
.photo-ajout:focus-within { outline: 2px solid var(--prune); outline-offset: 2px; }
.photo-ajout--occupe { opacity: .5; pointer-events: none; }

/* ------------------------------------------- les gestes qui restent sous la main

   Une feuille d'édition dont les champs montrent leur contenu en entier est
   plus haute que l'écran : « Enregistrer » se retrouve alors quelque part en
   bas, à chercher en faisant défiler, alors que le clavier occupe déjà la
   moitié de la hauteur. Les gestes se collent donc au bas de la feuille, sur
   son propre fond, et l'on écrit sans jamais les perdre de vue.

   `position: sticky` et non `fixed` : la feuille est ce qui défile, et un
   élément fixe se serait posé par rapport à la fenêtre — donc par-dessus la
   barre d'onglets, et immobile quand la feuille se ferme. */
.actions--collees {
  position: sticky;
  bottom: 0;
  z-index: 2;
  margin-top: 16px;
  padding: 12px 0 4px;
  background: #fff;
}

/* Un lien qui se choisit : la liste, et la case à taper qui s'ouvre dessous. */
.lien-interne { display: flex; flex-direction: column; gap: 6px; }

/* Quand la feuille amène un champ en vue, elle laisse la place de la barre :
   un champ tout en bas venait se ranger exactement sous « Enregistrer ». */
.feuille:has(.actions--collees) { scroll-padding-bottom: 84px; }

/* Un dégradé plutôt qu'une bordure : il dit que quelque chose continue
   au-dessous, là où un trait aurait dit que tout s'arrête. */
.actions--collees::before {
  content: '';
  position: absolute;
  left: 0; right: 0; top: -18px;
  height: 18px;
  background: linear-gradient(to bottom, rgba(255,255,255,0), #fff);
  pointer-events: none;
}

/* ------------------------------------------------------- voir ce qu'on compose

   On modifiait une section, on enregistrait, et rien ne montrait le résultat :
   il fallait connaître l'adresse de l'aperçu et l'ouvrir à la main. C'était le
   manque le plus coûteux de cet écran, et le moins cher à combler. */

.site__entete {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 14px;
}
.site__entete .site__mot { margin: 0; flex: 1 1 auto; }

.site__voir {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 40px;
  padding: 9px 14px;
  border-radius: 999px;
  background: hsl(var(--teinte) calc(var(--force) * 20%) 95%);
  color: var(--prune);
  font-family: var(--font-titre);
  font-size: 14px;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
}
.site__voir:hover { background: hsl(var(--teinte) calc(var(--force) * 24%) 91%); }
.site__voir:focus-visible { outline: 2px solid var(--prune); outline-offset: 2px; }

.site__voir svg {
  width: 15px; height: 15px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Dans une fiche, il vient après le bouton d'enregistrement : on regarde APRÈS
   avoir enregistré, jamais avant. Discret, donc, pour ne pas se disputer la
   place avec le geste principal. */
.site__voir--fiche {
  background: none;
  padding: 9px 4px;
  font-weight: 500;
}
.site__voir--fiche:hover { background: none; text-decoration: underline; }

/* De quelle page parle-t-on. La question ne se posait pas tant que le site n'en
   avait qu'une ; elle se pose depuis les mentions légales, et elle se posera
   davantage avec une page par activité. */
.site-pages {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 14px;
}
.site-page {
  min-height: 36px;
  padding: 8px 14px;
  border: 0;
  border-radius: 999px;
  background: hsl(var(--teinte) calc(var(--force) * 18%) 95%);
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 40%);
  font-family: var(--font-titre);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}
.site-page--ouverte { background: var(--prune); color: #fff; }
.site-page:focus-visible { outline: 2px solid var(--prune); outline-offset: 2px; }

/* ------------------------------------------------- les deux faces de l'écran

   Composer une page et tenir une réserve d'images sont deux besoins qui ne se
   ressemblent pas, mais qui servent la même chose. Ils partagent donc l'écran,
   et l'on passe de l'un à l'autre d'un doigt. */

.site-bascule {
  display: flex;
  gap: 4px;
  padding: 4px;
  margin-bottom: 14px;
  border-radius: 999px;
  background: hsl(var(--teinte) calc(var(--force) * 18%) 95%);
}
.site-bascule__onglet {
  flex: 1 1 0;
  min-height: 40px;
  /* Trois onglets tiennent sur un écran de 390 px, mais « Les photos » y passe
     à la ligne : on serre l'espacement plutôt que de rogner le mot. */
  padding: 0 6px;
  border: 0;
  border-radius: 999px;
  background: none;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 42%);
  font-family: var(--font-titre);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
}
.site-bascule__onglet--ouvert {
  background: #fff;
  color: var(--prune);
  box-shadow: 0 1px 3px hsl(var(--teinte) calc(var(--force) * 20%) 78% / .5);
}
.site-bascule__onglet:focus-visible { outline: 2px solid var(--prune); outline-offset: 2px; }

/* La réserve : la même galerie que le tiroir d'un champ photo, en plus grand.
   Une seule chose construite, deux chemins pour l'atteindre. */
.photo-reserve { margin-top: 12px; }
.photo-reserve .photo-grille {
  grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
  gap: 8px;
}

/* La fiche d'une photo. On la regarde d'abord — c'est ce qu'on est venu
   vérifier — puis on écrit ce qu'elle montre. */
.photo-fiche__vue {
  border-radius: 12px;
  overflow: hidden;
  background: hsl(var(--teinte) calc(var(--force) * 18%) 94%);
  margin-bottom: 10px;
  max-height: 46vh;
  display: grid;
  place-items: center;
}
.photo-fiche__vue img {
  width: 100%;
  height: auto;
  max-height: 46vh;
  object-fit: contain;
  display: block;
}

.photo-fiche__chiffres {
  margin: 0 0 14px;
  font-family: var(--font-titre);
  font-size: 13px;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
  font-variant-numeric: tabular-nums;
}

.photo-fiche__ou {
  margin: 14px 0 0;
  padding: 10px 12px;
  border-radius: 10px;
  background: hsl(var(--teinte) calc(var(--force) * 20%) 96%);
  font-size: 14px;
  line-height: 1.45;
}

/* L'avertissement avant de retirer une photo employée. Ambre et non rouge : ce
   n'est pas une erreur, c'est une conséquence qu'on doit connaître. */
.message--attention {
  background: #FDF1DC;
  color: #7A5410;
  border-radius: 10px;
  padding: 10px 12px;
  margin-top: 10px;
  font-size: 14px;
  line-height: 1.45;
}

/* La section qu'on vient de poser. Elle s'ajoute en bas d'une liste de quatorze,
   très au-dessus de l'écran : sans un signe, on croit que rien ne s'est passé et
   l'on touche de nouveau. */
.site-ligne--neuve {
  animation: site-ligne-neuve 2.2s ease-out;
  border-radius: 12px;
}
@keyframes site-ligne-neuve {
  0%, 55% { background: hsl(var(--teinte) calc(var(--force) * 30%) 92%); }
  100%    { background: transparent; }
}
@media (prefers-reduced-motion: reduce) {
  .site-ligne--neuve { animation: none; background: hsl(var(--teinte) calc(var(--force) * 30%) 92%); }
}

/* Dire que ce sont des pages. Sans ce mot, on croyait retrouver sous chacune les
   sections de l'accueil, et l'on ne comprenait pas ce que le catalogue des
   morceaux faisait là. */
.site-pages__mot {
  margin: 0 0 10px;
  font-size: 14px;
  line-height: 1.45;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}

/* Le catalogue des morceaux, replié. Quatorze possibilités sous une page qui
   n'en porte qu'une seule donnaient à croire que la page en était pleine. */
.site-ajouts__ouvrir {
  width: 100%;
  min-height: 48px;
  margin-top: 22px;
  padding: 12px 16px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  border: 1px dashed hsl(var(--teinte) calc(var(--force) * 22%) 82%);
  border-radius: 12px;
  background: none;
  color: var(--prune);
  font-family: var(--font-titre);
  font-size: 15px;
  font-weight: 600;
  text-align: left;
  cursor: pointer;
}
.site-ajouts__ouvrir:hover { background: hsl(var(--teinte) calc(var(--force) * 20%) 97%); }
.site-ajouts__ouvrir:focus-visible { outline: 2px solid var(--prune); outline-offset: 2px; }
.site-ajouts__ouvrir--ouvert {
  border-style: solid;
  border-bottom-left-radius: 0;
  border-bottom-right-radius: 0;
  margin-bottom: 0;
}
.site-ajouts__combien {
  font-weight: 400;
  font-size: 13px;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
  white-space: nowrap;
}
.site-ajouts__ouvrir--ouvert + .site-ajouts {
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 22%) 82%);
  border-top: 0;
  border-radius: 0 0 12px 12px;
  padding: 4px 12px 12px;
}

/* Créer une page : deux choses à décider, son titre et sa nature. */
.site-page--neuve {
  background: none;
  border: 1px dashed hsl(var(--teinte) calc(var(--force) * 24%) 78%);
  color: var(--prune);
}
.site-page--neuve:hover { background: hsl(var(--teinte) calc(var(--force) * 20%) 96%); }

.page-neuve__adresse {
  margin: 8px 0 18px;
  font-family: var(--font-titre);
  font-size: 13px;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}



/* ============================================================================
   L'allure du site public
   ----------------------------------------------------------------------------
   Six réglages, et un aperçu au-dessus. Une allure ne se juge pas sur une
   pastille de couleur : elle se juge en regardant la page, ce que cet écran
   rend possible sans quitter l'espace.
   ========================================================================== */

/* L'aperçu. Une fenêtre de 390 px de large — un téléphone — ramenée à la
   largeur disponible. La mise à l'échelle est faite par transformation et non
   par « zoom » : « zoom » n'existe pas chez tout le monde, et « width » seul
   rendrait une page d'ordinateur écrasée plutôt qu'un téléphone. */
.allure-apercu {
  position: relative;
  width: 100%;
  height: 300px;
  overflow: hidden;
  margin: 4px 0 10px;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 18%) 88%);
  border-radius: 14px;
  background: #fff;
  box-shadow: 0 1px 2px hsl(var(--teinte) calc(var(--force) * 20%) 80% / .5);
}
.allure-apercu__vitre {
  position: absolute;
  top: 0; left: 0;
  width: 390px;
  height: 640px;
  border: 0;
  transform-origin: 0 0;
  /* 300 / 640 ≈ 0,47 : on montre le haut de la page en entier. */
  transform: scale(.47);
}
@media (min-width: 520px) {
  .allure-apercu { height: 380px; }
  .allure-apercu__vitre { transform: scale(.59); }
}

.site__voir--allure { margin-bottom: 18px; }

.allure-bloc { margin: 0 0 22px; }
.allure-bloc__nom {
  margin: 0 0 2px;
  font-family: var(--font-titre);
  font-size: 15px;
  font-weight: 600;
  color: hsl(var(--teinte) calc(var(--force) * 22%) 32%);
}
.allure-bloc__quoi {
  margin: 0 0 10px;
  font-size: 13px;
  line-height: 1.45;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}

/* Deux colonnes, et non une rangée qui défile : un choix qu'il faut chercher
   en poussant du doigt ne se compare pas à celui d'à côté. */
.allure-choix {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(148px, 1fr));
  gap: 8px;
}
.allure-choix__un {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-height: 62px;
  padding: 10px 12px;
  text-align: left;
  border: 1px solid hsl(var(--teinte) calc(var(--force) * 18%) 88%);
  border-radius: 12px;
  background: #fff;
  cursor: pointer;
}
.allure-choix__un--pris {
  border-color: var(--prune);
  box-shadow: inset 0 0 0 1px var(--prune);
  background: hsl(var(--teinte) calc(var(--force) * 30%) 97%);
}
.allure-choix__un:focus-visible { outline: 2px solid var(--prune); outline-offset: 2px; }
.allure-choix__nom {
  font-family: var(--font-titre);
  font-size: 14px;
  font-weight: 600;
  color: hsl(var(--teinte) calc(var(--force) * 22%) 30%);
}
.allure-choix__quoi {
  font-size: 12px;
  line-height: 1.35;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 47%);
}

.allure-teintes { display: flex; gap: 3px; margin-bottom: 5px; }
.allure-teintes__un { width: 14px; height: 14px; border-radius: 50%; }

/* Quatre onglets ne tiennent plus au large sur un écran de 390 px : la bascule
   défile plutôt que de couper les mots en deux. */
@media (max-width: 430px) {
  .site-bascule { overflow-x: auto; scrollbar-width: none; }
  .site-bascule::-webkit-scrollbar { display: none; }
  .site-bascule__onglet { flex: 0 0 auto; padding: 0 12px; }
}

/* Une case à cocher tenait sa phrase entière sur une ligne : « Embarque
   l'adhésion à l'association — son montant s'ajoute au prix des cours. On la
   coche pour un abonnement à l'année, pas pour une carte de séances » prenait
   quatre lignes sur un téléphone, et trois cases voisines en prenaient onze.
   On ne lit plus, on saute.

   Le nom de la case répond à « qu'est-ce que ça fait », la ligne dessous à
   « pourquoi je la cocherais ». Séparés, ils se lisent en diagonale ; collés
   dans une même phrase, il fallait tout lire pour trouver le premier. */
.case-champ span b {
  display: block;
  font-weight: 600;
  line-height: 1.3;
}
.case-champ span small {
  display: block;
  margin-top: 1px;
  font-size: 13.5px;
  line-height: 1.32;
  color: hsl(var(--teinte) calc(var(--force) * 6.1%) 45.1%);
}

/* L'alerte d'adresse manquante : une épingle, aux couleurs de l'association.
   Le rouge est déjà pris par les séances annulées, et c'est la seule couleur
   qu'on ne peut pas dépenser deux fois — l'user pour une adresse manquante
   l'affaiblirait pour le jour où un cours saute. */
.alerte--adresse .alerte__icone { background: var(--prune); }

/* Le geste écrit en toutes lettres. Une carte entière cliquable sans rien qui
   le dise se regarde plus qu'elle ne se touche. */
.alerte__geste {
  display: inline-flex;
  align-items: center;
  margin-top: 8px;
  padding: 7px 15px;
  border-radius: 99px;
  background: var(--jaune);
  color: #3a2a12;
  font-family: var(--font-titre);
  font-size: 13.5px;
  font-weight: 700;
}
