/*
 | Feuille de style de l'application.
 |
 | Extraite de views/layout.php : elle y etait reenvoyee a chaque page, alors
 | qu'un fichier se met en cache une fois. Elle est aussi editable sans naviguer
 | dans du PHP, ce qui change tout des qu'on travaille le visuel.
 |
 | QUATRE REGLES, et tout le reste en decoule. Elles remplacent des valeurs
 | choisies a l'oeil au fil des besoins : l'ancienne feuille comptait treize
 | tailles de texte entre 10 et 23 px — dont six demi-pixels — et vingt-deux
 | valeurs d'espacement. Ni l'une ni l'autre ne formait un systeme, et c'est
 | precisement ce qui donnait a l'interface son air inachevee.
 |
 |   1. TYPOGRAPHIE — six crans, et aucune valeur en dur ailleurs. Pour accentuer,
 |      on augmente le POIDS avant la taille : un nom en 15/600 ressort mieux
 |      qu'en 15.5/400, et ne casse pas le rythme vertical.
 |
 |   2. ESPACEMENT — un rythme de 4 px, nomme par son multiplicateur. Un ecart de
 |      9 ou 13 px ne se distingue pas de 8 ou 12 : il ne cree pas de groupe, il
 |      cree du flou.
 |
 |   3. ELEVATION — trois niveaux d'ombre, teintees a l'encre et non au noir. Une
 |      ombre noire sur un fond colore parait sale. C'est le changement le plus
 |      visible : vingt-sept filets d'un pixel sur fond quasi blanc, c'etait le
 |      langage d'un formulaire non style.
 |
 |   4. MOUVEMENT — deux durees. Une interface qui ne repond pas au geste parait
 |      cassee, meme quand elle fonctionne. Tout est neutralise sous
 |      prefers-reduced-motion, en bas de fichier.
 |
 | Ce qui n'a PAS change, volontairement : la palette, desaturee et deja
 | coherente, et la signature du registre — l'onglet vertical colore qui encode
 | l'etat, les lignes revoquees hachurees plutot que grisees.
 */

:root{
  /* --- Palette, inchangee --- */
  --fond:#f5f7f6; --surface:#fff; --surface-creuse:#f7f9f8;
  --encre:#16262b; --encre-douce:#5a6e74; --encre-tenue:#8d9ea3;
  --accent:#2f5d62; --accent-fonce:#20444a; --accent-voile:#e2edec;
  --alerte:#8a3a32; --alerte-voile:#f7ebe9;
  --attente:#7d6216; --attente-voile:#fbf3df;

  /* --- Les fonds d'etat du planning ---
     ILS EXISTAIENT DEJA, ET NE SE SEPARAIENT PAS. « .ps-faite » reprenait le fond de
     « .ps-puce » — donc aucune information — et « .ps-valide » un voile a peine teinte.
     Sur une grille de soixante cases, trois quasi-blancs ne font pas trois etats.

     CE SONT DES FONDS, PAS DES ACCENTS : la meme famille froide, plus affirmee. La
     palette et son petrole ne bougent pas. */
  --afaire-voile:#c6dcd9; --faite-voile:#e4e8e7;
  --bord:#d5dddb; --bord-net:#b9c6c4;

  /* --- Les deux tons de la marque ---
     ILS SONT ICI, ET NON DANS QUATRE FICHIERS D'IMAGE. Une planche de charte livre la marque
     sur fond clair, sur fond transparent et sur fond sombre : quatre exports pour un seul
     dessin, donc quatre endroits ou une retouche s'oublie. Le bandeau redefinit ces deux
     variables, et sa version claire en decoule sans second fichier. */
  --logo-encre:#1e5b38; --logo-eclat:#a98d4f;

  /* --- 1. Echelle typographique : six crans, et un seul hors-piste ---
     Toute taille de texte du fichier vient de cette liste. La verification est
     mecanique : « grep font-size:[0-9] app.css » ne doit renvoyer que la ligne
     du .sejour, dont le libelle disparait en vue trimestre (font-size:0). */
  --t-micro:11px;    /* capitales mono : etiquettes, meta, labels de champ */
  --t-petit:13px;    /* aide, texte secondaire, menu, onglets */
  --t-controle:14px; /* boutons, cases, champs de recherche, liens de liste */
  --t-base:15px;     /* corps, champs de saisie, noms */
  --t-moyen:17px;    /* titres de section */
  --t-titre:26px;    /* titre de page, une fois par ecran */

  /* Le monospace parait plus gros que le sans a taille nominale egale : ses
     caracteres ont tous la largeur du plus large. Un cran en dessous n'est donc
     pas une entorse a l'echelle, c'est ce qui les fait paraitre de meme taille. */
  --t-mono:12.5px;

  /* --- 2. Rythme d'espacement, base 4 px. Le nom est le multiplicateur. --- */
  --e1:4px; --e2:8px; --e3:12px; --e4:16px; --e5:20px; --e6:24px; --e8:32px; --e12:48px;

  /* LA MARGE LATERALE DE L'APPLICATION, EN UN SEUL ENDROIT.
     Elle etait ecrite quatre fois — une dans « .page », trois dans « .pleine-largeur » — et les
     quatre DOIVENT concorder : un bloc pleine largeur qui ne s'aligne pas sur le contenu
     ordinaire produit un decalage de quelques pixels, visible partout et long a nommer. */
  --marge-page:48px;

  /* --- 3. Elevation. L'ombre est teintee a l'encre, jamais au noir. --- */
  --ombre1:0 1px 2px rgba(22,38,43,.05), 0 1px 1px rgba(22,38,43,.04);
  --ombre2:0 2px 4px rgba(22,38,43,.06), 0 6px 16px rgba(22,38,43,.06);
  --ombre3:0 4px 8px rgba(22,38,43,.08), 0 12px 32px rgba(22,38,43,.10);
  --anneau:0 0 0 3px rgba(47,93,98,.16);

  /* --- 4. Mouvement --- */
  --vite:120ms cubic-bezier(.4,0,.2,1);
  --doux:200ms cubic-bezier(.4,0,.2,1);

  /* Rayons legerement adoucis : 4 px au lieu de 3 sur les elements de saisie,
     6 px sur les cartes. Assez pour ne plus paraitre brut, pas assez pour perdre
     le caractere administratif que l'application assume. */
  --rayon:4px; --rayon-carte:6px; --rayon-puce:3px;

  --mono:ui-monospace,"SF Mono",Menlo,Consolas,monospace;
}

*{box-sizing:border-box}

/* =============================== L'ATTRIBUT « hidden » CACHE VRAIMENT ===========
   CE DEFAUT A ETE TROUVE PAR UN UTILISATEUR, et voici pourquoi il etait invisible.

   « hidden » n'est pas un mecanisme du navigateur : c'est une simple regle de SA feuille
   de style, « [hidden]{display:none} ». Or toute regle d'AUTEUR l'emporte sur la feuille du
   navigateur, quelle que soit la specificite — c'est la cascade, pas un conflit de poids.

   Consequence : tout element portant a la fois « hidden » et une classe qui declare
   « display » restait VISIBLE. Cinq cas dans ce projet, dont le plus couteux : le bloc des
   dates du panneau des sejours, « <div class="champs" data-sejour-dates hidden> ». Comme
   .champs declare display:grid, les dates s'affichaient sur TOUTES les reservations, y
   compris celles importees d'une plateforme — que le script prend soin de rendre
   inenvoyables en leur retirant leur « name ». On pouvait donc taper une date sur un sejour
   Airbnb, l'ecran l'acceptait, et rien ne partait. Trois autres cas montraient des boutons
   qui n'agissent qu'avec JavaScript.

   Le piege etait deja connu : « .bloc-chambre[hidden]{display:none} » vivait plus bas dans
   ce fichier — une rustine posee sur un seul cas, jamais generalisee. Elle a disparu, cette
   regle-ci la couvre.

   « !important » EST ICI A SA PLACE, et c'est l'un des rares endroits ou il l'est : la
   demande « cet element est cache » doit primer sur toute mise en forme, sinon elle ne veut
   rien dire. C'est ce que font les feuilles de normalisation. */
[hidden]{display:none !important}

body{
  margin:0; background:var(--fond); color:var(--encre);
  font:var(--t-base)/1.55 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
}
a{color:var(--accent-fonce)}

/* Anneau de focus a la place du contour : il epouse le rayon de l'element et se
   superpose sans decaler la mise en page. */
:focus-visible{outline:2px solid var(--accent); outline-offset:2px}
input:focus-visible, select:focus-visible, textarea:focus-visible{outline:none}

/* --- Icones ---
   Dimensionnees en em pour suivre le texte qui les accompagne, et colorees par
   currentColor : un meme symbole sert sur un bouton clair, dans le bandeau
   sombre et dans un message d'erreur, sans variante. */
.i{
  width:1.05em; height:1.05em; flex:none;
  fill:none; stroke:currentColor; stroke-width:1.75;
  stroke-linecap:round; stroke-linejoin:round;
  vertical-align:-.15em;
}
.i-grande{width:26px; height:26px; stroke-width:1.5}

/* --- Bandeau --- */
.bandeau{
  background:var(--accent-fonce); color:#dce8e7;
  display:flex; align-items:center; gap:var(--e4); flex-wrap:wrap;
  padding:var(--e3) var(--e6);
  box-shadow:var(--ombre2);
  position:relative; z-index:10;
}
/* --- La marque ---
   « .marque » A DISPARU AVEC SON TEXTE. Le bandeau portait « CONCIERGERIE / interventions » en
   capitales monospace ; le logo porte son propre nom. Les garder tous les deux aurait fait deux
   marques a 3 px l'une de l'autre, ce qui se lit comme un oubli plutot que comme une signature.

   LE BANDEAU CENTRE DESORMAIS SES ELEMENTS, ET C'ETAIT « baseline ». L'alignement sur la ligne
   d'ecriture etait juste entre deux textes — le nom et le menu partageaient leur assise. Un
   symbole dessine n'a pas de ligne d'ecriture : un element remplace s'aligne par son bord
   inferieur, ce qui aurait fait flotter le menu contre le bas de la cle. */
.logo{display:inline-flex; align-items:center; gap:var(--e3)}
.logo-symbole{
  width:auto; flex:none;
  fill:none; stroke:var(--logo-encre); stroke-width:2;
  stroke-linecap:round; stroke-linejoin:round;
}
/* Les corps sont pleins, le contour et la cle sont traces : c'est ce qui donne au symbole sa
   lisibilite a 26 px, ou un dessin tout en filets se refermerait sur lui-meme. */
.logo-corps-encre{fill:var(--logo-encre); stroke:none}
.logo-corps-eclat{fill:var(--logo-eclat); stroke:none}
.logo-cle{stroke:var(--logo-eclat)}
.logo-texte{display:flex; flex-direction:column; gap:var(--e1)}
.logo-nom{
  font-size:var(--t-moyen); font-weight:700; letter-spacing:.14em;
  text-transform:uppercase; color:var(--logo-encre); line-height:1;
}
.logo-signature{
  font-family:var(--mono); font-size:var(--t-micro); letter-spacing:.08em;
  text-transform:uppercase; color:var(--logo-eclat); line-height:1.25;
}
/* LE LOGO DU BANDEAU EST PASSE DE 26 A 34 PX. C'est la demande de la maquette, et cela
   change l'equilibre du bandeau entier : le nom du produit ne se lisait pas comme le
   premier element de la page, il se lisait comme une etiquette parmi les entrees de menu. */
.logo-bandeau .logo-symbole{height:34px}
.bandeau .logo-nom{font-size:var(--t-controle); letter-spacing:.16em}
.logo-complet .logo-symbole{height:58px}
.logo-complet .logo-nom{font-size:var(--t-titre); letter-spacing:.1em}

/* Sur le bandeau sombre, le vert profond deviendrait illisible : les deux tons basculent sur le
   couple blanc et or, qui est la troisieme ligne de la planche de charte. */
.bandeau .logo{--logo-encre:#fff; --logo-eclat:#cbb677}

/* --- Les ecrans a carte unique ---
   LA COLONNE FAIT 540 PX, ET CE N'EST PAS UN NOMBRE CHOISI ICI : c'est la largeur de « .carte »,
   posee pour la connexion — deux champs qu'on ne veut pas etaler. La colonne l'adopte, donc la
   carte la remplit exactement, et rien ne depasse d'un cote.

   « .page » CENTRE DEJA SES 1060 PX. La carte, elle, restait collee au bord gauche de ces
   1060 px : sur un ecran large, le logo etait au milieu et les champs a un tiers. C'est ce
   decalage qu'on supprime — la page etait centree, son contenu ne l'etait pas. */
.ecran-centre{max-width:540px; margin:0 auto}

/* La marque, au-dessus du formulaire.

   L'INTITULE N'EST PAS CENTRE, LUI. Il partage son bord gauche avec la carte, avec les libelles
   des champs et avec le bouton : une seule verticale pour tout ce qui se lit. Le logo est la
   seule piece centree, parce qu'un bloc symbole-plus-nom se lit comme un ensemble et non comme
   une ligne de texte. */
.accueil-marque{display:flex; justify-content:center; margin-bottom:var(--e6)}

/* Sous 620 px, la marque complete s'empile. Sa signature ferait autrement trois lignes serrees
   a cote du symbole : le texte se comprime avant de passer a la ligne, et c'est le symbole qui
   tient la largeur. Empilee et centree, elle reste une signature. */
@media (max-width:620px){
  .logo-complet{flex-direction:column; text-align:center; gap:var(--e3)}
  .logo-complet .logo-texte{align-items:center}
}
.bandeau .menu{display:flex; gap:var(--e1); font-size:var(--t-petit); flex-wrap:wrap}
.bandeau .menu a{
  color:#bfd6d4; text-decoration:none;
  display:inline-flex; align-items:center; gap:var(--e2);
  padding:var(--e2) var(--e3); border-radius:var(--rayon);
  transition:background var(--vite), color var(--vite);
}
.bandeau .menu a:hover{color:#fff; background:rgba(255,255,255,.09)}
/* « flex-wrap » A DISPARU, ET C'EST VOULU. Il servait quand l'identite tenait sur une ligne :
   le bloc pouvait se replier. Empilee, l'identite ne se replie plus — mais le FILET, lui,
   se retrouvait seul sur une ligne des que la place manquait, ce qui donnait un trait
   horizontal en travers du bandeau. Ces maquettes sont dessinees pour un ecran d'ordinateur ;
   sous cette largeur, le bandeau defile plutot que de se disloquer. */
.bandeau .qui{
  margin-left:auto; font-size:var(--t-petit); color:#a8c4c2;
  display:inline-flex; align-items:center; gap:var(--e3);
}
/* L'IDENTITE EMPILEE. « align-items:center » sur « .qui » aligne la vignette, la colonne de
   texte, le filet et le bouton sur un meme axe — c'est ce qui evite que le bouton de
   deconnexion se retrouve a la hauteur du role plutot qu'au milieu du bloc. */
.bandeau .qui-identite{
  display:flex; flex-direction:column; line-height:1.25; gap:1px;
}
.bandeau .qui strong{color:#fff; font-weight:600}
/* Le role est une precision, pas une identite : un cran plus bas en contraste comme en
   taille. Le mettre au meme niveau que le nom ferait hesiter sur ce qu'on doit lire. */
.bandeau .qui-role{font-size:var(--t-micro); color:#8fb0ad}
/* LE FILET : un trait vertical, pose sur la hauteur du bloc d'identite et non sur celle du
   bandeau — un trait pleine hauteur decouperait le bandeau en deux. */
.bandeau .qui-filet{
  width:1px; align-self:stretch; margin:0 var(--e2);
  background:rgba(255,255,255,.22);
}
/* Le bandeau est sombre : la bordure claire de la vignette y disparaitrait, et la photo
   flotterait sans contour. Les initiales, elles, gardent leur fond clair — c'est ce qui les
   rend lisibles sur ce fond-la. */
.bandeau .avatar{border-color:rgba(255,255,255,.28)}
.bandeau form{display:inline; margin-left:var(--e2)}
.bandeau button{
  background:none; border:0; padding:var(--e1) 0; cursor:pointer;
  color:#dce8e7; font-size:var(--t-petit); font-family:inherit;
  display:inline-flex; align-items:center; gap:var(--e1);
  border-bottom:1px solid rgba(220,232,231,.35);
  transition:color var(--vite), border-color var(--vite);
}
.bandeau button:hover{color:#fff; border-color:#fff}

/* --- Structure --- */
/* La marge du BAS est plus haute que les autres, et ce n'est pas de l'esthetique : les
   barres collantes (.barre-enregistrer, .barre-flottante) restent epinglees au bas de la
   fenetre tant qu'on n'a pas defile jusqu'a leur place naturelle. Sans assez de course
   apres elles, le dernier bloc de la page reste sous la barre, hors d'atteinte. Il faut
   donc au moins la hauteur d'une barre. */
.page{max-width:1060px; margin:0 auto; padding:var(--e8) var(--marge-page) 96px}
.entete{
  display:flex; align-items:flex-end; gap:var(--e4); flex-wrap:wrap;
  margin-bottom:var(--e6);
}
.entete h1{
  margin:0; font-size:var(--t-titre); font-weight:600; letter-spacing:-.015em;
  line-height:1.15;
}
.entete .compte{
  font-family:var(--mono); font-size:var(--t-micro); color:var(--encre-douce);
  padding-bottom:var(--e1); display:inline-flex; align-items:center; gap:var(--e1);
  text-transform:uppercase; letter-spacing:.06em;
}
.entete .actions{margin-left:auto; display:flex; gap:var(--e2); flex-wrap:wrap}

/* UN EN-TETE QUI PORTE UN BOUTON FAISAIT DESCENDRE SON TITRE, ET LE CALCUL EST SANS AMBIGUITE.
   « .entete » aligne ses enfants en BAS — ce qui pose joliment le compte sur la ligne de base du
   titre, tant que rien n'est plus haut que lui. Un « .btn » mesure 36 px (14 de texte, 2 x 10 de
   remplissage, 2 de bordure) et le titre 30 (26 px sur une interligne de 1.15) : le titre etait
   donc pousse de six pixels vers le bas, et l'on comparait deux ecrans en se demandant lequel
   avait tort.

   « baseline » DIT L'INTENTION QU'ON AVAIT, et resiste a un voisin plus grand : le titre et son
   compte partagent leur ligne de base, le bouton s'aligne sur la sienne — donc optiquement centre
   sur le titre — et c'est le titre, dont la hauteur au-dessus de la base est la plus grande, qui
   fixe le haut de la rangee. Il retrouve exactement la place qu'il a sur un ecran sans bouton.

   LE MODIFICATEUR EST « :has(.actions) » ET NON UN CHANGEMENT DE « .entete » : sur un en-tete qui
   ne porte que son titre et son compte, l'alignement en bas ne pose aucun probleme et n'a pas a
   changer. Cette regle-ci corrige les DIX ecrans dont l'en-tete porte un bouton, pas les autres. */
.entete:has(.actions){align-items:baseline}

/* --- Boutons ---
   L'ombre et le leger enfoncement a l'appui sont ce qui rend un bouton tactile
   plutot que dessine. */
.btn{
  display:inline-flex; align-items:center; justify-content:center; gap:var(--e2);
  font:500 var(--t-controle)/1 inherit; font-family:inherit;
  padding:10px var(--e4); border-radius:var(--rayon); border:1px solid transparent;
  cursor:pointer; text-decoration:none; text-align:center; white-space:nowrap;
  transition:background var(--vite), border-color var(--vite),
             box-shadow var(--vite), transform var(--vite);
}
.btn:active{transform:translateY(1px)}
.btn-primaire{background:var(--accent); color:#fff; box-shadow:var(--ombre1)}
.btn-primaire:hover{background:var(--accent-fonce); box-shadow:var(--ombre2)}
.btn-neutre{
  background:var(--surface); color:var(--encre); border-color:var(--bord-net);
  box-shadow:var(--ombre1);
}
.btn-neutre:hover{background:var(--surface-creuse); border-color:var(--encre-tenue)}
.btn-lien{
  display:inline-flex; align-items:center; gap:var(--e1);
  background:none; border:0; padding:var(--e1) 0; cursor:pointer;
  font:inherit; font-size:var(--t-petit); color:var(--accent-fonce);
  text-decoration:none; border-bottom:1px solid transparent;
  transition:color var(--vite), border-color var(--vite);
}
.btn-lien:hover{border-bottom-color:currentColor}
.btn-lien.danger{color:var(--alerte)}

/* --- UN BOUTON DESACTIVE DOIT EN AVOIR L'AIR ---
   IL N'Y AVAIT AUCUNE REGLE POUR CELA, et c'est un manque de fond, pas un oubli local : un
   « .btn-primaire » desactive gardait son fond d'accent et son texte blanc. Rien ne le distinguait
   d'un bouton actif — sinon l'absence de survol, qu'on ne remarque qu'apres avoir clique. On cliquait
   donc, rien ne se passait, et l'on cherchait ce qu'on avait mal fait.

   LA REGLE EST GENERALE, ET C'EST VOULU. Un bouton desactive se lit de la meme facon partout dans
   l'application ; la poser sur un seul ecran aurait laisse les autres mentir.

   LA SPECIFICITE EST CE QUI COMPTE ICI. « .btn:disabled » vaut deux classes — une pseudo-classe en
   compte pour une — donc il l'emporte sur « .btn-primaire », qui n'en vaut qu'une. Et il est declare
   APRES les variantes, ce qui le fait gagner aussi contre « .btn-primaire:hover », a specificite
   egale. Sans ces deux precautions, la regle serait la et ne s'appliquerait pas — l'exacte panne que
   cet ecran a payee trois fois.

   ON NEUTRALISE AUSSI LE SURVOL ET L'APPUI : un bouton qui s'assombrit sous le curseur, ou qui
   s'enfonce au clic, se dit cliquable quelle que soit sa couleur. Le geste ment plus fort que la
   teinte. */
.btn:disabled,
.btn[disabled]{
  background:var(--surface-creuse); color:var(--encre-tenue);
  border-color:var(--bord); box-shadow:none;
  cursor:not-allowed;
}
.btn:disabled:hover,
.btn[disabled]:hover{
  background:var(--surface-creuse); color:var(--encre-tenue);
  border-color:var(--bord); box-shadow:none;
}
.btn:disabled:active,
.btn[disabled]:active{transform:none}
/* L'icone suit le texte : une icone restee a pleine encre sur un fond pale se lit comme une faute
   d'affichage, et non comme un etat. */
.btn:disabled .i,
.btn[disabled] .i{opacity:.7}

/* --- Messages --- */
.flash{
  border-left:3px solid; border-radius:0 var(--rayon) var(--rayon) 0;
  padding:var(--e3) var(--e4); margin-bottom:var(--e3);
  background:var(--surface); font-size:var(--t-controle);
  display:flex; gap:var(--e3); align-items:flex-start;
  box-shadow:var(--ombre1);
}
.flash .i{margin-top:2px}
.flash-corps{flex:1; min-width:0}
.flash.succes{border-color:var(--accent); background:var(--accent-voile)}
.flash.erreur{border-color:var(--alerte); background:var(--alerte-voile)}
.flash.lien{border-color:var(--attente); background:var(--attente-voile)}
.flash-lien-boite{
  display:flex; gap:var(--e2); margin-top:var(--e3); align-items:stretch; flex-wrap:wrap;
}
.flash-lien-boite input{
  flex:1 1 280px; font-family:var(--mono); font-size:var(--t-mono);
  padding:var(--e2) 10px; border:1px solid var(--bord-net); border-radius:var(--rayon);
  background:var(--surface); color:var(--encre);
}

/* --- Registre : signature de l'interface ---
   Chaque ligne porte un onglet vertical dont la couleur encode l'etat du compte,
   comme un porte-cles derriere un comptoir. Les acces revoques sont hachures, pas
   seulement grises : l'etat se lit sans lire le libelle.

   Le registre garde ses filets internes — c'est une liste dense, la separation
   ligne a ligne y est de l'information. Ce sont les CARTES qui passent de la
   bordure a l'ombre. */
.registre{
  background:var(--surface); border-radius:var(--rayon-carte);
  box-shadow:var(--ombre1); overflow:hidden;
}
.ligne{
  display:grid; grid-template-columns:5px 1fr auto; align-items:center;
  border-bottom:1px solid var(--bord);
  transition:background var(--vite);
}
.ligne:last-child{border-bottom:0}
.ligne:hover{background:var(--surface-creuse)}
.ligne .onglet{align-self:stretch; background:var(--accent)}
.ligne.attente .onglet{background:var(--attente)}
.ligne.revoque .onglet{background:var(--bord-net)}
.ligne.verrouille .onglet{background:var(--alerte)}
.ligne.verrouille{background:var(--alerte-voile)}
.ligne.revoque{
  background-image:repeating-linear-gradient(
    -45deg, transparent 0 7px, rgba(90,110,116,.07) 7px 14px);
}
.ligne.revoque .identite .nom{color:var(--encre-douce)}
/* --- Une ligne qui porte une vignette ---
   .ligne est une GRILLE a trois colonnes : le liseret, l'identite, les commandes. Y glisser une
   quatrieme case sans le dire ferait tomber les commandes sur une seconde rangee — le genre de
   defaut qui ne se voit qu'a l'ecran, jamais dans une chaine de HTML.

   Un modificateur plutot qu'un elargissement de .ligne : ce meme balisage sert le registre des
   utilisateurs, la liste des interventions et la fiche d'un bien, et deux de ces trois n'ont
   pas de vignette. Leur reserver une colonne vide les decalerait toutes. */
.ligne-portrait{grid-template-columns:5px auto 1fr auto}
.ligne-portrait > .avatar,
.ligne-portrait > .avatar-lien{margin-left:var(--e4)}

.identite{padding:var(--e4) var(--e4); min-width:0}
.identite .nom{
  margin:0 0 2px; font-size:var(--t-base); font-weight:600;
  display:flex; align-items:center; gap:var(--e2); flex-wrap:wrap;
}
.identite .email{
  font-family:var(--mono); font-size:var(--t-mono); color:var(--encre-douce);
  overflow-wrap:anywhere;
}
.identite .meta{
  margin-top:var(--e1); font-family:var(--mono); font-size:var(--t-micro);
  color:var(--encre-tenue); text-transform:uppercase; letter-spacing:.06em;
}
.commandes{
  padding:var(--e4); display:flex; gap:var(--e4); align-items:center;
  flex-wrap:wrap; justify-content:flex-end;
}

/* --- Etiquettes --- */
.etiquette{
  display:inline-flex; align-items:center; font-family:var(--mono);
  font-size:var(--t-micro); letter-spacing:.09em; text-transform:uppercase; font-weight:600;
  padding:3px 7px; border-radius:var(--rayon-puce); white-space:nowrap;
}
.etiquette.actif{background:var(--accent-voile); color:var(--accent-fonce)}
.etiquette.attente{background:var(--attente-voile); color:var(--attente)}
.etiquette.revoque{background:#e7ebea; color:var(--encre-douce)}
/* « neutre » : un FAIT, ni un etat ni une alerte — « 3 nuits », « creneau non fixe ».
   MEME DESSIN QUE « revoque », ET UN AUTRE NOM QUAND MEME. Les deux se ressemblent parce qu'un
   fait et un etat eteint reculent tous deux au meme plan ; mais « revoque » sur le nombre de nuits
   d'un sejour dirait que le sejour est revoque. Un nom qui mentira un jour mentira au moment ou
   quelqu'un s'y fiera. */
.etiquette.neutre{background:#e7ebea; color:var(--encre-douce)}
/* « alerte » : un manque a corriger, non un etat verrouille — d'ou une variante a soi
   plutot que le detournement de .verrouille, dont le nom dirait autre chose.

   ROUGE MAIS PAS PLEIN : le fond plein de .verrouille ecrase la ligne et l'on ne lit plus le
   nom du bien a cote. Texte rouge sur fond rouge pale, avec un liseret : aussi visible, et
   la ligne reste lisible. */
.etiquette.alerte{
  background:var(--alerte-voile); color:var(--alerte);
  border:1px solid var(--alerte); font-weight:600;
}
.etiquette.alerte .i{width:11px; height:11px; margin-right:var(--e1); stroke-width:2.25}
.etiquette.verrouille{background:var(--alerte); color:#fff}
.etiquette.verrouille .i{width:11px; height:11px; margin-right:var(--e1); stroke-width:2.25}
/* Le role est une etiquette au trait, l'etat une etiquette pleine : deux
   informations de nature differente ne doivent pas se ressembler. */
.etiquette.role{background:none; color:var(--encre-douce); border:1px solid var(--bord-net)}
.etiquette.role .i{width:12px; height:12px; margin-right:var(--e1); stroke-width:2}

/* Ligne visible mais hors du perimetre d'action : on occupe la place des
   commandes pour que l'absence de bouton se lise comme une regle, pas un bogue. */
.hors-portee{
  display:inline-flex; align-items:center; gap:var(--e1);
  font-family:var(--mono); font-size:var(--t-micro); color:var(--encre-tenue);
  text-transform:uppercase; letter-spacing:.06em;
}

/* --- Rattachement --- */
.rattachement{
  margin-top:var(--e1); display:flex; align-items:center; gap:var(--e2);
  font-size:var(--t-petit); color:var(--accent-fonce);
}
/* L'ABSENCE, DITE COMME UNE ABSENCE.

   Elle etait ecrite dans dix-sept vues et stylee dans deux contextes seulement : partout
   ailleurs — la liste des interventions, celle des biens, celle des clients — « Aucun client »
   ou « creneau a fixer » sortait en texte ordinaire, donc lisible comme une vraie valeur.

   L'ITALIQUE PLUTOT QUE LA COULEUR SEULE : un gris pale sur un tableau deja gris ne se
   distingue pas, et la couleur seule ne dit rien a qui ne la voit pas. */
.orphelin{color:var(--encre-tenue); font-style:italic}

.rattachement .orphelin{
  font-family:var(--mono); font-size:var(--t-micro); color:var(--attente);
  text-transform:uppercase; letter-spacing:.05em;
}

/* --- Cartes ---
   Ici le changement le plus visible : la bordure d'un pixel disparait au profit
   d'une ombre. Une carte doit sembler posee sur le fond, pas decoupee dedans. */
.carte{
  background:var(--surface); border-radius:var(--rayon-carte);
  box-shadow:var(--ombre1); padding:var(--e6); max-width:540px;
}
/* 540 px conviennent a une connexion — deux champs, on ne veut pas les etaler.
   Des qu'un formulaire passe en grille, il lui faut de la place : 820 px tiennent
   deux colonnes confortables sans que l'oeil ait a traverser tout l'ecran. */
.carte-formulaire{max-width:820px}
.carte-large{max-width:820px; margin-top:var(--e6)}
.sous-titre{
  display:flex; align-items:center; gap:var(--e3);
  margin:0 0 var(--e6); font-size:var(--t-moyen); font-weight:600;
  padding-bottom:var(--e4); border-bottom:1px solid var(--bord);
  letter-spacing:-.01em;
}
/* Un intertitre DANS un formulaire, pour separer deux familles de champs — les plafonds et
   les tarifs d'une offre. Il ne reprend pas « .sous-titre » : le meme trait sous deux titres
   d'une meme carte donnerait deux sections d'egale importance, alors qu'il s'agit de deux
   groupes d'un seul formulaire. Plus petit, sans bordure, moins d'air au-dessus. */
.sous-titre-mineur{
  margin:var(--e5) 0 var(--e2); font-size:var(--t-controle); font-weight:600;
  color:var(--encre-douce); text-transform:uppercase; letter-spacing:.04em;
}

.sous-titre .compteur{
  margin-left:auto; font-family:var(--mono); font-size:var(--t-mono); font-weight:500;
  color:var(--encre-douce); background:var(--surface-creuse);
  border-radius:var(--rayon-puce); padding:3px var(--e2);
}
.registre-imbrique{box-shadow:none; border:1px solid var(--bord)}
.registre-imbrique .identite{padding:var(--e3) var(--e3)}
.registre-imbrique .commandes{padding:var(--e3)}

/* --- Formulaires ---
   Concus pour un ecran d'ordinateur : les champs se rangent sur deux ou trois
   colonnes plutot qu'en une seule pile. Un formulaire de compte tenait sur cinq
   rangees et 1100 px de haut ; il en occupe trois et tient dans une fenetre.
   Sous 760 px, la grille retombe a une colonne d'elle-meme.

   La regle de repartition : on regroupe par LONGUEUR de saisie, pas par theme.
   Un code postal et une ville tiennent cote a cote parce qu'on les tape d'un
   geste ; une adresse electronique prend toute la largeur parce qu'elle est
   longue et qu'un champ tronque se relit mal. */
.champs{display:grid; grid-template-columns:repeat(2, minmax(0,1fr)); gap:0 var(--e6)}
.champs-trois{grid-template-columns:repeat(3, minmax(0,1fr))}
.champ-large{grid-column:1 / -1}

/* Espacement vertical resserre : la grille prend en charge l'horizontal, et 20 px
   suffisent a separer deux rangees dont les libelles sont deja en capitales. */
.champ{margin-bottom:var(--e5)}
.champ label{
  display:block; margin-bottom:var(--e2); font-size:var(--t-micro); font-weight:600;
  letter-spacing:.06em; text-transform:uppercase; color:var(--encre-douce);
}
/*
 | LES CONTROLES D'UNE LISTE DE DEFINITIONS PARTAGENT LE STYLE DES CHAMPS.
 |
 | La section « L'intervention » est passee au modele libelle/valeur de la reservation — une
 | <dl>, comme le reste des fiches. Mais l'enveloppe « .champ » etait LA SEULE definition du
 | style des controles : en la retirant, selects et champs de date sont retombes aux valeurs
 | par defaut du navigateur, au milieu d'une application qui les habille partout ailleurs.
 |
 | ON ETEND LE SELECTEUR PLUTOT QUE DE RECOPIER LA REGLE. Une seconde declaration aux valeurs
 | voisines aurait diverge au premier ajustement — et c'est exactement ce qui avait produit
 | trois defauts d'un coup sur la matrice des notifications : un tableau ecrit a cote des
 | regles existantes au lieu de les reprendre.
 */
.champ input, .champ select, .champ textarea,
.fiche-technique dd input, .fiche-technique dd select, .fiche-technique dd textarea,
.quota-case input{
  width:100%; padding:10px var(--e3); font:inherit; font-size:var(--t-base);
  border:1px solid var(--bord-net); border-radius:var(--rayon);
  background:var(--surface); color:var(--encre);
  transition:border-color var(--vite), box-shadow var(--vite);
}
.champ textarea{font-size:var(--t-base); resize:vertical; line-height:1.55}
.champ input:hover, .champ select:hover, .champ textarea:hover,
.fiche-technique dd input:hover, .fiche-technique dd select:hover, .quota-case input:hover{border-color:var(--encre-tenue)}
.champ input:focus, .champ select:focus, .champ textarea:focus,
.fiche-technique dd input:focus, .fiche-technique dd select:focus, .quota-case input:focus{
  border-color:var(--accent); box-shadow:var(--anneau);
}

/*
 | DANS UNE <dl>, LES CONTROLES NE PRENNENT PAS TOUTE LA LARGEUR.
 |
 | « width:100% » convient a un champ empile sous son libelle ; dans la colonne de droite d'une
 | liste de definitions, une date occuperait alors toute la fiche. Ils se dimensionnent donc sur
 | leur contenu, et la ligne « date + heure + duree » tient sur une rangee.
 */
.fiche-technique dd input, .fiche-technique dd select{width:auto; max-width:100%}
.fiche-technique dd .champs-serres{flex-wrap:wrap; align-items:center}
.champ input:disabled{background:var(--surface-creuse); color:var(--encre-douce)}
.champ .aide{margin-top:var(--e2); font-size:var(--t-petit); color:var(--encre-douce); line-height:1.5}
.champ .aide code{font-family:var(--mono); font-size:var(--t-mono)}
.aide.encadre{
  background:var(--surface-creuse); padding:var(--e3) var(--e4);
  border-left:3px solid var(--bord-net); border-radius:0 var(--rayon) var(--rayon) 0;
  font-size:var(--t-petit); color:var(--encre-douce); line-height:1.55;
}
/* Regroupement visuel : des champs facultatifs au milieu de champs obligatoires
   ont besoin d'une frontiere explicite. */
.bloc{
  border:1px solid var(--bord); border-radius:var(--rayon-carte);
  padding:var(--e4) var(--e4) 2px; margin:0 0 var(--e6);
  background:var(--surface-creuse);
}
.bloc legend{
  padding:0 var(--e2); font-size:var(--t-micro); font-weight:600;
  letter-spacing:.06em; text-transform:uppercase; color:var(--encre-douce);
  display:flex; align-items:center; gap:var(--e2);
}
.pied-formulaire{
  display:flex; gap:var(--e3); align-items:center; flex-wrap:wrap;
  margin-top:var(--e6); padding-top:var(--e4); border-top:1px solid var(--bord);
}
/* Conserve : .grille-deux est l'ancien nom de .champs, encore employe par la fiche
   d'un bien. Les deux pointent vers le meme comportement. */
.grille-deux{display:grid; grid-template-columns:repeat(2, minmax(0,1fr)); gap:0 var(--e6)}

/* Cases a cocher : la surface cliquable couvre le libelle entier, et la case
   coloree signale l'etat sans avoir a lire. */
.cases{display:flex; flex-wrap:wrap; gap:var(--e2) var(--e4)}
.case{
  display:inline-flex; align-items:flex-start; gap:var(--e2); cursor:pointer;
  font-size:var(--t-controle); padding:var(--e2) 10px; border-radius:var(--rayon);
  border:1px solid transparent; transition:background var(--vite), border-color var(--vite);
}
.case:hover{background:var(--surface-creuse); border-color:var(--bord)}
.case input{margin-top:2px; flex:none; accent-color:var(--accent)}
.case span{display:flex; flex-direction:column; line-height:1.35}
.case em{font-style:normal; font-size:var(--t-micro); color:var(--encre-tenue); font-family:var(--mono)}

.titre-ajout{
  display:flex; align-items:center; gap:var(--e2); margin:0;
  padding-top:var(--e4); border-top:1px solid var(--bord);
  font-size:var(--t-controle); font-weight:600; color:var(--encre-douce);
}
.titre-ajout + .ajout-piece{border-top:0; padding-top:var(--e3)}
.ajout-piece{border-top:1px solid var(--bord); padding-top:var(--e4)}

/* Edition en ligne : le champ ne se signale qu'au survol, pour que la liste
   reste une liste et non un formulaire. */
/* Acces aux sejours depuis le planning : la seule porte d'entree d'un proprietaire,
   qui n'atteint pas le registre des biens. */
/* --- Liens dans l'en-tete ---
   A la suite des informations du bien : ce sont des deplacements vers sa fiche et ses
   tarifs, pas des actions sur cet ecran. Des liens, donc, et le meme vocabulaire que la
   liste des biens — des boutons y auraient donne le meme poids qu'a « enregistrer ». */
.entete-liens{
  display:inline-flex; align-items:center; gap:var(--e3); flex-wrap:wrap;
  margin-left:var(--e3); padding-left:var(--e3);
  border-left:1px solid var(--bord);
  text-transform:none; letter-spacing:0; font-family:inherit;
}

/* --- Onglets d'un ecran ---
   Plus marques que les onglets d'echelle du planning : ils changent ce que l'ecran MONTRE,
   pas seulement la fenetre de temps. */
.onglets-larges{margin-bottom:var(--e6)}
.onglets-larges a{
  padding:var(--e3) var(--e5); font-size:var(--t-controle); font-weight:500;
  display:inline-flex; align-items:center; gap:var(--e2);
}

/* --- Atelier : calendrier a gauche, edition a droite ---
   Le panneau reste visible pendant qu'on parcourt le calendrier : c'est ce qui permet de
   corriger sans quitter la vue. Il colle en haut pour rester atteignable sur un trimestre
   qui defile. En dessous de 1024 px il passe sous le calendrier — deux colonnes de 300 px
   ne servent personne. */
/* 380 px et non 340 : « Enregistrer » et « Annuler le sejour » doivent tenir sur une seule
   ligne, et 340 px les faisait passer a la ligne de deux pixels. Raccourcir le libelle
   aurait ete plus simple mais ambigu — « Annuler » a cote d'« Enregistrer » se lit comme
   « annuler la saisie ». Les 40 px viennent du calendrier, qui en a de reste. */
.atelier{display:grid; grid-template-columns:minmax(0,1fr) 380px; gap:var(--e6); align-items:start}
/* La rangee des onglets a disparu : ils sont dans l'en-tete, a gauche du bouton. */
.atelier-calendrier{max-width:none; margin-top:0}
.panneau{max-width:none; margin-top:0; position:sticky; top:var(--e4)}
/* L'en-tete du panneau : son titre, et la croix qui le referme.
   « .sous-titre » porte deja le filet du dessous ; il l'etale sur toute la largeur, la croix doit
   donc etre DANS la rangee du titre et non a cote — sinon le filet passe entre les deux. */
.panneau-entete{display:flex; align-items:flex-start; gap:var(--e3)}
.panneau-entete .sous-titre{flex:1 1 auto; margin-bottom:var(--e5)}
/* La croix s'aligne sur la premiere ligne du titre, pas sur le milieu du bloc : le titre porte un
   filet sous lui, et se caler au centre ferait descendre la croix sur ce filet. */
.panneau-entete .boite-fermer{margin-top:2px}
.panneau .nom{margin:0 0 var(--e3); font-size:var(--t-base); font-weight:600}
.panneau-bloc .champ{margin-bottom:var(--e4)}
.panneau-technique{grid-template-columns:minmax(84px, auto) 1fr; gap:2px var(--e3)}
.panneau-technique dd{margin-bottom:var(--e2)}
.panneau .pied-formulaire{margin-top:var(--e4); padding-top:var(--e4)}

/* --- CE QUE LE DEPLACEMENT CONTIENT ---
   Une ligne par prestation, sur un fond creux : le panneau enchaine plusieurs blocs, et un liste
   sans fond se confondrait avec les mentions d'aide qui l'entourent. Les quantites en chiffres
   tabulaires, pour qu'elles s'alignent d'une ligne a l'autre. */
.panneau-lignes{
  list-style:none; margin:0 0 var(--e4); padding:var(--e2) var(--e3);
  background:var(--surface-creuse); border-radius:var(--rayon);
  font-size:var(--t-controle);
}
.panneau-lignes li{
  display:flex; align-items:baseline; gap:var(--e2);
  padding:3px 0;
}
.panneau-lignes li + li{border-top:1px solid var(--bord)}
.panneau-ligne-nom{flex:1 1 auto; min-width:0}
.panneau-ligne-quantite{
  flex:none; font-family:var(--mono); font-size:var(--t-micro);
  color:var(--encre-douce); font-variant-numeric:tabular-nums;
}

/* --- LE COMPTE RENDU ---
   Ce que l'intervenant a constate, et la seule chose qu'il puisse ecrire sur la fiche. Un filet a
   gauche plutot qu'un cadre : c'est une CITATION — les mots de quelqu'un d'autre — et non un encadre
   d'alerte. « pre-wrap » garde les retours a la ligne qu'il a saisis ; sans cela, un compte rendu en
   trois paragraphes se lit comme une seule phrase. */
.panneau-rendu{
  margin-bottom:var(--e4); padding-left:var(--e3);
  border-left:3px solid var(--accent);
}
.panneau-rendu-titre{
  display:flex; align-items:center; gap:var(--e2);
  margin:0 0 var(--e2); font-size:var(--t-petit); font-weight:600; color:var(--encre-douce);
}
.panneau-rendu-date{
  margin-left:auto; font-family:var(--mono); font-size:var(--t-micro); color:var(--encre-tenue);
}
.panneau-rendu-texte{
  margin:0; white-space:pre-wrap; font-size:var(--t-controle); line-height:1.55;
}

/* --- LA SORTIE DU PANNEAU ---
   « Voir la fiche » etait un lien discret perdu au milieu des mentions d'aide, et c'est la seule
   sortie vers l'endroit ou tout se fait. Un filet au-dessus le detache de ce qui precede : il n'est
   pas la suite du bloc, il en sort. */
.panneau-sortie{
  margin-top:var(--e4); padding-top:var(--e4); border-top:1px solid var(--bord);
}
.panneau form + form{margin-top:var(--e3)}
.panneau-titre{
  display:flex; align-items:center; gap:var(--e2);
  margin:var(--e5) 0 var(--e3); padding-top:var(--e4);
  border-top:1px solid var(--bord);
  font-size:var(--t-petit); font-weight:600; color:var(--encre-douce);
  text-transform:uppercase; letter-spacing:.05em;
}

/* Les dates du sejour en tete, au format francais : c'est ce qu'on lit pour verifier
   qu'on a clique la bonne barre. */
.panneau-dates{
  display:flex; align-items:center; gap:var(--e2); flex-wrap:wrap;
  margin:0; font-size:var(--t-moyen); font-weight:600; color:var(--encre);
}

/* Enregistrer a gauche, annuler a droite, sur la meme ligne.
   Les deux appartiennent a des formulaires differents — un <form> ne s'imbrique pas — et
   c'est l'attribut « form » du bouton d'enregistrement qui permet de les voisiner sans les
   emboiter.
   L'annulation est un LIEN : deux boutons pleins ne tiennent pas dans les 340 px du
   panneau, et une action destructrice n'a pas a peser autant du regard que l'action
   normale. */
.panneau-commandes{display:flex; align-items:center; gap:var(--e3); flex-wrap:wrap}
.panneau-commandes form{margin-left:auto}
.panneau-fleche{color:var(--encre-tenue); font-weight:400}

/* L'etat, les nuitees et l'origine sur une seule ligne : le meme contenu que la premiere
   colonne du tableau, mais compact. Une liste de definitions y prenait quatre lignes pour
   trois mots. */
.panneau-resume{
  display:flex; align-items:center; gap:var(--e2); flex-wrap:wrap;
  margin:0 0 var(--e5); font-size:var(--t-petit);
}
.panneau-nuits{font-family:var(--mono); font-size:var(--t-mono); color:var(--encre-douce)}

/* Les prestations cochables du sejour : une ligne par prestation de l'offre. */
.panneau-prestations{list-style:none; margin:0; padding:0}
.panneau-prestations li{
  display:flex; align-items:center; gap:var(--e3);
  padding:var(--e2) 0; border-bottom:1px solid var(--bord);
}
.panneau-prestations li:last-child{border-bottom:0}
.panneau-prestations input[type=number]{
  width:52px; padding:var(--e1) var(--e2); font:inherit; font-size:var(--t-controle);
  border:1px solid var(--bord-net); border-radius:var(--rayon); background:var(--surface);
}
.panneau-prestations input[type=checkbox]{accent-color:var(--accent); cursor:pointer}
.panneau-prestation-nom{display:flex; flex-direction:column; font-size:var(--t-controle)}
.panneau-prestation-nom em{
  font-style:normal; font-size:var(--t-micro); color:var(--encre-tenue);
}
.panneau-prestations .case-verrouillee{margin-left:auto}

/* --- Boite de saisie modale ---
   Le gabarit envoie <dialog open> : sans JavaScript, un dialogue ouvert et non modal
   s'affiche dans le flux, et le formulaire reste utilisable. Il faut donc qu'il ressemble
   a une carte dans ce cas, et a une modale dans l'autre — d'ou deux jeux de regles, l'un
   sur l'element, l'autre sur :modal. */
.boite{
  display:block; width:100%; max-width:none; margin:var(--e6) 0;
  background:var(--surface); color:var(--encre);
  border:1px solid var(--bord); border-radius:var(--rayon-carte);
  box-shadow:var(--ombre1); padding:var(--e6);
}
.boite:not([open]){display:none}
.boite:modal{
  width:min(680px, calc(100vw - 2 * var(--e6)));
  margin:auto; box-shadow:var(--ombre3); border-color:var(--bord-net);
}
.boite::backdrop{background:rgba(22,38,43,.42)}
.boite-entete{
  display:flex; align-items:center; gap:var(--e4);
  margin-bottom:var(--e3);
}
.boite-fermer{
  margin-left:auto; background:none; border:0; cursor:pointer;
  font-size:22px; line-height:1; color:var(--encre-tenue); padding:0 var(--e1);
  border-radius:var(--rayon); transition:color var(--vite), background var(--vite);
}
.boite-fermer:hover{color:var(--encre); background:var(--surface-creuse)}

/* --- Confirmation de bascule d'un client ---
   La case porte la decision, pas un reglage accessoire : elle est donc encadree et sur
   fond creux, pour se distinguer du texte qui l'entoure. On confirme en la lisant, et une
   case noyee dans un paragraphe se coche sans etre lue. */
.case-cascade{
  display:flex; align-items:center; gap:var(--e3); cursor:pointer;
  padding:var(--e3) var(--e4); margin-bottom:var(--e4);
  background:var(--surface-creuse); border:1px solid var(--bord-net);
  border-radius:var(--rayon); font-size:var(--t-controle);
}
.case-cascade input[type=checkbox]{width:16px; height:16px; margin:0; accent-color:var(--accent)}
.case-cascade:focus-within{border-color:var(--accent); box-shadow:var(--anneau)}

.cascade-titre{
  display:flex; align-items:center; gap:var(--e2);
  margin:0 0 var(--e2); font-size:var(--t-micro); font-weight:600;
  letter-spacing:.06em; text-transform:uppercase; color:var(--encre-douce);
}
/* Bornee en hauteur et defilante : un client a trente logements, et la liste pousserait
   les deux boutons hors de l'ecran — on confirmerait alors sans voir ce qu'on confirme. */
.cascade-liste{
  margin:0 0 var(--e4); padding:0 0 0 var(--e4); list-style:none;
  max-height:180px; overflow-y:auto; font-size:var(--t-controle);
}
.cascade-liste li{padding:3px 0; border-bottom:1px solid var(--bord)}
.cascade-liste li:last-child{border-bottom:0}

/* Case verrouillee : la prestation est validee, elle ne se decoche pas d'un tableau.
   Un champ desactive n'enverrait rien et se lirait comme une case decochee — d'ou un
   lien vers la fiche, qui dit ou la decision se prend. */
.case-verrouillee{
  display:inline-flex; align-items:center; gap:2px;
  padding:2px var(--e2); border-radius:var(--rayon);
  background:var(--accent-voile); color:var(--accent-fonce);
  font-family:var(--mono); font-size:var(--t-mono); text-decoration:none;
}
.case-verrouillee:hover{background:var(--accent); color:#fff}

/* La ligne visee depuis le calendrier, le temps de la retrouver des yeux. */
.sejour-vise{box-shadow:inset 0 0 0 2px var(--accent)}

/* --- Agenda : un groupe par jour ---
   L'intertitre porte la date en clair. Sur un agenda, « jeudi 13 aout » se cherche des
   yeux ; une suite de lignes plates obligerait a lire chaque date. */
.agenda-jour{border-bottom:1px solid var(--bord)}
.agenda-jour:last-child{border-bottom:0}
.agenda-jour h3{
  display:flex; align-items:center; gap:var(--e2);
  margin:0; padding:var(--e3) var(--e4);
  background:var(--surface-creuse); border-bottom:1px solid var(--bord);
  font-size:var(--t-petit); font-weight:600; color:var(--encre-douce);
  text-transform:capitalize;
}
.agenda-jour .ligne:last-child{border-bottom:0}

/* --- Les lignes d'une visite, sur sa fiche ---
   Le detail de ce qui se fait pendant un deplacement. Un montant a zero y est legitime :
   c'est celui d'une location facturee sur l'autre visite. */
.fiche-lignes{list-style:none; margin:0; padding:0}
.fiche-lignes li{
  display:flex; align-items:baseline; gap:var(--e2); flex-wrap:wrap;
  padding:var(--e1) 0;
}
.fiche-lignes li + li{border-top:1px solid var(--bord)}
.fiche-ligne-montant{font-family:var(--mono); font-size:var(--t-mono); color:var(--encre-douce)}
.fiche-lignes em{font-style:normal; font-size:var(--t-petit)}

/* --- Prestations d'un sejour, sous la ligne de la reservation ---
   Une liste et non un tableau : les elements d'une ligne sont de nature differente —
   un etat, un libelle, une date, un montant — et se lisent comme une phrase. Un tableau
   imposerait des colonnes vides la ou une information manque. */
.sejour-prestations{
  list-style:none; margin:var(--e2) 0 0; padding:0;
  display:flex; flex-direction:column; gap:var(--e1);
}
.sejour-prestations li{
  display:flex; align-items:center; gap:var(--e2); flex-wrap:wrap;
  font-size:var(--t-petit); color:var(--encre-douce);
  padding:var(--e1) 0 var(--e1) var(--e3);
  border-left:2px solid var(--bord);
}
.sejour-prestations strong{color:var(--encre); font-weight:600}
.sejour-date{
  display:inline-flex; align-items:center; gap:var(--e1);
  font-family:var(--mono); font-size:var(--t-mono); color:var(--encre-douce);
}

/* Le formulaire de correction d'un sejour reste replie : il ne sert qu'aux
   reservations saisies a la main, donc rarement, et sept champs deplies sur chaque
   ligne rendraient la liste illisible. */
.sejour-edition{display:inline-block}
.sejour-edition summary{cursor:pointer; list-style:none}
.sejour-edition summary::-webkit-details-marker{display:none}
.sejour-edition input[type=date]{
  padding:var(--e2) 10px; font:inherit; font-size:var(--t-controle);
  border:1px solid var(--bord-net); border-radius:var(--rayon); background:var(--surface);
}

/* --- Tableau de saisie (tarifs d'un bien) ---
   table-layout:fixed avec des largeurs declarees en <colgroup> : c'est LA regle qui
   fait tenir l'alignement. Sans elle, le contenu de chaque cellule negocie sa largeur,
   une etiquette « non tarifee » elargit la premiere colonne et tous les champs de la
   ligne se decalent par rapport a ceux du dessus.
   Les champs prennent 100 % de leur colonne : ils ont donc exactement la meme largeur
   d'une ligne a l'autre, sans dimension ecrite a la main. */
/* overflow-x:auto, TOUJOURS. Une barre n'apparait alors que si le tableau ne rentre pas,
   ce qui est precisement le comportement voulu — inutile d'aller le chercher dans une
   requete de media. Le passage a « visible » avait fait l'inverse : le tableau debordait
   et se faisait couper par le overflow:hidden de la carte, sans barre pour y acceder.
   C'est aussi ce conteneur qui arrondit les coins, puisque la carte ne peut plus le
   faire sans risquer de rogner. */
.tableau-defilant{overflow-x:auto; border-radius:var(--rayon-carte)}
/* LE TABLEAU DES CONCIERGERIES PARTAGE CES REGLES, il ne les recopie pas.
   Ajouter sa classe aux selecteurs existants coute une virgule ; une seconde declaration aux
   valeurs voisines aurait diverge au premier ajustement — c'est deja arrive dans ce fichier
   avec le style des champs, et il a fallu le rattraper. */
.tableau-tarifs, .tableau-concierges{
  width:100%; border-collapse:collapse; table-layout:fixed; min-width:720px;
}
.tableau-tarifs th, .tableau-tarifs td,
.tableau-concierges th, .tableau-concierges td{
  padding:var(--e3) var(--e4); text-align:left; vertical-align:middle;
  border-bottom:1px solid var(--bord);
}
.tableau-tarifs thead th, .tableau-concierges thead th{
  position:sticky; top:0; z-index:1;
  background:var(--surface-creuse); color:var(--encre-tenue);
  font-family:var(--mono); font-size:var(--t-micro); font-weight:600;
  letter-spacing:.06em; text-transform:uppercase; white-space:nowrap;
  border-bottom:1px solid var(--bord-net);
}
.tableau-tarifs tbody tr:last-child th, .tableau-tarifs tbody tr:last-child td,
.tableau-concierges tbody tr:last-child th, .tableau-concierges tbody tr:last-child td{
  border-bottom:0;
}
.tableau-tarifs tbody tr:hover, .tableau-concierges tbody tr:hover{
  background:var(--surface-creuse);
}
.tableau-tarifs .centre{text-align:center}

/* ---- Ce qui est propre au portefeuille ----
   Dix colonnes ne tiennent pas dans une largeur fixe : on laisse le contenu decider, et
   .tableau-defilant fait glisser. Une largeur fixe ecraserait les quatre compteurs. */
.tableau-concierges{table-layout:auto; min-width:1100px}
.tableau-concierges .nombre{text-align:right; white-space:nowrap}
.tableau-concierges thead th.nombre{text-align:right}
.tableau-concierges .mono{font-family:var(--mono); font-size:var(--t-petit)}
.tableau-concierges tbody th[scope=row]{font-weight:600}
.tableau-concierges .cellule-sous{display:block; font-size:var(--t-micro); color:var(--encre-tenue)}

/* Une conciergerie desactivee reste lisible mais recule : elle n'est plus un client, et la
   liste doit d'abord montrer le portefeuille vivant. */
.ligne-eteinte{opacity:.55}

/* ---- Le tri par en-tete ----
   UN LIEN, PAS UN BOUTON DE SCRIPT : sans JavaScript le tri marche, et l'adresse obtenue se
   met en favori. La fleche n'apparait que sur la colonne active — trois fleches grises sur dix
   colonnes ne diraient plus laquelle porte l'ordre. */
/* LA LISTE DES INTERVENTIONS PARTAGE CES REGLES, elle ne les recopie pas : sa colonne Date se trie
   du meme geste, avec le meme lien et la meme fleche. Ajouter sa classe aux selecteurs coute une
   virgule ; une seconde declaration aux valeurs voisines aurait diverge au premier ajustement — ce
   fichier en garde le souvenir, sur le style des champs. */
.tableau-concierges .tri, .tableau-interventions .tri{
  color:inherit; text-decoration:none;
  display:inline-flex; align-items:center; gap:4px;
}
.tableau-concierges .tri:hover,
.tableau-interventions .tri:hover{color:var(--accent); text-decoration:none}
.tableau-concierges .tri-actif, .tableau-interventions .tri-actif{color:var(--accent)}
.tri-fleche{font-size:10px; line-height:1}

/* La case « voir les desactivees » vit dans la barre de filtres, a cote des selecteurs : elle
   s'aligne avec eux plutot que de se poser sur sa propre ligne. */
.case-inline{
  display:inline-flex; align-items:center; gap:var(--e2);
  font-size:var(--t-petit); color:var(--encre-douce); white-space:nowrap;
}
.case-inline input{width:auto}

/* La premiere cellule empile le libelle et son etiquette : c'est ce qui permet a
   l'etiquette de faire grandir la LIGNE sans deplacer un champ. */
.tableau-tarifs tbody th[scope=row]{font-weight:400}
.tarif-nom{display:block; font-weight:600; color:var(--encre)}
.tableau-tarifs .etiquette, .tarif-rappel{margin-top:3px}
.tarif-rappel{display:inline-block; font-size:var(--t-petit); color:var(--encre-tenue)}

.tableau-tarifs input[type=text], .tableau-tarifs input[type=number], .tableau-tarifs select{
  width:100%; padding:var(--e2) 10px; font:inherit; font-size:var(--t-base);
  border:1px solid var(--bord-net); border-radius:var(--rayon);
  background:var(--surface); color:var(--encre);
  transition:border-color var(--vite), box-shadow var(--vite);
}
.tableau-tarifs input:hover, .tableau-tarifs select:hover{border-color:var(--encre-tenue)}
.tableau-tarifs input:focus, .tableau-tarifs select:focus{
  border-color:var(--accent); box-shadow:var(--anneau); outline:none;
}
.tableau-tarifs input[type=checkbox]{width:auto; accent-color:var(--accent); cursor:pointer}

/* Une ligne sans prix reste lisible mais visiblement en attente ; une ligne retiree de
   l'offre s'efface, sans disparaitre — son prix est encore la. */
.tableau-tarifs .ligne-vide .tarif-nom{color:var(--encre-douce)}
.tableau-tarifs .ligne-retiree{background:var(--surface-creuse)}
.tableau-tarifs .ligne-retiree .tarif-nom{color:var(--encre-douce); text-decoration:line-through}

/* La colonne « Quand » du formulaire de demande : une ou deux occurrences empilees,
   chacune avec sa date deduite du sejour. */
.tarif-quand{display:flex; flex-direction:column; gap:var(--e1)}
.tarif-occurrence{
  display:inline-flex; align-items:center; gap:var(--e1);
  font-size:var(--t-petit); color:var(--encre-douce);
}
.tarif-occurrence strong{color:var(--encre)}
.tableau-tarifs input[type=date]{
  width:100%; padding:var(--e2) 10px; font:inherit; font-size:var(--t-controle);
  border:1px solid var(--bord-net); border-radius:var(--rayon); background:var(--surface);
}

/* Ligne d'un type retire du catalogue : elle se lit, elle ne se saisit pas. */
.tarif-inerte{font-size:var(--t-petit); color:var(--encre-douce); line-height:1.5}

.tableau-tarifs .ligne-section th{
  background:var(--surface-creuse); color:var(--encre-douce);
  font-size:var(--t-petit); font-weight:600; text-transform:uppercase; letter-spacing:.04em;
  border-bottom:1px solid var(--bord-net);
}

/* La barre d'enregistrement colle au bas de la fenetre : sur un long tableau, une
   correction faite en haut ne doit pas obliger a defiler jusqu'en bas. */
/* UNE VARIANTE NON COLLANTE, pour les pages ou la barre n'a rien a suivre.
   Une barre collante se justifie sous un long formulaire : on remplit, le bouton reste a
   portee. Sous une page de consultation qui s'acheve par une action rare — desactiver un
   client — elle ne sert a rien et recouvre le dernier bloc, qui devient inutilisable sur
   un ecran court. */
.barre-posee{position:static; box-shadow:var(--ombre1)}

.barre-enregistrer{
  position:sticky; bottom:0; z-index:2;
  display:flex; align-items:center; gap:var(--e4); flex-wrap:wrap;
  margin-top:var(--e4); padding:var(--e3) var(--e4);
  background:var(--surface); border:1px solid var(--bord); border-radius:var(--rayon);
  box-shadow:var(--ombre2);
}

/* --- Fleches d'ordonnancement ---
   Une colonne de plus dans la grille de .ligne, declaree par la classe .ordonnee sur la
   ligne elle-meme. Pas de :has() : la regle doit etre lisible dans le gabarit, et c'est
   le gabarit qui sait s'il a pose des fleches.
   La place vide compte autant que la fleche : sans .rangeur-vide, la premiere ligne
   n'aurait qu'une fleche et son libelle se decalerait vers le haut. */
.ligne.ordonnee{grid-template-columns:5px auto 1fr auto}
.rangeur{display:flex; flex-direction:column; gap:1px; padding:0 var(--e2) 0 var(--e3)}
.rangeur-fleche, .rangeur-vide{
  display:block; width:22px; height:15px; line-height:13px; text-align:center;
  font-size:9px; border-radius:3px; border:1px solid transparent;
}
.rangeur-fleche{
  padding:0; background:var(--surface-creuse); color:var(--encre-douce);
  border-color:var(--bord); cursor:pointer;
  transition:background var(--vite), color var(--vite), border-color var(--vite);
}
.rangeur-fleche:hover{background:var(--accent); color:#fff; border-color:var(--accent)}
.rangeur-fleche:focus-visible{box-shadow:var(--anneau); outline:none}

.ligne-editable{display:flex; align-items:center; gap:var(--e3); flex-wrap:wrap}
.ligne-editable input[type=text], .ligne-editable input[type=number]{
  padding:var(--e2) 10px; font:inherit; font-size:var(--t-base);
  border:1px solid var(--bord-net); border-radius:var(--rayon);
  background:var(--surface); transition:border-color var(--vite), box-shadow var(--vite);
}
.ligne-editable input[type=text]{flex:1 1 200px}
.ligne-editable input[type=number]{width:82px}
.ligne-editable input:focus{border-color:var(--accent); box-shadow:var(--anneau); outline:none}

.renommer-source{display:flex; align-items:center; gap:var(--e2); flex-wrap:wrap; margin-bottom:var(--e1)}
.renommer-source input[type=text]{
  flex:0 1 220px; padding:var(--e1) var(--e2); font:inherit; font-size:var(--t-base); font-weight:600;
  border:1px solid transparent; border-radius:var(--rayon); background:transparent;
  color:var(--encre); transition:border-color var(--vite), background var(--vite), box-shadow var(--vite);
}
.renommer-source input[type=text]:hover{border-color:var(--bord); background:var(--surface)}
.renommer-source input[type=text]:focus{
  border-color:var(--accent); background:var(--surface); font-weight:400;
  box-shadow:var(--anneau); outline:none;
}

/* --- Choices.js, habille a la palette du projet ---
   Sa feuille par defaut est en bleu-gris Bootstrap, avec ses propres rayons et
   ses propres tailles. Laissee telle quelle, elle aurait l'air rapportee : un
   composant venu d'ailleurs pose au milieu du formulaire. Ce bloc la ramene aux
   quatre regles du fichier — meme echelle, meme rythme, meme elevation, meme
   mouvement — et surtout a la meme couleur d'accent.

   Chargee APRES choices.min.css dans le gabarit, donc ces regles l'emportent
   sans avoir besoin de !important. */

/* LE DEROULANT PASSE AU-DESSUS DES BARRES COLLANTES.
   Choices ouvre sa liste avec z-index:1 (var --choices-z-index). Nos barres du bas valent
   2 et 20 : le menu s'ouvrait donc DERRIERE elles, et le dernier champ d'une page devenait
   inutilisable — on voyait la liste apparaitre, sans pouvoir cliquer dedans.

   L'echelle du projet, pour que la prochaine valeur se choisisse sans deviner :
       2   barre-enregistrer     collee sous un formulaire
      10   bandeau               l'en-tete de l'application
      20   barre-flottante       les actions d'une fiche
      30   menu-tiroir-corps     le tiroir du bandeau (dans son contexte)
      40   deroulant Choices     doit couvrir tout ce qui precede
   Les boites <dialog> ne figurent pas ici : le navigateur les place dans sa couche
   superieure, hors de toute echelle. */
.choices{margin-bottom:0; font-size:var(--t-base); --choices-z-index:40}
.choices:focus{outline:none}

/* La boite : identique a un .champ input, pour qu'un selecteur enrichi et un champ
   ordinaire ne se distinguent pas dans une meme colonne. */
.choices__inner{
  background:var(--surface); border:1px solid var(--bord-net);
  border-radius:var(--rayon); padding:var(--e1) var(--e2) 0;
  min-height:44px; font-size:var(--t-base);
  transition:border-color var(--vite), box-shadow var(--vite);
}
.choices:hover .choices__inner{border-color:var(--encre-tenue)}
.choices.is-focused .choices__inner,
.choices.is-open .choices__inner{
  border-color:var(--accent); box-shadow:var(--anneau); border-radius:var(--rayon);
}
.choices[data-type*=select-one] .choices__inner{padding-bottom:var(--e1)}
.is-disabled .choices__inner{background:var(--surface-creuse)}

/* Les etiquettes : a l'accent, comme les etiquettes d'etat du registre. */
.choices__list--multiple .choices__item{
  background:var(--accent); border:0; border-radius:var(--rayon-puce);
  padding:4px var(--e2); margin:0 var(--e1) var(--e1) 0;
  font-size:var(--t-petit); font-weight:500; line-height:1.4;
}
.choices__list--multiple .choices__item.is-highlighted{background:var(--accent-fonce)}
.choices[data-type*=select-multiple] .choices__button{
  border-left:1px solid rgba(255,255,255,.35); margin:0 -2px 0 var(--e2);
  padding-left:var(--e2); opacity:.7; transition:opacity var(--vite);
}
.choices[data-type*=select-multiple] .choices__button:hover{opacity:1}

/* La liste deroulante : meme elevation que les cartes, meme rayon. */
.choices__list--dropdown, .choices__list[aria-expanded]{
  background:var(--surface); border:1px solid var(--bord-net);
  border-radius:var(--rayon); box-shadow:var(--ombre2);
  margin-top:var(--e1); z-index:20;
}
.choices__list--dropdown .choices__item, .choices__list[aria-expanded] .choices__item{
  padding:var(--e2) var(--e3); font-size:var(--t-controle);
}
.choices__list--dropdown .choices__item--selectable.is-highlighted,
.choices__list[aria-expanded] .choices__item--selectable.is-highlighted{
  background:var(--accent-voile); color:var(--accent-fonce);
}
/* Choices reserve une gouttiere a droite pour son texte « Press to select », que
   nous avons vide : sans cette remise a zero, chaque ligne parait mal alignee. */
.choices__list--dropdown .choices__item--selectable::after,
.choices__list[aria-expanded] .choices__item--selectable::after{display:none}
.choices__list--dropdown .choices__item--selectable,
.choices__list[aria-expanded] .choices__item--selectable{padding-right:var(--e3)}

/* Le champ de recherche interne, et le texte de substitution. */
.choices__input{
  background:transparent; font-size:var(--t-base); padding:var(--e1) 0;
  margin-bottom:var(--e1); color:var(--encre);
}
.choices__list--dropdown .choices__input{
  background:var(--surface-creuse); border-bottom:1px solid var(--bord);
  padding:var(--e2) var(--e3); margin:0;
}
.choices__placeholder{color:var(--encre-tenue); opacity:1}
.choices__list--dropdown .choices__item--no-results,
.choices__list--dropdown .choices__item--no-choices{
  color:var(--encre-tenue); font-size:var(--t-petit);
}

/* La fleche du selecteur simple, ramenee a la couleur du texte secondaire. */
.choices[data-type*=select-one]::after{border-color:var(--encre-douce) transparent transparent}
.choices[data-type*=select-one].is-open::after{border-color:transparent transparent var(--encre-douce)}

/* Dans un fieldset .bloc, la boite est sur fond creux : on la garde blanche pour
   qu'elle se lise comme une zone de saisie et non comme une partie du bloc. */
.bloc .choices__inner{background:var(--surface)}

/* --- Barre de filtres --- */
/* align-items:flex-end et non center.
   Une barre de filtres melange des champs NUS — une recherche — et des champs ETIQUETES,
   ou le libelle surmonte le controle. Centrer sur l'ensemble posait le bouton a hauteur du
   libelle, en l'air a cote des champs. Sur une barre ou tout a la meme hauteur, les deux
   reglages donnent le meme resultat : on ne perd rien la ou c'etait deja droit. */
.filtres{display:flex; gap:var(--e3); align-items:flex-end; flex-wrap:wrap; margin-bottom:var(--e4)}
.filtres input[type=search]{
  padding:9px var(--e3); border:1px solid var(--bord-net); border-radius:var(--rayon);
  font:inherit; font-size:var(--t-controle); min-width:200px; background:var(--surface);
  transition:border-color var(--vite), box-shadow var(--vite);
}
.filtres input[type=search]:focus{border-color:var(--accent); box-shadow:var(--anneau); outline:none}


/* =============================== Barre de filtres des interventions ============
   Trois dimensions sur une ligne — client, etats, periode — la ou il n'y avait qu'une
   rangee d'onglets. La barre passe a la ligne plutot que de defiler : un filtre hors de
   l'ecran est un filtre qu'on ne sait pas actif, et l'on cherche alors pourquoi la liste
   est vide.

   L'ordre suit la question posee : le nom du client d'abord, parce que c'est le filtre le
   plus selectif.

   ALIGNEE SUR LE TABLEAU par pleine-largeur, que la vue pose aussi sur la barre. Attention
   en modifiant les regles ci-dessous : sur une classe qui accompagne pleine-largeur, on
   ecrit margin-top et margin-bottom, JAMAIS le raccourci margin — il remettrait a zero la
   marge gauche de centrage et la barre se recalerait a gauche pendant que le tableau reste
   centre. tests_style.php monte la garde. */
.filtres-interventions{
  align-items:flex-end; gap:var(--e3) var(--e4);

  /* UNE SEULE HAUTEUR ET UNE SEULE FONTE POUR TOUTE LA BARRE.
     Les quatre controles venaient de trois familles de regles : le champ de recherche
     (padding 9 px, 14 px), les selects et les dates (.champ : padding 10 px, 15 px) et la
     boite de Choices (min-height 44 px, 15 px). Trois hauteurs et deux fontes sur une meme
     ligne — ce qui se voit d'autant plus que les libelles sont alignes au-dessus.
     Les regles generales ne sont pas touchees : ailleurs, un champ de formulaire doit
     rester confortable a 44 px. */
  --h-filtre:36px;
}

.filtres-interventions .champ label{margin-bottom:5px}

.filtres-interventions input[type=search],
.filtres-interventions input[type=date],
.filtres-interventions select{
  min-height:var(--h-filtre); height:var(--h-filtre);
  padding-top:0; padding-bottom:0;
  font-size:var(--t-controle); line-height:1.4;
}
/* La loupe est posee DANS le champ : sa place doit etre preservee quand la marge
   interne verticale est remise a zero juste au-dessus. */
.filtres-interventions input[type=search]{padding-left:33px}

/* Le selecteur des etats, enrichi par Choices en champ a etiquettes.
   Une largeur minimale franche : sans elle, le champ se reduit a la taille du texte de
   substitution puis saute brutalement des qu'une etiquette apparait. La largeur maximale
   evite qu'il pousse les dates hors de la ligne quand les cinq etats sont retenus. */
.champ-etats{min-width:230px; max-width:340px; flex:1 1 230px}
.champ-etats .choices{margin:0}

/* La boite des etats a la hauteur de ses voisins.
   CENTREE PAR flex ET NON CALCULEE AU PIXEL : la hauteur du contenu depend du nombre
   d'etiquettes retenues, donc toute marge interne fixe laisserait les etiquettes collees
   en haut de la boite des qu'il y en a moins d'une rangee. */
.filtres-interventions .choices__inner{
  display:flex; align-items:center; flex-wrap:wrap;
  min-height:var(--h-filtre); padding:2px var(--e2);
  font-size:var(--t-controle);
}
.filtres-interventions .choices, .filtres-interventions .choices__input{
  font-size:var(--t-controle);
}

/* LES ETATS PLUS PETITS. Dans leur cartouche ils paraissaient occuper plus de place que
   les autres filtres : une etiquette a fond plein attire l'oeil bien au-dela de sa taille
   reelle, et cinq d'entre elles pesaient visuellement plus que le tableau qu'elles
   filtrent. La croix de suppression reste atteignable — c'est elle qui fixe le plancher. */
.filtres-interventions .choices__list--multiple .choices__item{
  padding:2px var(--e2); margin:2px var(--e1) 2px 0;
  font-size:var(--t-micro); line-height:1.5;
}
.filtres-interventions .choices[data-type*=select-multiple] .choices__button{
  margin:0 -1px 0 5px; padding-left:5px; width:7px; background-size:7px;
}

/* Les deux dates. Toujours actives depuis que la periode EST ces deux champs : il n'y a
   plus de mode ou elles seraient en lecture seule. */
.champ-date input[type=date]{min-width:132px}

/* Le bouton et le lien de remise a zero suivent la meme mesure. Le bouton est carre :
   c'est une icone seule, et un carre de 36 px se lit comme un bouton alors qu'un rectangle
   de 36 sur 40 se lit comme un bouton mal aligne. */
.filtres-interventions .btn-icone{
  min-height:var(--h-filtre); height:var(--h-filtre); width:var(--h-filtre);
  padding:0; display:inline-flex; align-items:center; justify-content:center;
}
.filtres-interventions .btn-lien{font-size:var(--t-controle); padding-left:0}

/* Champ de recherche avec la loupe posee dedans. */
.chercher{position:relative; display:inline-flex; align-items:center}
.chercher .i{position:absolute; left:11px; color:var(--encre-tenue); pointer-events:none}
.chercher input[type=search]{padding-left:33px}

/* Bouton de filtre reduit a son icone.
   La loupe est deja DANS les champs pour dire « ceci se cherche » ; le bouton
   porte donc un entonnoir, qui dit « applique le filtre ». Deux loupes cote a cote
   n'auraient rien distingue. Le libelle reste dans aria-label : une icone seule est
   muette pour un lecteur d'ecran. */
.btn-icone{padding:10px; width:40px}
.btn-icone .i{width:17px; height:17px}

/* Autocompletion : la puce indique qu'une liste de suggestions existe, ce que
   <datalist> ne signale pas de lui-meme sur tous les navigateurs. */
.chercher-suggere::after{
  content:''; position:absolute; right:11px; width:0; height:0;
  border-left:4px solid transparent; border-right:4px solid transparent;
  border-top:5px solid var(--encre-tenue); pointer-events:none;
}
.chercher-suggere input[type=search]{padding-right:26px}

.onglets{
  display:inline-flex; background:var(--surface); border-radius:var(--rayon);
  box-shadow:var(--ombre1); overflow:hidden;
}
.onglets a{
  padding:9px var(--e4); font-size:var(--t-petit); text-decoration:none; color:var(--encre-douce);
  display:inline-flex; align-items:center; gap:var(--e2);
  border-right:1px solid var(--bord);
  transition:background var(--vite), color var(--vite);
}
.onglets a:last-child{border-right:0}
.onglets a:hover{background:var(--surface-creuse); color:var(--encre)}
.onglets a[aria-current=page]{background:var(--accent); color:#fff; font-weight:500}
.onglets a[aria-current=page]:hover{background:var(--accent-fonce); color:#fff}
.onglets-roles{margin-bottom:var(--e4); flex-wrap:wrap}

/* --- La variante « segments » : un rail, et une pastille dedans ---
   Les onglets ordinaires sont des cases jointives separees par un filet, sur fond blanc. C'est
   juste pour une rangee d'onglets de section — quatre ou cinq, qui decoupent un ecran.

   POUR DEUX MODES D'AFFICHAGE DU MEME CONTENU, le rail dit mieux ce qui se passe : on ne change
   pas de page, on bascule un interrupteur. La pastille se detache DANS son rail au lieu de remplir
   une case, et l'espace autour d'elle montre qu'il y a une autre position ou aller.

   LE RAIL EST CREUX ET SANS OMBRE : une ombre le ferait flotter au-dessus de la page, alors qu'il
   y est enfonce. C'est la pastille qui porte l'ombre, puisque c'est elle qui est posee dessus. */
.onglets-segments{
  background:var(--surface-creuse); box-shadow:none;
  border:1px solid var(--bord); padding:3px; gap:2px; border-radius:8px;
}
.onglets-segments a{
  border-right:0; border-radius:6px; padding:7px var(--e4); font-weight:500;
}
.onglets-segments a:hover{background:var(--surface); color:var(--encre)}

/* --- LE RAIL DANS L'EN-TETE, A LA HAUTEUR DU BOUTON ---
   LES DEUX HAUTEURS SE CALCULENT, elles ne se reglent pas a l'oeil. Un « .btn » mesure 36 px :
   14 px de texte sur une interligne de 1, plus deux fois 10 px de marge interne, plus deux fois
   1 px de bordure. Le rail porte 3 px de marge interne et 1 px de bordure de chaque cote, soit 8 px
   a lui : ses liens doivent donc mesurer 28 px pour que l'ensemble en fasse 36.

   ON POSE DONC LA HAUTEUR DES LIENS, ET NON LEUR MARGE INTERNE VERTICALE. Une marge interne se
   combine a l'interligne du texte, qui depend de la police : le compte ne serait juste qu'avec
   celle d'aujourd'hui. Une hauteur explicite avec le texte centre est vraie quelle que soit la
   police.

   « margin-bottom:0 » : le rail avait la marge d'une rangee a lui. Il est maintenant dans une
   ligne, et c'est « .entete » qui espace. */
/* LES DEUX CONTROLES PORTENT UNE HAUTEUR EXPLICITE, ET C'EST L'ICONE QUI L'A IMPOSE.
   Un « .btn » ne mesure pas 36 px comme le calcul le laissait croire : son icone fait 1,05 em, soit
   14,7 px dans un bouton de 14 — c'est donc l'ICONE, et non le texte, qui donne sa hauteur a la
   ligne. Le rail, lui, tenait ses 36 px puisque ses liens ont une hauteur posee. Deux controles cote
   a cote qui manquent l'alignement d'un pixel ou deux se remarquent aussitot.

   ON NE LAISSE DONC PLUS LE CONTENU DECIDER, des deux cotes : 28 px de lien plus 8 px de rail font
   36, et le bouton en fait autant. Changer la taille d'une icone ne pourra plus les desaligner. */
.actions-onglets .btn{height:36px; padding:0 var(--e4)}
.onglets-entete{margin-bottom:0}
.onglets-entete a{
  height:28px; padding:0 var(--e4); font-size:var(--t-controle); font-weight:500;
}
.onglets-segments a[aria-current=page]{box-shadow:var(--ombre1)}

/* --- Etats vides ---
   Une bordure pointillee dit « il manque quelque chose ». On la garde, mais
   discrete : c'est une invitation, pas une alarme. */
.vide{
  background:var(--surface); border:1px dashed var(--bord-net);
  border-radius:var(--rayon-carte); padding:var(--e12) var(--e6); text-align:center;
}
.vide p{margin:0 0 var(--e4); color:var(--encre-douce); max-width:46ch; display:inline-block; line-height:1.6}
.vide .i-grande{color:var(--encre-tenue); margin:0 auto var(--e3); display:block}

/* --- Sommaire de section (Administration) --- */
.sommaire{display:grid; gap:var(--e3); max-width:800px}
.sommaire-entree{
  display:flex; gap:var(--e4); align-items:flex-start; padding:var(--e6);
  background:var(--surface); border-radius:var(--rayon-carte);
  box-shadow:var(--ombre1); text-decoration:none; color:var(--encre);
  border-left:3px solid var(--accent);
  transition:box-shadow var(--doux), transform var(--doux);
}
.sommaire-entree:hover{box-shadow:var(--ombre2); transform:translateY(-1px)}
.sommaire-entree .i-grande{color:var(--accent); margin-top:2px; flex:none}
.sommaire-entree span{
  display:flex; flex-direction:column; gap:var(--e1);
  font-size:var(--t-petit); color:var(--encre-douce); line-height:1.55;
}
.sommaire-entree strong{font-size:var(--t-moyen); color:var(--encre); font-weight:600}

/* --- Ecran des migrations --- */
.journal{
  margin:0; padding:var(--e4); background:var(--encre); color:#d6e2e1;
  border-radius:var(--rayon); font-family:var(--mono); font-size:var(--t-mono);
  line-height:1.65; white-space:pre-wrap; overflow-x:auto;
}
.fiche-technique{
  display:grid; grid-template-columns:minmax(170px, auto) 1fr;
  gap:var(--e3) var(--e6); margin:0; font-size:var(--t-petit);
}
.fiche-technique dt{font-weight:600; color:var(--encre-douce)}
.fiche-technique dd{margin:0; overflow-wrap:anywhere}
.fiche-technique code, .identite code{font-family:var(--mono); font-size:var(--t-mono)}
.fiche-technique .orphelin{
  font-family:var(--mono); font-size:var(--t-micro); color:var(--alerte);
  text-transform:uppercase; letter-spacing:.05em;
}

/* --- Suivi d'un compte ---
   Trois regles seulement : le tableau reprend .tableau-interventions et le bloc d'etat
   .fiche-technique, employes ailleurs. Reutiliser plutot que redefinir garde le meme
   vocabulaire visuel d'un ecran a l'autre — et rien de plus a maintenir. */

/* La categorie en petites capitales attenuees, PAS en pastille coloree. Sur deux cents
   lignes de journal, deux cents pastilles font du bruit et non de l'information : c'est
   l'icone de la colonne voisine qui distingue les evenements. */
.cellule-categorie{
  font-size:var(--t-micro); font-weight:600; letter-spacing:.05em;
  text-transform:uppercase; color:var(--encre-tenue); white-space:nowrap;
}

/* Une adresse IP se lit chiffre par chiffre et se compare d'une ligne a l'autre : la
   chasse fixe aligne les points, la proportionnelle les fait danser. */
.mono-petit{font-family:var(--mono); font-size:var(--t-mono); color:var(--encre-douce)}

.liste-echecs{margin:0; padding:0; list-style:none; font-size:var(--t-controle)}
.liste-echecs li{
  display:flex; justify-content:space-between; gap:var(--e3);
  padding:6px 0; border-bottom:1px solid var(--bord);
}
.liste-echecs li:last-child{border-bottom:0}


/* ======================= Planning hebdomadaire : intervenants x jours ==========
   UNE GRILLE CSS ET NON UN <table>.

   La contrainte est « une semaine sans defilement horizontal », et c'est elle qui a
   decide de la forme. Une colonne de noms a largeur fixe, puis sept colonnes egales qui
   se partagent le reste : « repeat(var(--jours), minmax(0, 1fr)) ». Le minmax(0, …) n'est
   pas decoratif — sans lui, une pastille au libelle long impose sa largeur a la colonne
   et la semaine deborde, ce que 1fr seul n'empeche pas.

   Un <table> aurait redistribue les largeurs selon son contenu, exactement ce qu'on ne
   veut pas ici. La grille les impose. */
.planning-semaine{
  display:grid;
  grid-template-columns:minmax(150px, 200px) repeat(var(--jours, 7), minmax(0, 1fr));
  gap:1px;
  background:var(--bord);
  border:1px solid var(--bord-net);
  border-radius:var(--rayon-carte);
  overflow:hidden;
  margin-top:var(--e4);
}

/* --- L'en-tete des jours --- */
.ps-entete{
  background:var(--surface-creuse); padding:var(--e2) var(--e3);
  display:flex; flex-direction:column; gap:1px;
  font-size:var(--t-micro); text-transform:uppercase; letter-spacing:.05em;
  color:var(--encre-tenue); font-weight:600;
  /* Collant : sur une equipe de dix, on descend dans la grille et l'on ne sait plus
     quelle colonne est quel jour. */
  position:sticky; top:0; z-index:1;
}
.ps-coin{justify-content:flex-end}
.ps-jour{color:var(--encre-douce)}
.ps-numero{font-size:var(--t-petit); text-transform:none; letter-spacing:0; color:var(--encre-tenue)}

/* Aujourd'hui se distingue par un TRAIT et un fond, pas par la seule couleur : la colonne
   du jour est ce qu'on cherche en arrivant. */
.ps-entete.ps-aujourdhui{
  background:var(--accent-voile); box-shadow:inset 0 -2px 0 var(--accent);
}
.ps-entete.ps-aujourdhui .ps-jour, .ps-entete.ps-aujourdhui .ps-numero{color:var(--accent-fonce)}

/* --- La colonne des noms --- */
.ps-nom{
  background:var(--surface); padding:var(--e3);
  display:flex; align-items:center; gap:var(--e2); flex-wrap:wrap;
  font-size:var(--t-controle); font-weight:500;
}
.ps-nom-texte{display:inline-flex; align-items:center; gap:5px; min-width:0}
.ps-nom-texte .i{flex:0 0 auto}

/* La ligne des non assignees : c'est du travail que personne n'a pris, donc elle appelle
   l'action. Un liseret d'alerte a gauche, comme les lignes en attente ailleurs. */
.ps-nom-sans{
  background:var(--attente-voile);
  box-shadow:inset 3px 0 0 var(--attente);
  font-weight:600;
}

/* La charge de la semaine, poussee a droite : elle sert a comparer les lignes entre elles,
   donc elle doit etre alignee. */
.ps-charge{
  margin-left:auto; font-family:var(--mono); font-size:var(--t-micro);
  color:var(--encre-tenue); background:var(--surface-creuse);
  padding:1px 6px; border-radius:999px;
}

/* --- Les cases --- */
.ps-case{
  background:var(--surface); padding:4px;
  display:flex; flex-direction:column; gap:3px;
  /* Une hauteur minimale, sans quoi une case vide se reduit a rien et la ligne devient
     un filet impossible a viser au depot. */
  min-height:58px;
}
.ps-case.ps-weekend, .ps-entete.ps-weekend{background:var(--surface-creuse)}
.ps-case.ps-aujourdhui{background:var(--accent-voile)}

/* La case survolee pendant un glissement. Un cadre INTERIEUR et non une bordure : une
   bordure changerait la largeur de la case et decalerait toute la grille au survol. */
.ps-survolee{box-shadow:inset 0 0 0 2px var(--accent); background:var(--accent-voile)}

/* --- Les pastilles d'intervention --- */
.ps-puce{
  display:flex; align-items:baseline; gap:5px;
  padding:4px 6px; border-radius:var(--rayon);
  font-size:var(--t-micro); line-height:1.35;
  text-decoration:none; color:var(--encre);
  background:var(--surface-creuse);
  border-left:3px solid var(--bord-net);
  transition:box-shadow var(--vite), transform var(--vite);
  cursor:pointer; min-width:0;
}
.ps-puce:hover{box-shadow:var(--ombre1); text-decoration:none}
.ps-puce:focus-visible{outline:2px solid var(--accent); outline-offset:1px}

/* L'etat par la couleur du liseret ET par le fond : un liseret seul est trop mince pour
   se lire d'un coup d'oeil sur une grille de soixante cases.

   CETTE REGLE ETAIT ECRITE ET NON TENUE. « .ps-faite » reposait le fond de « .ps-puce »
   — #f7f9f8 sur #f7f9f8 — et y ajoutait « opacity: .75 ». Une terminee ne se distinguait
   donc d'une case vide que par un liseret de trois pixels, attenue. Elle etait rendue, et
   invisible : « les interventions terminees sont masquees ».

   L'OPACITE EST RETIREE. Attenuer une couleur deja pale ne la rend pas discrete, elle la
   supprime. Le retrait de saturation suffit a dire « c'est fait », et le texte adouci le
   confirme sans effacer la case.

   « A FAIRE » EST LE PLUS APPUYE DES TROIS, et c'est voulu : c'est le seul etat qui
   demande quelque chose a quelqu'un. « A valider » attend une decision, « terminee »
   n'attend plus rien. */
.ps-attente{border-left-color:var(--attente); background:var(--attente-voile)}
.ps-valide{border-left-color:var(--accent); background:var(--afaire-voile)}
.ps-faite{
  border-left-color:var(--encre-tenue); background:var(--faite-voile);
  color:var(--encre-douce);
}

.ps-heure{font-family:var(--mono); font-weight:600; flex:0 0 auto}
.ps-sans-heure{color:var(--encre-tenue)}

/* Le nom du logement est ce qui deborde : il se coupe, et le titre de la pastille le donne
   en entier. Sans min-width:0 sur un enfant de flex, ellipsis ne s'applique pas. */
.ps-bien{
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; min-width:0; flex:1 1 auto;
}
.ps-alerte{flex:0 0 auto; color:var(--alerte); display:inline-flex}
.ps-alerte .i{width:12px; height:12px}

/* Les cases d'un intervenant qui n'est plus dans l'equipe : hachurees, pour dire qu'on ne
   depose pas la. On peut en revanche glisser DEPUIS elles — c'est le geste utile, reprendre
   son travail. */
.ps-figee{
  background-image:repeating-linear-gradient(45deg,
    transparent, transparent 5px, var(--bord) 5px, var(--bord) 6px);
  cursor:not-allowed;
}

/* --- Le lien qui couvre une case de la grille ---
   Pose en fond, il rend toute la case cliquable — y compris ses parties vides, ou l'on clique
   pour ouvrir la journee d'un intervenant. Les pastilles passent au-dessus par leur seul ordre
   dans le document : aucune n'a besoin de z-index, et un empilement de plus serait un
   empilement a tenir. */
.ps-ouvrir{position:absolute; inset:0; border-radius:var(--rayon)}
.ps-case{position:relative}
.ps-case > .ps-puce{position:relative}
.ps-ouvrir:hover{background:rgba(23,138,138,.06)}
.ps-ouvrir:focus-visible{outline:2px solid var(--accent); outline-offset:-2px}

/* ======================== LA JOURNEE D'UN INTERVENANT ==========================
   Deux colonnes : la frise horaire a gauche, le detail de la selection a droite. La frise
   est plus etroite — on y lit des heures et des noms, pas des paragraphes — et le detail
   prend le reste. Les deux defilent ensemble : la fenetre qui les porte a sa propre hauteur,
   et deux zones de defilement independantes s'y perdraient. */
/* LA FRISE A GAUCHE, LE CADRE DE LA FICHE A DROITE.

   DEUX ZONES DE DEFILEMENT, ET PAS UNE DE PLUS. La frise peut compter dix creneaux et la fiche
   est longue : les faire defiler ensemble obligerait a remonter toute la fiche pour changer
   d'heure, ce qui est le geste que cet ecran existe pour raccourcir. Chacune defile donc chez
   elle — mais la PAGE qui les porte, elle, ne doit jamais defiler. Voir plus bas. */
.jour{
  display:grid; grid-template-columns:minmax(0, 320px) minmax(0, 1fr);
  gap:var(--e4); align-items:start;
}
.jour-frise{
  max-height:84vh; overflow-y:auto; padding-right:var(--e2);
}

/* Le cadre remplit sa colonne. Aucune bordure : la fiche qu'il porte a la sienne, et deux
   cadres emboites donneraient un ecran a tiroirs. */
.jour-cadre iframe{
  width:100%; height:84vh; border:0; display:block;
  border-radius:var(--rayon-carte); background:var(--surface);
}

/* Une ligne de contexte, discrete : la fenetre porte deja le nom de l'intervenant et le jour
   dans son en-tete, et le repeter en grand doublait l'information. */
.jour-contexte{
  margin:0 0 var(--e3); font-size:var(--t-petit); color:var(--encre-tenue);
  display:flex; align-items:center; gap:var(--e2); flex-wrap:wrap;
}

@media (max-width: 820px){
  .jour{grid-template-columns:minmax(0, 1fr)}
  .jour-frise{max-height:none}
  .jour-cadre iframe{height:70vh}
}

.frise-jour{list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:2px}

/* --- Un creneau --- */
.frise-creneau{margin:0}
.frise-lien{
  display:flex; align-items:center; gap:var(--e3);
  padding:var(--e2) var(--e3); border-radius:var(--rayon);
  text-decoration:none; color:var(--encre);
  border-left:3px solid var(--bord-net); background:var(--surface-creuse);
  transition:box-shadow var(--vite), border-color var(--vite);
}
/* Le survol ne touche plus au fond : le fond porte maintenant l'etat, et l'eclaircir au
   passage de la souris ferait clignoter le code couleur sous le curseur. */
.frise-lien:hover{text-decoration:none; box-shadow:var(--ombre1)}

/* --- L'etat par la couleur ---
   Les trois memes classes que la grille hebdomadaire, et non une seconde famille : c'est la
   grille qu'on voit par transparence derriere cette fenetre, et deux codes couleur pour la
   meme chose obligeraient a en reapprendre un a chaque ouverture.

   DEUX CLASSES DANS LE SELECTEUR, ET C'EST NECESSAIRE. .ps-attente est declaree PLUS HAUT dans
   ce fichier que .frise-lien ; a specificite egale, c'est la derniere qui gagne, et le fond de
   .frise-lien aurait donc efface la teinte. On monte d'un cran plutot que de deplacer une
   regle dont depend la grille. */
.frise-lien.ps-attente{border-left-color:var(--attente); background:var(--attente-voile)}
.frise-lien.ps-valide{border-left-color:var(--accent); background:var(--accent-voile)}
.frise-lien.ps-faite{
  border-left-color:var(--encre-tenue); background:var(--surface-creuse); opacity:.75;
}

/* La selection est un ANNEAU, et non plus un fond.
   Elle posait l'accent sur le fond ET sur le liseret — ce qui, depuis que le liseret porte
   l'etat, effacait l'etat de la ligne ouverte. Or c'est celle qu'on regarde. L'anneau se
   superpose a la teinte au lieu de la remplacer. */
.frise-active .frise-lien{box-shadow:inset 0 0 0 2px var(--accent)}

/* Debut et fin sur une ligne : deux nombres empiles se lisaient comme deux rendez-vous.
   Largeur fixe pour que les logements s'alignent d'une ligne a l'autre — une colonne en
   dents de scie se parcourt deux fois plus lentement. */
.frise-heure{
  flex:0 0 96px; font-family:var(--mono); font-size:var(--t-micro); line-height:1.3;
  color:var(--encre); white-space:nowrap;
}
.frise-fin{color:var(--encre-tenue)}

.frise-corps{flex:1 1 auto; min-width:0; display:flex; flex-direction:column; line-height:1.3}

/* Petit, mais pas efface : c'est ce qu'on lit en premier sur chaque ligne. */
.frise-bien{
  font-size:var(--t-petit); font-weight:600;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}

/* Le client sous le logement, plus discret : il situe, il ne designe pas. */
.frise-client{
  font-size:var(--t-micro); color:var(--encre-tenue);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}

/* La legende ferme la colonne. Un trait au-dessus : elle explique la frise, elle n'en fait
   pas partie. */
.frise-legende{
  margin:var(--e4) 0 0; padding-top:var(--e3); border-top:1px solid var(--bord);
}

/* --- Le trajet entre deux creneaux ---
   AFFICHE SYSTEMATIQUEMENT ici, contrairement a la grille hebdomadaire qui n'en montre
   aucun. On vient dans cette vue pour le detail, on a la place, et un trajet confortable
   renseigne quand on cherche ou glisser une prestation de plus.

   Retrait a gauche et bordure en pointilles : le trajet n'est pas un rendez-vous, c'est ce
   qui separe deux rendez-vous. La forme le dit avant le texte. */
.frise-trajet{
  display:flex; align-items:center; gap:var(--e2);
  margin:0 0 0 var(--e6); padding:3px var(--e3);
  border-left:2px dotted var(--bord-net);
  font-size:var(--t-micro); color:var(--encre-tenue); line-height:1.35;
}
.frise-trajet-icone{display:inline-flex; flex:0 0 auto}
.frise-trajet .i{width:12px; height:12px}

/* JUSTE : ambre. Ca passe, mais le moindre retard fait deraper. */
.frise-trajet.ps-route-juste{
  color:var(--attente); border-left-color:var(--attente); font-weight:600;
}

/* IRREALISABLE : rouge. C'est le seul etat de cette vue qui merite de crier — une journee
   qui ne tient pas se decouvre autrement sur place, chez le client. */
.frise-trajet.ps-route-impossible{
  color:var(--alerte); border-left-color:var(--alerte); font-weight:600;
  background:var(--alerte-voile); border-radius:0 var(--rayon) var(--rayon) 0;
}

/* La pastille en cours de deplacement s'efface : on doit voir la case visee a travers. */
.ps-portee{opacity:.4}

/* La fleche « semaine suivante » est la meme icone que « precedente », retournee : le
   sprite n'en porte qu'une, et deux glyphes pour un aller-retour seraient deux dessins a
   tenir coherents. */
/* « .semaine-suivante » A ETE RETIREE : elle retournait la fleche circulaire « retour » pour
   figurer « semaine suivante ». Un miroir de fleche circulaire reste une fleche circulaire —
   le retournement corrigeait le sens sans corriger le symbole, et deux de ces fleches en
   vis-a-vis se lisaient comme un rafraichissement. Les deux boutons portent desormais de
   vrais chevrons, qui ne disent que la direction. */

.ps-legende{display:inline-flex; align-items:center; gap:5px; margin-right:var(--e3)}
.ps-pastille{
  width:10px; height:10px; border-radius:3px; display:inline-block;
  border-left:3px solid currentColor;
}

/* Sous 900 px, sept colonnes de 40 px ne portent plus rien de lisible : la grille passe en
   defilement horizontal plutot que d'ecraser ses pastilles. C'est la seule concession, et
   elle ne concerne pas l'ecran d'ordinateur pour lequel cet ecran est fait. */
@media (max-width: 900px) {
  .planning-semaine{overflow-x:auto; grid-template-columns:minmax(120px, 150px) repeat(var(--jours, 7), minmax(96px, 1fr))}
}

/* --- Planning : liste a gauche, calendrier au centre --- */
.planning{display:grid; grid-template-columns:280px 1fr; gap:var(--e6); align-items:start}
.planning-cote{
  background:var(--surface); border-radius:var(--rayon-carte);
  box-shadow:var(--ombre1); padding:var(--e4); position:sticky; top:var(--e4);
}
.planning-filtres{display:flex; flex-direction:column; gap:var(--e3); margin-bottom:var(--e4)}
.planning-filtres .chercher{display:flex}
.planning-filtres-pied{display:flex; align-items:center; gap:var(--e3); margin-top:var(--e1)}
/* Les selecteurs de la colonne laterale sont etroits : la liste deroulante doit
   pouvoir depasser leur largeur, sinon un nom de bien long devient illisible. */
.planning-cote .choices__list--dropdown{min-width:240px}
.planning-filtres input[type=search]{
  width:100%; padding:9px var(--e3) 9px 33px; font:inherit; font-size:var(--t-controle);
  border:1px solid var(--bord-net); border-radius:var(--rayon); background:var(--surface);
  transition:border-color var(--vite), box-shadow var(--vite);
}
.planning-filtres input[type=search]:focus{border-color:var(--accent); box-shadow:var(--anneau); outline:none}
.planning-groupe{margin-bottom:var(--e4)}
.planning-groupe h2{
  display:flex; align-items:center; gap:var(--e2); margin:0 0 var(--e1);
  font-size:var(--t-micro); font-weight:600; letter-spacing:.08em; text-transform:uppercase;
  color:var(--encre-tenue);
}
.planning-groupe ul{list-style:none; margin:0; padding:0}
.planning-groupe a{
  display:flex; align-items:center; gap:var(--e2); padding:var(--e2) 10px;
  text-decoration:none; color:var(--encre); border-radius:var(--rayon);
  border-left:3px solid transparent; font-size:var(--t-controle);
  transition:background var(--vite), border-color var(--vite);
}
.planning-groupe a:hover{background:var(--surface-creuse)}
.planning-groupe a[aria-current]{
  background:var(--accent-voile); border-left-color:var(--accent); font-weight:600;
}
.planning-groupe a span{display:flex; flex-direction:column; min-width:0; flex:1}
.planning-groupe a em{
  font-style:normal; font-size:var(--t-micro); color:var(--encre-tenue); font-family:var(--mono);
}
.planning-barre{display:flex; align-items:center; gap:var(--e4); flex-wrap:wrap; margin-bottom:var(--e4)}
.planning-navigation{display:flex; gap:var(--e1); margin-left:auto}
.planning-navigation .btn{padding:var(--e2) var(--e3)}

/* --- Grilles de calendrier ---
   Une table, parce que c'en est une : sept colonnes de jours, une ligne par
   semaine. Les lecteurs d'ecran l'annoncent correctement, ce qu'une grille de div
   n'obtient qu'a coups d'attributs ARIA. */
.calendriers{display:grid; gap:var(--e6)}
.calendriers-trois{grid-template-columns:repeat(3, 1fr)}
.calendrier{
  background:var(--surface); border-radius:var(--rayon-carte);
  box-shadow:var(--ombre1); padding:var(--e4); overflow:hidden;
}
.calendrier h3{
  margin:0 0 var(--e3); font-size:var(--t-petit); font-weight:600;
  color:var(--encre-douce); text-transform:uppercase; letter-spacing:.06em;
}
.calendrier table{width:100%; border-collapse:collapse; table-layout:fixed}
.calendrier th{
  padding:var(--e1) 2px var(--e2); font-family:var(--mono); font-size:var(--t-micro); font-weight:600;
  letter-spacing:.06em; text-transform:uppercase; color:var(--encre-tenue);
  border-bottom:1px solid var(--bord);
}
.calendrier td{
  height:62px; vertical-align:top; padding:3px 3px 0;
  border:1px solid var(--bord); background:var(--surface); position:relative;
}
.calendriers-trois .calendrier td{height:40px}
.calendrier td.hors-mois{background:var(--surface-creuse)}
.calendrier td.hors-mois .jour{color:var(--encre-tenue)}
.calendrier td.aujourdhui{box-shadow:inset 0 0 0 2px var(--accent)}
.calendrier .jour{font-family:var(--mono); font-size:var(--t-micro); color:var(--encre-douce); display:block}

/* --- Barres d'occupation ---
   Positionnees en absolu, et non empilees en blocs, pour une raison precise : le
   jour de rotation porte un depart ET une arrivee, qui doivent occuper les deux
   MOITIES d'une meme ligne. Des blocs les auraient mis l'un sous l'autre, donnant
   a lire un conflit inexistant.
     depart   du bord gauche au milieu — les cles sont rendues le matin ;
     arrivee  du milieu au bord droit — le locataire entre l'apres-midi ;
     complet  de bord a bord.
   Les valeurs negatives franchissent la bordure et les 3 px de retrait de la case,
   pour que deux journees consecutives se rejoignent sans couture.
   --rang empile les sejours qui se recouvrent vraiment : une double reservation
   entre deux plateformes doit se voir, pas se cacher. */
.sejour{
  position:absolute; height:16px;
  top:calc(21px + var(--rang, 0) * 18px);
  background:hsl(var(--teinte, 205) 46% 54%);
  color:#fff; font-size:var(--t-micro); line-height:16px;
  overflow:hidden; white-space:nowrap; font-weight:500;
}
.sejour.complet{left:-4px; right:-4px; padding:0 var(--e1)}
.sejour.arrivee{left:50%; right:-4px; border-radius:9px 0 0 9px; padding:0 var(--e1) 0 7px}
.sejour.depart{left:-4px; right:50%; border-radius:0 9px 9px 0}
/* Reservation sans source : saisie a la main. Couleur de l'accent, pour qu'elle ne
   se confonde avec aucune plateforme. */
.sejour-manuel{background:var(--accent)}

/* LA GRILLE NE REDOUBLE PAS LA MARGE DE LA NAVIGATION : elle se resserre en haut, et garde en bas
   la respiration qui la separe de la legende. */
.calendrier-sejours{padding-top:var(--e2)}

/* --- LA NAVIGATION DU MOIS, en tete de la grille ---
   Elle etait dessinee par FullCalendar et est partie avec lui. Des LIENS : changer de mois est une
   navigation, l'adresse se met en favori et le mois s'affiche sans JavaScript. */
/* LE TITRE ETAIT LOIN DE SES ENTETES. Trois marges s'ajoutaient sans qu'on les voie separement :
   celle-ci, la marge interne de la grille, et l'espace au-dessus du libelle des jours. On garde une
   respiration, pas un intervalle. */
.calendrier-navigation{
  display:flex; align-items:center; gap:var(--e2);
  margin-bottom:var(--e1);
}
/* Le mois est le titre de la grille : il prend la place laissee par les fleches, centre entre
   elles et le bord. « flex:1 » le pousse au milieu sans qu'on mesure quoi que ce soit. */
.calendrier-mois{
  flex:1 1 auto; text-align:center;
  font-size:var(--t-moyen); font-weight:600; letter-spacing:-.01em;
}
.calendrier-navigation .btn-icone{flex:none}

/* --- Ce que le calendrier des reservations ajoute a la grille du planning ---
   La grille, les barres et les pastilles sont celles du planning : meme modele, meme CSS. Ce qui
   suit est propre a l'ecran des reservations, ou l'on CHOISIT une barre pour la modifier.

   LES BARRES SONT DES BOUTONS ICI, et des <span> sur le planning. Un bouton porte une bordure, un
   fond et une police du systeme : on les remet a plat, sinon la barre cesse d'etre une barre. */
.calendrier-sejours .sejour,
.calendrier-sejours .interv{
  border:0; font-family:inherit; cursor:pointer; text-align:left;
}
/* LES PASTILLES SEULES RECLAMENT LA LARGEUR DE LEUR CONTENEUR — un bouton ne la prend pas de
   lui-meme. LA BARRE EN EST DESORMAIS EXCLUE, et ce n'etait pas un detail : ce « width:100% »
   portait la meme specificite que la largeur du segment, et c'est lui qui restait des que celle-ci
   etait ecartee. Une barre large d'une case quelle que soit la duree du sejour — rapporte trois
   fois, et invisible a toute assertion qui relit le texte de la regle. */
.calendrier-sejours .interv{width:100%}
/* La barre, elle, est en position absolue : sa largeur vient de left/right, pas de 100%. */
/* --- LA GEOMETRIE D'UN SEGMENT ---
   Une boite couvre desormais une SUITE de journees, et sa largeur se calcule : « --jours » cases,
   plus les filets qui les separent. Le pas d'une colonne n'est pas 100% de la case — les bordures
   sont fusionnees, chaque colonne mesure donc une case PLUS un filet. Sans ce filet, un segment de
   sept jours accusait sept pixels de retard sur sa derniere case.

   LES DEUX BOUTS SE COUPENT A MIDI, ET SEULEMENT S'ILS SONT DE VRAIS BOUTS. Un segment coupe par le
   bord de la semaine se poursuit : il prend le bord de la case, carre, et le lundi suivant reprend
   exactement la ou il s'etait arrete. Les cles sont rendues le matin et reprises l'apres-midi :
   c'est cela que « midi » traduit, et c'est ce qui met une rotation sur une seule ligne. */
/*
   UN SEUL NIVEAU DE CALCUL, ET AUCUNE VARIABLE INTERMEDIAIRE.
   La largeur passait par « --pas », une propriete personnalisee qui contenait elle-meme un calc()
   melant un pourcentage et des pixels, relu ensuite dans un second calc(). Les barres sortaient a
   la largeur de leur texte : la propriete etait invalide a l'usage, donc « width » retombait sur
   « auto » — et un absolu sans largeur se reduit a son contenu. Aucune erreur, aucun avertissement,
   juste une declaration ignoree.
   ON N'IMBRIQUE DONC PLUS RIEN : une multiplication, une addition, et « --jours » lu directement.
   C'est la forme la plus simple qu'un navigateur puisse avoir a evaluer.
   LE FILET ENTRE DEUX CASES N'EST PLUS COMPTE, et c'est un abandon assume : il valait un pixel par
   journee, soit six sur une semaine entiere, pour un terme qui doublait la longueur de chaque
   expression. Les 8 px de debord l'absorbent. */
/* LA LARGEUR ET LES DECALAGES NE SONT PLUS ICI : ils sont poses en attribut « style » par la vue,
   depuis Calendrier::geometrieSegment(). La feuille garde ce qui ne se calcule pas — la disposition
   du libelle, et l'arrondi des bouts. */
/* --- LA BARRE DOIT PASSER AU-DESSUS DES CASES SUIVANTES ---
   ET C'EST LA LE DEFAUT, PAS LA LARGEUR. La barre etait bien large de sept cases ; on n'en voyait
   qu'une. « .calendrier td » porte « position:relative » — pour servir de reference aux barres
   absolues — et une cellule positionnee dont le « z-index » vaut « auto » peint son FOND et ses
   descendants positionnes comme un seul bloc, dans l'ordre du document. La case suivante peint donc
   son fond PAR-DESSUS la partie de la barre qui depasse chez elle, et la case d'apres aussi.

   « z-index:2 » SORT LA BARRE DE CE BLOC. Un « z-index » chiffre sur un element positionne le fait
   participer au contexte d'empilement de l'ANCETRE — la case ne creant pas de contexte, faute d'un
   z-index chiffre elle-meme — donc au-dessus de tous les fonds de cellules, quel que soit leur rang
   dans le document.

   C'EST AUSSI L'EXPLICATION DU « DECROCHEMENT » signale il y a des semaines. Les barres du planning
   depassent de 4 px chez leur voisine pour se souder a la suivante ; ces 4 px etaient recouverts par
   le fond de la voisine, d'ou une encoche a chaque jonction. Je l'avais traitee par un « ::after »
   et une variable de trait — un cataplasme sur la consequence, la cause etant ici.

   LA BARRE CHOISIE RESTE AU-DESSUS, avec son 3 : le liseret ne doit pas passer sous une barre
   voisine. */
/* --- UNE CASE HAUTE DE DEUX TIERS DE SA LARGEUR ---
   62 px sur 170 faisait un rapport de 0,36 : des cases en bandeau, ou deux barres et une pastille
   remplissaient tout. Le rapport demande est de 2/3, et il doit SUIVRE LA LARGEUR — celle d'une
   colonne varie presque du simple au double entre un ecran etroit et la pleine page, et une hauteur
   fixe ne serait juste qu'a un seul endroit.

   UNE MARGE INTERNE EN POURCENTAGE SE MESURE TOUJOURS SUR LA LARGEUR, jamais sur la hauteur. C'est
   contre-intuitif, et c'est precisement ce qui en fait le seul moyen de tenir un rapport ici :
   « aspect-ratio » ne s'applique pas aux cases d'un tableau — la propriete exclut les boites
   internes de tableau, ce qu'une case est.

   FLOTTANTE ET SANS LARGEUR, pour ne rien deranger : le numero du jour et les pastilles coulent a
   cote d'elle comme si elle n'existait pas. Et une case de tableau etablit toujours un contexte de
   formatage de bloc, donc elle CONTIENT ses flottantes — c'est ce qui fait que celle-ci impose sa
   hauteur au lieu de deborder sous la ligne.

   LE « height » DE LA GRILLE RESTE, EN PLANCHER : si cette marge n'aboutissait pas, la case garderait
   la hauteur qu'elle avait plutot que de s'affaisser sur son contenu. */
.calendrier-sejours td::before{
  content:''; float:left; width:0; padding-top:66.67%;
}

.calendrier-sejours .sejour{
  display:flex; align-items:center; gap:var(--e2);
  border-radius:0; padding:0 7px; z-index:2;
}
/* Un bout coupe a midi est un VRAI bout : il s'arrondit. Un bout coupe par le bord de la semaine se
   poursuit — il reste carre, et le lundi suivant reprend exactement la ou il s'etait arrete. */
.calendrier-sejours .sejour.ouvre-midi{border-radius:9px 0 0 9px}
.calendrier-sejours .sejour.ferme-midi{border-radius:0 9px 9px 0}
.calendrier-sejours .sejour.ouvre-midi.ferme-midi{border-radius:9px}

/* --- LE NOM A GAUCHE, LES NUITS A DROITE ---
   Chaque journee est une boite confinee a sa case : il n'existe pas de boite unique couvrant le
   sejour ou l'on pourrait mettre les deux bouts. On les pose donc aux DEUX EXTREMITES de la barre —
   le nom sur son premier jour visible, les nuits sur le dernier — et les boites se rejoignant sans
   couture, l'ensemble se lit comme une seule barre.

   « min-width:0 » EST CE QUI FAIT MARCHER L'ELLIPSE du nom : un element flex refuse par defaut de
   descendre sous la largeur de son contenu, l'ellipse ne se declenche jamais, et c'est le compte de
   nuits qui se fait pousser hors de la barre. Meme regle que dans les listes. */
.calendrier-sejours .sejour-nom{
  min-width:0; overflow:hidden; white-space:nowrap; text-overflow:ellipsis;
}
/* Les nuits ne se compriment pas : c'est l'information la plus courte et la plus utile de la barre,
   un nom long doit ceder devant elle. « margin-left:auto » les colle a droite meme quand elles sont
   seules sur leur boite — le cas d'un sejour a cheval sur deux semaines. */
/* IL HERITE DE LA BARRE, ET NE GARDE PAS SA COULEUR DE TABLEAU. « .sejour-nuits » est ecrit pour
   la liste : encre douce sur fond blanc, dans une taille monospace d'un cran au-dessus. Sur une
   barre — fond sature, texte blanc, ligne de 16 px — cela donnait du gris-bleu sur du bleu, qu'on
   ne lisait pas, et qui debordait en hauteur. */
.calendrier-sejours .sejour-nuits{
  color:inherit; font-size:var(--t-micro); opacity:.85;
  flex:none; margin-left:auto; font-variant-numeric:tabular-nums; opacity:.85;
}

/* --- UN SEJOUR ANNULE EST GRIS, ET NON TEINTE ---
   Il portait la couleur de sa source avec une hachure par-dessus : on lisait d'abord « Airbnb »,
   puis on remarquait la trame. L'annulation est ce qu'il faut voir en premier — la barre sort donc
   des couleurs de plateforme pour un gris qui ne se confond avec aucune.

   LA HACHURE RESTE, et double le signal pour qui distingue mal les couleurs. */
.calendrier-sejours .sejour-annule{
  background-color:#c8d0ce; color:var(--encre-douce);
  background-image:repeating-linear-gradient(135deg, transparent 0 4px, rgba(255,255,255,.5) 4px 8px);
}

/* --- LE JOUR COURANT EST JAUNE ---
   Il portait un liseret a l'accent — le meme petrole que les barres saisies a la main et que les
   controles actifs. Trois choses de la meme couleur pour trois sens differents : on cessait de
   savoir ce que l'accent disait. Le jaune ne sert qu'a cela dans cet ecran.

   UN FOND ET NON UN LISERET : la case est reperee d'un coup d'oeil sur une grille de six semaines,
   et le fond passe SOUS les barres au lieu de les encadrer. */
.calendrier-sejours td.aujourdhui{
  box-shadow:none; background:var(--attente-voile);
}
.calendrier-sejours td.aujourdhui .jour{color:var(--attente); font-weight:700}

/* --- L'APERCU DU GLISSER ---
   Les cases parcourues pendant le glisser, avant relachement. Le meme jaune que le jour courant
   serait un contresens : ceci n'est pas une date, c'est une intention. On prend l'accent, qui dit
   « en cours » partout ailleurs dans l'application. */
.calendrier-sejours td.jour-vise{background:var(--accent-voile)}
/* Pendant un glisser, le curseur dit qu'on trace une periode. */
.calendrier-sejours td.jour-vise .jour{color:var(--accent-fonce); font-weight:700}

/* CE QU'ON VIENT DE CHOISIR SE MARQUE, ET UNE SEULE CHOSE A LA FOIS.
   Sur un mois charge on ne sait plus laquelle on a cliquee — et le panneau, lui, ne dit pas de
   quelle barre il parle. Un liseret a l'encre, qui se voit sur toutes les teintes de source. */
/* « position:relative » ETAIT UNE FAUTE ICI : il l'emportait sur le « position:absolute » de
   « .sejour », donc la barre choisie sortait du positionnement absolu et retombait dans le flux de
   sa case — elle sautait au clic, au moment meme ou l'on venait de la designer. Un « z-index »
   s'applique tel quel a un element deja positionne. */
.calendrier-sejours .sejour-choisi,
.calendrier-sejours .interv-choisi{box-shadow:0 0 0 2px var(--encre); z-index:3}

/* --- Prestations dans la case ---
   Une pastille dans le flux, pas une barre : une intervention est un rendez-vous
   dans une journee, elle n'occupe pas le logement d'un apres-midi a un matin comme
   un sejour. Lui donner la meme forme brouillerait les deux lectures.
   Les barres etant en absolu, elles ne poussent rien : --sejours, pose par le
   gabarit, compte leurs rangs et rend la marge qu'elles auraient prise. La hauteur
   de case (62 px) est un minimum pour un td : une journee chargee fait grandir la
   ligne au lieu de rogner. */
.prestations{
  display:flex; flex-direction:column; gap:2px; position:relative;
  /* 4 px : le flux commence 3 px plus haut que les barres (top:21px), il faut donc
     un peu plus que leur seule hauteur pour ne pas mordre sur la derniere. */
  margin:calc(4px + var(--sejours, 0) * 18px) -1px 3px;
}
.interv{
  display:block; height:15px; line-height:15px; border-radius:3px;
  padding:0 4px; font-size:var(--t-micro); font-weight:500;
  overflow:hidden; white-space:nowrap; text-overflow:ellipsis;
  background:hsl(var(--teinte, 184) 42% 40%); color:#fff; text-decoration:none;
}
a.interv:hover{background:hsl(var(--teinte, 184) 46% 32%); text-decoration:none}
/* Non validee : hachuree et sans teinte. L'absence de couleur pleine est le message
   — rien n'est encore engage. La hachure double le signal pour qui distingue mal
   les couleurs. */
.interv-attente{
  background:repeating-linear-gradient(
    135deg, var(--surface-creuse) 0 4px, var(--bord) 4px 8px
  );
  color:var(--encre-douce); box-shadow:inset 0 0 0 1px var(--bord);
}
a.interv-attente:hover{color:var(--encre); box-shadow:inset 0 0 0 1px var(--encre-tenue)}
/* Le point qui signale un changement demande, en attente d'arbitrage. */
.interv-alerte{color:var(--attente); font-weight:700}

/* En trimestre, les libelles disparaissent comme ceux des sejours : il ne reste que
   la couleur et l'infobulle, seules lisibles a cette echelle. */
.calendriers-trois .prestations{margin-top:calc(2px + var(--sejours, 0) * 11px)}
.calendriers-trois .interv{height:8px; font-size:0; padding:0; border-radius:2px}

/* --- Tableau des sejours ---
   DECLARE APRES .tableau-tarifs, ET C'EST INDISPENSABLE. Les deux selecteurs ont la meme
   specificite — une classe — donc l'ordre du fichier tranche. Place avant, cette section
   voyait ses width:auto et sa marge interne resserree ecrases par .tableau-tarifs, et le
   tableau continuait a tasser ses colonnes au lieu de deborder. */
.pleine-largeur{
  /* max-width:none EST INDISPENSABLE : .carte et .carte-large plafonnent a 540 et 820 px,
     et max-width l'emporte toujours sur width. Sans cette ligne, le bloc restait a 820 px
     quelle que soit la largeur declaree juste en dessous. */
  max-width:none;
  width:min(1560px, calc(100vw - 2 * var(--marge-page)));
  /* Le centrage par marge negative : 50 % renvoie a la largeur du conteneur de page, dont
     on retire la moitie de la largeur voulue. */
  margin-left:calc(50% - min(1560px, calc(100vw - 2 * var(--marge-page))) / 2);
}
/* width:auto avec table-layout:fixed — les largeurs de <colgroup> sont alors prises
   telles quelles et la largeur du tableau est leur somme. Avec width:100 %, le navigateur
   les traitait comme des proportions et tassait les colonnes au lieu de deborder ; on ne
   voyait donc jamais de barre. min-width:100 % le fait remplir quand la place existe. */
.tableau-sejours{width:auto; min-width:100%}
/* Huit colonnes ou plus : 16 px de marge interne de chaque cote coutaient plus de 250 px
   de largeur a eux seuls. Une grille se lit dense. */
.tableau-sejours th, .tableau-sejours td{padding:var(--e2) var(--e3)}
.tableau-sejours th[scope=row]{font-weight:400; vertical-align:middle}
/* L'etat et l'origine empiles : l'etat repond a « est-ce en ordre ? », l'origine a
   « d'ou cela vient-il ? ». La seconde question est secondaire, elle passe dessous. */
.sejour-origine{
  display:flex; align-items:center; gap:var(--e1); margin-top:3px;
  font-size:var(--t-petit); color:var(--encre-tenue);
}
/* L'ARRIVEE PASSE DE 14 A 13 px. Une date n'est pas un titre : elle se lit d'un coup et n'a pas
   besoin d'appeler l'oeil. Les deux bornes prennent ainsi la meme taille et se lisent comme UN
   intervalle, ce que la cellule dit deja par sa fleche. La distinction reste, portee par la couleur :
   l'arrivee en encre pleine, le depart en encre douce. */
.sejour-fixe{display:block; font-size:var(--t-petit); color:var(--encre)}
.sejour-nuits{font-family:var(--mono); font-size:var(--t-mono); color:var(--encre-douce)}
.tableau-sejours thead th{font-size:10px; letter-spacing:.04em}
.colonne-double{
  display:inline-block; margin-left:2px; padding:0 3px; border-radius:2px;
  background:var(--attente-voile); color:var(--attente); font-size:9px;
}
/* Une ligne passee reste modifiable mais s'efface : on corrige rarement le passe. */
.tableau-sejours .ligne-passee{opacity:.62}
.tableau-sejours .ligne-passee:hover{opacity:1}


/* --- Legende ---
   Indissociable des couleurs : une teinte sans legende n'est qu'une decoration. */
.legende{
  display:flex; flex-wrap:wrap; align-items:center; gap:var(--e2) var(--e4);
  margin-top:var(--e4); padding-top:var(--e3); border-top:1px solid var(--bord);
  font-size:var(--t-petit); color:var(--encre-douce);
}
.legende-entree{display:inline-flex; align-items:center; gap:var(--e2)}
.legende-puce{
  width:22px; height:11px; border-radius:6px; flex:none;
  background:hsl(var(--teinte, 205) 46% 54%);
}
.legende-puce-manuel{background:var(--accent)}
/* La pastille de legende est la vraie pastille, hachure comprise : une imitation
   finirait par deriver de ce qu'elle est censee expliquer. */
.legende-interv{width:auto; height:auto; line-height:15px; padding:0 var(--e2)}
/* LA NOTE EN PIED DE LEGENDE A DISPARU : elle decrivait ce qu'on a sous les yeux, et annoncait un
   controle retire. La regle part avec elle — une regle sans emploi est une regle que personne
   n'osera enlever ensuite.

   A SA PLACE, UN GROUPE : un intertitre et ses pastilles. Les teintes de source disent D'OU vient la
   reservation, celles des prestations OU EN EST le travail : deux codes distincts qu'il faut lire
   comme tels, d'ou le titre qui les separe. */
.legende-groupe{display:inline-flex; align-items:center; gap:var(--e2); flex-wrap:wrap}
.legende-titre{
  font-weight:600; color:var(--encre-douce); margin-right:var(--e1);
}

/* --- L'interrupteur de la legende ---
   « margin-left:auto » le pousse au bout de la rangee : il est le seul reglage parmi des
   explications, et le bout de la ligne est la ou l'on cherche une commande.

   IL PASSE AVANT LA NOTE parce que celle-ci occupe toute une ligne a elle (« flex:1 1 100% ») :
   place apres, il serait tombe SOUS le paragraphe au lieu de finir la rangee des pastilles. */
.interrupteur{
  display:inline-flex; align-items:center; gap:var(--e2);
  margin-left:auto; flex:none; position:relative;
  color:var(--encre-douce); text-decoration:none; white-space:nowrap;
}
.interrupteur:hover{color:var(--encre)}

/* La piste est creuse et le galet pose dessus — le meme partage que le rail des segments : ce qui
   est enfonce ne porte pas d'ombre, ce qui est pose en porte une. */
.interrupteur-piste{
  position:relative; flex:none; width:34px; height:18px; border-radius:9px;
  background:var(--surface-creuse); border:1px solid var(--bord-net);
  transition:background .12s ease, border-color .12s ease;
}
.interrupteur-piste::after{
  content:''; position:absolute; top:2px; left:2px; width:12px; height:12px;
  border-radius:50%; background:#fff; box-shadow:var(--ombre1);
  transition:transform .12s ease;
}
.interrupteur-actif .interrupteur-piste{background:var(--accent); border-color:var(--accent)}
.interrupteur-actif .interrupteur-piste::after{transform:translateX(16px)}
.interrupteur:focus-visible .interrupteur-piste{outline:2px solid var(--accent); outline-offset:2px}

/* Le compte de ce qui est cache. Au ton d'attente : ce n'est pas une alerte, c'est un rappel. */
.interrupteur-compte{
  flex:none; min-width:18px; padding:0 5px; border-radius:9px;
  background:var(--attente-voile); color:var(--attente);
  font-size:var(--t-micro); font-weight:600; text-align:center;
}



/* --- Adaptation aux ecrans etroits ---
   1024 px est le seuil demande : au-dela, le tableau des sejours tient sans defilement ;
   en dessous, on prefere le faire glisser que le tasser jusqu'a l'illisible. */
@media (max-width:1024px){
  /* Le bloc rentre dans la colonne de page. Rien a dire du defilement : .tableau-defilant
     est deja en overflow-x:auto, la barre apparait d'elle-meme. */
  .pleine-largeur{width:auto; margin-left:0; max-width:none}
  /* Le panneau d'edition passe sous le calendrier : deux colonnes de 300 px ne servent
     personne, et il perd son adherence — coller un bloc en haut d'un ecran etroit mange
     la moitie de la hauteur utile. */
  .atelier{grid-template-columns:1fr}
  .panneau{position:static}
}

/* --- Adaptation aux petits ecrans --- */
@media (max-width:900px){
  .planning{grid-template-columns:1fr}
  .planning-cote{position:static}
  .calendriers-trois{grid-template-columns:1fr}
  .calendriers-trois .calendrier td{height:58px}
  /* Le trimestre passe sur une colonne : les cases retrouvent la place d'afficher les
     libelles, donc la taille normale. Le pas d'empilement suit la hauteur, sinon deux
     barres se recouvriraient — et la marge des prestations suit le pas. */
  .calendriers-trois .sejour{
    height:17px; font-size:var(--t-micro); padding:0 var(--e1);
    top:calc(21px + var(--rang, 0) * 18px);
  }
  .calendriers-trois .prestations{margin-top:calc(4px + var(--sejours, 0) * 18px)}
  .calendriers-trois .interv{height:15px; font-size:var(--t-micro); padding:0 4px; border-radius:3px}
}
@media (max-width:620px){
  .page{padding:var(--e6) var(--e4) var(--e12)}
  .bandeau{padding:var(--e3) var(--e4)}
  .grille-deux{grid-template-columns:1fr}
  .ligne{grid-template-columns:5px 1fr}
  .ligne .commandes{grid-column:2; padding-top:0; justify-content:flex-start}
  /* .ligne.ordonnee compte deux classes, donc l'emporte sur la regle ci-dessus : sans
     cette reprise, la ligne garderait quatre colonnes et deborderait. Les fleches
     restent, elles occupent 22 px. */
  .ligne.ordonnee{grid-template-columns:5px auto 1fr}
  .ligne.ordonnee .commandes{grid-column:3}
  /* MEME RAISON POUR LA LIGNE A VIGNETTE, et le meme piege : « .registre .ligne:has(...) » pese
     plus que « .ligne » ci-dessus, donc elle garderait ses QUATRE colonnes sur un telephone et
     deborderait. Il faut la reprendre ici, sans quoi la regle large gagne dans l'etroit.
     LA VIGNETTE RESTE, LES COMMANDES DESCENDENT : elle est etroite et fixe (38 px), et c'est ce
     qu'on regarde d'abord pour reconnaitre un logement. Ce sont les commandes qui passent
     dessous, comme pour toutes les autres lignes de l'application. */
  .registre .ligne:has(> .vignette-bien){grid-template-columns:5px auto 1fr}
  .registre .ligne:has(> .vignette-bien) .commandes{grid-column:3}
  .entete .actions{margin-left:0; width:100%}
  .entete .actions .btn{width:100%}
  .fiche-technique{grid-template-columns:1fr; gap:2px 0}
  .fiche-technique dd{margin-bottom:var(--e3)}
}

/* Toutes les animations sont neutralisees pour qui l'a demande au systeme. La
   regle 4 est un confort, jamais une condition de fonctionnement. */
@media (prefers-reduced-motion:reduce){
  *{transition:none !important; animation:none !important}
  .sommaire-entree:hover, .btn:active{transform:none}
}

/* ================================================================= INTERVENTIONS ===
   La liste et la fiche, refondues : un tableau la ou l'on parcourt, un grand cadre
   sectionne la ou l'on decide. */

/* --- La liste ---
   Un tableau, et non la pile de cartes d'avant. Le registre du tableau de bord garde sa
   forme : quelques lignes a traiter, chacune meritant de la place. Ici on parcourt et on
   compare, et un tableau met les dates les unes sous les autres. */
.tableau-interventions{width:100%; border-collapse:collapse; font-size:.92rem}
/* LE CONTENU EST CENTRE DANS LA HAUTEUR DE SA CELLULE, ET NON CALE EN HAUT.
   C'est la demande, et c'est aussi une mise en accord : « .tableau-tarifs » et
   « .tableau-concierges » sont en vertical-align:middle depuis toujours. Deux familles de
   tableaux qui alignent differemment sur les memes ecrans se remarquent sans se nommer.

   POURQUOI CELA CHANGE QUELQUE CHOSE ICI : une ligne mele des cellules d'une ligne — la date, le
   tarif, le statut — et des cellules de deux ou trois — le nom sur son role, le bien sur sa ville,
   la vignette de 38 px. Calees en haut, les premieres pendent au plafond d'une ligne dont les
   autres occupent toute la hauteur, et l'oeil ne suit plus de rangee horizontale.

   L'EN-TETE SUIT LA MEME REGLE et n'en souffre pas : ses libelles tiennent tous sur une ligne. */
.tableau-interventions th, .tableau-interventions td{
  padding:10px 12px; text-align:left; vertical-align:middle;
  border-bottom:1px solid var(--bord);
}
.tableau-interventions thead th{
  font-size:.72rem; text-transform:uppercase; letter-spacing:.06em;
  color:var(--encre-tenue); font-weight:600; background:var(--surface-creuse);
  border-bottom:1px solid var(--bord); white-space:nowrap;
}
.tableau-interventions tbody tr:last-child th,
.tableau-interventions tbody tr:last-child td{border-bottom:0}
.tableau-interventions tbody tr:hover{background:var(--surface-creuse)}
.tableau-interventions .droite, .tableau-prestations .droite{text-align:right}

/* L'onglet lateral colore, comme sur les lignes du registre : c'est le meme vocabulaire
   visuel d'un ecran a l'autre, et la couleur porte l'etat avant le texte. */
.tableau-interventions tbody tr td:first-child{border-left:3px solid transparent}
.tableau-interventions tbody tr.ligne-attente td:first-child{border-left-color:var(--attente)}
.tableau-interventions tbody tr.ligne-valide td:first-child{border-left-color:var(--accent)}
.tableau-interventions tbody tr.ligne-revoque td:first-child{border-left-color:var(--bord-net)}
.tableau-interventions tbody tr.ligne-revoque{color:var(--encre-tenue)}

/* Le meme onglet lateral pour les etats de QUOTA, sur le tableau de consommation du forfait.
 |
 | Il portait « class="tableau" », qui n'existe dans aucune feuille : le tableau etait donc rendu
 | nu — ni bordures, ni en-tetes distincts, ni chiffres alignes. Il rejoint « .tableau-interventions »
 | pour lire comme la liste des factures.
 |
 | LE PREMIER ELEMENT EST UN <th scope="row">, PAS UN <td> : les regles ci-dessus visent
 | « td:first-child » et ne l'atteindraient pas. « > :first-child » prend les deux, et pose ici la
 | bordure transparente que ces lignes n'heritent donc pas.
 |
 | LES CLASSES VIENNENT DU DOMAINE — autorise() et bientotAtteint() — et colorent deja le texte
 | (voir « .quota-plein » plus bas). On n'ajoute que l'onglet. */
.tableau-interventions tbody tr.quota-proche > :first-child,
.tableau-interventions tbody tr.quota-plein > :first-child{border-left-width:3px; border-left-style:solid}
.tableau-interventions tbody tr.quota-proche > :first-child{border-left-color:var(--attente)}
.tableau-interventions tbody tr.quota-plein > :first-child{border-left-color:var(--alerte)}

/* La seconde ligne d'une cellule : la ville sous le bien, l'heure sous la date. Elle
   porte le detail, jamais l'information principale. */
.cellule-sous{display:block; font-size:.8rem; color:var(--encre-tenue); margin-top:2px}
.cellule-tronquee{
  display:block; max-width:100%; overflow:hidden;
  white-space:nowrap; text-overflow:ellipsis;
}

/* --- La fiche : le grand cadre --- */
/* --- L'en-tete de la fiche ---
   Quatre elements sur une rangee : le retour, le titre, la pastille d'etat, la reference. « .entete »
   les aligne deja sur la ligne de base ; le retour, lui, se cale au milieu du titre — aligne sur la
   base, un bouton rond parait pendre sous la ligne. */
.fiche-entete{align-items:center}
.fiche-entete h1{margin-right:var(--e1)}

/* LE BOUTON DE RETOUR : rond, discret, a l'endroit ou l'oeil cherche la fleche du navigateur.
   Il ne porte pas « .btn » : les boutons de cette application sont rectangulaires et ont un
   libelle. Celui-ci n'a qu'un symbole, et un carre de 38 px a cote d'un titre de 26 px pese plus
   que le titre. */
.btn-retour{
  display:inline-flex; align-items:center; justify-content:center;
  width:34px; height:34px; flex:none; border-radius:50%;
  background:var(--surface); border:1px solid var(--bord); color:var(--encre-douce);
  box-shadow:var(--ombre1); text-decoration:none;
  transition:border-color var(--vite), color var(--vite), background var(--vite);
}
.btn-retour:hover{border-color:var(--bord-net); color:var(--encre); background:var(--surface-creuse)}
.btn-retour:focus-visible{outline:2px solid var(--accent); outline-offset:2px}

/* La reference : on ne la lit pas, on la copie. Elle recule donc d'un cran en couleur comme en
   taille, et garde le monospace qui rend un identifiant relisible caractere par caractere. */
.fiche-reference{
  font-family:var(--mono); font-size:var(--t-mono); color:var(--encre-tenue);
  letter-spacing:.02em;
}

/* LE GRAND CADRE N'EST PLUS UNE CARTE, C'EST UNE PILE DE CARTES.
   Il portait une seule surface blanche et separait ses sections par un filet d'un pixel. Cinq
   sujets — le bien, le sejour, les prestations, l'intervention, l'historique — se lisaient comme
   un seul document dont il fallait suivre les filets pour savoir ou l'un finissait.

   IL GARDE SA CLASSE ET PERD SON APPARENCE : ni fond, ni ombre, ni rayon. Ce sont ses enfants qui
   les prennent. Le balisage ne change pas — c'est ce qui permet a ce changement de tenir dans la
   feuille, et non dans une refonte de la vue.

   overflow:visible EST INDISPENSABLE : le cadre le mettait a « hidden » pour ne pas rogner ses
   coins arrondis, or ce sont maintenant les cartes qui arrondissent les leurs. Le garder
   couperait les panneaux qui debordent — un <details> ouvert, une infobulle. */
.fiche-cadre{
  padding:0; overflow:visible;
  background:none; box-shadow:none; border-radius:0;
  display:flex; flex-direction:column; gap:var(--e4);
}

/* CHAQUE BLOC EST UNE CARTE. Le filet de separation disparait : c'est l'espace entre deux cartes
   qui dit la separation, et il la dit mieux qu'un trait — on voit ou l'on est sans avoir a lire. */
.fiche-cadre > .fiche-tetes,
.fiche-cadre > .fiche-section{
  background:var(--surface); border-radius:var(--rayon-carte); box-shadow:var(--ombre1);
  border-bottom:0; padding:var(--e5);
}

/* L'en-tete a deux colonnes : le bien a gauche, son client a droite. Elles tombent l'une
   sous l'autre en dessous de 720 px — cote a cote, elles y deviendraient deux colonnes de
   trois mots.

   LE TRAIT VERTICAL LES SEPARE, maintenant qu'elles sont seules sur leur carte blanche : sans lui
   et sans le fond grise qu'elles avaient, deux colonnes de texte a egale distance ne se lisent plus
   comme deux sujets. Il est pose en bordure de la premiere, dans la gouttiere. */
.fiche-tetes{
  display:grid; grid-template-columns:1fr 1fr; gap:var(--e6);
}
.fiche-tetes > .fiche-tete:first-child{
  border-right:1px solid var(--bord); padding-right:var(--e6);
}
@media (max-width:720px){
  .fiche-tetes > .fiche-tete:first-child{
    border-right:0; padding-right:0;
    border-bottom:1px solid var(--bord); padding-bottom:var(--e4);
  }
}
@media (max-width:720px){ .fiche-tetes{grid-template-columns:1fr} }
.fiche-tete .sous-titre{margin:0 0 8px}
.fiche-tete-nom{margin:0; font-weight:600; font-size:1.02rem}
.fiche-adresse{font-style:normal; color:var(--encre-tenue); line-height:1.5; margin-top:4px}
.fiche-contact{margin:2px 0 10px; font-size:.9rem}
.fiche-contact a{color:var(--encre-tenue)}
.fiche-contact a:hover{color:var(--accent)}

/* Chaque section separee par un trait, pas par une carte : le cadre doit se lire comme
   UN document, et non comme cinq encarts poses l'un sous l'autre. */
/* Le remplissage et le filet vivent desormais dans la regle des cartes, plus haut. Ces deux
   declarations restaient : la seconde ne servait qu'a retirer le filet du dernier bloc, filet qui
   n'existe plus. La garder ferait chercher un trait qu'aucune regle ne pose. */
.fiche-section .sous-titre{margin-top:0}

/* Une valeur en lecture occupe la meme place que le champ qu'elle remplace : le passage
   en edition ne doit pas faire sauter la mise en page. */
.champ-lecture{
  margin:0; padding:9px 0; min-height:38px; line-height:1.5;
  overflow-wrap:anywhere;
}
.champs-serres{display:flex; gap:8px}
.champs-serres input[type="time"]{flex:1 1 auto; min-width:0}
.champs-serres input[type="number"]{width:92px; flex:0 0 auto}

/* --- Le tableau des prestations --- */
.tableau-prestations{width:100%; border-collapse:collapse}
.tableau-prestations th, .tableau-prestations td{
  padding:9px 12px; text-align:left; border-bottom:1px solid var(--bord);
}
.tableau-prestations thead th{
  font-size:.72rem; text-transform:uppercase; letter-spacing:.06em;
  color:var(--encre-tenue); font-weight:600;
}
.tableau-prestations tbody th{font-weight:500}
.tableau-prestations tfoot th, .tableau-prestations tfoot td{
  border-bottom:0; border-top:2px solid var(--bord-net); font-weight:600;
}
.tableau-prestations .total{font-size:1.05rem}

/* --- L'historique ---
   Une frise verticale : l'oeil suit le fil, et la pastille coloree dit d'un coup si
   l'evenement a fait avancer la prestation ou l'a arretee. */
.frise{list-style:none; margin:0; padding:0}
.frise-ligne{
  display:grid; grid-template-columns:26px 1fr; gap:10px;
  padding:0 0 14px; position:relative;
}
/* Le fil qui relie les pastilles, sauf apres la derniere. */
.frise-ligne:not(:last-child)::before{
  content:""; position:absolute; left:12px; top:24px; bottom:0;
  width:1px; background:var(--bord);
}
.frise-puce{
  display:flex; align-items:center; justify-content:center;
  width:25px; height:25px; border-radius:50%;
  background:var(--surface-creuse); border:1px solid var(--bord);
  color:var(--encre-tenue);
}
.frise-puce .i{width:13px; height:13px}
.frise-ligne.valide .frise-puce{background:var(--accent); border-color:var(--accent); color:#fff}
.frise-ligne.attente .frise-puce{border-color:var(--attente); color:var(--attente)}
.frise-ligne.revoque .frise-puce{border-color:var(--bord-net); color:var(--encre-tenue)}
.frise-ligne > div{padding-top:3px; font-size:.92rem; line-height:1.5}
.frise-mot{
  margin:6px 0 0; padding:8px 10px; border-radius:var(--rayon);
  background:var(--surface-creuse); white-space:pre-wrap;
}
.frise-detail{margin:4px 0 0; font-size:.85rem; color:var(--encre-tenue)}

/* --- La barre d'actions flottante ---
   Collee en bas : la fiche est longue, et les decisions doivent rester atteignables sans
   remonter. Elle ne s'affiche que s'il reste un geste possible. */
/* LA BARRE D'ACTIONS DEVIENT UNE CARTE, ET RESTE COLLANTE.
   Elle traversait l'ecran d'un bord a l'autre, avec un filet en haut et une ombre vers le haut :
   la forme d'un plancher, pas d'un bloc. Au bas d'une pile de cartes, elle etait la seule chose
   qui ne s'alignait sur rien.

   « position:sticky » NE BOUGE PAS, et c'est deliberement plus que la maquette ne montre : une
   image ne peut pas dire qu'un bloc suit le defilement. Sur une fiche longue — cinq blocs, une
   frise, une galerie — les quatre actions doivent rester sous la main sans remonter. La carte
   colle donc au bas de la fenetre tant qu'on defile, et se pose a sa place a la fin.

   L'OMBRE RESTE ORIENTEE VERS LE HAUT en plus de celle de la carte : c'est ce qui dit qu'elle
   flotte AU-DESSUS du contenu qu'elle recouvre, et non qu'elle en fait partie. */
.barre-flottante{
  position:sticky; bottom:var(--e4); z-index:20; margin-top:var(--e4);
  background:var(--surface); border-radius:var(--rayon-carte);
  box-shadow:var(--ombre1), 0 -6px 18px rgba(22,38,43,.07);
}
.barre-flottante-corps{
  display:flex; align-items:center; gap:10px; flex-wrap:wrap;
  padding:var(--e3) var(--e5);
}
/* Pousse ce qui suit vers la droite : les actions destructrices se tiennent a l'ecart
   des actions courantes, pour qu'on ne les atteigne pas par inadvertance. */
.barre-espace{flex:1 1 auto}
.barre-note{margin:0; flex:0 1 auto}
@media (max-width:640px){
  .barre-espace{display:none}
  .barre-flottante-corps{gap:8px}
}

/* --- Les bandeaux de tete --- */
.bandeau-alerte{border-left:3px solid var(--alerte)}
.bandeau-attente{border-left:3px solid var(--attente)}
.valeur-remplacee{text-decoration:line-through; color:var(--encre-tenue)}

/* --- La boite du compte rendu ---
   Pas de padding sur le corps : .boite porte deja le sien, et le redoubler donnerait
   une boite deux fois trop aeree pour six lignes de texte. */
.boite-corps{margin:0}
.boite-pied{display:flex; align-items:center; gap:12px; margin-top:var(--e4)}

/* ============================================================== JOURNAL D'ERREURS ===
   L'ecran superadmin qui remplace le client FTP. Ce qui s'y affiche vient du journal,
   donc parfois d'un visiteur : tout y est echappe cote PHP. */

/* Un bouton destructeur doit en avoir l'air. .danger n'existait que pour .btn-lien, et
   posee sur un vrai bouton elle ne faisait rien du tout. */
.btn.danger{border-color:var(--alerte); color:var(--alerte)}
.btn.danger:hover{background:var(--alerte-voile); border-color:var(--alerte)}

/* margin-top/bottom ET NON le raccourci « margin » : cette liste porte « pleine-largeur »
   depuis que le fil des notifications occupe toute la page, et cette classe pose un
   margin-left calcule pour le centrage. Un raccourci l'ecraserait, et le fil se decalerait
   de deux cents pixels vers la gauche. tests_style verifie la regle sur toutes les classes
   qui accompagnent « pleine-largeur ». */
.journal-liste{list-style:none; margin-top:0; margin-bottom:0; padding:0; display:grid; gap:10px}
.journal-entree{
  border:1px solid var(--bord); border-left-width:3px;
  border-radius:var(--rayon); padding:10px 12px; background:var(--surface);
}
/* Trois teintes seulement, comme partout : ce qui a casse une page, ce qui l'a salie,
   le reste. Vingt couleurs rendraient la liste illisible. */
.journal-grave{border-left-color:var(--alerte)}
.journal-attention{border-left-color:var(--attente)}
.journal-info{border-left-color:var(--bord-net)}

.journal-tete{display:flex; align-items:center; gap:8px; flex-wrap:wrap}
.journal-quand{
  font-family:var(--mono); font-size:var(--t-micro); color:var(--encre-tenue);
}
/* overflow-wrap et non nowrap : un message d'erreur peut faire trois cents caracteres
   sans un espace, et il doit rester dans la page plutot que l'elargir. */
.journal-message{
  margin:4px 0 0; font-size:.92rem; line-height:1.5; overflow-wrap:anywhere;
}
.journal-trace{margin-top:6px}
.journal-trace summary{
  cursor:pointer; font-size:var(--t-micro); color:var(--encre-tenue);
  padding:2px 0; user-select:none;
}
.journal-trace summary:hover{color:var(--encre)}
/* La trace garde ses colonnes : un chemin coupe en deux ne se relit pas. D'ou le
   defilement horizontal, borne a ce bloc. */
.journal-trace pre{
  margin:6px 0 0; padding:8px 10px; border-radius:var(--rayon);
  background:var(--surface-creuse); font-family:var(--mono);
  font-size:var(--t-micro); line-height:1.55;
  overflow-x:auto; white-space:pre;
}

/* Les deux gestes d'arbitrage, sous le tableau des ecarts.
   Ils vivaient ailleurs — une case au milieu de la fiche, un bouton dans la barre du bas
   — et il fallait descendre pour decider de ce qu'on venait de lire en haut. */
.bandeau-actions{
  display:flex; align-items:center; gap:10px; flex-wrap:wrap;
  margin-top:var(--e4);
}

/* --- Le tiroir « Reservations » du proprietaire ---
   Un <details> plutot qu'un deroulant au survol : le survol n'existe pas sur un ecran
   tactile, et un deroulant en JavaScript rendrait la navigation dependante d'un script. */
.bandeau .menu details{position:relative}
.bandeau .menu summary{
  display:flex; align-items:center; gap:var(--e2);
  padding:6px var(--e3); border-radius:var(--rayon);
  color:#dce8e7; cursor:pointer; list-style:none;
  transition:color var(--vite), background var(--vite);
}
/* Le triangle natif est remplace par le notre, aligne avec le texte. */
.bandeau .menu summary::-webkit-details-marker{display:none}
.bandeau .menu summary::marker{content:""}
.bandeau .menu summary:hover{color:#fff; background:rgba(255,255,255,.09)}
.menu-chevron{font-size:.7em; opacity:.7; transition:transform var(--vite)}
.bandeau .menu details[open] summary{color:#fff; background:rgba(255,255,255,.14)}
.bandeau .menu details[open] .menu-chevron{transform:rotate(180deg)}

/* Le corps flotte au-dessus de la page. .bandeau porte deja position:relative et
   z-index:10, donc ce tiroir passe devant le contenu sans reglage supplementaire. */
.menu-tiroir-corps{
  position:absolute; top:calc(100% + 6px); left:0; z-index:30;
  min-width:250px; max-width:340px; max-height:min(60vh, 420px); overflow-y:auto;
  background:var(--surface); color:var(--encre);
  border:1px solid var(--bord-net); border-radius:var(--rayon-carte);
  box-shadow:var(--ombre3); padding:var(--e2);
}
/* LES LIENS DU TIROIR SONT PREFIXES « .bandeau .menu », ET C'EST INDISPENSABLE.
   Le tiroir vit DANS le bandeau, qui est sombre, mais son corps flotte sur un fond BLANC.
   Il herite donc de regles ecrites pour l'inverse :

     .bandeau .menu a        deux classes + un type   color:#bfd6d4
     .bandeau .menu a:hover  deux classes + un type   color:#fff
     .menu-tiroir-corps a    UNE classe + un type     color:var(--encre)

   La derniere est pourtant plus loin dans le fichier — mais l'ordre ne tranche qu'a
   specificite EGALE. Les deux premieres l'emportaient, et l'on obtenait du gris pale sur
   blanc, puis du blanc sur blanc au survol : illisible dans les deux etats.

   Trois classes suffisent a reprendre la main. C'est un utilisateur qui l'a signale, et
   c'est normal : rien ne le signale autrement — la page s'affiche, le texte est la, il est
   simplement invisible. tests_style.php compare desormais les deux specificites. */
.bandeau .menu .menu-tiroir-corps a{
  display:block; padding:8px var(--e3); border-radius:var(--rayon);
  color:var(--encre); text-decoration:none; font-size:var(--t-petit);
}
.bandeau .menu .menu-tiroir-corps a:hover{
  color:var(--encre); background:var(--surface-creuse);
}
/* Le nom du logement reste lisible au survol : sans cette regle il heritait du blanc. */
.bandeau .menu .menu-tiroir-corps a:hover strong{color:var(--encre)}
.menu-tiroir-corps strong{display:block; font-weight:600; color:var(--encre)}
.menu-tiroir-corps span{color:var(--encre-tenue); font-size:var(--t-micro)}

/* Sous 640 px le bandeau passe sur plusieurs lignes : un tiroir flottant y sortirait de
   l'ecran. Il reprend alors sa place dans le flux. */
@media (max-width:640px){
  .menu-tiroir-corps{
    position:static; max-width:none; margin-top:6px; box-shadow:none;
    max-height:220px;
  }
}

/* ====================================== BANDEAU DE LA LISTE DES RESERVATIONS ======
   Trois zones : les reglages a gauche, la periode en grand au milieu, l'enregistrement
   a droite. Les trois etaient empiles sur trois lignes, la periode se lisait deux fois
   en minuscules, et le bouton d'enregistrement vivait sous le tableau — hors de vue des
   qu'il y avait dix sejours. */
/* NI FOND NI MARGE INTERIEURE, et c'est ce qui aligne. Le bandeau portait les deux : ses
   bords tombaient bien sur ceux du tableau, mais son CONTENU etait rentre d'une marge que
   le tableau n'a pas — les filtres flottaient a droite de la premiere colonne et le bouton
   a gauche de la derniere. Une barre d'outils n'est pas une carte : elle se pose sur la
   page, elle ne s'y encadre pas. */
/* --- LA BARRE DE LA LISTE : UNE LIGNE, ET DES BOITES BLANCHES DESSUS ---
   ELLE A EU TROIS COLONNES, puis deux, puis une rangee a part pour les comptes — et cette derniere
   forme faisait DEUX lignes : la periode au-dessus, les sept filtres en dessous. La periode et les
   cartes partagent donc une seule ligne. « flex:1 » sur les cartes leur donne toute la place qui
   reste apres les fleches, quel que soit le libelle de la periode.

   LA LIGNE ELLE-MEME N'A PAS DE FOND, et c'est une correction : je l'avais faite blanche, et les
   cartes — blanches aussi — s'y fondaient. Un cadre blanc sur un cadre blanc ne separe rien. Ce sont
   donc les ELEMENTS qui portent le blanc, chacun dans sa boite, sur le gris de la page. La ligne ne
   fait que les aligner.

   PAS DE « flex-wrap » : c'est justement le repli a la ligne qu'on ne veut plus. Sous les seuils
   etroits, ce sont les CARTES qui se replient entre elles, en grille — la barre, elle, reste une
   ligne jusqu'a 900 px. */
.barre-liste{
  display:flex; align-items:center; gap:var(--e3); padding:0;
  /* JAMAIS le raccourci « margin » ICI.
     .pleine-largeur centre le bloc par une marge GAUCHE calculee ; « margin:x 0 » la remet a zero
     et le bandeau se recalait a gauche pendant que le tableau, lui, restait centre. */
  margin-top:var(--e4);
  margin-bottom:var(--e4);
}
/* LES REGLAGES SONT UNE BOITE BLANCHE, comme les cartes : c'est ce qui les pose sur la meme ligne
   sans les confondre avec elles. Ils gardent leur largeur — ce sont eux qui commandent, les cartes
   prennent le reste. */
.barre-liste-reglages{
  display:flex; align-items:center; gap:var(--e2); flex:none; margin:0;
  padding:var(--e2); background:var(--surface);
  border:1px solid var(--bord); border-radius:var(--rayon-carte);
}
.liste-navigation{display:flex; align-items:center; gap:var(--e2)}

/* Le marqueur d'aide : ce qui reste du pave d'explication. Discret par construction — on ne lit ce
   texte qu'une fois. Sa regle etait partie avec l'ancienne barre, et le marqueur serait sorti nu. */
.barre-liste-aide{
  display:inline-flex; align-items:center; justify-content:center;
  width:26px; height:26px; flex:0 0 auto;
  border-radius:50%; border:1px solid var(--bord);
  color:var(--encre-tenue); cursor:help;
}
.barre-liste-aide:hover, .barre-liste-aide:focus{
  color:var(--accent); border-color:var(--accent); outline:none;
}
.barre-liste-aide .i{width:14px; height:14px}

/* LA PERIODE A UNE LARGEUR MINIMALE, et c'est ce qui empeche les fleches de danser. Sans elle,
   « Aout 2026 » et « Semaine du 3 au 9 aout » deplacent le chevron de droite d'un mois a l'autre :
   on vise un bouton qui n'est plus la ou il etait au clic precedent. */
.liste-periode{
  min-width:150px; text-align:center;
  font-size:var(--t-moyen); font-weight:600; letter-spacing:-.01em;
}

/* Le tiroir des bornes a ete retire avec le selecteur d'echelle : le filtrage passe par les
   cartes d'etat, et « periode » reste lu et reconduit sans avoir de controle a l'ecran. Les regles
   partent avec lui — une regle sans emploi est une regle que personne n'osera enlever ensuite. */

/* --- LES CINQ COMPTES ---
   Le nombre en grand, le mot dessous : on lit le chiffre d'abord, et le mot seulement s'il surprend.

   UNE CARTE A ZERO RESTE VISIBLE, mais s'efface — fond creux, icone a la place du chiffre. La
   retirer ferait une barre dont la composition change d'un mois a l'autre, et l'on chercherait la
   carte manquante. L'icone dit « rien de ce genre », ce qui est une reponse ; l'absence ne dit rien.

   LES CHIFFRES SONT TABULAIRES : cinq cartes cote a cote dont les nombres ne s'alignent pas se
   lisent comme cinq blocs sans rapport. */
/* --- LE TABLEAU DE LA LISTE : LES CELLULES QUI ONT CHANGE DE FORME ---
   L'INTERVALLE SUR DEUX LIGNES. L'arrivee en encre pleine, le depart en dessous et plus discret :
   c'est la meme information, et la fleche dit qu'il s'agit d'une suite. Deux colonnes de dates se
   lisaient comme deux faits sans rapport. */
.sejour-intervalle .sejour-vers{
  display:block; font-size:var(--t-petit); color:var(--encre-douce);
}

/* Le locataire : l'information par laquelle on reconnait un sejour. En encre pleine, donc, et non
   en note sous l'etat comme avant. */
.sejour-locataire{font-size:var(--t-controle); color:var(--encre)}

/* CETTE REGLE DOIT BATTRE « .tableau-tarifs input[type=text] », ET ELLE LE FAIT PAR SA
   SPECIFICITE, non par sa position — a specificite egale, deplacer un bloc plus haut suffirait a
   annuler l'effet sans rien casser de visible. Le defaut est deja venu trois fois dans ce fichier.

   LE CHAMP DU LOCATAIRE EST PLUS DISCRET QUE CEUX DES PRESTATIONS, et c'est voulu : il y en a un
   par ligne, donc dix a l'ecran, et au repos ils ne doivent pas se lire comme un formulaire. La
   bordure se revele au survol et a la mise au point — la ou l'on va ecrire. */
.tableau-tarifs .sejour-locataire input[type=text]{
  padding:5px 8px; font-size:var(--t-controle);
  border-color:transparent; background:transparent;
}
.tableau-tarifs .sejour-locataire input[type=text]:hover{
  border-color:var(--bord-net); background:var(--surface);
}
.tableau-tarifs .sejour-locataire input[type=text]:focus{background:var(--surface)}
.tableau-tarifs .sejour-locataire input[type=text]::placeholder{
  color:var(--encre-douce); font-style:italic;
}

/* --- LE PAS A PAS D'UN NOMBRE ---
   « − 1 + » A LA PLACE DES FLECHES DU NAVIGATEUR. Les fleches natives font quatre pixels de large,
   se visent a la souris et n'existent pas au doigt ; sur une colonne de quantites, on finit par
   selectionner le chiffre et le retaper.

   LE COMPOSANT EST POSE PAR LE SCRIPT, jamais par le gabarit : deux boutons ecrits en dur seraient
   inertes sans JavaScript. La classe n'existe donc que si le script a tourne — c'est pourquoi les
   fleches natives ne sont masquees QUE DANS « .pas-a-pas », et restent la sinon.

   LA REGLE BAT « .tableau-tarifs input[type=number] » ET « .panneau-prestations input[type=number] »
   PAR SA SPECIFICITE, non par sa position : trois classes contre deux. A egalite, deplacer un bloc
   suffirait a la desarmer sans que rien ne se voie — le defaut est deja venu quatre fois ici. */
.pas-a-pas{
  display:inline-flex; align-items:stretch; overflow:hidden;
  border:1px solid var(--bord-net); border-radius:var(--rayon);
  background:var(--surface);
  transition:border-color var(--vite), box-shadow var(--vite);
}
.pas-a-pas:hover{border-color:var(--encre-tenue)}
.pas-a-pas:focus-within{border-color:var(--accent); box-shadow:var(--anneau)}

.pas-a-pas button{
  display:flex; align-items:center; justify-content:center;
  width:26px; padding:0; border:0; background:transparent;
  font:inherit; font-size:var(--t-controle); line-height:1;
  color:var(--encre-tenue); cursor:pointer;
  transition:background var(--vite), color var(--vite);
}
.pas-a-pas button:hover{background:var(--surface-creuse); color:var(--accent)}
.pas-a-pas button:disabled{color:var(--bord); cursor:default; background:transparent}

.tableau-tarifs .pas-a-pas input[type=number],
.panneau-prestations .pas-a-pas input[type=number],
.pas-a-pas input[type=number]{
  width:34px; min-width:0; padding:5px 0; text-align:center;
  border:0; border-radius:0; background:transparent; box-shadow:none;
  font:inherit; font-size:var(--t-controle); color:var(--encre);
  /* Firefox : sans quoi il garde ses fleches a l'interieur du composant. */
  -moz-appearance:textfield; appearance:textfield;
}
.tableau-tarifs .pas-a-pas input[type=number]:focus,
.panneau-prestations .pas-a-pas input[type=number]:focus,
.pas-a-pas input[type=number]:focus{border:0; box-shadow:none; outline:none}
.pas-a-pas input[type=number]::-webkit-outer-spin-button,
.pas-a-pas input[type=number]::-webkit-inner-spin-button{-webkit-appearance:none; margin:0}

/* --- LES PRECISIONS DU DEMANDEUR ---
   TROIS LIGNES, COMME SUR LA FICHE : c'est le meme champ, et le retrouver au meme format evite de
   se demander si c'en est un autre.

   « resize:vertical » ET NON « none » : un commentaire de dix lignes existe, et l'interdire oblige
   a defiler dans une fenetre de trois lignes. Horizontalement, en revanche, l'elargir deborderait
   la colonne et decalerait le tableau entier.

   LA REGLE BAT « .tableau-tarifs input », plus haut, PAR SA SPECIFICITE et non par sa position :
   deux classes et un type contre une classe et un type. A egalite, deplacer un bloc suffirait a
   l'annuler sans que rien ne se voie — le defaut est deja venu trois fois dans ce fichier. */
.sejour-precisions{vertical-align:top}
.tableau-tarifs .sejour-precisions textarea{
  width:100%; min-height:calc(3em + 16px); resize:vertical;
  padding:var(--e2) 10px; font:inherit; font-size:var(--t-controle); line-height:1.4;
  border:1px solid var(--bord-net); border-radius:var(--rayon);
  background:var(--surface); color:var(--encre);
  transition:border-color var(--vite), box-shadow var(--vite);
}
.tableau-tarifs .sejour-precisions textarea:hover{border-color:var(--encre-tenue)}
.tableau-tarifs .sejour-precisions textarea:focus{
  border-color:var(--accent); box-shadow:var(--anneau); outline:none;
}
.tableau-tarifs .sejour-precisions textarea::placeholder{color:var(--encre-douce); font-style:italic}

/* Le texte qu'on ne peut plus changer : il se lit, il ne se saisit pas. Ni bordure ni fond — sinon
   il ressemblerait a un champ desactive, ce qui laisse chercher comment l'activer. */
.sejour-precisions .champ-lecture{
  margin:0; font-size:var(--t-petit); color:var(--encre-douce); line-height:1.4;
  white-space:normal;
}
.sejour-precisions-scindees{display:flex; gap:6px; align-items:flex-start}
.sejour-precisions-scindees .i{flex:none; width:13px; height:13px; margin-top:2px}

/* --- L'INTERVENTION ASSOCIEE ---
   Trois choses par deplacement : quand, quoi, ou cela en est. Empilees, parce qu'un sejour peut en
   porter deux — la pose des draps a l'arrivee, le menage au depart — et qu'il faut alors les
   distinguer d'un coup d'oeil. */
.sejour-visites{font-size:var(--t-petit)}

/* DEUX COLONNES, ET NON UN FLOTTANT. Le crayon se tient a droite de ce que la visite dit ; en
   « float », il aurait pu deborder sous la visite suivante — un bloc sans contexte de formatage ne
   contient pas ses flottants, et la bordure de separation serait passee dessous. La grille le
   contient par construction. */
.sejour-visite{
  display:grid; grid-template-columns:minmax(0, 1fr) auto;
  align-items:start; column-gap:var(--e2); line-height:1.35;
}
.sejour-visite + .sejour-visite{margin-top:var(--e2); padding-top:var(--e2); border-top:1px solid var(--bord)}

/* LE CRAYON D'UNE VISITE : la taille d'une cible cliquable, pas celle d'un bouton. « .btn-icone »
   fait 40 px de cote — deux d'entre eux empiles depassent la hauteur d'une ligne du tableau. */
.sejour-visite-lien{
  display:inline-flex; align-items:center; justify-content:center;
  width:26px; height:26px; border-radius:var(--rayon-puce);
  border:1px solid var(--bord); background:var(--surface-creuse);
  color:var(--encre-tenue); text-decoration:none;
  transition:color var(--vite), border-color var(--vite);
}
.sejour-visite-lien:hover{color:var(--accent); border-color:var(--accent)}
.sejour-visite-lien .i{width:13px; height:13px}
.sejour-visite-date{
  display:block; font-family:var(--mono); font-size:var(--t-micro); color:var(--encre-douce);
}
.sejour-visite-quoi{display:block; color:var(--encre); margin-bottom:2px}

/* --- LA CASE ET SON JOUR ---
   Le jour souhaite ne concerne que les prestations a DATE LIBRE : il se tient donc a cote de la
   case qui le porte, et non dans une colonne a lui ou l'on ne devinait pas a quoi il s'appliquait.
   Le tiroir garde la colonne etroite : une date par ligne sur dix lignes remplissait l'ecran de
   champs qu'on ne touche presque jamais. */
.case-et-jour{display:inline-flex; align-items:center; gap:var(--e1)}
.jour-souhaite{position:relative; display:inline-flex}
.jour-souhaite > summary{
  list-style:none; cursor:pointer; color:var(--encre-tenue);
  display:inline-flex; align-items:center; padding:2px; border-radius:var(--rayon);
}
.jour-souhaite > summary::-webkit-details-marker{display:none}
.jour-souhaite > summary:hover{color:var(--accent); background:var(--surface-creuse)}
.jour-souhaite[open] > summary{color:var(--accent)}
.jour-souhaite .i{width:14px; height:14px}
.jour-souhaite-corps{
  position:absolute; top:calc(100% + 4px); left:50%; transform:translateX(-50%); z-index:20;
  display:flex; flex-direction:column; gap:var(--e2); width:210px; padding:var(--e3);
  background:var(--surface); border:1px solid var(--bord);
  border-radius:var(--rayon-carte); box-shadow:var(--ombre2); text-align:left;
}

/* --- LA COLONNE DES ACTIONS ---
   « Voir le detail » et le menu sur la meme ligne. Le bouton ne parait que si la ligne porte une
   intervention : il n'existe pas d'ecran de detail d'une reservation, et un bouton sans cible
   laisse croire a une panne. */
/* --- LES DATES ET LEUR MENU ---
   LA COLONNE D'ACTIONS N'EXISTE PLUS : elle ne portait qu'un menu de trois points, et ce menu ne
   parle que des dates. Il est donc a cote d'elles. Ses regles ont suivi — laisser « .colonne-actions »
   derriere aurait laisse trois declarations sans cible, qui se lisent comme une intention.

   PAS DE « flex » SUR LA CELLULE : un « td » en conteneur flexible sort du calcul de largeur du
   tableau, et les colgroup perdent la main. Deux blocs en ligne suffisent. */
.sejour-intervalle{white-space:nowrap}
.sejour-bornes{display:inline-block; vertical-align:top; white-space:normal}
.sejour-intervalle .ligne-menu{display:inline-block; vertical-align:top; margin-left:var(--e1)}
/* Le menu de ligne porte des CHAMPS, et non des liens : il lui faut la place d'un formulaire. */
.sejour-intervalle .ligne-menu-corps{min-width:230px; gap:var(--e3); align-items:stretch}
.sejour-intervalle .ligne-menu-corps .champ{margin:0}

/* --- LE PIED DU TABLEAU ---
   Le compte a gauche, les pages au milieu, la taille a droite : trois choses de meme nature, et
   l'ordre dans lequel on se les demande. */
.pied-liste{
  display:flex; align-items:center; justify-content:space-between;
  gap:var(--e3) var(--e4); flex-wrap:wrap;
  padding:var(--e3) var(--e4); border-top:1px solid var(--bord);
  font-size:var(--t-petit); color:var(--encre-douce);
}
.pied-liste-taille{display:inline-flex; align-items:center; gap:var(--e1)}

/* --- LES SEPT CARTES DE LA LISTE, DANS UN BANDEAU BLANC ---
   ON REPREND LE COMPOSANT DE LA LISTE DES INTERVENTIONS — « .cartes-etat », « .carte-etat » — au
   lieu d'en entretenir un second. Ce qui suit n'en est qu'une VARIANTE : sept cartes au lieu de six,
   plus serrees, et reunies dans un seul bandeau blanc au lieu d'etre sept cartes separees.

   LA SPECIFICITE FAIT LE TRAVAIL, ET NON L'ORDRE DU FICHIER. « .cartes-etat-sejours » seul vaut une
   classe, exactement comme « .cartes-etat » : a egalite, c'est le DERNIER declare qui gagne — et
   celui-la est declare plus loin, dans la section des interventions. La grille a sept colonnes ne
   prenait donc pas, le septieme passait a la ligne, et rien dans la regle ne le laissait deviner.
   « .cartes-etat.cartes-etat-sejours » vaut deux classes : elle gagne ou qu'elle soit ecrite.

   C'est le troisieme defaut de cascade de cet ecran — apres le bouton desactive et la largeur des
   barres. La lecon est la meme : quand une regle doit en surpasser une autre, on le tient par la
   specificite, jamais par la position. */
/* LE CONTENEUR N'EST QU'UNE GRILLE : ni fond ni cadre, ce sont les cartes qui les portent. C'est le
   contraire de ce que j'avais fait — un bandeau blanc contenant des cartes blanches — et l'inverse
   est plus lisible : sept boites posees sur le gris de la page se comptent d'un coup d'oeil.

   « min-width:0 » AUTORISE LA GRILLE a descendre sous la largeur de ses libelles, faute de quoi elle
   pousserait la barre au lieu de se serrer. */
.cartes-etat.cartes-etat-sejours{
  grid-template-columns:repeat(7, minmax(0, 1fr));
  gap:var(--e2); flex:1 1 auto; min-width:0; margin:0;
}

/* LES CARTES PERDENT LEUR CADRE : c'est le bandeau qui le porte desormais. Un cadre dans un cadre
   compte double a l'oeil, et sept fois double remplit la rangee de traits. */
/* CHAQUE CARTE GARDE SON FOND BLANC ET SON CADRE : c'est ce qui la distingue de sa voisine, et de la
   boite des reglages. Elle herite donc du composant partage, et l'on ne redeclare ici que la
   DISPOSITION — en colonne, centree — parce que sept cartes sur une ligne ne tiennent pas l'icone a
   cote du texte. Un carre de 28 px plus un libelle de treize caracteres ne tiennent pas dans un
   septieme de la place restante ; empiles, si. */
.cartes-etat-sejours .carte-etat{
  flex-direction:column; align-items:center; text-align:center;
  padding:var(--e2) var(--e1); gap:1px; min-width:0;
}

/* ELLES SE SERRENT, pour que les sept tiennent sur une ligne. Le carre d'icone descend de 34 a
   28 px et le nombre d'un cran dans l'echelle : deux mesures, pas dix, et l'echelle typographique
   reste respectee — aucune taille en pixels dans le texte. */
/* L'ICONE NE PORTE PLUS SON CARRE DE FOND : empilee au-dessus du nombre, elle n'a plus de place a
   remplir, et le carre teinte serait devenu une pastille de couleur au milieu de la carte. Le ton
   passe donc a l'icone elle-meme, par « color » — c'est ce que les classes « .ton-* » posent deja. */
.cartes-etat-sejours .carte-etat-icone{
  width:auto; height:auto; background:none; border-radius:0;
}
.cartes-etat-sejours .carte-etat-icone .i{width:14px; height:14px}

/* --- LE NOMBRE, PUIS SON LIBELLE ---
   J'AVAIS D'ABORD SERRE EN DESCENDANT A 9 PX. C'etait sortir de l'echelle typographique du projet —
   dont la plus petite valeur est 11 px — pour gagner quelques pixels, et rendre deux lignes de texte
   a peine lisibles. La vraie economie etait ailleurs : « Sejours confirmes » dit deja l'unite, donc
   la troisieme ligne n'a pas lieu d'etre. Une ligne de moins vaut mieux que deux lignes plus petites.

   NI MAJUSCULES NI INTERLETTRAGE ICI : ce sont eux qui rendaient le libelle large. « INTERVENTIONS
   PLANIFIEES » espace prend un tiers de plus que la meme chaine en minuscules, pour la meme
   information.

   L'ELLIPSE PLUTOT QUE LE REPLI : sous les seuils etroits, une carte dont le libelle passe a la
   ligne fait grandir toute la rangee. Elle se coupe, et l'infobulle du lien porte le texte entier. */
.cartes-etat-sejours .carte-etat-mots{align-items:center; gap:0; width:100%}
.cartes-etat-sejours .carte-etat-nombre{
  font-size:var(--t-moyen); line-height:1.15;
}
.cartes-etat-sejours .carte-etat-mot{
  font-size:var(--t-micro); text-transform:none; letter-spacing:0; font-weight:500;
  max-width:100%; overflow:hidden; white-space:nowrap; text-overflow:ellipsis;
}
/* L'unite est dans le libelle : la ligne separee n'a plus d'objet. */
.cartes-etat-sejours .carte-etat-unite{display:none}

/* LA COURANTE GARDE LE MARQUAGE DU COMPOSANT — cadre a l'accent, liseret interieur — puisque les
   cartes ont retrouve leur cadre. On n'ajoute qu'un fond tres pale : sur sept boites blanches
   identiques, la seule bordure ne suffit pas a designer celle qui filtre. */
.cartes-etat-sejours .carte-etat-courante{background:var(--accent-voile)}
.cartes-etat-sejours .carte-etat-courante .carte-etat-mot{color:var(--accent-fonce)}

/* Sept cartes de rien ne servent personne : elles passent a quatre par rangee, puis a deux. Le
   bandeau les suit, puisqu'il les contient. */
/* SOUS 1100 PX, CE SONT LES CARTES QUI SE REPLIENT — pas la barre. Quatre par rangee puis deux : la
   periode reste a gauche, et le bandeau grandit en hauteur au lieu de se couper en deux. */
@media (max-width:1100px){
  .cartes-etat.cartes-etat-sejours{grid-template-columns:repeat(4, minmax(0, 1fr))}
}
@media (max-width:900px){
  .cartes-etat.cartes-etat-sejours{grid-template-columns:repeat(2, minmax(0, 1fr))}
  .barre-liste{flex-direction:column; align-items:stretch}
}

/* --- La fiche d'intervention ouverte en fenetre ---
   1320 ET NON 1040, ET C'EST LA JOURNEE D'UN INTERVENANT QUI L'A IMPOSE.
   Cette fenetre porte DEUX colonnes — une frise a gauche, une fiche entiere a droite — et la
   fiche est l'ecran le plus charge de l'application. A 1040, il lui restait 680 px : ses
   listes de definitions passaient a la ligne et son tableau des prestations defilait.
   La borne « 100vw moins deux marges » garde le comportement sur un ecran etroit. */
.boite-cadre:modal{
  width:min(1320px, calc(100vw - 2 * var(--e5)));
  max-width:none; padding:0; overflow:hidden;
}
.boite-cadre .boite-entete{
  margin:0; padding:var(--e3) var(--e4);
  border-bottom:1px solid var(--bord); background:var(--surface-creuse);
}
.boite-cadre .boite-fermer{text-decoration:none}
/* La fiche defile DANS le cadre : la fenetre garde une taille stable quelle que soit la
   longueur de l'historique. */
.boite-cadre iframe{
  display:block; width:100%; height:min(78vh, 780px); border:0; background:var(--fond);
}

/* Dans un cadre, la page n'a ni bandeau ni marge d'application : elle occupe tout. */
body.dans-un-cadre{background:var(--fond)}
body.dans-un-cadre .page{padding-top:var(--e4)}

/* ---- LA JOURNEE DANS SA FENETRE : DEUX BARRES DE DEFILEMENT, PAS TROIS ----
 |
 | IL Y EN AVAIT UNE DE TROP, ET ELLE VENAIT D'UNE ARITHMETIQUE QUI NE POUVAIT PAS TOMBER JUSTE.
 |
 | La journee mesurait ses deux colonnes en « vh » — 84 % de la hauteur du cadre — et la page
 | qui les porte ajoutait par-dessus ses marges : var(--e4) en haut, et surtout 96 px en bas.
 | Le contenu faisait donc « 84 % de la hauteur + 112 px », ce qui depasse cette hauteur des que
 | 112 px valent plus que les 16 % restants, c'est-a-dire sur toute fenetre de moins de 700 px.
 | La page se mettait alors a defiler A COTE des colonnes qui defilaient deja.
 |
 | UNE HAUTEUR EXACTE PLUTOT QU'UNE FRACTION. La journee occupe ce qui reste une fois les marges
 | retirees, les colonnes s'etirent dedans, et la page n'a plus rien a faire defiler. Le calcul
 | ne peut plus etre faux, parce qu'il n'y a plus de calcul : c'est la meme valeur des deux
 | cotes de la soustraction.
 |
 | LES 96 PX DU BAS SONT DE LA RESPIRATION EN FIN DE PAGE — la barre d'actions de la fiche est
 | « sticky », elle ne se cache derriere rien. Sur une page qui ne defile pas, ils n'ont aucun
 | role, et on les retire pour cette vue seulement.
 |
 | « :has » VISE LA PAGE QUI CONTIENT UNE JOURNEE, et non toutes les pages en cadre : la fiche
 | s'affiche dans le meme gabarit, elle est longue, elle DOIT defiler et garder sa respiration.
 |
 | ET LA LARGEUR AVEC : .page plafonne a 1060 px, si bien que l'elargissement de la fenetre a
 | 1320 px ne servait a rien — la journee restait centree dans 1060, avec 130 px de vide de
 | chaque cote. Le plafond a du sens sur une page de texte, aucun sur deux colonnes qui
 | remplissent une fenetre. */
body.dans-un-cadre .page:has(.jour){
  max-width:none; padding:var(--e4);
}
body.dans-un-cadre .jour{
  height:calc(100vh - 2 * var(--e4));
  align-items:stretch;
}
/* max-height:none EFFACE LA FRACTION : c'est la grille qui donne la hauteur maintenant, et
   « height:100% » s'y rapporte. Laisser les deux se disputer rendrait la plus petite gagnante,
   donc le vide en bas. */
body.dans-un-cadre .jour-frise{max-height:none; height:100%}
body.dans-un-cadre .jour-cadre{height:100%}
body.dans-un-cadre .jour-cadre iframe{height:100%}

/* Sous 820 px, la grille passe a une seule colonne : les deux blocs s'empilent, et une hauteur
   figee les ecraserait l'un sur l'autre dans une seule fenetre. On rend donc la main au
   defilement de la page — c'est le seul cas ou il est le bon comportement. */
@media (max-width: 820px){
  body.dans-un-cadre .jour{height:auto}
  body.dans-un-cadre .jour-frise{height:auto}
  body.dans-un-cadre .jour-cadre{height:auto}
}

/* ======================= GRAPHIQUE DU CHIFFRE PAR MOIS ==========================
   En CSS, sans bibliotheque : le deploiement est une copie FTP sans etape de
   construction, et pour douze barres par annee une dependance couterait plus qu'elle
   n'apporte. La bulle au survol se fait sans une ligne de script. */
/* A cheval sur les deux colonnes de .grille-deux, et sans le plafond de .carte-large.
   C'est ce qui aligne le graphique sur les listes au-dessus : sa largeur est celle des
   deux colonnes plus leur gouttiere, par construction, et non une valeur a maintenir. */
.grille-pleine{grid-column:1 / -1; max-width:none}

/* Meme largeur que la grille, pour un bloc qui n'y est pas. .carte-large plafonne a
   820 px, ce qui laissait le bandeau plus etroit que tout ce qui le suit. */
.pleine-page{max-width:none}

.graphe{display:grid; gap:var(--e5)}
.graphe-titre{
  display:flex; align-items:baseline; gap:var(--e3);
  margin-bottom:var(--e2); padding-bottom:4px; border-bottom:1px solid var(--bord);
}
.graphe-titre strong{font-size:var(--t-moyen); font-weight:600; letter-spacing:-.01em}
.graphe-titre span{font-size:var(--t-micro); color:var(--encre-tenue)}

/* Douze colonnes d'egale largeur : c'est ce qui rend deux annees comparables au regard,
   et ce qui laisse voir qu'une saison ne dure que deux mois. */
.graphe-barres{
  display:grid; grid-template-columns:repeat(12, 1fr); gap:4px; align-items:end;
}
.graphe-colonne{position:relative; display:flex; flex-direction:column; align-items:center}

/* Le fut donne sa hauteur de reference a la barre : sans lui, un pourcentage n'aurait
   rien a quoi se rapporter. */
.graphe-fut{
  display:flex; align-items:flex-end; justify-content:center;
  width:100%; height:96px;
  background:var(--surface-creuse); border-radius:var(--rayon) var(--rayon) 0 0;
}
.graphe-barre{
  width:100%; min-height:2px; border-radius:var(--rayon) var(--rayon) 0 0;
  background:linear-gradient(180deg, var(--accent), var(--accent-fonce));
  transition:filter var(--vite);
}
/* Un mois sans chiffre garde sa colonne mais pas sa barre : le creux est une information. */
.graphe-vide .graphe-barre{background:none; min-height:0}
.graphe-mois{
  margin-top:4px; font-size:var(--t-micro); color:var(--encre-tenue);
  font-family:var(--mono);
}

/* --- La bulle ---
   Au survol ET au focus : une infobulle qu'on ne peut atteindre qu'a la souris exclut
   ceux qui naviguent au clavier. La colonne est focalisable pour cette raison. */
.graphe-bulle{
  position:absolute; bottom:calc(100% + 8px); left:50%; transform:translateX(-50%);
  z-index:15; display:none; width:max-content; max-width:200px;
  padding:6px 10px; border-radius:var(--rayon);
  background:var(--encre); color:#fff; font-size:var(--t-micro); line-height:1.45;
  box-shadow:var(--ombre2); pointer-events:none; text-align:center;
}
.graphe-bulle strong{display:block; font-weight:600}
.graphe-colonne:hover .graphe-bulle,
.graphe-colonne:focus-within .graphe-bulle{display:block}
.graphe-colonne:hover .graphe-barre{filter:brightness(1.12)}

/* Sous 720 px, douze colonnes deviennent illisibles : on reduit le fut et on masque un
   libelle sur deux plutot que de tout tasser. */
@media (max-width:720px){
  .graphe-fut{height:64px}
  .graphe-colonne:nth-child(even) .graphe-mois{visibility:hidden}
}

/* Le bouton d'action d'un sous-titre : le « + » qui cree depuis la section elle-meme.
   Pousse a droite pour ne pas coller au compteur, et reduit — c'est un raccourci, pas
   l'action principale de l'ecran. */
.sous-titre-action{margin-left:auto; padding:6px; width:30px; min-height:30px}
.sous-titre-action .i{width:15px; height:15px}

/* ============================================================ NOTIFICATIONS ====
 |
 | LA CLOCHE DU BANDEAU, ET SES DEUX ETATS.
 |
 | Un compteur unique melangerait « trois prestations terminees » et « un sejour a disparu
 | sous une intervention validee ». Ce sont deux urgences differentes : celui qui voit « 12 »
 | sans distinction finit par ne plus le regarder. La pastille porte donc le total, et la
 | COULEUR dit s'il y a une alerte dedans — l'information la plus utile en un coup d'oeil,
 | sans deuxieme nombre a dechiffrer.
 |
 | Les regles sont posees sous « .bandeau .menu » : deux classes, comme les liens du bandeau
 | qu'elles doivent surcharger. Une seule classe perdrait au profit de « .bandeau .menu a »,
 | et la cloche s'afficherait comme un lien ordinaire — le piege de specificite qui avait
 | rendu le sous-menu des biens illisible. */
.bandeau .menu .cloche{position:relative; display:inline-flex; align-items:center; gap:6px}
.bandeau .menu .cloche-compte{
  display:inline-flex; align-items:center; justify-content:center;
  min-width:18px; height:18px; padding:0 5px;
  border-radius:9px; background:var(--encre-tenue); color:var(--surface);
  font-size:var(--t-micro); font-weight:700; line-height:1;
}
/* L'alerte se voit sur la pastille, pas sur le texte : un libelle colore dans un bandeau
   deja dense se confondrait avec un survol. */
.bandeau .menu .cloche-alerte .cloche-compte{background:var(--alerte); color:#fff}

/* ---------------------------------------------------------------- Le fil ------
 |
 | Le fil reprend les classes du journal d'audit (.journal-liste, .journal-entree) : meme
 | forme, meme lecture chronologique, et rien a reinventer. Ne s'ajoute ici que ce qui lui
 | est propre — l'etat lu, et le bouton d'ouverture. */

/* UNE LIGNE LUE S'EFFACE SANS DISPARAITRE. Elle reste consultable — c'est le registre de ce
   qui a ete envoye, et une notification qu'on ne retrouve plus ne prouve rien. Mais elle
   cesse d'attirer l'oeil, sinon le fil ne se distingue plus d'une archive. */
.fil-lue{opacity:.62}
.fil-lue .journal-message{font-weight:400}

/* Le formulaire d'ouverture ne doit pas occuper une ligne pour un seul bouton. */
.fil-ouvrir{display:inline-block; margin-top:4px}

/* ------------------------------------------------------- La matrice -----------
 |
 | UNE CASE SANS OBJET NE DOIT PAS RESSEMBLER A UNE CASE DECOCHEE. Prevenir un proprietaire
 | de sa propre demande n'a aucun sens : offrir la case la ferait cocher, rien n'arriverait,
 | et l'on en conclurait que la fonction est cassee. Le tiret est donc franc et centre, sans
 | bordure — il dit « rien a decider ici », pas « eteint ». */



/* Sous la case, le canal effectif — « courriel » ou « notification ». C'est ce qui evite de
   croire que toute case cochee declenche un envoi : le canal depend de l'evenement, pas du
   reglage. Ecrit petit, parce qu'il se lit une fois puis se devine. */
.fil-case .case{flex-direction:column; gap:2px; align-items:center; justify-content:center}
.fil-case .cellule-sous{font-size:var(--t-micro)}

/* -------------------------------------------------- La croix du fil -----------
 |
 | Poussee a droite de l'en-tete de ligne, la ou l'oeil la cherche. Discrete au repos et
 | franche au survol : une croix rouge en permanence sur chaque ligne transformerait le fil
 | en liste de choses a supprimer, alors que c'est une liste de choses a lire. */
.fil-fermer{margin-left:auto; line-height:1}
.fil-croix{
  border:0; background:none; cursor:pointer; padding:0 2px;
  color:var(--encre-tenue); font-size:20px; line-height:1;
  transition:color var(--vite);
}
.fil-croix:hover,
.fil-croix:focus-visible{color:var(--alerte)}

/* ------------------------------------------- La matrice des notifications -----
 |
 | ELLE REPREND .tableau-tarifs, ET C'EST LA CORRECTION.
 |
 | La premiere version declarait son propre tableau : table-layout par defaut, et des
 | largeurs posees en « width » sur les en-tetes. Trois symptomes, une seule cause.
 |
 |   LA PREMIERE COLONNE SE REPLIAIT SUR CINQ OU SIX LIGNES. Sans table-layout:fixed, le
 |   contenu de chaque cellule negocie sa largeur : les trois listes deroulantes tiraient
 |   leurs colonnes au large et ecrasaient celle du libelle. Le commentaire de
 |   .tableau-tarifs le disait deja, mot pour mot — « c'est LA regle qui fait tenir
 |   l'alignement ». Il n'a pas ete lu avant d'ecrire.
 |
 |   LES LISTES ETAIENT MINUSCULES. « height:var(--t-controle) » — or --t-controle vaut
 |   14px et designe une TAILLE DE POLICE, pas une hauteur. Les selects mesuraient donc
 |   quatorze pixels de haut. Un jeton employe hors de son role ne produit pas d'erreur :
 |   il produit un resultat plausible et faux.
 |
 |   RIEN N'ETAIT HOMOGENE. Padding, bordures, survol, focus : tout etait reecrit a cote
 |   des regles existantes, avec des valeurs voisines mais pas egales.
 |
 | Ne reste ici que ce qui est PROPRE a cette matrice. Le reste vient de .tableau-tarifs,
 | y compris le style des selects — donc identique a celui de l'ecran des tarifs. */

/* Le compte de destinataires, sous le nom du role. En bloc : sur la meme ligne il
   allongerait l'en-tete, et white-space:nowrap le ferait deborder. */
.mn-compte{
  display:block; margin-top:3px;
  font-family:var(--mono); font-size:var(--t-micro); font-weight:400;
  text-transform:none; letter-spacing:0; white-space:normal;
  color:var(--encre-tenue);
}

/* Une case sans objet : centree et franche, sans bordure — elle dit « rien a decider
   ici », pas « ne pas prevenir ». */
.mn-vide{display:block; text-align:center; color:var(--encre-tenue); user-select:none}

/* Le reperage d'une derogation. SOUS le controle et non a cote : a cote, il decalerait le
   select et ruinerait l'alignement qu'on vient tout juste d'obtenir. */
.mn-derogation{
  display:block; margin-top:4px;
  font-family:var(--mono); font-size:var(--t-micro); font-weight:600;
  letter-spacing:.04em; text-transform:uppercase; color:var(--accent);
}

/* -------------------------------------------------- La croix du fil -----------
 |
 | Poussee a droite de l'en-tete de ligne, la ou l'oeil la cherche. Discrete au repos et
 | franche au survol : une croix rouge en permanence sur chaque ligne transformerait le fil
 | en liste de choses a supprimer, alors que c'est une liste de choses a lire. */
.fil-fermer{margin-left:auto; line-height:1}
.fil-croix{
  border:0; background:none; cursor:pointer; padding:0 2px;
  color:var(--encre-tenue); font-size:20px; line-height:1;
  transition:color var(--vite);
}
.fil-croix:hover,
.fil-croix:focus-visible{color:var(--alerte)}

/* ================================================================ PHOTOS =======
 |
 | LA TAILLE VIENT D'ICI, ET SON ABSENCE S'EST VUE IMMEDIATEMENT.
 |
 | La balise porte width et height reels — 1600 pixels de cote — parce que ces attributs
 | reservent la place pendant le chargement et empechent la page de sauter. Mais ils donnent
 | aussi la taille d'affichage tant qu'aucune regle ne dit le contraire : sans ce bloc, une
 | photo de profil s'affichait a 1600 pixels de large.
 |
 | C'est le genre de manque qu'aucun test ne rattrape et qu'un seul coup d'oeil suffit a voir. */

.photo-bloc{display:flex; flex-direction:column; gap:var(--e2); align-items:flex-start}

/* max-width:100% seul ne suffit PAS : il borne la largeur sans toucher la hauteur, et une photo
   en portrait resterait haute de 1600 pixels. Les deux dimensions sont donc bornees, et
   object-fit:cover recadre au centre plutot que de deformer. */
.photo-vue{
  display:block; max-width:100%;
  border-radius:var(--rayon); border:1px solid var(--bord);
  object-fit:cover; background:var(--surface-creuse);
}

/* L'emplacement vide : meme encombrement que la photo, pour que rien ne bouge quand on en
   ajoute une. Un cadre en pointilles dit « il peut y avoir quelque chose ici » sans imiter un
   bouton. */
.photo-vide{
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  gap:var(--e1); text-align:center;
  border:1px dashed var(--bord-net); border-radius:var(--rayon);
  background:var(--surface-creuse); color:var(--encre-tenue);
  font-size:var(--t-petit);
}
.photo-vide .i{color:var(--bord-net)}

/* ---- L'avatar : un profil, un visage. Petit et rond. ---- */
.photo-avatar .photo-vue,
.photo-avatar .photo-vide{width:140px; height:140px; border-radius:50%}
.photo-avatar .photo-vide{padding:var(--e2)}

/* ---- La facade d'un logement : large, rectangulaire, proportions de photo. ---- */
.photo-large .photo-vue,
.photo-large .photo-vide{width:100%; max-width:360px; height:220px}

/* ========================== LES QUOTAS D'UN ABONNEMENT ==========================
 |
 | DEUX FORMES POUR DEUX GESTES : « .quotas » se saisit, « .quotas-lecture » se lit. Les
 | confondre aurait donne des cases de formulaire sur un ecran de consultation, ce que la fiche
 | d'intervention a deja paye une fois.
 |
 | QUATRE COLONNES QUI SE REPLIENT. Les quatre plafonds se comparent entre eux — « 3 concierges
 | mais 200 logements » se lit d'un coup — et une colonne unique obligerait a defiler pour
 | comparer deux nombres. auto-fit les replie sur les ecrans etroits sans media query. */
.quotas{
  display:grid; gap:var(--e3); margin:var(--e3) 0;
  grid-template-columns:repeat(auto-fit, minmax(150px, 1fr));
}
.quota-case{display:flex; flex-direction:column; gap:4px}
.quota-case span{
  font-size:var(--t-micro); color:var(--encre-douce);
  text-transform:uppercase; letter-spacing:.06em;
}
/* Le meme habillage que les autres champs, par extension du selecteur et non par recopie :
   une seconde declaration aux valeurs voisines divergerait au premier ajustement. */
.quota-case input{font-family:var(--mono)}

.quotas-lecture{display:flex; flex-wrap:wrap; gap:var(--e2) var(--e4); margin-top:var(--e2)}
.quota{
  display:inline-flex; align-items:baseline; gap:5px;
  font-size:var(--t-petit); color:var(--encre-douce);
}
.quota strong{font-family:var(--mono); font-size:var(--t-controle); color:var(--encre)}

/* L'APPROCHE ET LE MUR SE DISTINGUENT, et ce sont deux situations differentes : l'une laisse
   le temps d'agir, l'autre a deja bloque quelqu'un. Une seule couleur pour les deux ferait
   traiter de la meme facon ce qui appelle une relance et ce qui appelle un appel. */
.quota-proche strong{color:var(--attente)}
.quota-plein{color:var(--alerte)}
.quota-plein strong{color:var(--alerte)}

/* ======================= LA VIGNETTE D'UNE PERSONNE, EN LISTE ===================
 |
 | Distincte de .photo-avatar ci-dessus, qui est le bloc d'EDITION du profil : celui-ci ne
 | s'edite pas, ne porte pas de formulaire, et vit dans une ligne de liste ou dans un bandeau.
 |
 | DEUX TAILLES SEULEMENT. Une echelle continue donnerait autant de diametres que d'ecrans, et
 | des colonnes qui ne s'alignent plus d'une liste a l'autre.
 |
 | UNE TAILLE FIXE, PAS UN MAXIMUM. La balise porte les dimensions REELLES de l'image — 1600
 | pixels — et sans regle explicite ce sont elles qui s'appliquent. C'est exactement le defaut
 | qui a fait afficher une photo de profil en pleine page.
 |
 | flex:none EST INDISPENSABLE : dans une ligne en flex, une vignette sans lui se laisse
 | comprimer par un nom long jusqu'a devenir un trait. */
.avatar{
  display:inline-flex; align-items:center; justify-content:center;
  flex:none; border-radius:50%; object-fit:cover;
  background:var(--surface-creuse); border:1px solid var(--bord);
  overflow:hidden; vertical-align:middle;
}
.avatar-s{width:28px; height:28px; font-size:11px}
.avatar-m{width:40px; height:40px; font-size:14px}

/* Les initiales : le repli, et non un etat degrade. La plupart des comptes n'auront jamais de
   photo — une case vide ferait des trous dans chaque liste, la ou il n'y a qu'un choix.

   La teinte vient du nom (crc32), donc ne varie jamais pour une meme personne : c'est ce qui
   la rend reconnaissable du coin de l'oeil. Luminosite basse et fond clair de la meme teinte :
   le contraste tient pour les 360 valeurs, ce qu'une couleur pleine ne garantirait pas. */
.avatar-initiales{
  font-weight:600; letter-spacing:.02em; line-height:1;
  color:hsl(var(--avatar-teinte, 205) 42% 34%);
  background:hsl(var(--avatar-teinte, 205) 46% 92%);
  border-color:hsl(var(--avatar-teinte, 205) 40% 82%);
}

/* Le lien n'ajoute rien a la vignette : il la rend cliquable, et se signale au survol. */
.avatar-lien{display:inline-flex; flex:none; border-radius:50%}
.avatar-lien:hover .avatar{border-color:var(--accent); box-shadow:0 0 0 2px var(--accent-voile)}
.avatar-lien:focus-visible{outline:2px solid var(--accent); outline-offset:2px}

.photo-actions{display:flex; flex-wrap:wrap; gap:var(--e2); align-items:center}

/* LE CHAMP DE FICHIER EST CACHE DERRIERE SON ETIQUETTE. Un <input type=file> ne se style pas —
   chaque navigateur impose son bouton et son texte « Aucun fichier selectionne ». On le rend
   donc invisible et l'on clique l'etiquette, ce qui est le comportement natif d'un <label>.
   Pas de display:none : cela le retirerait de la navigation au clavier. */
.photo-choisir{position:relative; overflow:hidden; cursor:pointer}
.photo-choisir input[type=file]{
  position:absolute; inset:0; width:100%; height:100%;
  opacity:0; cursor:pointer;
}

/* ---- La photo A GAUCHE du profil ---- */
/*
 | DEUX FORMULAIRES COTE A COTE, et c'est ce qui a impose cette grille.
 |
 | La photo doit rester dans SON formulaire : un envoi de fichier exige
 | enctype="multipart/form-data", et l'appliquer au formulaire du profil changerait l'encodage de
 | tous ses champs, mots de passe compris. Deux formulaires distincts, donc — mais l'usage veut
 | l'avatar a gauche de l'identite, pas au-dessus dans une carte a part.
 |
 | La grille les rapproche visuellement sans les fusionner : la mise en page ne dicte pas la
 | structure du formulaire.
 */
/*
 | LA PREMIERE COLONNE EST BORNEE EN DUR, ET « auto » ETAIT LA CAUSE DU DEFAUT.
 |
 | « auto » dimensionne la colonne sur son CONTENU. L'avatar fait 140 pixels, mais la legende
 | dessous est du texte : elle reclame toute la largeur qu'on lui laisse, la colonne s'elargit avec
 | elle, et le formulaire part hors de l'ecran. Le symptome ne venait donc pas de la photo, mais de
 | la phrase sous la photo — et c'est pourquoi le raccourcir ne suffisait pas : il fallait borner.
 |
 | 180 pixels : l'avatar plus sa marge. La legende s'y replie, et la colonne ne bouge plus quel que
 | soit son texte.
 */
.profil-entete{
  display:grid; grid-template-columns:180px minmax(0, 1fr);
  gap:var(--e5); align-items:start;
}

/* Le bloc ne depasse jamais sa colonne : c'est ce qui force la legende a se replier plutot qu'a
   pousser. Sans cette borne, un mot long suffirait a elargir la colonne malgre sa largeur fixe. */
.profil-entete .photo-bloc{max-width:100%}

/* La legende sous la photo : petite, et surtout REPLIABLE. overflow-wrap l'empeche de pousser sa
   colonne a cause d'un mot que rien ne coupe. */
.photo-bloc .legende-note{
  margin:0; max-width:100%;
  font-size:var(--t-micro); line-height:1.4;
  overflow-wrap:anywhere;
}

/* Sous 720 px, deux colonnes ne tiennent plus : l'avatar repasse au-dessus, centre. */
@media (max-width:720px){
  .profil-entete{grid-template-columns:1fr; gap:var(--e4)}
  .profil-entete .photo-bloc{align-items:center}
}

/* ------------------------------------------ Les preuves d'une prestation -------
 |
 | Une grille de vignettes carrees. CARREES, et non aux proportions de chaque photo : un menage se
 | photographie en portrait, une facade en paysage, et melanger les deux dans une meme rangee donne
 | un alignement en dents de scie. object-fit:cover recadre au centre — on perd les bords, on garde
 | la lisibilite d'ensemble. Le detail se regarde en grand, dans un onglet. */
.galerie{display:flex; flex-direction:column; gap:var(--e3)}

.galerie-liste{
  display:grid; grid-template-columns:repeat(auto-fill, minmax(120px, 1fr));
  gap:var(--e3); margin:0; padding:0; list-style:none;
}

/* position:relative : c'est le repere de la croix, posee en surimpression. */
.galerie-vignette{position:relative; display:flex; flex-direction:column; gap:2px}

.galerie-vignette img{
  display:block; width:100%; height:120px;
  object-fit:cover;
  border:1px solid var(--bord); border-radius:var(--rayon);
  background:var(--surface-creuse);
}
.galerie-vignette a:hover img,
.galerie-vignette a:focus-visible img{border-color:var(--accent)}

/* La date de chaque photo, petite et en mono : c'est une donnee, pas une phrase. Elle rend honnete
   le fait d'accepter un depot apres la fin de la prestation — un ajout tardif se voit. */
.galerie-quand{
  font-family:var(--mono); font-size:var(--t-micro);
  color:var(--encre-tenue); text-align:center;
}

/* La croix EN SURIMPRESSION sur la vignette, et non dessous : sous l'image, elle allongerait
   chaque case et se retrouverait loin de ce qu'elle supprime. Le fond opaque la garde lisible sur
   une photo claire comme sur une photo sombre. */
.galerie-oter{position:absolute; top:4px; right:4px; line-height:1}
.galerie-oter .fil-croix{
  background:var(--surface); border-radius:50%;
  width:24px; height:24px; padding:0;
  display:flex; align-items:center; justify-content:center;
  font-size:16px; box-shadow:0 1px 3px rgba(0,0,0,.25);
}

.galerie-ajout{display:flex; flex-wrap:wrap; gap:var(--e2); align-items:center}

/* Les boutons d'arbitrage poses sur une ligne de liste. Les formulaires sont en ligne pour que
   les trois commandes — valider, refuser, ouvrir — restent sur la meme rangee ; empiles, ils
   feraient grandir chaque ligne d'un tiers sur une liste qu'on parcourt du regard. */
.ligne-arbitrage{display:inline-flex}
.commandes .btn-menu{padding:4px 10px; font-size:var(--t-petit)}

/* ============================================ CLIENTS ET BIENS, UNE SEULE LISTE ===
 |
 | Les logements groupes par client : chaque carte porte un client en en-tete, ses logements en
 | lignes. Deux niveaux d'action qui ne doivent pas se confondre — l'en-tete agit sur le client,
 | chaque ligne sur son logement — d'ou une separation nette entre les deux. */

.groupe-client{padding:0}

/* L'en-tete du client : meme disposition qu'une ligne de registre — identite a gauche, commandes
   a droite — pour que l'oeil retrouve le meme reperage a tous les niveaux de la page. */
.groupe-tete{
  display:flex; flex-wrap:wrap; gap:var(--e3);
  align-items:center; justify-content:space-between;
  padding:var(--e4);
  background:var(--surface-creuse);
  border-bottom:1px solid var(--bord);
  border-radius:var(--rayon-carte) var(--rayon-carte) 0 0;
}
/* flex:1 SUR L'IDENTITE, ET C'EST LA VIGNETTE QUI L'A IMPOSE. L'en-tete est en
   « space-between » : a deux enfants, cela collait le nom a gauche et les commandes a droite.
   A trois, l'espace se serait reparti AUTOUR de l'identite, detachant la vignette du nom
   qu'elle illustre. En laissant l'identite absorber le vide, la vignette reste contre son nom
   et les commandes gardent leur bord. */
.groupe-tete .identite{min-width:0; flex:1 1 auto}

/* Le nom du client porte le poids de la carte : c'est le titre du groupe, pas une ligne parmi
   d'autres. Les logements en dessous restent a la taille du registre. */
.groupe-tete .nom{margin:0; font-size:var(--t-moyen); font-weight:600; color:var(--encre)}
.groupe-tete .meta{margin-top:var(--e1)}
.groupe-tete .commandes{flex:0 0 auto}

/* Le « + » ajoute un logement A CE CLIENT : il est plein, contrairement aux autres commandes qui
   sont des liens. C'est le seul geste de creation de la carte, et il doit se distinguer d'un
   « ouvrir » qui ne fait que naviguer. */
.groupe-client .registre{padding:var(--e2) var(--e4) var(--e4)}
.groupe-client > .aide{padding:var(--e4)}

/* ==================== LA LIGNE D'UN LOGEMENT ==================================
 |
 | UNE COLONNE DE PLUS QUE LA LIGNE ORDINAIRE, ET ELLE EST TENUE PAR LA SPECIFICITE, non par
 | l'ordre du fichier : « .registre .ligne » l'emporte sur « .ligne » ou qu'on la place. Une regle
 | qui ne gagne que parce qu'elle est ecrite plus bas se perd au premier deplacement.
 |
 | LA VIGNETTE TIENT LA PLACE D'UNE PHOTO QUI N'EXISTE PAS ENCORE : un logement peut en porter une,
 | aucun n'en a. Le cadre est pose des maintenant pour que la mise en page ne bouge pas le jour ou
 | les premieres arriveront — c'est l'icone du type qui l'occupe en attendant.
 */
.registre .ligne:has(> .vignette-bien){grid-template-columns:5px auto 1fr auto}
.vignette-bien{
  display:flex; align-items:center; justify-content:center;
  width:38px; height:38px; margin-left:var(--e4);
  border-radius:var(--rayon); background:var(--surface-creuse);
  border:1px solid var(--bord); color:var(--encre-douce);
}
.vignette-bien .i{width:19px; height:19px}

/* LE MENU DE LIGNE FLOTTE, ET « .registre » LE COUPAIT. Le registre porte « overflow:hidden » pour
   que ses lignes respectent l'arrondi de la carte ; un panneau en position absolue s'y trouvait
   tranche net. On ne leve la coupe QUE pendant l'ouverture, faute de quoi l'arrondi serait perdu
   tout le temps pour un menu qu'on ouvre une fois par semaine. */
.registre:has(.ligne-menu[open]){overflow:visible}

/* ==================== LE REPLI D'UN GROS CLIENT ===============================
 |
 | IL N'Y A DE CHEVRON QUE S'IL Y A DE QUOI REPLIER — la vue ne pose le <details> qu'au-dela de
 | trois logements. Un chevron qui n'ouvre rien est le premier qu'on essaie, et le dernier auquel
 | on croit.
 |
 | LE LIBELLE SUIT L'ETAT SANS UNE LIGNE DE SCRIPT : « [open] » choisit lequel des deux mots
 | s'affiche. Et le chevron pointe a droite ferme, vers le bas ouvert — la convention du triangle
 | de divulgation, obtenue par une rotation faute d'avoir une icone « chevron-bas ». */
/* LA COULEUR EST CELLE D'UN CONTROLE, PAS CELLE D'UNE LEGENDE — et je l'avais prise a l'envers.
   « --encre-tenue » donne 2,8 pour 1 sur le blanc : sous le seuil de 4,5 attendu d'un texte, et
   sous 3 pour 1 attendu meme d'un grand caractere. A 13 px, la ligne se devinait. « --encre-douce »
   donne 5,4 pour 1, et le demi-gras acheve de la distinguer d'un commentaire : ce qui se clique doit
   avoir l'air de se cliquer. */
.repli-logements > summary{
  list-style:none; cursor:pointer;
  display:flex; align-items:center; gap:var(--e2);
  padding:var(--e2) var(--e4) 0;
  font-size:var(--t-petit); font-weight:500; color:var(--encre-douce);
  transition:color var(--vite);
}
.repli-logements > summary::-webkit-details-marker{display:none}
.repli-logements > summary:hover{color:var(--encre)}
.repli-logements > summary .i{transition:transform var(--vite)}
.repli-logements[open] > summary .i{transform:rotate(90deg)}
.repli-logements > summary .plier{display:none}
.repli-logements[open] > summary .plier{display:inline}
.repli-logements[open] > summary .deplier{display:none}

/* ==================== LA BARRE D'UNE CONCIERGERIE ==============================
 |
 | Le fil d'Ariane est DANS la barre et non au-dessus : le nom de la conciergerie est ce qui
 | distingue « les interventions » de « les interventions DE CE CLIENT », et sur l'ecran des
 | interventions rien d'autre ne le dirait. */
.entete-conciergerie{
  display:flex; align-items:center; gap:var(--e3); flex-wrap:wrap;
  margin-bottom:var(--e2); font-size:var(--t-petit); color:var(--encre-douce);
}
.entete-conciergerie strong{font-size:var(--t-moyen); color:var(--encre); font-weight:600}

/* ========================= LA BARRE DE FILTRES PARTAGEE ==========================
 |
 | POURQUOI ELLE REMPLACE HUIT BARRES DIFFERENTES.
 |
 | L'ancienne posait un libelle AU-DESSUS de chaque controle — la disposition d'un formulaire
 | de SAISIE appliquee a une barre de CONSULTATION. Mesure faite sur les interventions :
 | 11 px de libelle + 5 de marge + 36 de controle, quatre fois, plus la rangee d'onglets
 | d'etat, soit 174 px avant la premiere ligne de donnees. Sur un portable, 19 % de la
 | hauteur utile.
 |
 | Au repos, celle-ci tient en 44 px.
 |
 | TOUT FONCTIONNE SANS JAVASCRIPT : le panneau est un <details>, les jetons sont des liens.
 | C'est la regle du projet — le tri d'une colonne est un lien, la fenetre de fiche un
 | « target= », le tiroir du menu un <details>. */

.barre-filtres{display:flex; flex-direction:column; gap:10px; margin-bottom:var(--e4)}

.bf-ligne{display:flex; align-items:center; gap:var(--e2); flex-wrap:wrap}

/* --- La recherche, toujours visible ---
   C'est le filtre qu'on emploie neuf fois sur dix : l'enfouir derriere un bouton ajouterait
   un clic au geste le plus frequent. */
.bf-recherche{
  flex:1 1 260px; min-width:190px; max-width:420px;
  height:38px; display:flex; align-items:center; gap:var(--e2);
  padding:0 10px; background:var(--surface);
  border:1px solid var(--bord-net); border-radius:var(--rayon);
  transition:border-color var(--vite), box-shadow var(--vite);
}
.bf-recherche:focus-within{border-color:var(--accent); box-shadow:var(--anneau)}
.bf-recherche .i{color:var(--encre-tenue); flex:none}

/* Le champ n'a NI bordure NI fond : c'est son enveloppe qui les porte, sinon on verrait deux
   cadres imbriques. « min-width:0 » l'empeche de refuser de retrecir — un input a une largeur
   propre par defaut, et sans cela l'enveloppe deborde de la ligne. */
.bf-recherche input{
  flex:1 1 auto; min-width:0;
  border:0; background:none; outline:none; padding:0;
  font:inherit; font-size:var(--t-controle); color:var(--encre);
}
.bf-recherche input::-webkit-search-cancel-button{cursor:pointer}

/* --- Le declencheur et son panneau --- */
.bf-panneau{position:relative}

/* La fleche par defaut du <summary> est retiree : le bouton doit ressembler aux autres
   boutons de l'application, pas a un titre de section depliable. */
.bf-declencheur{
  display:inline-flex; align-items:center; gap:6px; cursor:pointer;
  height:38px; padding:0 var(--e3);
  border:1px solid var(--bord-net); border-radius:var(--rayon);
  background:var(--surface); color:var(--encre);
  font-size:var(--t-controle); white-space:nowrap;
  list-style:none;
  transition:border-color var(--vite), background var(--vite);
}
.bf-declencheur::-webkit-details-marker{display:none}
.bf-declencheur::marker{content:""}
.bf-declencheur:hover{border-color:var(--encre-tenue)}
.bf-panneau[open] .bf-declencheur{
  border-color:var(--accent); color:var(--accent); background:var(--accent-voile);
}
.bf-declencheur:focus-visible{outline:2px solid var(--accent); outline-offset:2px}

/* Le nombre de filtres appliques : sans lui, un panneau ferme cache son propre etat. */
.bf-compte{
  display:inline-flex; align-items:center; justify-content:center;
  min-width:18px; height:18px; padding:0 5px; border-radius:9px;
  background:var(--accent); color:#fff;
  font-size:11px; font-weight:700; font-variant-numeric:tabular-nums;
}
.bf-panneau[open] .bf-compte{background:var(--accent-fonce)}

/* EN SURIMPRESSION, ET NON DANS LE FLUX. Deplie dans le flux, le panneau pousserait la liste
   de deux cents pixels a chaque ouverture — il rendrait par intermittence le probleme qu'on
   vient de regler. */
.bf-corps{
  position:absolute; z-index:30; top:calc(100% + 6px); left:0;
  min-width:min(560px, 92vw);
  background:var(--surface);
  border:1px solid var(--bord-net); border-radius:var(--rayon-carte);
  box-shadow:var(--ombre3);
  padding:var(--e4);
}

/* Sur un ecran etroit, le panneau se cale a DROITE de son declencheur plutot que de deborder
   hors de la page. */
@media (max-width:640px){
  .bf-corps{left:auto; right:0; min-width:min(560px, 94vw)}
}

.bf-corps .champs{margin:0}
.bf-pied{
  display:flex; align-items:center; justify-content:flex-end; gap:var(--e3);
  margin-top:var(--e4); padding-top:var(--e3); border-top:1px solid var(--bord);
}

/* --- Les jetons : ce qui est applique, et de quoi le defaire --- */
.bf-jetons{display:flex; flex-wrap:wrap; gap:6px; align-items:center}

.bf-jeton{
  display:inline-flex; align-items:center; gap:6px;
  height:26px; padding:0 6px 0 10px; border-radius:13px;
  background:var(--accent-voile); border:1px solid #cfe0de;
  color:var(--accent); font-size:var(--t-petit);
  text-decoration:none; white-space:nowrap;
  transition:background var(--vite), border-color var(--vite);
}
.bf-jeton:hover{background:#d5e6e4; border-color:var(--accent); text-decoration:none}
.bf-jeton:focus-visible{outline:2px solid var(--accent); outline-offset:2px}

.bf-croix{
  display:inline-flex; align-items:center; justify-content:center;
  width:16px; height:16px; border-radius:50%;
  background:rgba(47,93,98,.14); font-size:12px; line-height:1;
}
.bf-jeton:hover .bf-croix{background:rgba(47,93,98,.24)}

.bf-vider{
  font-size:var(--t-petit); color:var(--encre-douce);
  text-decoration:underline; text-underline-offset:2px; padding:0 var(--e2);
}
.bf-vider:hover{color:var(--encre)}

/* Pour les lecteurs d'ecran seulement. Ni « display:none » ni « visibility:hidden » : les deux
   retirent l'element de l'arbre d'accessibilite, donc du texte qu'on voulait justement lui
   donner. */
.hors-ecran{
  position:absolute; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip-path:inset(50%); white-space:nowrap; border:0;
}

/* Une case a cocher n'a pas de libelle AU-DESSUS : son texte est a cote d'elle. Sans cette
   regle elle se cale donc en haut de sa cellule de grille — a la hauteur des libelles des
   champs voisins — et se lit comme un titre de colonne plutot que comme un controle.
   « justify-content:flex-end » la descend au niveau des champs de saisie.

   La marge basse compense celle que .champ porte deja : sans elle, la case se collerait au
   bas de la cellule au lieu de s'aligner sur la BASE des controles. */
.champ-case{
  display:flex; flex-direction:column; justify-content:flex-end;
  padding-bottom:9px;
}

/* --- Les actions de l'ecran, dans la barre de filtres ---
   Elles vivaient dans l'en-tete, sur leur propre rangee : deux lignes pour ce qui tient sur
   une, et deux hauteurs de bouton differentes puisque rien ne les accordait.

   « margin-left:auto » les pousse a droite : la gauche appartient a ce qui REDUIT la liste,
   la droite a ce qui en SORT. Les deux gestes ne se confondent pas. */
.bf-actions{display:flex; align-items:center; gap:var(--e2); margin-left:auto}

/* UNE SEULE HAUTEUR POUR TOUTE LA LIGNE, et c'est la demande.
   La recherche et le declencheur sont a 38 px ; un bouton ordinaire vaut 36 px par son
   remplissage (10 + 14 + 10 + bordures), et .btn-icone 40 de large. Trois valeurs voisines sur
   une meme rangee se voient — d'autant plus que les bords sont alignes. On les accorde ici,
   sans toucher aux regles generales : ailleurs, un bouton doit rester confortable. */
.barre-filtres .btn{height:38px; padding-top:0; padding-bottom:0}
.barre-filtres .btn-icone{width:38px; padding:0}

/* Une en-tete qui ne porte plus que son titre et son compte — les actions ayant rejoint la
   barre de filtres — laisse les deux tiers de sa rangee vides si elle reste calee a gauche,
   au-dessus d'un tableau qui occupe toute la largeur. On la centre.

   UN MODIFICATEUR, ET NON UN CHANGEMENT DE « .entete » : les autres ecrans y gardent des
   boutons a droite, et les centrer les pousserait vers le milieu de la page. */
.entete-centree{justify-content:center; text-align:center}

/* ====================== LA BARRE D'OUTILS DES LISTES SANS FILTRE ======================
 |
 | POURQUOI CE N'EST PAS LA BARRE DE FILTRES.
 |
 | Neuf listes n'ont AUCUN filtre : les offres, les types de piece, les migrations, le journal,
 | les notifications, les trajets... Leur passer « partials/filtres » aurait rendu un bouton
 | loupe « Appliquer les filtres » qui ne filtre rien — un controle qui ment sur ce qu'il fait,
 | et le premier qu'on essaie.
 |
 | Elles reprennent donc la MOITIE DROITE de la barre de filtres, et rien d'autre : meme
 | hauteur de bouton, meme espacement, meme marge basse. L'oeil retrouve la meme rangee d'un
 | ecran a l'autre ; c'est ce que « actions a droite » demande, sans inventer un filtre absent.
 |
 | « justify-content:flex-end » plutot que « margin-left:auto » sur un enfant : ici il n'y a
 | rien a gauche a pousser. */
.barre-outils{
  display:flex; align-items:center; justify-content:flex-end;
  gap:var(--e2); flex-wrap:wrap; margin-bottom:var(--e4);
}

/* La meme mise au diapason que dans la barre de filtres, et pour la meme raison : sans elle,
   un bouton ordinaire (36 px) et un bouton en icone (40 de large) se cotoient sur une rangee
   aux bords alignes, ou l'ecart se voit. */
.barre-outils .btn{height:38px; padding-top:0; padding-bottom:0}
.barre-outils .btn-icone{width:38px; padding:0}

/* Une barre vide ne doit pas laisser un trou : sans enfant, elle ne reserve aucune hauteur.
   Le cas se produit — les actions d'un ecran dependent parfois du role de qui regarde. */
.barre-outils:empty{display:none}

/* ================== L'ETAT VIDE SUIT LA LARGEUR DE SA LISTE ==================
 |
 | LE DEFAUT RAPPORTE, DANS SON CAS LE PLUS DISCRET.
 |
 | « Certaines listes n'occupent pas toute la largeur de la page. » La correction a consiste a
 | elargir chaque conteneur de liste — mais un ecran dont la liste est VIDE n'a pas de
 | conteneur a elargir. Il gardait donc une barre a 1560 px au-dessus d'un message a 1060 : le
 | meme decalage de 250 px de chaque cote, aux seuls moments ou l'on n'a rien d'autre a
 | regarder. Et « .vide » porte une bordure tiretee et un fond — sa largeur SE VOIT.
 |
 | AUCUNE REGLE ICI, ET C'EST LE POINT.
 |
 | J'avais d'abord ecrit « .barre-filtres.pleine-largeur + .vide { ... } ». Elegant, et
 | INVERIFIABLE : le harnais lit du HTML, pas la feuille de style. Une regle qu'aucune assertion
 | ne peut voir ne peut pas etre protegee, et celle-ci se serait tue au premier element glisse
 | entre la barre et le bloc vide — ce qui est deja le cas sur le journal d'erreurs.
 |
 | Les etats vides portent donc « pleine-largeur » DANS LEUR BALISAGE, comme leurs listes. Le
 | mecanisme est celui de toute la famille, et le controle partage le voit. */

/* --- Deux commandes dans une meme cellule ---
   « Modifier » est un lien, « Retirer » un bouton dans son propre <form> — un <form> est un
   bloc, il passerait donc a la ligne sous le lien. Cette rangee les remet cote a cote et les
   pousse a droite, comme le reste de la colonne d'actions.

   flex-end, ET NON text-align : le <form> ne se laisse pas aligner par le texte de sa
   cellule ; c'est le conteneur qui doit le placer. */
.commandes-ligne{
  display:flex; align-items:center; justify-content:flex-end;
  gap:var(--e3); flex-wrap:wrap;
}
.commandes-ligne form{margin:0}

/* Le nom d'un intervenant mene a son agenda. Il garde la forme d'un nom — vignette et texte
   alignes — plutot que de prendre celle d'un bouton : la ligne est deja occupee par sept
   cases ou l'on depose, et une commande de plus la rendrait plus difficile a viser. */
.ps-nom-lien{
  display:inline-flex; align-items:center; gap:var(--e2);
  text-decoration:none; color:inherit; border-radius:var(--rayon);
  transition:color var(--vite);
}
.ps-nom-lien:hover{color:var(--accent)}
.ps-nom-lien:hover .ps-nom-texte{text-decoration:underline}

/* ============================ L'AGENDA D'UNE RESSOURCE ============================
 |
 | Sept jours en colonnes, les heures en lignes, une seule personne. La grille hebdomadaire
 | range les intervenants en lignes et repond a « qui fait quoi » ; celle-ci repond a
 | « cette journee tient-elle debout ».
 |
 | LES BLOCS SONT POSITIONNES EN ABSOLU, a la minute. C'est ce qui permet a une intervention
 | de 9h15 de se placer a 9h15 plutot qu'au creneau le plus proche — et sur un planning ou
 | l'on verifie qu'un enchainement TIENT, le quart d'heure est exactement ce qu'on cherche a
 | voir. Les traits de fond ne sont qu'une reglette derriere ; ce sont les positions qui font
 | foi. */

.agenda{
  background:var(--surface); border:1px solid var(--bord);
  border-radius:var(--rayon-carte); overflow:hidden; margin-bottom:var(--e4);
}

/* La marge des heures et les sept jours : une seule grille, partagee par les trois rangees
   — en-tetes, bande sans horaire, corps. Sans grid-template-columns commun, les colonnes ne
   s'aligneraient pas d'une rangee a l'autre. */
.agenda-entetes,
.agenda-sans-heure,
.agenda-corps{
  display:grid; grid-template-columns:46px repeat(7, 1fr);
}

.agenda-entetes{
  border-bottom:1px solid var(--bord-net); background:var(--surface-creuse);
  position:sticky; top:0; z-index:2;
}
.agenda-entetes .agenda-jour{
  padding:var(--e2) var(--e2); text-align:center;
  border-left:1px solid var(--bord);
}
.agenda-nom{
  display:block; font-size:var(--t-micro); text-transform:uppercase;
  letter-spacing:.06em; color:var(--encre-douce);
}
.agenda-numero{display:block; font-size:var(--t-controle); font-weight:600}

/* Le jour courant se teinte, comme partout dans ce projet : c'est le repere qu'on cherche
   en arrivant sur l'ecran. */
.agenda-aujourdhui{background:var(--accent-voile)}
.agenda-weekend{background:var(--surface-creuse)}
.agenda-entetes .agenda-aujourdhui .agenda-numero{color:var(--accent)}

/* --- La bande des interventions sans horaire ---
   Elles existent et n'ont pas de position. Les ecarter serait les masquer sur l'ecran meme
   qui doit les montrer ; les poser a une heure inventee ferait croire a une donnee saisie.
   D'ou une bande a part, au-dessus de la grille. */
.agenda-sans-heure{
  border-bottom:1px solid var(--bord-net);
  background:repeating-linear-gradient(
    -45deg, transparent, transparent 6px,
    var(--surface-creuse) 6px, var(--surface-creuse) 12px
  );
}
.agenda-sans-heure .agenda-jour{
  border-left:1px solid var(--bord); padding:3px; min-height:34px;
  display:flex; flex-direction:column; gap:3px;
}
.agenda-sans-heure .agenda-marge{
  display:flex; align-items:center; justify-content:center; color:var(--attente);
}

.agenda-corps{position:relative}

/* La marge porte les heures. position:relative pour que les graduations s'y placent en
   absolu, a la meme hauteur que les traits des colonnes. */
.agenda-corps .agenda-marge{position:relative; border-right:1px solid var(--bord-net)}

.agenda-graduation{
  position:absolute; right:5px; transform:translateY(-50%);
  font-family:var(--mono); font-size:var(--t-mono); color:var(--encre-tenue);
}

.agenda-corps .agenda-jour{
  position:relative; border-left:1px solid var(--bord); overflow:hidden;
}

/* --- Les traits de fond ---
   Un par quart d'heure. Ceux des heures pleines sont plus marques : sans cette distinction,
   cinquante-deux traits identiques feraient une trame grise ou l'on ne repere plus rien. */
.agenda-trait{
  position:absolute; left:0; right:0; height:1px;
  background:var(--bord); opacity:.45;
}
.agenda-trait-heure{background:var(--bord-net); opacity:1}

/* --- Un bloc d'intervention ---
   Sa hauteur EST sa duree : c'est ce qui rend un chevauchement visible et un trou evident.
   min-height garde lisible une intervention de quinze minutes, quitte a la dessiner un peu
   plus haute qu'elle ne dure — mieux vaut un bloc leger trop grand qu'un bloc illisible.

   LE FOND VIENT DES CLASSES DE TEINTE — ps-attente, ps-valide, ps-faite — comme sur la grille
   hebdomadaire. Ce bloc ne declare NI background NI border-left-color : les poser ici les
   ecraserait, et les blocs redeviendraient TRANSPARENTS.

   C'est le defaut rapporte : les classes employees — « ps-validee », « ps-demandee » — n'exis-
   taient dans aucune feuille de style. Aucune erreur n'etait levee, une classe CSS inconnue ne
   fait rien, et l'on ne distinguait plus les interventions du fond de la grille. */
.agenda-bloc{
  position:absolute; overflow:hidden;
  padding:2px 5px; border-radius:var(--rayon);
  border-left-width:3px; border-left-style:solid;
  font-size:var(--t-micro); line-height:1.25;
  text-decoration:none; min-height:18px;
  color:var(--encre);
  box-shadow:var(--ombre1);
  transition:box-shadow var(--vite), transform var(--vite);
}
.agenda-bloc:hover{box-shadow:var(--ombre2); transform:translateY(-1px); z-index:3}

.agenda-heure{display:block; font-family:var(--mono); font-size:var(--t-mono); opacity:.85}
.agenda-bien{display:block; font-weight:600}
.agenda-client{display:block; opacity:.75}

/* Une duree non renseignee se signale par un bord hachure : le bloc a bien une hauteur —
   sinon il serait invisible — mais elle est une CONVENTION, pas une donnee. Sans ce signal,
   on planifierait la suivante par-dessus. */
.agenda-duree-inconnue{
  border-left-style:dashed;
  background-image:repeating-linear-gradient(
    -45deg, transparent, transparent 4px,
    rgba(0,0,0,.045) 4px, rgba(0,0,0,.045) 8px
  );
}

.agenda-vignette{
  display:block; padding:2px 5px; border-radius:var(--rayon);
  border-left-width:3px; border-left-style:solid; font-size:var(--t-micro);
  line-height:1.2; text-decoration:none; color:var(--encre); box-shadow:var(--ombre1);
}

/* Le selecteur de ressource, dans la barre d'outils. */
.agenda-choix{display:flex; align-items:center; gap:var(--e2)}
.agenda-choix select{height:38px; min-width:180px}

/* --- La legende ---
   Les etats se lisent au code couleur sur les blocs : il n'y a pas la place d'y ecrire
   « validee ». Une couleur sans legende ne se devine pas.

   margin-bottom ET NON le raccourci margin : cette classe accompagne « pleine-largeur », qui
   pose un margin-left calcule pour le centrage. Un raccourci l'ecraserait et decalerait la
   legende de deux cents pixels. tests_style verifie cette regle. */
.agenda-legende{
  display:flex; flex-wrap:wrap; gap:var(--e4);
  font-size:var(--t-petit); color:var(--encre-douce); margin-bottom:var(--e6);
}
.agenda-cle{display:inline-flex; align-items:center; gap:var(--e2)}
.agenda-pastille{
  width:14px; height:14px; border-radius:3px;
  border-left-width:3px; border-left-style:solid; box-shadow:var(--ombre1);
}

/* ------------------------- Deplacer et etirer les blocs -------------------------
 |
 | LE CURSEUR EST LA SEULE ANNONCE DU GESTE. Rien, sur un bloc d'agenda, ne dit qu'il se
 | deplace : il ressemble a une etiquette. La main ouverte le dit avant qu'on essaie, et la
 | double fleche verticale, sur les sept derniers pixels, dit qu'on y etire plutot qu'on y tire.
 |
 | LE SELECTEUR PORTE SUR [draggable], ET NON SUR .agenda-bloc. Une intervention terminee n'est
 | pas deplacable, et la vue ne lui pose pas l'attribut : lui donner une main ouverte
 | promettrait un geste que le serveur refuserait. Un element qu'on peut saisir mais qui refuse
 | de se poser est plus penible qu'un element manifestement fixe — on croit avoir rate son
 | geste, et l'on recommence. */
.agenda-bloc[draggable="true"]{cursor:grab}
.agenda-bloc[draggable="true"]:active{cursor:grabbing}

/* LA VIGNETTE « A CALER » SE SAISIT COMME UN BLOC, et le curseur doit le dire : c'est la seule
   chose qui annonce qu'on peut la glisser dans la grille pour lui donner une heure. Sans lui, le
   geste existe et personne ne le trouve — l'infobulle l'ecrit, mais on ne survole pas ce qu'on ne
   soupconne pas.

   ET LE SELECTEUR SUIT L'ATTRIBUT, PAS LA CLASSE : « draggable » n'est pose que si le creneau se
   modifie, donc la main ne parait que sur ce qui peut vraiment bouger. Une vignette terminee garde
   le curseur d'un lien, qui est ce qu'elle est. */
.agenda-vignette[draggable="true"]{cursor:grab}
.agenda-vignette[draggable="true"]:active{cursor:grabbing}

/* La poignee couvre toute la largeur du bas du bloc : sur un bloc de quinze minutes, haut de
   vingt pixels, une poignee en coin serait intuvable. Elle reste transparente tant qu'on ne
   survole pas — un agenda charge aurait sinon une rangee de traits gris a chaque bloc. */
.agenda-poignee{
  position:absolute; left:0; right:0; bottom:0; height:7px;
  cursor:ns-resize;
}

/* Le trait ne parait qu'au survol, et c'est un ::after plutot qu'une bordure sur la poignee :
   une bordure haute de 2 px reduirait la zone cliquable a cinq pixels. */
.agenda-poignee::after{
  content:''; position:absolute; left:50%; bottom:2px;
  width:22px; height:2px; margin-left:-11px; border-radius:2px;
  background:currentColor; opacity:0; transition:opacity var(--vite);
}
.agenda-bloc:hover .agenda-poignee::after{opacity:.5}

/* Pendant l'etirement, on suspend le decollement du survol : le bloc grandit sous le curseur,
   et un saut d'un pixel a chaque passage de la souris ferait croire a un tremblement. */
.agenda-bloc[data-etire]{
  transform:none; z-index:4; box-shadow:var(--ombre2);
}

/* ==================================================================================
   LE FIL DES NOTIFICATIONS
   ================================================================================== */

/* Deux colonnes : le fil, et les raccourcis. La colonne de droite est FIXE — elle porte des
   nombres courts, et la laisser s'etirer volerait de la largeur aux cartes, qui en ont besoin
   pour leur citation et leurs vignettes.

   « align-items:start » EMPECHE LA COLONNE DE S'ETIRER sur la hauteur du fil : sans lui, la
   derniere carte de droite se retrouve tiree jusqu'en bas d'un fil de cinquante lignes. */
/* L'en-tete de cet ecran s'aligne a gauche : « .entete-centree » est la forme des registres,
   un titre au-dessus d'un tableau pleine largeur. Ici le titre surplombe deux colonnes, et le
   centrer le poserait a cheval sur leur separation. */
.fil-entete{align-items:center; gap:var(--e3)}

/* Le compte des non-lues : une pastille, et non une mention grise. C'est le seul nombre de
   l'ecran qui appelle une action ; en petites capitales tenues, il se rangeait avec les
   libelles et ne se voyait plus. */
.fil-badge{
  display:inline-flex; align-items:center;
  padding:var(--e1) var(--e3); border-radius:999px;
  background:var(--accent-voile); color:var(--accent);
  font-size:var(--t-petit); font-weight:600; white-space:nowrap;
}
/* Quand tout est lu, la pastille reste — un vide a cet endroit se lirait comme un chargement
   qui n'a pas abouti — mais elle cesse d'appeler. */
.fil-badge-calme{background:var(--surface-creuse); color:var(--encre-tenue); font-weight:400}

.fil-agencement{
  display:grid; grid-template-columns:minmax(0, 1fr) 300px;
  gap:var(--e6); align-items:start;
}
.fil-principal{min-width:0; display:flex; flex-direction:column; gap:var(--e2)}

/* Sous 900 px la colonne passe SOUS le fil, et non a cote en plus etroit : a 200 px elle ne
   porterait plus ses libelles sans les couper. */
@media (max-width:900px){
  .fil-agencement{grid-template-columns:minmax(0, 1fr)}
}

/* --- La barre : onglets a gauche, outils a droite --- */
.fil-barre{
  display:flex; align-items:center; gap:var(--e4); flex-wrap:wrap;
  border-bottom:1px solid var(--bord); padding-bottom:var(--e2);
}
.fil-onglets{display:flex; gap:var(--e1); flex-wrap:wrap}
.fil-onglet{
  display:inline-flex; align-items:center; gap:var(--e2);
  padding:var(--e2) var(--e3); border-radius:var(--rayon);
  font-size:var(--t-controle); color:var(--encre-douce); text-decoration:none;
  border-bottom:2px solid transparent; margin-bottom:-1px;
  transition:color var(--vite), border-color var(--vite);
}
.fil-onglet:hover{color:var(--encre); text-decoration:none}
/* L'onglet courant se marque par un LISERET, pas par un fond : un fond en ferait un bouton, et
   l'on chercherait ce qu'il declenche. Un liseret dit « vous etes ici ». */
.fil-onglet-courant{color:var(--accent); border-bottom-color:var(--accent); font-weight:600}
.fil-pastille{
  font-family:var(--mono); font-size:var(--t-micro); line-height:1;
  padding:3px 6px; border-radius:var(--rayon-puce);
  background:var(--accent); color:#fff;
}
.fil-outils{margin-left:auto; display:flex; align-items:center; gap:var(--e2); flex-wrap:wrap}
.fil-choix{display:flex; align-items:center; gap:var(--e1)}
/* LE SELECTEUR EST A LA TAILLE DES BOUTONS QUI L'ENTOURENT. Rendu nu, il prenait la taille par
   defaut du navigateur — plus petit, plus bas, d'une autre famille — et cassait la ligne de la
   barre. Ce sont les memes reglages que « .btn », a l'exception du fond, qui reste clair pour
   dire qu'on y choisit plutot qu'on y clique. */
.fil-choix select{
  min-width:220px; padding:var(--e2) var(--e3);
  font:500 var(--t-controle)/1.4 inherit;
  color:var(--encre); background:var(--surface);
  border:1px solid var(--bord-net); border-radius:var(--rayon);
}

/* --- Le bandeau d'alerte --- */
/* --- MES NOTIFICATIONS : CE QUE MOI JE RECOIS ---
   Une ligne par evenement, quatre choix par ligne. Des boutons radio et rien d'autre : cet ecran
   se manoeuvre sans JavaScript, comme tous les autres.

   « display:flex » ET « flex-wrap » : quatre libelles — dont « Notification et courriel » — ne
   tiennent pas sur une ligne d'ecran etroit. Ils passent a la ligne au lieu de deborder la carte. */
.mes-alertes-quoi{display:block; font-size:var(--t-controle); color:var(--encre)}

/* Ce qui s'applique en l'absence de choix. En encre douce : c'est une explication, pas une valeur
   qu'on regle — la confondre avec les boutons ferait chercher comment la changer ici. */
.mes-alertes-defaut{
  display:block; margin-top:2px;
  font-size:var(--t-micro); color:var(--encre-douce); font-weight:400;
}

.mes-alertes-choix{display:flex; flex-wrap:wrap; gap:var(--e2) var(--e4)}

/* La cible cliquable est TOUTE l'etiquette, pas le seul rond de 13 px : un « for » sur le label
   suffirait a le rendre cliquable, mais pas a le faire paraitre cliquable. */
.mes-alertes-option{
  display:inline-flex; align-items:center; gap:6px;
  padding:4px 10px 4px 8px; border-radius:999px;
  border:1px solid var(--bord); background:var(--surface);
  font-size:var(--t-petit); color:var(--encre-soft, var(--encre)); cursor:pointer;
  transition:border-color var(--vite), background var(--vite);
}
.mes-alertes-option:hover{border-color:var(--encre-tenue)}

/* L'option retenue se voit sans lire : le rond coche seul demande de comparer quatre ronds. */
.mes-alertes-option:has(input:checked){
  border-color:var(--accent); background:var(--accent-voile, var(--surface-creuse));
  color:var(--encre); font-weight:500;
}
.mes-alertes-option:focus-within{box-shadow:var(--anneau)}
.mes-alertes-option input{margin:0; accent-color:var(--accent); cursor:pointer}

.fil-alerte{
  display:flex; align-items:center; gap:var(--e4);
  padding:var(--e4); border-radius:var(--rayon-carte);
  background:var(--alerte-voile); border:1px solid rgba(138,58,50,.18);
}
.fil-alerte-icone{
  flex:none; width:38px; height:38px; border-radius:50%;
  display:inline-flex; align-items:center; justify-content:center;
  background:var(--alerte); color:#fff;
}
.fil-alerte-corps{display:flex; flex-direction:column; gap:2px; min-width:0}
.fil-alerte-note{font-size:var(--t-petit); color:var(--encre-douce)}
.fil-alerte .btn{margin-left:auto; flex:none}

/* --- Le separateur de journee --- */
.fil-jour{
  margin:var(--e3) 0 0; font-family:var(--mono); font-size:var(--t-micro);
  text-transform:uppercase; letter-spacing:.08em; color:var(--encre-tenue);
}

/* --- Une carte --- */
/* LA GRILLE NOMME SES COLONNES plutot que de compter : marque, auteur, filet, pastille, corps,
   menu. Une carte qui gagne une colonne demain se relit sans recompter les fractions. */
.fil-carte{
  position:relative; display:grid;
  grid-template-columns:auto 84px 1px auto minmax(0, 1fr) auto;
  gap:var(--e3); align-items:start;
  padding:var(--e3) var(--e4) var(--e3) var(--e3);
  background:var(--surface); border:1px solid var(--bord);
  border-radius:var(--rayon-carte); box-shadow:var(--ombre1);
}

/* LE POINT DE NON-LU EST A GAUCHE, comme l'onglet colore des registres de ce projet : l'etat se
   lit toujours au meme endroit. Il occupe sa colonne meme quand il est invisible — sinon les
   cartes lues et non lues n'auraient pas le meme alignement, et la liste ondulerait. */
.fil-marque{
  width:8px; height:8px; border-radius:50%; margin-top:6px;
  background:transparent;
}
.fil-carte-non-lue .fil-marque{background:var(--accent)}
.fil-carte-non-lue{border-color:var(--bord-net)}

.fil-auteur{
  display:flex; flex-direction:column; align-items:center; gap:1px; text-align:center;
  line-height:1.15;
}
.fil-auteur-nom{font-size:var(--t-petit); font-weight:600; line-height:1.2}
.fil-auteur-role{font-size:var(--t-micro); color:var(--encre-tenue); line-height:1.2}
/* Quand personne n'a agi — le rapprochement iCal — on montre un symbole a la place de la
   vignette. Un rond vide se lirait comme une photo qui n'a pas charge. */
.fil-auteur-machine{
  width:40px; height:40px; border-radius:50%; flex:none;
  display:inline-flex; align-items:center; justify-content:center;
  background:var(--surface-creuse); border:1px solid var(--bord); color:var(--encre-tenue);
}
.fil-separateur{align-self:stretch; width:1px; background:var(--bord)}

/* --- La pastille d'etat --- */
.fil-pastille-etat{
  flex:none; width:36px; height:36px; border-radius:50%;
  display:inline-flex; align-items:center; justify-content:center;
}
/* TROIS TONS, ET ILS REPONDENT A UNE QUESTION TRANCHABLE : ce qui est arrive est-il conforme a ce
   qu'on attendait ? Le domaine decide, la feuille peint — voir EvenementNotification::ton(). */
.pastille-fait{background:var(--accent-voile); color:var(--accent)}
.pastille-contre{background:var(--alerte-voile); color:var(--alerte)}
.pastille-cours{background:var(--attente-voile); color:var(--attente)}

/* --- Le corps de la carte --- */
/* Deux pixels entre les lignes, et non huit. Elles forment une seule phrase en trois temps —
   ce qui s'est passe, qui l'a fait, ou — et non trois blocs distincts. L'interligne du texte
   suffit a les separer. */
.fil-corps{display:flex; flex-direction:column; gap:2px; min-width:0; line-height:1.4}
.fil-titre{
  margin:0; font-size:var(--t-base); font-weight:600;
  display:flex; align-items:baseline; gap:var(--e1); flex-wrap:wrap;
}
/* L'heure exacte est collee au titre — « a quelle heure est-ce arrive » — quand le temps relatif,
   a droite, repond a « est-ce recent ». Deux questions, deux places. */
.fil-exacte{
  font-family:var(--mono); font-size:var(--t-micro); font-weight:400;
  color:var(--encre-tenue);
}
.fil-heure{
  font-family:var(--mono); font-size:var(--t-micro); font-weight:400;
  color:var(--encre-tenue); margin-left:auto;
}
/* LA PHRASE EST LE CONTENU DE LA CARTE, pas une mention secondaire. En gris elle se rangeait
   avec le lieu et l'heure ; c'est pourtant la seule ligne qui dise ce qui s'est passe.

   LA PRESTATION Y EST EN GRAS parce que c'est ce qu'on cherche en parcourant : « lequel de mes
   menages ». Le reste de la phrase n'est que la grammaire qui la porte. */
.fil-detail{margin:0; font-size:var(--t-controle); color:var(--encre)}
.fil-detail strong{font-weight:600}
/* L'evenement brut, quand le code ne le connait plus : lisible mais discret. Il ne s'adresse
   pas a l'utilisateur, il s'adresse a celui qui viendra corriger. */
.fil-brut{font-family:var(--mono); font-size:var(--t-micro); color:var(--encre-tenue)}

/* L'etat d'envoi du courriel. C'est la seule trace visible qu'une alerte est partie — ou ne
   l'est pas — et sans elle « je n'ai rien recu » n'a d'autre reponse qu'une requete SQL. */
.fil-courriel{
  margin:0; display:inline-flex; align-items:center; gap:var(--e1);
  font-size:var(--t-micro); color:var(--encre-tenue);
}
.fil-courriel-echec{color:var(--alerte)}

.fil-lieu{
  margin:0; display:inline-flex; align-items:center; gap:var(--e1);
  font-size:var(--t-petit); color:var(--encre-tenue);
}

/* La citation du compte rendu : ce que la personne a ECRIT, pas ce que le systeme raconte. Le
   fond la detache du reste de la carte pour qu'on ne la lise pas comme une phrase de l'outil. */
.fil-citation{
  margin:var(--e1) 0 0; padding:var(--e2) var(--e3);
  background:var(--accent-voile); border-radius:var(--rayon);
  font-size:var(--t-controle); color:var(--encre); font-style:italic;
}

.fil-pied{display:flex; align-items:center; gap:var(--e3); flex-wrap:wrap; margin-top:var(--e2)}
.fil-vignettes{display:flex; gap:var(--e2)}
.fil-vignette{display:block; line-height:0; border-radius:var(--rayon); overflow:hidden}
.fil-vignette img{
  width:104px; height:74px; object-fit:cover; display:block;
  border:1px solid var(--bord);
  transition:transform var(--vite);
}
.fil-vignette:hover img{transform:scale(1.04)}
.fil-pied .fil-ouvrir{margin-left:auto}

/* --- Le menu par carte : un <details>, aucun script --- */
.fil-menu, .ligne-menu{position:relative}
.fil-menu > summary, .ligne-menu > summary{
  list-style:none; cursor:pointer; padding:var(--e1) var(--e2);
  border-radius:var(--rayon); color:var(--encre-tenue);
  transition:background var(--vite), color var(--vite);
}
.fil-menu > summary::-webkit-details-marker,
.ligne-menu > summary::-webkit-details-marker{display:none}
.fil-menu > summary:hover,
.ligne-menu > summary:hover{background:var(--surface-creuse); color:var(--encre)}
/* Le panneau flotte AU-DESSUS de la carte suivante : sans « position:absolute », l'ouvrir
   pousserait toute la liste vers le bas, et l'on perdrait ce qu'on regardait. */
.fil-menu-corps, .ligne-menu-corps{
  position:absolute; right:0; top:100%; z-index:5; min-width:200px;
  padding:var(--e2); background:var(--surface);
  border:1px solid var(--bord); border-radius:var(--rayon-carte); box-shadow:var(--ombre2);
  display:flex; flex-direction:column; gap:var(--e1); align-items:flex-start;
}

/* --- La colonne de droite --- */
.fil-cote{display:flex; flex-direction:column; gap:var(--e3)}
.fil-cote .carte{padding:var(--e3) var(--e4)}
.fil-cote .sous-titre{margin-bottom:var(--e2); padding-bottom:var(--e2); font-size:var(--t-controle)}

/* Les deux listes de la colonne portent leur propre empilement plutot que de s'en remettre au
   flux : sans cela, l'ecart entre deux filtres vient des marges de <a>, qui n'en ont pas, et
   la liste se colle. Ce sont deux classes qui font quelque chose — une classe posee dans le
   balisage et absente de la feuille est exactement ce que ce projet traque. */
.fil-resume{display:flex; flex-direction:column}
.fil-filtres{display:flex; flex-direction:column; gap:0}

.fil-resume-ligne{
  display:flex; align-items:center; gap:var(--e3);
  padding:var(--e1) 0; text-decoration:none; color:var(--encre);
  border-bottom:1px solid var(--bord);
}
.fil-resume-ligne:last-child{border-bottom:0}
.fil-resume-ligne:hover{text-decoration:none; color:var(--accent)}
.fil-resume-nombre{
  font-size:var(--t-moyen); font-weight:700; min-width:28px; text-align:right;
  font-variant-numeric:tabular-nums;
}
.fil-resume-mot{font-size:var(--t-petit); color:var(--encre-douce)}
.fil-resume-point{
  width:8px; height:8px; border-radius:50%; background:var(--accent); margin-left:auto;
}

.fil-filtre{
  display:flex; align-items:center; gap:var(--e3);
  padding:var(--e1) var(--e3); border-radius:var(--rayon);
  font-size:var(--t-petit); color:var(--encre-douce); text-decoration:none;
}
.fil-filtre:hover{background:var(--surface-creuse); color:var(--encre); text-decoration:none}
/* Le filtre courant porte un FOND, la ou l'onglet portait un liseret : ce sont deux presentations
   du meme etat, et les distinguer evite de croire qu'on a coche deux choses. */
.fil-filtre-courant{background:var(--accent-voile); color:var(--accent); font-weight:600}
.fil-filtre-nombre{
  margin-left:auto; font-family:var(--mono); font-size:var(--t-micro);
  color:var(--encre-tenue); font-variant-numeric:tabular-nums;
}

/* --- La carte d'aide --- */
/* Le symbole a gauche, les deux lignes a sa droite : c'est la forme d'une carte de contact,
   pas celle d'une liste. Elle n'a donc pas d'intertitre souligne — le filet y couperait trois
   elements en deux moities dont la seconde n'est pas une suite. */
.fil-aide-tete{display:flex; align-items:center; gap:var(--e3)}
/* UN CARRE ARRONDI, ET NON UN ROND. Le rond est la forme des PERSONNES dans cette
   application — les vignettes de profil le sont partout. Un symbole de fonction dans un rond
   se lit comme un avatar, et l'oeil cherche un visage. Le carre arrondi dit « un objet, une
   categorie », ce qu'un telephone est ici. C'est aussi la forme des pastilles de la carte
   « Vue d'ensemble » sur la maquette. */
.fil-aide-icone{
  flex:none; width:42px; height:42px; border-radius:14px;
  display:inline-flex; align-items:center; justify-content:center;
  background:var(--accent-voile); color:var(--accent);
}
.fil-aide-mots{display:flex; flex-direction:column; line-height:1.3; min-width:0}
.fil-aide-mots span{font-size:var(--t-petit); color:var(--encre-douce)}

/* LE BOUTON EST VERT PALE, ET NON BORDE DE GRIS. Il mene a la messagerie : c'est l'action de
   la carte, pas une sortie de secours. Un bouton neutre le rangeait avec « Annuler ».

   IL N'EST PAS PLEIN POUR AUTANT : la messagerie n'existe pas encore, et l'onglet le dit
   lui-meme. Un bouton primaire promettrait plus que ce qui attend derriere. */
/* LE BOUTON GARDE SA BORDURE. Un aplat vert sans contour, sur une carte blanche, se lit comme
   une zone de la carte plutot que comme un bouton — la maquette le borde, et c'est ce qui le
   fait paraitre cliquable. Le fond reste vert pale : c'est l'action de la carte, pas une
   sortie de secours. */
.fil-aide-bouton{
  width:100%; justify-content:center; margin-top:var(--e3);
  background:var(--accent-voile); color:var(--accent);
  border:1px solid var(--bord-net);
}
.fil-aide-bouton:hover{background:#cfe2e0; color:var(--accent-fonce); border-color:var(--accent)}


/* La marge laterale se reduit sur un ecran etroit : 48 px de chaque cote mangeraient un quart
   d'un telephone. Le jeton est redefini, donc « .page » ET « .pleine-largeur » suivent — c'est
   tout l'interet de n'avoir qu'une source. */
@media (max-width:640px){
  :root{--marge-page:16px}
}

/* ==================================================================================================
   LA LISTE DES INTERVENTIONS
   ==================================================================================================

   Trois etages : l'en-tete, les six cartes d'etat, le tableau. Puis la pagination.

   LES CINQ TONS SONT DECLARES UNE FOIS ET PORTES PAR TROIS OBJETS — la pastille de la premiere
   colonne, l'etiquette de la colonne « Statut », le carre d'icone d'une carte. Un ton pose un fond
   et une encre, jamais une taille ni une forme : c'est ce qui permet au meme mot de couleur de
   servir a un rond de 24 px et a un carre de 32.

   AUCUNE COULEUR NOUVELLE. « A faire » reprend --afaire-voile et « Terminee » --faite-voile, les
   deux fonds d'etat du planning : le meme etat porte donc la meme teinte dans la grille et dans la
   liste. --------------------------------------------------------------------------------------- */
.ton-neutre {background:var(--surface-creuse); color:var(--encre-douce)}
.ton-attente{background:var(--attente-voile); color:var(--attente)}
.ton-accent {background:var(--afaire-voile);  color:var(--accent-fonce)}
.ton-fait   {background:var(--faite-voile);   color:var(--encre-douce)}
.ton-contre {background:var(--alerte-voile);  color:var(--alerte)}

/* --- L'en-tete ---
   .entete aligne ses enfants sur la ligne de base et les met cote a cote ; ici le titre et son
   compte forment une rangee, et le sous-titre passe dessous. On repasse donc en colonne. */
/* LA RANGEE DE TETE : le titre a gauche, les filtres a droite.
   Ils etaient l'un sous l'autre, soit deux rangees pour ce qui tient sur une — la barre pleine
   largeur poussait cartes et tableau d'une quarantaine de pixels pour occuper son tiers gauche.

   « flex-end » ALIGNE LES DEUX BAS, et non les deux hauts : a droite il n'y a qu'une rangee de
   controles, a gauche un titre et son sous-titre. Cales en haut, la barre flotterait au-dessus du
   sous-titre ; calee sur le bas, elle s'assied sur la meme ligne que lui. */
.liste-tete{
  display:flex; align-items:flex-end; justify-content:space-between;
  gap:var(--e4); flex-wrap:wrap; margin-bottom:var(--e5);
}
/* La marge du bas vit sur la rangee : les deux moities la porteraient en double. */
.liste-entete{flex-direction:column; align-items:flex-start; gap:var(--e2); margin-bottom:0}
.liste-titre{display:flex; align-items:baseline; gap:var(--e3); flex-wrap:wrap}

/* --- La barre de filtres, moitie droite de la rangee ---
   « flex:0 1 auto » EST LA REGLE QUI COMPTE : sans elle la barre s'etirerait sur toute la place
   laissee par le titre, et sa recherche irait chercher les 420 px de son plafond meme quand la
   rangee est large. Elle se cale sur son contenu et reste a droite.

   La marge du bas de « .barre-filtres » disparait ici : c'est la rangee qui l'assure. */
.barre-a-droite{flex:0 1 auto; margin-bottom:0; align-items:flex-end}
/* Les jetons suivent la barre a droite, sinon ils s'accrochent a son bord gauche et paraissent
   flotter loin des controles qu'ils resument. */
.barre-a-droite .bf-jetons{justify-content:flex-end}

/* LES TROIS CONTROLES RESTENT SUR UNE LIGNE, ET C'EST UN CORRECTIF.
   « .bf-ligne » est en flex-wrap:wrap — ce qui est juste pour une barre pleine largeur, ou le
   passage a la ligne est la seule reponse quand les controles ne tiennent plus. Calee a droite du
   titre, la barre recoit une largeur bien plus etroite : la recherche prenait ses 420 px de plafond
   et le bouton loupe tombait seul a la ligne suivante, sous le declencheur.

   nowrap FORCE LE PARTAGE au lieu du renvoi : la recherche se comprime jusqu'a ses 190 px utiles,
   le declencheur et la loupe gardent leur taille. Une base de 320 px lui evite d'y arriver dans le
   cas courant. */
.barre-a-droite .bf-ligne{flex-wrap:nowrap}
.barre-a-droite .bf-recherche{flex:0 1 320px}

/* LE PANNEAU S'OUVRE VERS LA GAUCHE, SOUS SON DECLENCHEUR.
   Il s'ancrait a gauche — bon reglage pour une barre qui commence a gauche de la page. Le
   declencheur etant maintenant a quelques pixels du bord droit, ses 560 px partaient hors de
   l'ecran : on voyait le panneau coupe, et ses champs inaccessibles.

   C'est le meme reglage que la barre etroite appliquait deja en dessous de 640 px, pour la meme
   raison. Il ne dependait pas de la largeur de l'ecran mais de la POSITION du declencheur. */
.barre-a-droite .bf-corps{left:auto; right:0}

/* En dessous de 900 px les deux moities s'empilent : cote a cote, le titre et une barre a trois
   controles se disputent la meme largeur et la recherche tombe sous ses 190 px utiles. La barre
   redevient pleine largeur, donc elle retrouve le renvoi a la ligne et l'ancrage a gauche. */
@media (max-width:900px){
  .liste-tete{flex-direction:column; align-items:stretch}
  .barre-a-droite{flex:1 1 auto}
  .barre-a-droite .bf-jetons{justify-content:flex-start}
  .barre-a-droite .bf-ligne{flex-wrap:wrap}
  .barre-a-droite .bf-recherche{flex:1 1 260px}
}

/* Le compte du FILTRE, pas celui de la page. En pastille et non en petites capitales grises
   (« .entete .compte ») : il change quand on filtre, et c'est le nombre qu'on vient lire. */
.liste-badge{
  font-family:var(--mono); font-size:var(--t-micro); font-variant-numeric:tabular-nums;
  color:var(--accent-fonce); background:var(--accent-voile);
  padding:3px var(--e2); border-radius:999px; white-space:nowrap;
  text-transform:uppercase; letter-spacing:.06em;
}
.liste-sous-titre{margin:0; font-size:var(--t-petit); color:var(--encre-douce)}

/* --- Les six cartes d'etat ---
   Six colonnes egales. En dessous de 1200 px elles passent a trois, puis a deux : ecrasees a
   six, le nombre et son unite se chevauchaient. */
.cartes-etat{
  display:grid; grid-template-columns:repeat(6, 1fr); gap:var(--e3);
  margin-bottom:var(--e4);
}

/* La carte est un LIEN entier, pas un bloc avec un lien dedans : toute sa surface se clique, ce
   qui est le seul comportement qu'une carte de filtre puisse avoir sans surprendre. */
.carte-etat{
  display:flex; align-items:center; gap:var(--e3);
  padding:var(--e3); background:var(--surface);
  border:1px solid var(--bord); border-radius:var(--rayon-carte);
  color:inherit; text-decoration:none;
  transition:border-color var(--vite), box-shadow var(--vite);
}
.carte-etat:hover{border-color:var(--bord-net); box-shadow:var(--ombre1)}
.carte-etat:focus-visible{outline:2px solid var(--accent); outline-offset:2px}

/* LA CARTE COURANTE SE MARQUE PAR SON CADRE, ET NON PAR SON FOND : un fond teinte entrerait en
   concurrence avec le carre d'icone, qui porte deja le ton de l'etat. L'ombre interieure epaissit
   la bordure sans decaler d'un pixel la mise en page — ce qu'un border-width:2px ferait. */
.carte-etat-courante{
  border-color:var(--accent);
  box-shadow:inset 0 0 0 1px var(--accent), var(--ombre1);
}

.carte-etat-icone{
  display:inline-flex; align-items:center; justify-content:center;
  width:34px; height:34px; flex:none; border-radius:var(--rayon);
}
.carte-etat-icone .i{width:18px; height:18px}

.carte-etat-mots{display:flex; flex-direction:column; min-width:0; gap:1px}
.carte-etat-mot{
  font-size:var(--t-micro); color:var(--encre-douce);
  text-transform:uppercase; letter-spacing:.06em; font-weight:600;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
/* --t-moyen ET NON --t-titre : l'echelle reserve 26 px au titre de page, une fois par ecran. Six
   nombres a cette taille auraient fait six titres, et le vrai n'en serait plus un. */
.carte-etat-nombre{
  font-size:var(--t-moyen); font-weight:600; line-height:1.1;
  font-variant-numeric:tabular-nums; color:var(--encre);
}
.carte-etat-unite{font-size:var(--t-micro); color:var(--encre-tenue)}

/* --- La premiere colonne : la pastille d'etat, puis le client --- */
.ligne-intervention{display:flex; align-items:center; gap:var(--e2)}
/* min-width:0 EST CE QUI FAIT MARCHER « .cellule-tronquee » : sans lui, un element flex refuse de
   descendre sous la largeur de son contenu, l'ellipse ne se declenche jamais et c'est la colonne
   qui s'elargit. */
.ligne-intervention-mots{display:flex; flex-direction:column; min-width:0}
/* --- Le nom et sa precision, serres comme dans le bandeau ---
   ILS HERITAIENT DE L'INTERLIGNE DU CORPS DE TEXTE, soit 1.5 : sur deux lignes de 12 px cela fait
   dix pixels d'air entre le nom et le role, et les deux cessent de se lire comme UN bloc. Le
   bandeau de la page les serre a 1.25 avec un pixel d'ecart depuis toujours — c'est la meme
   information, elle doit avoir la meme forme.

   LE « margin-top » DE « .cellule-sous » EST REPRIS A ZERO ICI, sans quoi il s'ajouterait au gap
   et l'on aurait resserre l'un pour rouvrir l'autre. Il reste pour les autres colonnes — l'heure
   sous la date, le compte de prestations — ou la sous-ligne est un detail et non une identite. */
.ligne-intervention-mots,
.ligne-intervenant-mots{line-height:1.25; gap:1px}
.ligne-intervention-mots .cellule-sous,
.ligne-intervenant-mots .cellule-sous{margin-top:0; font-size:var(--t-micro)}

.pastille-etat{
  display:inline-flex; align-items:center; justify-content:center;
  width:26px; height:26px; flex:none; border-radius:50%;
}
.pastille-etat .i{width:14px; height:14px}

/* --- Le logement et sa vignette --- */
.ligne-bien{display:flex; align-items:center; gap:var(--e2)}
.ligne-bien-mots{display:flex; flex-direction:column; min-width:0}
.ligne-bien-photo{
  width:38px; height:38px; flex:none; border-radius:var(--rayon);
  object-fit:cover; background:var(--surface-creuse); border:1px solid var(--bord);
}
/* LE REPLI N'EST PAS UN CADRE VIDE. Un logement sans photo garde sa place et montre un symbole de
   maison : un rectangle vide se lirait comme une image qui n'a pas charge, et rien du tout ferait
   sauter l'alignement d'une ligne a l'autre. */
.ligne-bien-vide{
  display:inline-flex; align-items:center; justify-content:center; color:var(--encre-tenue);
}
.ligne-bien-vide .i{width:18px; height:18px}

/* --- L'intervenant --- */
.ligne-intervenant{display:flex; align-items:center; gap:var(--e2)}
.ligne-intervenant-mots{display:flex; flex-direction:column; min-width:0}
/* LE POINTILLE DIT « PLACE A POURVOIR ». Le meme rond en trait plein se lirait comme un compte
   sans photo — or il n'y a pas de compte du tout : personne n'est assigne. */
.ligne-intervenant-vide{
  display:inline-flex; align-items:center; justify-content:center;
  width:28px; height:28px; flex:none; border-radius:50%;
  border:1px dashed var(--bord-net); color:var(--encre-tenue);
  background:var(--surface-creuse);
}
.ligne-intervenant-vide .i{width:15px; height:15px}

/* --- La colonne « Statut » ---
   L'etat est deja dit par la pastille de gauche. Ici il porte le MOT : on parcourt avec la
   pastille, on s'arrete avec l'etiquette. */
.etiquette-etat{
  display:inline-flex; align-items:center; white-space:nowrap;
  font-size:var(--t-micro); font-weight:600;
  text-transform:uppercase; letter-spacing:.05em;
  padding:3px var(--e2); border-radius:999px;
}

/* --- Les actions de ligne --- */
.ligne-actions{display:flex; align-items:center; justify-content:flex-end; gap:var(--e1)}
.ligne-actions .btn{white-space:nowrap}

/* LE MENU DEBORDE DU CONTENEUR QUI DEFILE, ET IL FAUT L'Y AUTORISER.
   « .tableau-defilant » est en overflow-x:auto, ce qui rend AUSSI l'axe vertical scrollable : le
   panneau flottant d'une ligne du bas s'y ferait couper. Ouvrir un menu leve donc le debordement.
   LE PRIX EST CONNU : sur un ecran etroit, ou le tableau defile reellement, la position
   horizontale revient a zero a l'ouverture. Au-dessus de 1024 px « .pleine-largeur » donne jusqu'a
   1560 px, le tableau tient, et rien ne defile — donc rien ne saute. */
.tableau-defilant:has(.ligne-menu[open]){overflow:visible}

/* --- La pagination ---
   Le compte a gauche, les pages a droite : on lit d'abord combien il y en a, puis ou l'on est. */
.pagination{
  display:flex; align-items:center; justify-content:space-between;
  gap:var(--e4); flex-wrap:wrap; margin-top:var(--e4);
}
.pagination-compte{
  font-family:var(--mono); font-size:var(--t-micro); color:var(--encre-douce);
  text-transform:uppercase; letter-spacing:.06em; font-variant-numeric:tabular-nums;
}
.pagination-pages{display:flex; align-items:center; gap:var(--e1)}

.pagination-page, .pagination-fleche{
  display:inline-flex; align-items:center; justify-content:center;
  min-width:32px; height:32px; padding:0 var(--e1);
  border:1px solid var(--bord); border-radius:var(--rayon);
  background:var(--surface); color:var(--encre-douce);
  font-size:var(--t-controle); font-variant-numeric:tabular-nums;
  text-decoration:none;
  transition:border-color var(--vite), background var(--vite), color var(--vite);
}
a.pagination-page:hover, a.pagination-fleche:hover{
  border-color:var(--bord-net); background:var(--surface-creuse); color:var(--encre);
}
.pagination-page:focus-visible, .pagination-fleche:focus-visible{
  outline:2px solid var(--accent); outline-offset:2px;
}
.pagination-courante{
  border-color:var(--accent); background:var(--accent-voile);
  color:var(--accent-fonce); font-weight:600;
}
/* LA FLECHE INERTE GARDE SA PLACE AU LIEU DE DISPARAITRE. Un bouton qui s'efface fait glisser
   toute la rangee d'un cran : on clique « suivant », les numeros se decalent, et le clic d'apres
   tombe ailleurs. */
.pagination-inerte{opacity:.4; background:var(--surface-creuse)}
.pagination-trou{
  padding:0 var(--e1); color:var(--encre-tenue); font-size:var(--t-controle);
}

/* --- Les seuils ---
   1200 px : six cartes cessent de tenir sans ecraser le nombre contre son unite.
   640 px : deux cartes, et la pagination s'empile pour ne pas serrer le compte contre les pages. */
@media (max-width:1200px){
  .cartes-etat{grid-template-columns:repeat(3, 1fr)}
}
@media (max-width:640px){
  .cartes-etat{grid-template-columns:repeat(2, 1fr)}
  .pagination{flex-direction:column; align-items:flex-start; gap:var(--e2)}
}
