/* =========================================================================
   SOCLE COMMUN — direction artistique « Bleu et blanc » (LENSA IMMO)
   Blanc et bleus de marque. Motifs dessinés en CSS, zéro image.
   Aucune ressource externe, aucune police distante.
   Mobile first : tout est écrit pour 375 px, puis élargi.

   Refonte du 18 septembre 2026 — consigne de la cliente, mot pour mot :
   « Nous sommes sur du bleu et blanc. Que les couleurs de l'application
   ne soient plus en orange ou doré. Il faut que tout concorde avec le
   logo. » Le logo (public/assets/logo-lensa-immo.svg) porte trois bleus
   (--bleu-marine #2B3190, --bleu-marque #3E7CC0, --bleu-cadre #6FA8DC),
   plus noir et blanc — rien d'orange, rien de doré.

   CE QUI CHANGE, ET CE QUI NE CHANGE PAS DE NOM.
   Ce fichier reprend la méthode déjà utilisée le 14/09/2026 pour --indigo :
   « le nom du jeton ne change pas, sa valeur oui ». Tous les jetons nommés
   d'après l'ancienne palette crème/terre cuite/ocre GARDENT leur nom (pour
   qu'aucun gabarit — agence, propriétaire, locataire, démarcheur, site
   public — n'ait à être retouché ; aucun n'écrit une couleur en dur, tous
   passent par ces variables) mais REÇOIVENT une valeur bleue ou neutre :
     · --creme / --creme-2 / --creme-3 / --champ-fond : blanc et blanc
       bleuté très pâle (fonds), au lieu du crème chaud.
     · --encre / --encre-2 / --encre-clair : encre bleu-nuit quasi noire,
       au lieu du brun chaud.
     · --terre (action principale, partout où elle n'est pas déjà --vert) :
       un bleu « azur » soutenu, au lieu de la terre cuite.
     · --terre-fonce (chrome locataire) et --brun-fonce (chrome démarcheur) :
       recolorés hors de la famille orange/brun — voir plus bas.
     · --ocre (accent réservé au chrome sombre) : un bleu ciel clair, au
       lieu du doré — la règle d'usage (jamais sur fond clair, texte/icône
       uniquement sur chrome sombre) ne change pas, seule la teinte change.
     · --filet / --filet-fort / --bord : gris-bleu, au lieu du beige.
   --vert, --vert-fonce, --rouge, --ambre, --violet ne bougent PAS : ce ne
   sont pas des couleurs orange/dorées, et section 8 du cahier des charges
   (statuts d'argent — impayé, encaissé, en attente) leur donne un sens
   qui doit rester lisible indépendamment de la marque. Tous les rapports
   de contraste ci-dessous ont été RECALCULÉS (luminance relative WCAG,
   formule (L1+0,05)/(L2+0,05)) sur les nouveaux fonds, pas recopiés de
   l'ancienne palette — un fond qui change invalide tous les calculs faits
   sur l'ancien.

   POURQUOI QUATRE CHROMES RESTENT DIFFÉRENTS, MALGRÉ « BLEU ET BLANC ».
   La demande de la cliente porte sur l'IMAGE GÉNÉRALE du logiciel : plus
   d'orange, plus de doré, tout doit rappeler le logo. Elle ne dit pas
   « une seule couleur pour tout » — et la raison pour laquelle les quatre
   espaces (agence, propriétaire, locataire, démarcheur) portaient déjà
   quatre teintes DIFFÉRENTES, pas quatre nuances d'une même teinte, est
   une raison de sécurité posée avant cette refonte (voir plus bas,
   [data-espace]) : qu'une gestionnaire ne puisse jamais croire, d'un
   simple coup d'œil, qu'elle regarde l'écran d'un propriétaire. Passer
   les quatre chromes en quatre bleus aurait satisfait la lettre de la
   demande et détruit cette sécurité — deux bleus voisins se confondent
   plus vite que deux teintes franchement différentes, y compris pour qui
   distingue mal les couleurs. Le compromis retenu, à confirmer avec la
   cliente si elle souhaite trancher plus strictement : le bleu de marque
   reste la couleur DOMINANTE et par défaut (fond, action, agence, site
   public), et les trois autres espaces gardent des teintes FROIDES mais
   distinctes (vert, sarcelle, ardoise) — jamais de retour à l'orange ou
   au doré, mais pas un unique bleu partout non plus.

   Ordre du fichier
     1. Jetons          2. Remise à zéro     3. Typographie
     4. Mise en page    5. Boutons           6. Formulaires
     7. Aide « ? »      8. Pastilles d'état  9. Indicateurs
    10. Tableaux        11. Cartes           12. Onglets & filtres
    13. États vides     14. Divers

   Règles de couleur à ne pas enfreindre :
     · --ocre ne s'emploie QUE sur un fond sombre (chrome). Jamais sur crème.
     · Le bord d'un contrôle de saisie est --bord (≥3:1), jamais --filet.
     · Le prix / montant en vedette est --vert. Une seule couleur saturée
       par bloc d'information.
     · Un état (impayé/encaissé/attente) ne se lit JAMAIS à la seule
       couleur : le libellé et/ou le symbole (✓ ✗ ○ ●) restent le repère
       principal — inchangé par cette refonte, voir section 8 « Pastilles
       d'état ».

   ARBITRAGE DENSITÉ (douceur des surfaces vs. back-office dense) :
     · Les CONTENEURS (.bloc, .carte, .indicateur, .filtres, .etat-vide)
       reçoivent le traitement doux : bordure fine (1px), ombre diffuse,
       angles généreux. Un conteneur ne porte pas d'information à la ligne
       près — l'air autour de lui ne coûte rien à la lecture.
     · Les TABLEAUX (.tableau, y compris les lignes empilées sur téléphone)
       gardent des séparateurs nets et aucune ombre : un gestionnaire qui
       scanne 40 loyers a besoin de repères francs, pas d'une ambiance.
     · La hauteur des champs de saisie augmente de 48 à 52px partout : un
       coût réel sur les formulaires à dix champs (bail, dépense), accepté
       car c'est le point que la cliente a désigné le plus précisément.
   ========================================================================= */

/* ---------------------------------------------------------------- 1. JETONS */

/* ===========================================================================
   POLICE — Inter, hébergée chez nous
   ---------------------------------------------------------------------------
   Demandée par la cliente le 18 septembre 2026 : « essaie de changer la
   police », dans la direction qu'elle a fixée — soft, épuré, classe,
   futuriste, comme les applications des USA.

   Inter est précisément la police de ces applications-là. Elle est dessinée
   pour les écrans : hauteur d'x généreuse, chiffres lisibles, et surtout un
   « 1 », un « l » et un « I » qu'on ne confond pas — ce qui compte quand on
   lit des montants et des références de biens toute la journée.

   ⚠️ TROIS PRÉCAUTIONS, et elles comptent plus que le choix lui-même :

   1. HÉBERGÉE CHEZ NOUS, pas chez un tiers. Une police servie par un
      fournisseur étranger ajoute un aller-retour réseau depuis Abidjan, et
      fait dépendre l'affichage d'un service qu'on ne contrôle pas.

   2. LE LATIN SEUL — 47 Ko. Les variantes cyrillique, grecque et
      vietnamienne pèsent autant et ne servent à personne ici. Le sous-ensemble
      latin couvre é, è, à, ç, ô, û : tout le français.

   3. `font-display: swap` — le texte s'affiche IMMÉDIATEMENT dans la police
      du système, puis bascule. Une page qui attend sa police est une page
      blanche, et sur un forfait limité elle le reste longtemps. La lisibilité
      ne dépend jamais du téléchargement.

   La pile de repli reste complète : si le fichier manque, rien ne casse.
   =========================================================================== */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url('../polices/inter-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
                 U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F,
                 U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF,
                 U+FFFD;
}


:root{
  /* Fonds — blanc pur (surfaces : .bloc, .carte) et blanc bleuté très pâle
     (fond de page), pour garder la même technique de calage qu'avant (le
     fond de page légèrement distinct fait « flotter » les cartes) sans
     aucune trace de crème. Recalculé, pas recopié : voir chaque ratio. */
  --creme:      #F5F8FC;   /* fond de PAGE — blanc à peine teinté de bleu */
  --creme-2:    #E9EFF8;   /* panneau secondaire (filtres, .creme-2)      */
  --creme-3:    #DCE6F2;   /* fond désactivé / tint le plus soutenu       */
  --blanc:      #FFFFFF;   /* surfaces : cartes, .bloc                    */
  --champ-fond: #F5F8FC;   /* = --creme : fond « presque imperceptible » des champs, 16,30:1 avec --encre */

  /* Encres — bleu-nuit quasi noir, au lieu du brun chaud : reste dans la
     famille du logo (le noir du monogramme, rendu ici légèrement bleuté
     pour ne jamais paraître un simple gris neutre importé d'ailleurs). */
  --encre:      #101A2E;   /* 16,30:1 sur crème · 17,37:1 sur blanc */
  --encre-2:    #46536E;   /*  7,24:1 sur crème ·  7,71:1 sur blanc */
  --encre-clair:#C7D3E8;   /* texte secondaire sur chrome sombre, ≥ 5,09:1 (le plus bas des quatre chromes) */

  /* Couleurs de marque LENSA IMMO (docs/design/charte-lensa-immo.md §3).
     ⭐ CORRIGÉES le 21/09/2026, sur constat de la cliente : « ce ne sont pas
     les mêmes bleus ». Elle avait raison, et l'ancien commentaire le disait
     lui-même — « relevé VISUEL, à confirmer sur les fichiers d'origine ».
     Les valeurs précédentes étaient #2B3190 / #3E7CC0 / #6FA8DC.

     ⛔ La faute la plus voyante : --bleu-marine valait #2B3190, un indigo
     VIOLACÉ qui n'apparaît NULLE PART sur le kakémono de l'agence. C'est ce
     qui faisait que le bandeau des métiers ne ressemblait pas à sa charte.

     MÉTHODE — relevé au pixel sur le kakémono transmis le 21/09/2026
     (`outils/` n'est pas concerné : échantillonnage ponctuel en PHP/GD) :
       · bandeau bleu du kakémono ...... #366FB2  (aplat, 8 600 px : CERTAIN)
       · carré du « i » du logo ......... #376FAE  (aplat : CERTAIN)
       · barre du sol du logo ........... #406DA7  (aplat : CERTAIN)
       · liseré clair du bandeau ........ #68A9D3  (aplat : CERTAIN)
       · filet du double encadrement .... #7FA5BE  (aplat : CERTAIN)
       · diagonale sombre du toit ....... ~#383858 (⚠️ APPROXIMATIF)

     ⚠️ POURQUOI LA DIAGONALE SOMBRE RESTE APPROXIMATIVE, et il faut le dire :
     c'est un TRAIT FIN dans un JPEG compressé. Chaque pixel y est mélangé
     avec le blanc du fond, donc mesuré plus clair que la couleur réelle. La
     valeur retenue ci-dessous est légèrement assombrie pour compenser.
     👉 À REMPLACER dès que la cliente fournit le fichier d'origine du logo
     (vectoriel de préférence, ou PNG non compressé). C'est la SEULE des six
     valeurs qui ne soit pas mesurée sur un aplat. */
  /* ⭐ MESURÉES SUR LA PLAQUETTE COMMERCIALE — 27/09/2026.
     La directrice a transmis « immo docs.pdf », son catalogue de présentation
     des services : 25 pages, le logo en qualité d'impression. C'est le
     fichier d'origine que le commentaire ci-dessus réclamait depuis le
     18/09 pour remplacer la diagonale « APPROXIMATIVE ».

     Relevé sur la couverture rendue à 2600 px de large, en comptant les
     pixels d'aplat et en écartant blanc, noir et gris :
       · diagonale du toit ....... #2A3371  (210 px) — était #2F3A5C, estimé
       · bleu moyen du logo ...... #286BA5  (218 px) — était #366FB2, estimé
       · filet clair du cadre .... #B6CDE0  ( 34 px) — était #7FA5BE, estimé
     Et, sur l'ensemble des pages, les deux bleus de mise en page :
       · fond dominant ........... #25498D  (13,4 % des pixels colorés)
       · titres et encart slogan . #3D6BA6  ( 6,6 %)

     ⚠️ LE CONTRASTE S'AMÉLIORE, il ne se dégrade pas — vérifié par calcul
     avant remplacement :
       #2A3371 sur blanc : 11,60:1 (au lieu de 11,17:1)
       #286BA5 sur blanc :  5,62:1 (au lieu de 5,16:1)
     Le bleu moyen repasse ainsi au-dessus du seuil AA de 4,5:1, qu'il
     frôlait : il cesse d'être interdit au texte courant. */
  /* ⭐ VALEUR DE LA CHARTE — tranchée par la directrice le 30/09/2026 :
     « utilise la couleur de la charte ».

     Elle remplace #2A3371, relevé le 27/09 sur le CATALOGUE de présentation
     des services. Les deux documents de l'agence divergeaient : le catalogue
     donnait #2A3371, la plaquette « Supports de communication » — la charte
     graphique proprement dite — donne #1F3059. Vingt-sept points d'écart sur
     441 : invisible sur un écran, visible sur une quittance posée à côté
     d'une carte de visite imprimée. C'est la CHARTE qui fait foi.

     ⚠️ CE JETON PORTE AUSSI --indigo (chrome de l'espace agence) : le
     changement touche l'application entière, pas seulement le site. Tous les
     rapports ci-dessous ont été RECALCULÉS le 30/09/2026 sur la nouvelle
     valeur, jamais recopiés — la teinte est plus SOMBRE, donc chaque couple
     s'améliore, mais ça se vérifie, ça ne se suppose pas. */
  --bleu-marine: #1F3059;  /* 12,92:1 sur blanc · 12,13:1 sur le fond de page ·
                              blanc dessus 12,92:1 · accent --ocre dessus 7,64:1 — MESURÉS */
  --bleu-marque: #286BA5;  /* bandeau des métiers, barre du sol, carré du « i ».
                               RÉSERVÉ aux fonds, gros titres gras (≥18px) et
                               bordures — 5,62:1 sur blanc depuis la mesure du
                               27/09/2026 : au-dessus du seuil AA de 4,5:1. */
  --bleu-cadre:  #B6CDE0;  /* filets du double encadrement — décoratif, logo : JAMAIS du texte. MESURÉ */
  --bleu-lisere:  #68A9D3;  /* liseré clair du bandeau, et carte décalée derrière les
                               insignes des métiers — décoratif uniquement. */
  /* Les deux bleus de MISE EN PAGE de la plaquette — ils ne sont pas dans le
     logo, ils l'entourent. `--bleu-fond` couvre les grandes surfaces (la page
     de la mascotte, les pleines pages de section) ; `--bleu-titre` porte le
     nom LENSA IMMO en couverture et l'encart du slogan. Les reprendre ici,
     c'est ce qui fait que le site et la plaquette se ressemblent enfin. */
  /* ⭐ L'ORANGE DE LA PLAQUETTE — réintroduit le 27/09/2026, à sa demande :
     « il a mis de l'orange, il faut qu'on apporte des couleurs comme un peu
     ce qu'il a fait ».

     ⚠️ CETTE COULEUR AVAIT ÉTÉ EXCLUE PAR ELLE — « plus d'orange » —, et
     toute la palette avait été refaite pour l'en sortir (voir --terre plus
     bas). Elle revient donc sur cette consigne, en connaissance de cause, et
     parce que son propre graphiste l'emploie. C'est écrit ici pour que
     personne ne croie plus tard à un oubli.

     ⚠️ ET ELLE REVIENT AVEC SON RÔLE, PAS SEULE. Relevé page par page sur le
     catalogue, l'orange n'y est JAMAIS une couleur d'ambiance : il ne fait ni
     les titres, ni les fonds de page, ni les boutons. Il n'a que deux
     emplois, toujours les mêmes :
       1. le panneau de CITATION où se tient la mascotte ;
       2. les NUMÉROS D'ÉTAPE, en alternance avec le bleu (01 bleu, 02 orange).
     Employé autrement, il cesserait de ressembler au catalogue — c'est le
     rôle qui fait la ressemblance, pas la teinte.

     ⚠️ DU TEXTE BLEU MARINE DESSUS, JAMAIS DU BLANC.
     Rapports RECALCULÉS le 30/09/2026 sur l'orange de la charte (#F68712),
     pas recopiés de ceux du catalogue — un fond qui change invalide tout
     calcul fait sur l'ancien :
        #25375F sur #F68712 : 4,69:1  ✓ lisible
        blanc   sur #F68712 : 2,50:1  ✗ illisible
     Son graphiste a fait le bon choix ; il faut le tenir. */
  /* ⭐ VALEUR DE LA CHARTE elle aussi (30/09/2026), en remplacement de
     #EB8B2D relevé sur le catalogue. Même arbitrage que --bleu-marine. */
  --orange:      #F68712;  /* citation de la mascotte, numéros d'étape pairs, filets.
                              ⛔ JAMAIS DE BLANC DESSUS : 2,50:1, illisible. Le seul texte
                              admis reste --orange-texte, MESURÉ à 4,69:1 sur cette teinte. */
  --orange-texte:#25375F;  /* le SEUL texte admis sur l'orange */
  --bleu-fond:   #25498D;  /* 8,69:1 avec du blanc dessus */
  --bleu-titre:  #3D6BA6;  /* 5,45:1 avec du blanc dessus */
  --noir:        #000000;  /* monogramme, nom de marque */

  /* --terre : c'était la terre cuite, l'action principale de l'ancienne
     palette « Marché ». La cliente l'a nommément exclue (« plus d'orange »).
     Devient un bleu « azur » soutenu — assez différent du --bleu-marine du
     chrome agence pour qu'un bouton reste identifiable par sa forme ET sa
     teinte, jamais confondu avec l'en-tête, tout en restant dans la même
     famille de bleu que le logo. Nom du jeton inchangé : aucun gabarit ne
     référence une couleur en dur, tous lisent var(--terre). */
  --terre:      #1D4E89;   /*  7,88:1 sur crème · 8,39:1 sur blanc — action principale */
  /* --terre-fonce : chrome de l'espace locataire. Restait dans la famille
     terre cuite (#7F2A0D) — recoloré en sarcelle profond : une teinte
     froide, bleu-vert, nettement différente du bleu-marine (agence) et du
     vert profond (propriétaire), pour que les trois chromes distincts déjà
     en place avant cette refonte (voir [data-espace] plus bas) restent
     aussi faciles à distinguer qu'avant — jamais un dégradé de bleus. */
  --terre-fonce:#0A4249;   /* chrome espace locataire — sarcelle, 10,44:1 sur crème */
  --indigo:     var(--bleu-marine); /* 10,14:1 sur crème · 10,80:1 sur blanc — chrome agence.
                               Anciennement un bleu marine générique (#12304E) :
                               vaut maintenant la couleur de marque LENSA IMMO.
                               Le nom du jeton ne change pas, sa valeur oui —
                               tous les usages existants en profitent. */
  --vert:       #1B6340;   /*  6,79:1 sur crème · 7,23:1 sur blanc — montants, paiement (inchangé, hors sujet « orange/doré ») */
  --vert-fonce: #13513A;   /* chrome espace propriétaire (inchangé, déjà vert) */
  /* --brun-fonce : chrome de l'espace démarcheur. Restait dans la famille
     brun/orange (#3E2415) — recoloré en ardoise bleu-gris foncé, neutre et
     froid, quatrième teinte de la famille « ni bleu-marine, ni vert, ni
     sarcelle » qui garde les quatre espaces distincts au premier coup d'œil. */
  --brun-fonce: #33415C;   /* chrome espace démarcheur — ardoise, 9,61:1 sur crème */
  --ocre:       #A9CBEA;   /* ≥ 5,0:1 sur tous les chromes (5,48:1 au plus bas) — JAMAIS sur crème.
                               Anciennement un doré (#F0B43C), explicitement exclu par la
                               cliente : devient un bleu ciel clair, seul assez lumineux
                               pour rester lisible en texte/icône sur les quatre chromes
                               sombres. Même règle d'usage qu'avant, seule la teinte change. */

  /* Sémantique — impayé/encaissé/attente/déclaré. Ni orange, ni doré au
     sens de la charte : ce sont des couleurs de statut (rouge, vert, ambre,
     violet), pas la couleur de marque. Inchangées à dessein — les recolorer
     casserait des repères déjà appris par les quatre espaces. Recalculées
     ci-dessous sur les nouveaux fonds, pas recopiées. */
  --rouge:      #A8231C;   /* retard, impayé, refus — 6,75:1 sur crème · 7,19:1 sur blanc */
  --ambre:      #8A5A0B;   /* en attente, à valider — 5,56:1 sur crème · 5,92:1 sur blanc.
                               Une teinte brune existe aussi en dehors de la famille
                               orange/doré de marque : c'est un jaune-brun de signalisation
                               (« attention »), universel, jamais la couleur de l'app. */
  --violet:     #5C3A86;   /* déclaré, information — 8,20:1 sur crème · 8,73:1 sur blanc */

  --tint-vert:  #DCEFE3;   /* 6,02:1 avec --vert (inchangé) */
  --tint-rouge: #FBE2E0;   /* 5,84:1 avec --rouge (inchangé) */
  --tint-ambre: #FBEBCF;   /* 5,04:1 avec --ambre (inchangé) */
  --tint-indigo:#DDE7F0;   /*  8,62:1 avec --indigo (inchangé, déjà bleu) */
  --tint-violet:#EBE3F6;   /* 7,01:1 avec --violet (inchangé) */
  --tint-neutre:#D7E6F7;   /* 6,08:1 avec --encre-2 — bleu pâle au lieu du tan, pour rester
                               visiblement distinct de --creme-2 (badges, compteurs, case cochée) */

  /* Filets — gris-bleu, au lieu du beige de l'ancienne palette. */
  --filet:      #D8E2F0;   /* séparateur décoratif */
  --filet-fort: #B9C7DE;   /* bordure de carte     */
  --bord:       #6B7A99;   /* bordure de contrôle de saisie — 4,31:1 sur blanc · 4,05:1 sur --champ-fond */

  /* Typographie : pile système uniquement, aucune police distante.
     ui-rounded se déclenche sur macOS/iOS (San Francisco Rounded) : c'est le
     seul palier où l'arrondi de la référence s'obtient réellement dans le
     dessin des lettres. Windows (Segoe UI) et Android (Roboto) n'ont pas de
     variante « rounded » système sans embarquer une police — ce que le
     cahier des charges interdit. Sur ces plateformes, l'effet « humaniste
     arrondi » est porté par le contraste de graisse et par les rayons
     généreux des surfaces et des champs, pas par le tracé des lettres. */
  /* « ui-rounded » retiré : il donnait une allure arrondie, presque enfantine,
     sur les appareils Apple — l'inverse de « classe ». Inter d'abord, et la
     pile système ensuite, intacte, comme repli. */
  --pile: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
          "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif;
  --pile-chiffres: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;

  --t-xs:  12.5px;
  --t-s:   14px;
  --t-m:   16px;   /* corps */
  --t-l:   18px;
  --t-xl:  21px;
  --t-2xl: 25px;
  --t-3xl: 30px;

  /* Rythme */
  --e1: 4px;  --e2: 8px;  --e3: 12px; --e4: 16px; --e5: 24px; --e6: 32px; --e7: 48px;

  /* Rayons — « la bordure des écrans ». Un cran plus généreux qu'avant sur
     toute la ligne (14→18, 8→10, 5→6) : ça se propage à tous les écrans
     sans qu'aucun gabarit n'ait à changer. --r-hero est réservé aux
     surfaces de premier contact (connexion, mot de passe) — l'équivalent
     des 16-20px observés sur la carte de la référence. */
  --r:      18px;  /* surfaces : .bloc, .carte, .indicateur, .filtres      */
  --r-s:    10px;  /* champs de saisie, petits contrôles                  */
  --r-xs:   6px;
  --r-hero: 22px;  /* carte de connexion / mot de passe                   */
  --max:  1240px;

  /* Ombres — diffuses, jamais de contour marqué. Toujours doublées d'une
     bordure fine et réelle (jamais « ombre seule ») : en mode contraste
     élevé (forced-colors), les navigateurs redessinent les bordures avec
     les couleurs système mais ignorent les box-shadow — la bordure reste
     donc le repère qui ne disparaît jamais. Teinte chaude (--encre) pour
     rester dans la famille de couleur du reste de la palette. */
  --ombre-s:  0 1px 2px rgba(16,26,46,.05), 0 2px 8px rgba(16,26,46,.05);
  --ombre:    0 4px 10px rgba(16,26,46,.07), 0 12px 28px rgba(16,26,46,.08);
  --ombre-lg: 0 12px 24px rgba(16,26,46,.10), 0 28px 64px rgba(16,26,46,.16);

  /* Habillage par défaut : agence. Redéfini par [data-espace]. */
  --chrome:     var(--indigo);
  --chrome-sur: var(--creme);
  --action:     var(--terre);
  --action-sur: var(--creme);
}

/* Habillages des quatre profils — un seul système, quatre identités. */
[data-espace="agence"]      { --chrome: var(--indigo);      --action: var(--terre); }
[data-espace="proprietaire"]{ --chrome: var(--vert-fonce);  --action: var(--terre); }
[data-espace="locataire"]   { --chrome: var(--terre-fonce); --action: var(--vert);  }
[data-espace="demarcheur"]  { --chrome: var(--brun-fonce);  --action: var(--terre); }
[data-espace="public"]      { --chrome: var(--indigo);      --action: var(--terre); }

/* ------------------------------------------------------- 2. REMISE À ZÉRO */
*,*::before,*::after{ box-sizing:border-box; }
html{ -webkit-text-size-adjust:100%; }
body{
  margin:0;
  background:var(--creme);
  color:var(--encre);
  font-family:var(--pile);
  font-size:var(--t-m);
  line-height:1.55;
  -webkit-font-smoothing:antialiased;
  overflow-wrap:break-word;
}
img,svg{ max-width:100%; height:auto; display:block; }
ul,ol{ margin:0; padding:0; list-style:none; }
p{ margin:0; }
figure{ margin:0; }

:where(a,button,input,select,textarea,summary,[tabindex]):focus-visible{
  outline:3px solid var(--terre);
  outline-offset:2px;
  border-radius:var(--r-xs);
}
[data-espace="locataire"] :where(a,button,input,select,textarea,summary):focus-visible{
  outline-color:var(--indigo);
}

/* ---------------------------------------------------------- 3. TYPOGRAPHIE */
h1,h2,h3,h4{ margin:0; font-weight:800; line-height:1.18; letter-spacing:-.022em; }
h1{ font-size:var(--t-2xl); }
h2{ font-size:var(--t-xl); }
h3{ font-size:var(--t-l); }
h4{ font-size:var(--t-m); }
a{ color:var(--terre); }
a:hover{ text-decoration-thickness:2px; }
strong,b{ font-weight:800; }
small{ font-size:var(--t-s); }

.titre-page{ font-size:var(--t-2xl); }
.chapo{ color:var(--encre-2); font-size:var(--t-s); margin-top:var(--e2); max-width:70ch; }
.sourdine{ color:var(--encre-2); }
.minuscule{ font-size:var(--t-xs); color:var(--encre-2); }
.capitales{ font-size:var(--t-xs); font-weight:800; letter-spacing:.09em;
  text-transform:uppercase; color:var(--encre-2); }

/* Montants : chiffres alignés, jamais coupés */
.montant{ font-variant-numeric:tabular-nums; font-weight:800; white-space:nowrap;
  letter-spacing:-.02em; }
.montant-vedette{ font-size:var(--t-2xl); color:var(--vert); }
.montant-negatif{ color:var(--rouge); }
.montant .unite{ font-size:var(--t-s); font-weight:700; color:var(--encre-2);
  letter-spacing:0; }

.sr{ position:absolute; width:1px; height:1px; overflow:hidden;
  clip:rect(0 0 0 0); clip-path:inset(50%); white-space:nowrap; }
.saut{ position:absolute; left:-9999px; }
.saut:focus{ left:var(--e2); top:var(--e2); z-index:99; background:var(--chrome);
  color:var(--creme); padding:12px 16px; border-radius:var(--r-s);
  text-decoration:none; font-weight:800; display:inline-flex; align-items:center;
  min-height:44px; }

/* ---------------------------------------------------------- 4. MISE EN PAGE */
.enveloppe{ width:100%; max-width:var(--max); margin-inline:auto;
  padding-inline:var(--e4); }
.pile{ display:grid; gap:var(--e4); }
.pile-serree{ display:grid; gap:var(--e2); }
.bloc{ background:var(--blanc); border:1px solid var(--filet);
  border-radius:var(--r); padding:var(--e4); box-shadow:var(--ombre-s); }
.bloc + .bloc{ margin-top:var(--e4); }
/* Un .bloc entier cliquable (ex. carte de comparaison d'un état des lieux) :
   l'ancre porte le style de carte, jamais un lien bleu souligné à
   l'intérieur d'un cadre — le focus clavier reste visible malgré tout. */
a.lien-carte{ display:block; color:inherit; text-decoration:none; }
a.lien-carte:hover{ border-color:var(--filet-fort); }
a.lien-carte:focus-visible{ outline:3px solid var(--indigo); outline-offset:2px; }
/* Surface de premier contact : connexion, mot de passe. Rayon et ombre
   plus marqués que le .bloc courant — c'est l'écran que voient les quatre
   profils avant tout le reste. */
.surface-hero{ border-radius:var(--r-hero); box-shadow:var(--ombre-lg);
  border-color:var(--filet); }
/* Sélecteur à deux classes : gagne systématiquement face à .bloc (une seule
   classe), quel que soit l'ordre des règles dans le fichier — y compris
   face à la règle @768px qui redéfinit le rembourrage de .bloc plus bas. */
.bloc.surface-hero{ padding:var(--e5); }
@media (min-width:600px){ .bloc.surface-hero{ padding:var(--e6); } }

/* Le double encadrement — signature graphique de la charte LENSA IMMO
   (docs/design/charte-lensa-immo.md §2) : un filet bleu extérieur, du
   blanc, un filet bleu intérieur. Obtenu par empilement de box-shadow sans
   flou, chaque anneau plus large que le précédent — aucune balise
   supplémentaire, aucune image. L'ombre diffuse Horizon referme
   l'empilement, la plus éloignée de toutes : la bordure de marque et le
   traitement « surfaces douces » cohabitent sur la même carte.
   Volontairement PAS posé sur .bloc par défaut : voir la note en tête de
   fichier (ARBITRAGE DENSITÉ). Réservé aux surfaces de marque. */
.cadre-double{
  border-color:transparent;
  box-shadow:
    0 0 0 2px var(--bleu-cadre),
    0 0 0 6px var(--blanc),
    0 0 0 8px var(--bleu-cadre),
    var(--ombre-lg);
}

/* Scène des pages « coque nue » (connexion, mot de passe) : partagée par
   templates/composants/carte-connexion.php. Dégradé --bleu-marque →
   --bleu-marine avec un éclairage doux et directionnel en haut à gauche —
   la charte transpose explicitement le traitement de son affiche de marque
   (« volumes blancs sur fond bleu dégradé », §4) à cet écran. Le motif à
   chevrons doré de l'ancienne palette a été retiré : la charte est stricte
   sur ce point — « aucune couleur chaude », les lueurs dorées de l'affiche
   sont une lumière, pas une couleur de marque. Zéro photographie, zéro
   octet réseau. */
.connexion-scene{
  min-height:100vh; min-height:100dvh; display:flex; align-items:center;
  justify-content:center; padding:var(--e6) var(--e4);
  background-color:var(--bleu-marine);
  background-image:
    radial-gradient(120% 90% at 12% -10%, rgba(255,255,255,.16), transparent 55%),
    linear-gradient(155deg, var(--bleu-marque) 0%, var(--bleu-marine) 60%);
}
.connexion-carte{ width:100%; max-width:420px; }
.connexion-panneau{ background:var(--blanc); }
.connexion-entete{ text-align:center; margin-bottom:var(--e5); }
.connexion-entete .sigle{
  margin-inline:auto; width:56px; height:56px; font-size:var(--t-l);
  background:var(--chrome); color:var(--creme); border:0; }
/* Logo vectoriel LENSA IMMO (public/assets/logo-lensa-immo.svg) — voir le
   commentaire en tête de ce fichier SVG : reconstruction à valider par la
   cliente. Hauteur fixe, largeur libre (le fichier est un cartouche haut,
   pas un carré).

   Agrandi le 18 septembre 2026 à la demande de la cliente : « le logo devant
   l'espace client doit être bien grand ». 56 px le réduisaient à une vignette
   où le monogramme et la mention « Agence immobilière by LENSAGROUP »
   devenaient illisibles.

   Il devient le premier élément de la page, avant le titre — c'est la marque
   qui accueille, pas un mot. Hauteur exprimée en unités de vue et bornée :
   elle suit la taille de l'écran sans jamais écraser le formulaire, qui reste
   la seule chose à faire ici. */
.connexion-entete .logo{
  height:clamp(96px, 18vh, 148px);
  width:auto; margin-inline:auto; display:block;
}
.connexion-entete h1{ margin-top:var(--e4); font-size:var(--t-2xl);
  color:var(--indigo); font-weight:800; letter-spacing:-.015em; }
.connexion-entete p{ margin-top:6px; color:var(--encre-2); font-size:var(--t-s);
  font-weight:500; max-width:32ch; margin-inline:auto; }
.connexion-pied{ text-align:center; margin-top:var(--e4); }
.connexion-pied a{ color:var(--encre-clair); display:inline-flex; align-items:center;
  justify-content:center; min-height:44px; padding:0 8px; font-weight:700;
  text-decoration:none; }
.connexion-pied a:hover{ text-decoration:underline; }
.bloc-titre{ display:flex; align-items:center; gap:var(--e2);
  flex-wrap:wrap; margin-bottom:var(--e3); }
.bloc-titre h2,.bloc-titre h3{ font-size:var(--t-l); }
.separateur{ height:2px; background:var(--filet); border:0; margin:var(--e5) 0; }

/* Fond de bandeau — APLAT, plus de croisillons.
   ---------------------------------------------------------------------------
   Le 18 septembre 2026, la cliente : « je veux du bleu, pas les carreaux ».
   Les deux diagonales croisées formaient un tissu écossais qui contredisait
   directement la direction qu'elle a fixée — soft, épuré, classe. Un motif
   répété attire l'œil sur lui-même au lieu de le laisser aller au texte
   posé dessus, et il fatigue à la lecture sur un petit écran.

   À la place, un DÉGRADÉ DES TROIS BLEUS DU LOGO, demandé par la cliente :
   « un dégradé de bleu qui respecte mon logo ». Ce sont exactement les bleus
   de son cartouche — le bleu profond des lignes du toit, le bleu de marque
   du carré du « i », et le bleu clair du double encadrement. Rien d'inventé.

   Le sens de lecture va du foncé (en haut à gauche) au plus clair (en bas à
   droite) : la lumière descend, comme sur ses visuels 3D. Le texte blanc se
   pose sur la partie la plus sombre, où le contraste est le meilleur.

   ⚠️ Le nom `.motif` est conservé pour ne pas réécrire les gabarits qui s'y
   accrochent ; seul son rendu change.

   ⚠️ Les ESPACES CONNECTÉS gardent leur propre teinte (`--chrome`) : c'est
   ce qui distingue l'agence, le propriétaire, le locataire et le démarcheur
   d'un coup d'œil. Le dégradé de marque ne s'applique donc qu'au site
   public, où il n'y a qu'une seule identité à porter. */
.motif{
  background-color:var(--chrome);
  background-image:
    linear-gradient(150deg,
      color-mix(in srgb, var(--chrome) 88%, black 12%) 0%,
      var(--chrome) 55%,
      color-mix(in srgb, var(--chrome) 80%, var(--bleu-cadre) 20%) 100%);
}

/* Site public : le dégradé porte les trois bleus du logo, sans passer par
   `--chrome`. Une seule identité à afficher, donc la marque peut s'exprimer
   pleinement. */
/* Le gabarit du site public pose `data-espace="public"` sur le <body> —
   c'est ce marqueur qui commande, pas une classe qu'il faudrait penser à
   ajouter sur chaque page. */
/* ⭐ RECALÉ le 21/09/2026 sur le kakémono de l'agence, la cliente ayant
   relevé que « ce ne sont pas les mêmes bleus ».

   Avant : le dégradé partait de --bleu-marine (alors #2B3190, un indigo
   violacé absent de la charte) et n'arrivait au bleu de marque qu'en bas.
   Le bandeau lisait donc VIOLET là où le kakémono est BLEU.

   Maintenant : --bleu-marque (#366FB2, l'aplat mesuré sur le kakémono) porte
   tout le bandeau. Le dégradé ne fait que le creuser légèrement en haut et
   l'éclaircir vers le liseré clair en bas — la même construction que le
   kakémono, qui borde son bandeau d'un filet plus clair.

   ⚠️ CONTRASTE, et c'est la raison pour laquelle le bandeau n'est pas encore
   PLUS clair : blanc pur sur #366FB2 donne 5,15:1, au-dessus du seuil AA de
   4,5:1. L'ancien #E6EDF4 n'y serait plus qu'à 4,39:1 — SOUS le seuil. Les
   textes secondaires de ce bandeau sont donc passés au blanc (voir
   site.css, .chapo / .metier-detail / .metiers-note). Éclaircir davantage le
   fond casserait la lisibilité. */
[data-espace="public"] .motif{
  background-color:var(--bleu-marque);
  background-image:
    linear-gradient(150deg,
      color-mix(in srgb, var(--bleu-marque) 78%, black 22%) 0%,
      var(--bleu-marque) 58%,
      color-mix(in srgb, var(--bleu-marque) 88%, var(--bleu-lisere) 12%) 100%);
}
.liseré{ height:6px; background:repeating-linear-gradient(90deg,
  var(--terre) 0 18px, var(--ocre) 18px 36px, var(--indigo) 36px 54px, var(--vert) 54px 72px); }

/* -------------------------------------------------------------- 5. BOUTONS */
.btn{
  display:inline-flex; align-items:center; justify-content:center; gap:var(--e2);
  min-height:44px; padding:11px 18px;
  font:inherit; font-size:var(--t-m); font-weight:800; line-height:1.2;
  border-radius:100px; border:2px solid transparent; cursor:pointer;
  text-decoration:none; text-align:center;
}
.btn-principal{ background:var(--action); color:var(--creme); }
.btn-principal:hover{ filter:brightness(1.1); }
.btn-second{ background:var(--blanc); color:var(--chrome); border-color:var(--chrome); }
.btn-second:hover{ background:var(--tint-neutre); }
.btn-discret{ background:var(--creme-2); color:var(--encre); border-color:var(--filet-fort); }
.btn-discret:hover{ background:var(--creme-3); }
.btn-danger{ background:var(--blanc); color:var(--rouge); border-color:var(--rouge); }
.btn-petit{ min-height:38px; padding:8px 14px; font-size:var(--t-s); }
/* Jusqu'à 1024 px inclus (iPad paysage compris), l'appareil est très
   probablement tactile : aucune cible ne descend sous 44 px, quel que soit
   le style. La densité de --btn-petit ne joue qu'à l'écran, jamais sur la
   cible ; elle ne se resserre qu'au-delà, sur un poste tenu à la souris. */
@media (max-width:1024px){ .btn-petit{ min-height:44px; } }
.btn-bloc{ width:100%; }

/* Lien d'action discret — « Refuser » face à « Approuver » */
.lien-action{ display:inline-flex; align-items:center; justify-content:center;
  min-height:44px; padding:6px 10px; background:none; border:0; cursor:pointer;
  font:inherit; font-size:var(--t-s); font-weight:700; color:var(--rouge);
  text-decoration:underline; text-underline-offset:3px; }
/* .lien-action n'est pas toujours un refus (rouge) : un simple lien
   secondaire (« Annuler », « Retour ») ou un lien de la couleur de l'espace
   reprend la même cible et la même graisse, sans l'alerte. La double classe
   l'emporte sur .lien-action quel que soit l'ordre des règles. */
.lien-action.sourdine{ color:var(--encre-2); }
.lien-action.texte-chrome{ color:var(--chrome); }
.lien-action.texte-indigo{ color:var(--indigo); }

/* Bouton hamburger du menu en tiroir — structure et icône seulement.
   Partagé par la coque d'application ET le site public (qui ne charge pas
   application.css) : la structure vit donc ici, une seule fois. Chaque
   contexte n'a plus qu'à fixer ses couleurs (voir application.css et
   site.css). */
.bouton-menu{
  display:inline-flex; align-items:center; gap:8px; flex:none;
  min-width:48px; min-height:48px; padding:10px 12px;
  border-radius:100px; cursor:pointer; font:inherit;
  font-size:var(--t-s); font-weight:800;
  background:var(--tint-neutre); color:var(--encre);
  border:2px solid var(--bord);
}
.bouton-menu i{ display:block; width:18px; height:2.5px; background:currentColor;
  position:relative; border-radius:2px; font-style:normal; }
.bouton-menu i::before,.bouton-menu i::after{ content:""; position:absolute; left:0;
  width:18px; height:2.5px; background:currentColor; border-radius:2px; }
.bouton-menu i::before{ top:-6px; } .bouton-menu i::after{ top:6px; }

/* Divulgation générique <details> — un second geste qui doit rester secondaire
   et jamais pré-rempli (ex. le motif de refus d'une dépense, à côté du bouton
   plein « Approuver »). Sans « ? » : contrairement à .aide, ce n'est pas de
   l'aide contextuelle. Sans JavaScript, entièrement au clavier. */
.divulgation > summary{ list-style:none; cursor:pointer; }
.divulgation > summary::-webkit-details-marker{ display:none; }
.divulgation > .volet{
  margin-top:var(--e2); padding:var(--e3); background:var(--creme-2);
  border:2px solid var(--filet-fort); border-radius:var(--r-s); }

/* Une action impossible est désactivée, jamais laissée en échec. */
.btn[disabled],.btn[aria-disabled="true"],
.lien-action[disabled],.lien-action[aria-disabled="true"]{
  background:var(--creme-3); color:var(--encre-2); border-color:var(--filet-fort);
  cursor:not-allowed; filter:none; text-decoration:none; opacity:1;
}
.motif-desactivation{ display:block; font-size:var(--t-xs); color:var(--encre-2);
  margin-top:var(--e1); font-weight:600; }

.rangee-actions{ display:flex; flex-wrap:wrap; gap:var(--e2); align-items:center; }

/* ---------------------------------------------------------- 6. FORMULAIRES */
.formulaire{ display:grid; gap:var(--e4); }
.champ{ display:grid; gap:6px; }
.champ > label,.champ > .etiquette{
  font-size:var(--t-s); font-weight:800; color:var(--encre);
  display:flex; align-items:center; gap:6px; flex-wrap:wrap; }
.champ .obligatoire{ color:var(--rouge); font-weight:800; }
.champ .indication{ font-size:var(--t-xs); color:var(--encre-2); }

input[type=text],input[type=tel],input[type=email],input[type=password],
input[type=date],input[type=number],input[type=search],input[type=file],
select,textarea{
  font:inherit; font-size:var(--t-m); width:100%;
  min-height:52px; padding:12px 15px;
  color:var(--encre); background:var(--champ-fond);
  border:1.5px solid var(--bord); border-radius:var(--r-s);
}
/* Texte indicatif : gris moyen, jamais noir — et jamais la seule façon de
   comprendre le champ (voir .champ-icone et la remarque de accessibilité
   plus bas : un <label> réel existe toujours, visible ou masqué). */
::placeholder{ color:var(--encre-2); opacity:1; font-weight:500; }
textarea{ min-height:120px; line-height:1.5; resize:vertical; }
select{
  appearance:none; padding-right:42px;
  background-image:linear-gradient(45deg,transparent 50%,var(--encre-2) 50%),
    linear-gradient(135deg,var(--encre-2) 50%,transparent 50%);
  background-position:right 21px center, right 15px center;
  background-size:6px 6px,6px 6px; background-repeat:no-repeat;
}
input:disabled,select:disabled,textarea:disabled{
  background:var(--creme-3); color:var(--encre-2); border-color:var(--filet-fort); }
input[aria-invalid="true"],select[aria-invalid="true"],textarea[aria-invalid="true"]{
  border-color:var(--rouge); background:var(--tint-rouge); }
.erreur-champ{ font-size:var(--t-s); font-weight:700; color:var(--rouge); }

/* Icône grise en tête de champ — « le CSS des cases ». Purement décoratif
   (aria-hidden côté HTML) : l'identification du champ reste portée par un
   <label> réel, visible ou en .sr, jamais par la seule icône. */
.champ-icone{ position:relative; display:block; }
.champ-icone svg{
  position:absolute; left:16px; top:50%; transform:translateY(-50%);
  width:20px; height:20px; color:var(--encre-2); pointer-events:none; }
.champ-icone input{ padding-left:48px; }

/* Bouton « Voir » d'un champ mot de passe (interface.js § 14). Créé par le
   JavaScript, jamais par le gabarit : sans JavaScript il n'existe pas, et
   le champ reste un champ mot de passe ordinaire, pleinement utilisable.
   Le champ gagne une réserve à droite UNIQUEMENT quand le bouton a été
   posé (data-avec-voir), sinon on creuserait un vide dans un champ qui
   n'a rien à y mettre. */
[data-avec-voir]{ position:relative; }
[data-avec-voir] input{ padding-right:52px; }
.voir-mdp{
  position:absolute; right:7px; top:50%; transform:translateY(-50%);
  display:grid; place-items:center;
  width:38px; height:38px; padding:0;
  color:var(--encre-2); background:transparent;
  border:1.5px solid transparent; border-radius:var(--r-s);
  cursor:pointer;
}
.voir-mdp svg{ width:20px; height:20px; }
/* Barre affichée quand le mot de passe est MASQUÉ (l'œil est barré : rien
   n'est visible). Elle disparaît quand il est affiché. */
.voir-mdp[aria-pressed="true"] .barre{ display:none; }
.voir-mdp:hover{ color:var(--encre); background:var(--creme-3); }
.voir-mdp:focus-visible{ border-color:var(--bord); color:var(--encre); }
.voir-mdp[aria-pressed="true"]{ color:var(--encre); }

.paire{ display:grid; gap:var(--e4); }
/* Un champ 'pleine'=>true (composants/champ.php) occupe toute la largeur —
   déjà vrai dans .filtres (règle plus bas) ; manquait ici pour .paire, la
   grille à deux colonnes des formulaires (ex. l'adresse d'un bien, le nom
   d'un utilisateur). Sans effet sur mobile, où .paire n'a qu'une colonne. */
.paire .pleine{ grid-column:1/-1; }
.champ-monnaie{ position:relative; }
.champ-monnaie input{ padding-right:64px; font-variant-numeric:tabular-nums;
  font-weight:800; }
.champ-monnaie .devise{ position:absolute; right:14px; top:50%; transform:translateY(-50%);
  font-size:var(--t-s); font-weight:800; color:var(--encre-2); pointer-events:none; }

/* Taux en points de base (composants/champ.php, type pourcentage_bp) : la
   valeur saisie ET transmise reste en points de base, jamais convertie à
   l'affichage — voir le commentaire du gabarit. .mini-conversion est un
   aperçu JS facultatif (« ≈ 5 % ») qui n'existe pas sans JavaScript : le
   champ reste pleinement utilisable, juste sans ce repère. */
.champ-pourcentage{ position:relative; }
.champ-pourcentage input{ padding-right:112px; font-variant-numeric:tabular-nums;
  font-weight:800; }
.champ-pourcentage .unite{ position:absolute; right:14px; top:50%; transform:translateY(-50%);
  font-size:var(--t-xs); font-weight:700; color:var(--encre-2); text-align:right;
  line-height:1.2; pointer-events:none; }
.mini-conversion{ font-size:var(--t-xs); font-weight:700; color:var(--encre-2); }
.mini-conversion:empty{ display:none; }

/* Notice légale à côté d'un champ (plafond borné par la loi) : visible en
   permanence, jamais derrière la bulle « ? » — une borne imposée par le
   Code n'est pas une simple aide, la cacher tromperait sur sa nature. */
.note-legale{ display:flex; align-items:flex-start; gap:6px; margin:0;
  font-size:var(--t-xs); font-weight:700; color:var(--ambre);
  background:var(--tint-ambre); border:1px solid var(--ambre);
  border-radius:var(--r-s); padding:8px 10px; }

/* Choix en pastilles — plus rapides au pouce qu'une liste déroulante */
.pastilles{ display:flex; flex-wrap:wrap; gap:var(--e2); }
.pastilles button,.pastilles .pastille{
  min-height:44px; padding:10px 16px; border-radius:100px; cursor:pointer;
  font:inherit; font-size:var(--t-s); font-weight:800; white-space:nowrap;
  background:var(--blanc); color:var(--encre-2); border:2px solid var(--bord); }
.pastilles [aria-pressed="true"],.pastilles .pastille.active{
  background:var(--chrome); color:var(--creme); border-color:var(--chrome); }

/* Cases et boutons radio en « carte cliquable » : cible large */
.choix{ display:flex; align-items:flex-start; gap:var(--e3);
  min-height:48px; padding:12px; cursor:pointer;
  background:var(--champ-fond); border:1.5px solid var(--bord); border-radius:var(--r-s); }
.choix input{ width:22px; height:22px; margin:0; flex:none; accent-color:var(--chrome); }
.choix span{ font-size:var(--t-s); font-weight:700; }
.choix:has(input:checked){ border-color:var(--chrome); background:var(--tint-neutre); }
/* Case à cocher courte, en rangée qui passe à la ligne (ex. sélection de
   plusieurs mois à comparer) : largeur mini au lieu de s'étirer sur 100 %. */
.choix-etroit{ min-width:120px; flex:0 0 auto; }
/* Case cliquable qui encadre un bloc plus riche qu'un simple libellé (ex. un
   choix de relance avec aperçu du message) : les enfants s'étirent en
   hauteur plutôt que de rester alignés en haut. */
.choix-etire{ align-items:stretch; padding:var(--e4); }

/* Lignes répétables — composition du loyer, pièces jointes */
.lignes{ display:grid; gap:var(--e3); }
.ligne-repetable{
  display:grid; gap:var(--e3); padding:var(--e3);
  background:var(--creme-2); border:2px solid var(--filet); border-radius:var(--r-s); }
.ligne-repetable .retirer{
  justify-self:start; min-height:44px; padding:8px 14px; border-radius:100px;
  font:inherit; font-size:var(--t-s); font-weight:800; cursor:pointer;
  background:var(--blanc); color:var(--rouge); border:2px solid var(--rouge); }
.total-lignes{ display:flex; justify-content:space-between; align-items:baseline;
  gap:var(--e3); padding:var(--e3); border-radius:var(--r-s);
  background:var(--tint-vert); font-weight:800; }
.total-lignes .montant{ font-size:var(--t-xl); color:var(--vert); }

/* Barre de validation collante : le bouton principal reste atteignable */
.barre-validation{
  position:sticky; bottom:0; z-index:5;
  display:flex; flex-wrap:wrap; gap:var(--e3); align-items:center;
  margin-top:var(--e5); padding:var(--e3) var(--e4)
    calc(var(--e3) + env(safe-area-inset-bottom));
  background:var(--creme); border-top:2px solid var(--filet-fort);
  margin-inline:calc(var(--e4) * -1);
}
.barre-validation .btn-principal{ flex:1 1 220px; }
/* Barre de validation posée à l'intérieur d'un bloc (ex. encaissement manuel
   au milieu de la fiche loyer) plutôt que collée en bas d'écran : on annule
   la position collante et l'habillage de bordure/fond. */
.barre-validation-en-ligne{ position:static; background:none; border-top:0;
  margin:var(--e3) 0 0; padding:0; }

/* ------------------------------------------------------- 7. AIDE « ? » */
/* Sans une ligne de JavaScript : <details> natif, clavier compris.        */
.aide{ position:relative; display:inline-block; vertical-align:middle; }
.aide > summary{
  list-style:none; cursor:pointer; display:inline-flex;
  align-items:center; justify-content:center;
  width:44px; height:44px; margin:-10px -10px;   /* cible 44 px, pastille 24 px */
  color:var(--encre-2);
}
.aide > summary::-webkit-details-marker{ display:none; }
.aide > summary::before{
  content:"?"; display:grid; place-items:center;
  width:24px; height:24px; border-radius:50%;
  background:var(--tint-neutre); border:1.5px solid var(--bord);
  font-size:var(--t-xs); font-weight:800; line-height:1; color:var(--encre-2);
}
.aide[open] > summary::before{ background:var(--chrome); color:var(--creme);
  border-color:var(--chrome); }
.aide > .bulle{
  position:absolute; z-index:40; top:calc(100% + 6px); left:-12px;
  width:min(280px,78vw); padding:var(--e3) var(--e4);
  background:var(--encre); color:#EAF2FC;
  border-radius:var(--r-s); font-size:var(--t-s); font-weight:500;
  line-height:1.5; letter-spacing:0; text-transform:none; text-align:left;
  box-shadow:0 6px 20px rgba(16,26,46,.28);
}
.aide > .bulle::before{ content:""; position:absolute; top:-6px; left:18px;
  width:12px; height:12px; background:var(--encre); transform:rotate(45deg); }
.aide--fin > .bulle{ left:auto; right:-12px; }
.aide--fin > .bulle::before{ left:auto; right:18px; }
/* Sur chrome sombre */
.sur-chrome .aide > summary::before{ background:rgba(255,255,255,.16);
  border-color:rgba(255,255,255,.5); color:var(--creme); }

/* --------------------------------------------------- 8. PASTILLES D'ÉTAT */
.etat{
  display:inline-flex; align-items:center; gap:6px;
  padding:4px 11px; border-radius:100px; white-space:nowrap;
  font-size:var(--t-xs); font-weight:800; letter-spacing:.01em;
  background:var(--tint-neutre); color:var(--encre-2); }
.etat::before{ content:""; width:8px; height:8px; border-radius:50%;
  background:currentColor; flex:none; }
.etat-paye,.etat-approuve,.etat-actif,.etat-disponible{
  background:var(--tint-vert);  color:var(--vert); }
.etat-retard,.etat-impaye,.etat-refuse{
  background:var(--tint-rouge); color:var(--rouge); }
.etat-attente,.etat-brouillon{
  background:var(--tint-ambre); color:var(--ambre); }
.etat-declare{
  background:var(--tint-violet); color:var(--violet); }
.etat-loue,.etat-termine,.etat-info{
  background:var(--tint-indigo); color:var(--indigo); }

/* Étapes d'un cycle (état des lieux : brouillon → à valider → validé ;
   cessation : préavis → sortie → décompte → clôture). Une liste de repères,
   jamais une seule couleur : le libellé de chaque étape reste écrit, l'état
   « fait/en cours/à venir » est redondant entre la couleur et le symbole. */
.cycle-etapes{ display:flex; flex-wrap:wrap; gap:var(--e2); list-style:none; margin:0; padding:0; }
.cycle-etapes li{ display:flex; align-items:center; gap:7px; font-size:var(--t-s); font-weight:700;
  color:var(--encre-2); padding:7px 14px; border-radius:100px; background:var(--tint-neutre); }
.cycle-etapes li::before{ content:"○"; font-size:var(--t-xs); }
.cycle-etapes li[data-etape="fait"]{ background:var(--tint-vert); color:var(--vert); }
.cycle-etapes li[data-etape="fait"]::before{ content:"●"; }
.cycle-etapes li[data-etape="actif"]{ background:var(--tint-ambre); color:var(--ambre); }
.cycle-etapes li[data-etape="actif"]::before{ content:"◐"; }

/* Galerie de vignettes (photos d'état des lieux). */
.galerie-photos{ display:flex; flex-wrap:wrap; gap:var(--e2); margin-top:var(--e2); }
.galerie-photos a{ display:block; width:84px; height:84px; flex:none; border-radius:var(--r-s);
  overflow:hidden; border:1.5px solid var(--filet-fort); }
.galerie-photos img{ width:100%; height:100%; object-fit:cover; display:block; }
.galerie-photos a:focus-visible{ outline:3px solid var(--indigo); outline-offset:2px; }
/* ⭐ 30/09/2026 — LA VIDÉO DANS LA GALERIE DE L'ÉTAT DES LIEUX.
   ⚠️ Une vidéo ne tient pas dans la vignette de 84 px des photos : à cette
   taille les commandes de lecture se chevauchent et deviennent intouchables
   au doigt. Elle prend donc sa propre largeur, et toute la colonne sur un
   téléphone — c'est là que les gestionnaires consultent, sur le terrain. */
.galerie-photos video{ width:260px; max-width:100%; height:auto; flex:none;
  border-radius:var(--r-s); border:1.5px solid var(--filet-fort);
  background:var(--encre); display:block; }
@media (max-width:600px){ .galerie-photos video{ width:100%; } }

/* ------------------------------------------------------- 9. INDICATEURS */
.indicateurs{ display:grid; gap:var(--e3); grid-template-columns:1fr; }
.indicateur{
  background:var(--blanc); border:1px solid var(--filet); border-radius:var(--r);
  border-bottom-width:5px; border-bottom-color:var(--chrome); box-shadow:var(--ombre-s);
  padding:var(--e4); display:grid; gap:var(--e1); align-content:start; }
.indicateur .intitule{ display:flex; align-items:center; gap:4px; flex-wrap:wrap;
  font-size:var(--t-s); font-weight:800; color:var(--encre-2); }
.indicateur .valeur{ font-size:var(--t-2xl); font-weight:800;
  font-variant-numeric:tabular-nums; letter-spacing:-.03em; line-height:1.1; }
.indicateur .detail{ font-size:var(--t-xs); color:var(--encre-2); font-weight:600; }
.indicateur-vert   .valeur{ color:var(--vert); }
.indicateur-vert   { border-bottom-color:var(--vert); }
.indicateur-rouge  .valeur{ color:var(--rouge); }
.indicateur-rouge  { border-bottom-color:var(--rouge); }
.indicateur-terre  { border-bottom-color:var(--terre); }
.indicateur-ambre  { border-bottom-color:var(--ambre); }
.indicateur-vedette{ border-bottom-color:var(--terre); background:var(--tint-neutre); }
.indicateur-vedette .valeur{ font-size:var(--t-3xl); }

/* --------------------------------------------------------- 10. TABLEAUX */
/* Un tableau sur téléphone devient une pile de cartes. Jamais de           */
/* défilement horizontal de la page : la largeur reste celle de l'écran.    */
.tableau-enveloppe{ margin-top:var(--e3); }
.tableau{ width:100%; border-collapse:collapse; font-size:var(--t-s); }
.tableau caption{ text-align:left; font-size:var(--t-xs); color:var(--encre-2);
  padding-bottom:var(--e2); }
.tableau th{ text-align:left; font-weight:800; }
.tableau thead th{
  padding:10px 12px; font-size:var(--t-xs); color:var(--encre-2);
  background:var(--creme-2); border-bottom:2px solid var(--filet-fort);
  white-space:nowrap; vertical-align:middle; }
.tableau thead th:first-child{ border-top-left-radius:var(--r-s); }
.tableau thead th:last-child{ border-top-right-radius:var(--r-s); }
.tableau tbody td{ padding:12px; border-bottom:1px solid var(--filet);
  vertical-align:middle; background:var(--blanc); }
.tableau tbody tr:hover td{ background:var(--creme); }
.tableau .cellule-titre{ font-weight:800; font-size:var(--t-m); }
.tableau .cellule-titre .secondaire{ display:block; font-size:var(--t-xs);
  font-weight:600; color:var(--encre-2); }
.tableau .num{ text-align:right; font-variant-numeric:tabular-nums;
  font-weight:800; white-space:nowrap; }
.tableau .cellule-actions{ white-space:nowrap; }
.tableau tfoot td{ padding:12px; background:var(--tint-neutre); font-weight:800;
  border-top:2px solid var(--filet-fort); }

@media (max-width:767px){
  .tableau thead{ display:none; }
  .tableau,.tableau tbody,.tableau tfoot{ display:block; }
  .tableau tr{
    display:block; background:var(--blanc); border:2px solid var(--filet);
    border-radius:var(--r); padding:var(--e3); margin-bottom:var(--e3); }
  .tableau tbody td,.tableau tfoot td{
    display:flex; gap:var(--e3); justify-content:space-between; align-items:baseline;
    padding:8px 0; border:0; border-bottom:1px solid var(--filet);
    background:none; text-align:left; }
  .tableau td:last-child{ border-bottom:0; padding-bottom:0; }
  .tableau td::before{
    content:attr(data-intitule); flex:0 0 40%;
    font-size:var(--t-xs); font-weight:800; color:var(--encre-2); }
  .tableau .cellule-titre{ display:block; padding-top:0; }
  .tableau .cellule-titre::before{ display:none; }
  .tableau .num{ text-align:right; }
  .tableau .cellule-actions{ display:block; white-space:normal; padding-top:var(--e3); }
  .tableau .cellule-actions::before{ display:none; }
  .tableau .cellule-actions .btn{ width:100%; }
  .tableau .cellule-actions .rangee-actions > *{ flex:1 1 140px; }
}
/* Tableau large (récapitulatif croisé) : le défilement reste DANS le cadre.
   Sous 768 px, on ne force PAS de min-width : le tableau reste en cartes
   empilées pleine largeur (comme un tableau normal) plutôt que d'imposer un
   défilement horizontal supplémentaire à l'intérieur d'une carte déjà en
   défilement vertical — chaque valeur reste visible sans geste du pouce. Le
   défilement horizontal encadré ne sert qu'à partir de la tablette, quand le
   tableau redevient un vrai <table>. */
.tableau-defile{ overflow-x:auto; -webkit-overflow-scrolling:touch;
  border:2px solid var(--filet); border-radius:var(--r); background:var(--blanc); }
@media (min-width:768px){
  .tableau-defile .tableau{ min-width:720px; margin:0; }
  .tableau-defile .tableau tr{ border:0; }
}

/* ----------------------------------------------------------- 11. CARTES */
.grille{ display:grid; gap:var(--e4); grid-template-columns:1fr; }
.carte{
  position:relative; display:flex; flex-direction:column;
  background:var(--blanc); border:1px solid var(--filet);
  border-radius:var(--r); overflow:hidden; box-shadow:var(--ombre-s); }
.carte:hover{ border-color:var(--terre); box-shadow:var(--ombre); }
@media (prefers-reduced-motion:no-preference){ .carte{ transition:box-shadow .15s ease-out; } }
.carte .visuel{ position:relative; aspect-ratio:4/3; display:grid; place-items:center;
  background:linear-gradient(145deg,#3E7CC0,#2B3190); }
.carte .visuel span{ color:#FFF; font-size:var(--t-s); font-weight:700;
  text-align:center; padding:0 var(--e4); text-shadow:0 1px 3px rgba(0,0,0,.65); }
.carte .visuel::after{
  content:"Emplacement photo"; position:absolute; right:8px; bottom:8px;
  font-size:10px; font-weight:800; letter-spacing:.09em; text-transform:uppercase;
  color:var(--creme); background:rgba(16,26,46,.82); padding:4px 8px;
  border-radius:100px; }
/* Vignettes de secours tant qu'aucune vraie photo n'est téléversée (M7 du
   cahier des charges du site public) — six couleurs pour distinguer les
   biens d'un coup d'œil, aucune orange ni dorée (18/09/2026) : .v1 et .v4
   étaient une terre cuite et un doré dans l'ancienne palette « Marché »,
   recolorées ici dans les bleus de marque et une teinte cyan froide. */
.v1{ background:linear-gradient(145deg,#3E7CC0,#2B3190)!important; }
.v2{ background:linear-gradient(145deg,#2C6E8F,#10304A)!important; }
.v3{ background:linear-gradient(145deg,#3F8A63,#17422C)!important; }
.v4{ background:linear-gradient(145deg,#2B95A6,#134A54)!important; }
.v5{ background:linear-gradient(145deg,#7A5C8E,#392642)!important; }
.v6{ background:linear-gradient(145deg,#4E6F8C,#213A52)!important; }
.etiquette{ position:absolute; top:10px; left:10px; z-index:2;
  font-size:11.5px; font-weight:800; padding:6px 12px; border-radius:100px;
  background:var(--creme); color:var(--terre); }
.etiquette-loc{ background:var(--vert); color:var(--creme); }
.carte .corps{ padding:var(--e3); display:flex; flex-direction:column;
  gap:var(--e2); flex:1; }
.carte h3{ font-size:var(--t-m); font-weight:700; }
.carte h3 a{ text-decoration:none; color:var(--encre); }
.carte h3 a::after{ content:""; position:absolute; inset:0; }
.lieu{ font-size:var(--t-s); font-weight:800; color:var(--terre); }
.caracs{ display:flex; flex-wrap:wrap; gap:6px; margin-top:auto; padding-top:var(--e2); }
.caracs li{ font-size:var(--t-xs); font-weight:700; color:var(--encre-2);
  background:var(--creme-2); border-radius:100px; padding:5px 11px; }

/* ------------------------------------------------ 12. ONGLETS & FILTRES */
.barre-outils{ display:grid; gap:var(--e3); margin-bottom:var(--e4); }
.onglets{ display:flex; gap:var(--e2); overflow-x:auto; padding-bottom:var(--e2);
  -webkit-overflow-scrolling:touch; scrollbar-width:thin; }
.onglets::-webkit-scrollbar{ height:5px; }
.onglets::-webkit-scrollbar-thumb{ background:var(--filet-fort); border-radius:5px; }
.onglets a,.onglets button{
  flex:none; display:inline-flex; align-items:center; gap:7px;
  min-height:44px; padding:10px 16px; border-radius:100px; cursor:pointer;
  font:inherit; font-size:var(--t-s); font-weight:800; white-space:nowrap;
  text-decoration:none; color:var(--encre-2);
  background:var(--blanc); border:2px solid var(--bord); }
.onglets [aria-current="page"],.onglets [aria-selected="true"]{
  background:var(--chrome); color:var(--creme); border-color:var(--chrome); }
.onglets .compte{ font-variant-numeric:tabular-nums;
  background:var(--tint-neutre); color:var(--encre-2);
  border-radius:100px; padding:1px 8px; font-size:var(--t-xs); }
.onglets [aria-current="page"] .compte,.onglets [aria-selected="true"] .compte{
  background:rgba(255,255,255,.22); color:var(--creme); }

.filtres{ display:grid; gap:var(--e3); background:var(--creme-2);
  border:1px solid var(--filet); border-radius:var(--r); padding:var(--e3);
  box-shadow:var(--ombre-s); }
.filtres .champ > label{ font-size:var(--t-xs); }
.filtres input,.filtres select{ min-height:44px; font-size:var(--t-s); }
.filtres-actions{ display:flex; flex-wrap:wrap; gap:var(--e2); }
.outils-secondaires{ display:flex; flex-wrap:wrap; gap:var(--e2); }
.recherche-globale{ position:relative; }

/* --------------------------------------------------------- 13. ÉTATS */
.etat-vide{
  display:grid; gap:var(--e3); justify-items:center; text-align:center;
  padding:var(--e6) var(--e4); background:var(--blanc);
  border:2px dashed var(--filet-fort); border-radius:var(--r); }
.etat-vide .pict{ width:56px; height:56px; border-radius:50%;
  background:var(--tint-neutre); display:grid; place-items:center; font-size:24px; }
.etat-vide h3{ font-size:var(--t-l); }
.etat-vide p{ color:var(--encre-2); font-size:var(--t-s); max-width:46ch; }

.messages-flash{ display:grid; gap:var(--e2); margin-bottom:var(--e4); }
.messages-flash:empty{ display:none; margin:0; }
.encart{ display:grid; gap:var(--e2); padding:var(--e4);
  border-radius:var(--r); border:2px solid var(--filet);
  background:var(--tint-neutre); font-size:var(--t-s); }
.encart h3{ font-size:var(--t-m); }
.encart-alerte{ background:var(--tint-rouge); border-color:var(--rouge); }
.encart-attente{ background:var(--tint-ambre); border-color:var(--ambre); }
.encart-succes{ background:var(--tint-vert); border-color:var(--vert); }
.encart-info{ background:var(--tint-indigo); border-color:var(--indigo); }

/* Pastille de filtre courant, en plus de [aria-pressed] (bouton) : un lien de
   filtre (site public) exprime l'état par [aria-current="page"], pas aria-pressed. */
.pastilles [aria-current="page"]{
  background:var(--chrome); color:var(--creme); border-color:var(--chrome); }

/* ---------------------------------------------------------- 14. DIVERS */
.fil-ariane{ display:flex; flex-wrap:wrap; gap:var(--e2); align-items:center;
  font-size:var(--t-xs); font-weight:700; color:var(--encre-2);
  margin-bottom:var(--e3); }
.fil-ariane a{ color:var(--encre-2); display:inline-flex; align-items:center; }
.fil-ariane li + li::before{ content:"›"; margin-right:var(--e2); color:var(--filet-fort); }
.fil-ariane li{ display:inline-flex; align-items:center; }
/* Cible tactile : comme .btn-petit, la cible ne descend sous 44 px que sur un
   poste tenu à la souris (voir la règle 1024 px, section 5) — le fil d'Ariane
   garde son texte compact, seule la zone cliquable s'agrandit. */
@media (max-width:1024px){ .fil-ariane a{ min-height:44px; } }

.copiable{ display:flex; align-items:center; gap:var(--e2); flex-wrap:wrap;
  justify-content:space-between; padding:10px 12px; background:var(--creme-2);
  border:2px solid var(--filet); border-radius:var(--r-s); }
.copiable .valeur{ font-family:var(--pile-chiffres); font-size:var(--t-s);
  font-weight:700; word-break:break-all; }

.cascade{ display:grid; gap:var(--e3); counter-reset:etape; }
.cascade .indicateur{ position:relative; padding-left:56px; }
.cascade .indicateur::before{
  counter-increment:etape; content:counter(etape);
  position:absolute; left:var(--e4); top:var(--e4);
  width:28px; height:28px; border-radius:50%;
  background:var(--chrome); color:var(--creme);
  display:grid; place-items:center; font-size:var(--t-s); font-weight:800; }
.cascade .operation{ font-size:var(--t-xs); font-weight:800; color:var(--encre-2); }

.progression{ display:grid; gap:var(--e2); list-style:none; }
.progression li{ display:flex; gap:var(--e3); align-items:flex-start;
  font-size:var(--t-s); font-weight:700; color:var(--encre-2); }
.progression li::before{ content:"○"; font-size:18px; line-height:1.2; color:var(--filet-fort); }
.progression li.faite{ color:var(--encre); }
.progression li.faite::before{ content:"●"; color:var(--vert); }
.progression li.courante{ color:var(--encre); }
.progression li.courante::before{ content:"◉"; color:var(--terre); }

.apercu-fichier{ display:flex; align-items:center; gap:var(--e3);
  padding:var(--e3); background:var(--creme-2); border:2px solid var(--filet);
  border-radius:var(--r-s); font-size:var(--t-s); font-weight:700; }
/* Variante texte libre de .apercu-fichier : relecture d'un message WhatsApp
   avant envoi (relance de loyer). Graisse plus légère qu'un nom de fichier —
   c'est une phrase à lire, pas une étiquette. */
.apercu-message{ background:var(--creme-2); font-weight:500; }
.apercu-message-brut{ white-space:pre-wrap; }
/* Variante « champ statique » de .apercu-fichier (type 'statique' de
   composants/champ.php) : fond un cran plus soutenu, pour se distinguer
   d'un champ actif alors qu'il occupe la même place dans le formulaire. */
.apercu-fichier-lecture{ background:var(--creme-3); }
/* Variante REFUS : l'envoi dépasse la limite du serveur (29/09/2026,
   champ « Photos et vidéos du bien »). Rouge --rouge, mesuré à 7,19:1 sur
   blanc — le message doit se lire, c'est lui qui évite une page blanche
   et un formulaire perdu. `align-items:flex-start` parce que ce texte
   fait deux à trois lignes, là où un nom de fichier en fait une. */
.apercu-fichier-refus{ align-items:flex-start; color:var(--rouge);
  background:#FDF2F1; border-color:var(--rouge); font-weight:600;
  line-height:1.45; }


/* ------------------------------------------------------ 15. UTILITAIRES */
/* Ajustements ponctuels de rythme ou d'alignement, qui ne justifient pas un
   composant à eux seuls (M5 de l'audit sécurité : la CSP interdit les
   attributs style="…" — tout passe par une classe). Toujours des jetons
   (var(--e*), couleurs, tailles), jamais de valeur arbitraire. Un motif
   employé une seule fois reste ici plutôt que dans le composant qui
   l'utilise, pour rester réutilisable par le prochain écran. */
.marge-haut-1{ margin-top:var(--e1); } .marge-bas-1{ margin-bottom:var(--e1); }
.marge-haut-2{ margin-top:var(--e2); } .marge-bas-2{ margin-bottom:var(--e2); }
.marge-haut-3{ margin-top:var(--e3); } .marge-bas-3{ margin-bottom:var(--e3); }
.marge-haut-4{ margin-top:var(--e4); } .marge-bas-4{ margin-bottom:var(--e4); }
.marge-haut-5{ margin-top:var(--e5); } .marge-bas-5{ margin-bottom:var(--e5); }
.marge-haut-6{ margin-top:var(--e6); } .marge-bas-6{ margin-bottom:var(--e6); }
.marge-haut-7{ margin-top:var(--e7); } .marge-bas-7{ margin-bottom:var(--e7); }
.sans-marge{ margin:0; }

.aff-bloc{ display:block; }
.aff-aucun{ display:none; }
.texte-centre{ text-align:center; }
.sans-decoration{ text-decoration:none; }
.sans-retrait{ padding-left:0; }
.espace-entre{ justify-content:space-between; }
.centre-flex{ justify-content:center; }
.pleine-flex{ flex:1 1 100%; }
.pleine-grille{ grid-column:1/-1; }
.aligne-debut{ justify-self:start; }
.centre-inline{ margin-inline:auto; }
.chiffres{ font-family:var(--pile-chiffres); }
.interieur-haut-5{ padding-top:var(--e5); }
.interieur-vertical-6{ padding-block:var(--e6); }
/* Réglages fins hors échelle de rythme (e1 = 4px déjà couvert par
   .marge-haut-1) : nudge de 2px pour aligner visuellement une case à cocher
   ou un repère sur la ligne de base du texte voisin. */
.reglage-fin-haut{ margin-top:2px; }
.marge-droite-fine{ margin-right:6px; }
/* display:grid + gap + width:100% : le conteneur d'un choix riche (titre,
   aperçu, lien) à l'intérieur d'une carte .choix. */
.pile-pleine{ display:grid; gap:var(--e2); width:100%; }

.texte-s{ font-size:var(--t-s); }
.texte-m{ font-size:var(--t-m); }
.texte-l{ font-size:var(--t-l); }
.texte-xl{ font-size:var(--t-xl); }
.texte-3xl{ font-size:var(--t-3xl); }
.texte-fort{ font-weight:800; }
.texte-demi{ font-weight:600; }

.texte-encre{ color:var(--encre); }
.texte-clair{ color:var(--encre-clair); }
.texte-vert{ color:var(--vert); }
.texte-rouge{ color:var(--rouge); }
.texte-indigo{ color:var(--indigo); }
.texte-chrome{ color:var(--chrome); }

/* Rangée flexible générique — variante compacte de .rangee-actions quand les
   éléments n'ont pas besoin d'être des cibles de 44 px alignées au centre. */
.rangee-libre{ display:flex; flex-wrap:wrap; gap:var(--e2); }
/* Avatar + nom/rôle sur une ligne (ex. carte du gestionnaire) : jamais de
   retour à la ligne entre le sigle et le texte. */
.rangee-identite{ display:flex; align-items:center; gap:var(--e3); }
.rangee-ecartee{ display:flex; flex-wrap:wrap; justify-content:space-between; gap:var(--e2); }

/* Carte imbriquée dans un .bloc (historique, sous-liste) : même forme, fond
   légèrement distinct pour signaler l'emboîtement sans ajouter de bordure. */
.bloc-secondaire{ background:var(--creme-2); }

/* --------------------------------------------------------------------------
   LOT 2 — Administration des personnes (14/09/2026)
   Cumul des fonctions (admin/utilisateur-formulaire) et assignation des
   biens à un gestionnaire (admin/gestionnaire-assignation).
   -------------------------------------------------------------------------- */

/* Pastilles neutres — les fonctions cumulées d'un utilisateur. Neutres à
   dessein : « la couleur seule ne doit jamais porter l'information » est une
   règle constante de cette charte ; c'est le libellé qui distingue une
   direction d'une comptabilité, jamais une teinte. */
.badges-fonctions{ display:inline-flex; flex-wrap:wrap; gap:6px; }
.badge-fonction{
  display:inline-flex; align-items:center; padding:4px 11px;
  border-radius:100px; white-space:nowrap; letter-spacing:.01em;
  font-size:var(--t-xs); font-weight:800;
  background:var(--tint-neutre); color:var(--encre-2); }

/* Révélation conditionnelle catégorie → fonction → champs propres, sans une
   ligne de JavaScript (voir .choix:has(input:checked) plus haut, même
   technique). ÉCHEC OUVERT délibéré : la base est visible, :has() se
   contente de MASQUER ce qui ne s'applique pas. Un navigateur qui ignore
   :has() (le sélecteur complet devient alors invalide et la règle entière
   est ignorée) laisse tous les volets affichés — plus dense, jamais bloqué.
   L'inverse (base masquée, :has() pour révéler) couperait la saisie des
   champs obligatoires sur ce navigateur : jamais acceptable pour un
   formulaire. */
.volet-categorie,.volet-fonction{ margin-top:var(--e4); }
#creation-utilisateur:not(:has(#cat-interne:checked)) .volet-interne,
#creation-utilisateur:not(:has(#cat-prestataire:checked)) .volet-prestataire,
#creation-utilisateur:not(:has(#cat-client:checked)) .volet-client,
#creation-utilisateur:not(:has(#fonction-gestionnaire:checked)) .volet-gestionnaire,
#creation-utilisateur:not(:has(#fonction-demarcheur:checked)) .volet-demarcheur,
#creation-utilisateur:not(:has(#fonction-proprietaire:checked)) .volet-proprietaire,
#creation-utilisateur:not(:has(#fonction-locataire:checked)) .volet-locataire,
#creation-utilisateur:not(:has(#ouvrir-acces:checked)) .volet-acces{
  display:none; }

/* Groupe de biens assignables, replié/déplié — même principe que
   .divulgation, mais habillé comme un .bloc (c'est une section de contenu,
   pas une action secondaire). */
.groupe-assignation > summary{
  display:flex; align-items:center; justify-content:space-between; gap:var(--e3);
  cursor:pointer; list-style:none; font-size:var(--t-l); font-weight:700; }
.groupe-assignation > summary::-webkit-details-marker{ display:none; }
.groupe-assignation > summary::after{
  content:"⌄"; flex:none; font-weight:800; color:var(--encre-2); }
.groupe-assignation[open] > summary::after{ content:"⌃"; }
.groupe-assignation .pile-serree{ margin-top:var(--e3); }

/* Barre de recherche/filtre au-dessus d'une longue liste à cocher (biens à
   assigner). Repli sans JavaScript : la recherche ne filtre plus rien, mais
   les groupes par bâtiment (repliables) et le Ctrl-F du navigateur restent
   disponibles — rien n'est perdu, la liste reste complète. */
.filtre-coche{ position:relative; margin-bottom:var(--e4); }
.aucun-resultat{ padding:var(--e4); text-align:center; color:var(--encre-2); }

/* --------------------------------------------------------------------------
   LA « CASE ROUGE » — vérification requise (migration 108, 19/09/2026)
   docs/import/classeur-gestion-2026.md § 6, mot pour mot : « applique ce
   qu'on a dit mais laisse ça en case rouge, de sorte à ce que je devrais
   vérifier moi et te donner une réponse. » Une ligne importée douteuse mais
   exploitable reste IMPORTÉE et se voit MARQUÉE, dans l'écran de travail
   lui-même — jamais dans un rapport à part.

   Contraste MESURÉ (formule WCAG L1+0,05 / L2+0,05, calculée ici, pas
   recopiée) avant d'écrire ces règles :
     · --rouge #A8231C sur --tint-rouge #FBE2E0 (pastille)  → 5,84:1
     · --rouge #A8231C sur --blanc #FFFFFF (contour de ligne) → 7,19:1
     · --encre #101A2E sur --tint-rouge (texte du motif)    → 14,11:1
   Tous au-dessus du seuil AA 4,5:1 du texte courant. Cette charte ne connaît
   PAS de mode sombre : aucune règle `prefers-color-scheme` n'existe dans ce
   dépôt à ce jour (recherché avant d'écrire ceci — voir aussi la section 1,
   « Refonte du 18 septembre 2026 », qui ne mentionne aucun mode sombre non
   plus). Rien n'est donc affirmé ici sur un rendu sombre qui n'existe pas
   encore dans l'application — seul le mode clair, réellement rendu, est
   mesuré et garanti.

   PAS UNE COULEUR SEULE : icône « ⚠ » + libellé écrit « À vérifier » +
   contour — un daltonien distingue la ligne même sans percevoir le rouge.
   Repose sur <details>/<summary>, comme `aide()` dans _fonctions.php :
   fonctionne au clavier et au doigt (tactile), pas seulement à la souris —
   un simple `title` de survol ne marche ni au clavier ni sur téléphone,
   donc jamais seul ici (title ajouté en complément, pour la souris).
   -------------------------------------------------------------------------- */
.case-rouge{ display:inline-block; }
.case-rouge > summary{
  display:inline-flex; align-items:center; gap:6px; cursor:pointer; list-style:none;
  padding:4px 11px; border-radius:100px; white-space:nowrap;
  font-size:var(--t-xs); font-weight:800; letter-spacing:.01em;
  background:var(--tint-rouge); color:var(--rouge); border:1.5px solid var(--rouge); }
.case-rouge > summary::-webkit-details-marker{ display:none; }
.case-rouge .case-rouge-motif{
  display:block; margin-top:6px; padding:var(--e2) var(--e3);
  background:var(--blanc); border:1.5px solid var(--rouge); border-radius:var(--r-s);
  color:var(--encre); font-size:var(--t-s); font-weight:400; max-width:42ch; }

/* Bloc d'alerte sur une fiche (bien/contrat/loyer) : une ligne par marque
   active, chacune avec son bouton de levée. Couleur reprise de
   .encart.encart-alerte (déjà --rouge/--tint-rouge, déjà mesurée ci-dessus) ;
   seule la disposition en liste, propre à la case rouge, est ajoutée ici. */
.case-rouge-fiche{ display:grid; gap:var(--e3); }
.case-rouge-fiche .case-rouge-ligne{
  display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:var(--e3); }
.case-rouge-fiche .case-rouge-ligne p{ max-width:56ch; }

/* Compteur en évidence (« N ligne(s) à vérifier ») — même famille visuelle,
   posé en tête d'écran, jamais un simple chiffre discret : sans lui, une
   marque rouge devient un décor qu'on cesse de voir au bout d'une semaine
   (exigence explicite de la cliente, § 6 du document cité plus haut). */
.case-rouge-compteur{
  display:flex; align-items:center; gap:var(--e2); font-weight:800; }
.case-rouge-compteur .case-rouge-nombre{
  display:inline-flex; align-items:center; justify-content:center;
  min-width:28px; height:28px; padding-inline:8px; border-radius:100px;
  background:var(--rouge); color:var(--blanc); font-size:var(--t-s); }

/* ------------------------------------------------------- PALIERS D'ÉCRAN */
/* 600 px : la tablette en portrait étroit et le grand téléphone.           */
@media (min-width:600px){
  .paire{ grid-template-columns:1fr 1fr; }
  .indicateurs{ grid-template-columns:repeat(2,1fr); }
  .grille{ grid-template-columns:repeat(2,1fr); }
  .filtres{ grid-template-columns:repeat(2,1fr); align-items:end; }
  .filtres .pleine{ grid-column:1/-1; }
  .barre-validation{ margin-inline:calc(var(--e5) * -1); padding-inline:var(--e5); }
}
/* 768 px : tablette portrait. Les tableaux redeviennent des tableaux.      */
@media (min-width:768px){
  :root{ --t-2xl:27px; --t-3xl:33px; }
  .enveloppe{ padding-inline:var(--e5); }
  .bloc{ padding:var(--e5); }
  .cascade{ grid-template-columns:repeat(2,1fr); }
}
/* 1024 px : tablette paysage et petit portable. Densité accrue.            */
@media (min-width:1024px){
  .indicateurs{ grid-template-columns:repeat(4,1fr); }
  .grille{ grid-template-columns:repeat(3,1fr); }
  .filtres{ grid-template-columns:repeat(4,1fr); }
  .filtres .pleine{ grid-column:auto; }
  .cascade{ grid-template-columns:repeat(3,1fr); }
  .barre-outils{ grid-template-columns:1fr auto; align-items:center; }
  .barre-outils .onglets{ grid-column:1; }
  .barre-outils .outils-secondaires{ grid-column:2; justify-content:flex-end; }
  .barre-outils .filtres{ grid-column:1/-1; }
}
/* 1280 px : ordinateur de bureau. Densité maximale.                        */
@media (min-width:1280px){
  .grille{ grid-template-columns:repeat(4,1fr); }
  .cascade{ grid-template-columns:repeat(6,1fr); }
  .cascade .indicateur{ padding-left:var(--e4); padding-top:var(--e7); }
  .cascade .indicateur::before{ top:var(--e3); left:var(--e4); }
}
@media (prefers-reduced-motion:reduce){
  *{ transition:none!important; animation:none!important; scroll-behavior:auto!important; }
}

/* ------------------------------------------- GALERIE PHOTOS D'UN BIEN */
/* Ajoutée le 21/09/2026 avec le dépôt de photos (fiche bien). Grille qui
   se remplit d'elle-même : deux vignettes sur téléphone, davantage sur
   grand écran, sans point de rupture à maintenir. */
.galerie-bien{
  display:grid; gap:var(--e3);
  grid-template-columns:repeat(auto-fill, minmax(150px, 1fr)); }
.galerie-bien-vignette{ margin:0; }
.galerie-bien-vignette img{
  width:100%; aspect-ratio:4/3; object-fit:cover;
  border-radius:8px; border:1px solid var(--filet-fort); background:var(--champ-fond); }
.galerie-bien-vignette figcaption{ margin-top:var(--e1); }
.galerie-bien-vignette form{ margin-top:var(--e1); }

/* ------------------------------------- CACHET DE L'AGENCE (25/09/2026)
   Posé sur la quittance, sous la mention « Cachet et signature ».
   ⚠️ Il n'apparaît QUE sur un document dont l'existence prouve déjà la
   double validation — voir le commentaire dans ecrans/agence/quittance.php.
   `mix-blend-mode: multiply` : le cachet se pose SUR le trait de signature
   comme un tampon d'encre, sans le masquer d'un carré blanc. */
.cachet-agence{
  display:block; width:150px; height:auto; margin:.4rem 0 0 auto;
  opacity:.92; mix-blend-mode:multiply;
}
@media print{
  /* À l'impression, jamais de fond : une imprimante rendrait le blanc en
     gris sale autour du tampon. */
  .cachet-agence{ width:38mm; opacity:1; -webkit-print-color-adjust:exact; print-color-adjust:exact; }
}

/* ------------------------------------ LE LION D'ACCUEIL (27/09/2026)
   Demande de la directrice : « il faut que le lion soit là, pour dire
   connectez-vous ». La mascotte de sa plaquette imprimée, détourée.

   ⚠️ `position:absolute` DANS la scène, jamais dans la carte : le
   formulaire garde sa largeur et sa place exactes. Une illustration ne
   doit jamais décaler un champ de saisie.

   ⚠️ INVISIBLE SOUS 900 px. Sur un téléphone, la place appartient aux
   deux champs et au bouton : une illustration qui pousse le bouton
   « Se connecter » sous la ligne de flottaison transforme une connexion
   en défilement.

   `display:none` et non `opacity:0`, pour que l'image ne prenne aucune
   place dans la mise en page. S'y ajoute `loading="lazy"` sur la balise :
   une image paresseuse hors du champ visible n'est en principe pas
   téléchargée, ce qui épargnerait son poids à quelqu'un qui se connecte en
   3G à Abidjan.

   ⚠️ « EN PRINCIPE » : je ne l'ai PAS vérifié sur un cache vide. Le seul
   essai fait l'a été sur un navigateur qui avait déjà l'image en mémoire,
   et il ne prouve donc rien. Ne pas transformer cette phrase en
   affirmation sans avoir mesuré.

   ⚠️ CE QUI EST MESURÉ, en revanche : le poids du fichier. Le lion
   « bienvenue » pèse 105 Ko en WebP, contre 560 Ko pour le même dessin en
   PNG. C'est la raison du WebP — pas une mode. Le dessin reste celui de la
   plaquette, masque de transparence du graphiste compris. */
.connexion-scene{ position:relative; overflow:hidden; }

/* ⭐ SOUS 880 px — LE LION ENTIER, AU-DESSUS DE LA CARTE.
   27/09/2026. Il était d'abord masqué sous 1100 px : la directrice, qui
   ouvre le portail sur son téléphone, n'en voyait donc jamais aucun et a
   conclu — à raison — que rien n'avait été déployé. Je l'ai ensuite
   remplacé par un buste, qu'elle a refusé : « le lion il est à moitié,
   c'est pas intéressant ». C'est donc le lion ENTIER, partout.

   Il passe DANS LE FLUX : la scène devient une colonne, le lion s'empile
   au-dessus de la carte. Hors du flux il aurait chevauché soit le
   formulaire, soit le lien du bas — les deux ont été essayés et vus à
   l'écran.

   ⚠️ HAUTEUR BORNÉE — ET LA BORNE A ÉTÉ MESURÉE, PAS ESTIMÉE. À 24 % de
   l'écran, le bouton « Se connecter » tombait 17 px SOUS la ligne de
   flottaison sur un Android de 360×640 : relevé dans le navigateur, après
   avoir écrit l'inverse. D'où la seconde règle ci-dessous, qui rapetisse
   le lion sur les écrans courts. Mesures retenues :
     · 390×844 → bas du bouton à 727 px, aucun défilement ;
     · 375×667 et 360×640 → voir la règle `max-height:700px`. */
.connexion-scene{ flex-direction:column; gap:var(--e2); }
.lion-accueil{
  position:static; flex:0 0 auto;
  height:min(24vh, 190px); width:auto;
  pointer-events:none; user-select:none;
  filter:drop-shadow(0 10px 18px rgba(8,16,34,.34));
}

/* ⚠️ ÉCRAN COURT — le lion rapetisse, il ne disparaît pas. Sur un
   téléphone de 640 px de haut, la carte seule en occupe déjà 520 : c'est
   le lion qui cède la place, pas le bouton. Il reste ENTIER — c'est la
   demande. */
@media (max-height:700px){
  .lion-accueil{ height:min(16vh, 108px); }
}

.connexion-carte{ position:relative; z-index:1; }

/* ⭐ À PARTIR DE 880 px — LE LION PASSE À GAUCHE DE LA CARTE, main tendue
   vers le formulaire.

   880 et non 1100 : à 880 px la gouttière — (fenêtre − carte) ÷ 2 — fait
   encore 190 px, soit un lion de 252 px de haut, parfaitement lisible.
   J'avais fixé 1100 en jugeant qu'en dessous il serait « méconnaissable » :
   c'était faux, et cela privait de lion toutes les fenêtres de portable
   non plein écran.

   ⚠️ IL EST ACCROCHÉ À LA CARTE, PAS AU BORD DE L'ÉCRAN. `right` part du
   milieu, ajoute la demi-carte (210 px, voir `.connexion-carte`) et 20 px
   de marge : la main tendue s'arrête donc toujours juste avant la carte.
   Calé au bord de la fenêtre, elle passait DERRIÈRE — 77 px de
   recouvrement mesurés en 1400×900, et c'est la main qui fait le geste. */
@media (min-width:880px){
  .connexion-scene{ flex-direction:row; gap:0; }
  .lion-accueil{
    position:absolute; bottom:0; left:auto; right:calc(50% + 230px);
    width:min(calc((100vw - 420px) / 2 - 40px), 430px);
    height:auto;
    filter:drop-shadow(0 18px 28px rgba(8,16,34,.42));
    z-index:0;
  }
}
/* Écran bas (portable 13 pouces posé sur un bureau) : on rapetisse plutôt
   que de laisser le lion dépasser du cadre. */
@media (min-width:880px) and (max-height:760px){
  .lion-accueil{ width:min(calc((100vw - 420px) / 2 - 40px), 330px); }
}

/* ═══════════════════════════════════════════════════════════════════════════
   CE QUI N'EXISTE QU'À L'IMPRESSION — corrigé le 27/09/2026.
   ---------------------------------------------------------------------------
   ⚠️ CETTE RÈGLE ÉTAIT ÉCRITE DANS impression.css, ET N'A JAMAIS SERVI. Cette
   feuille-là est appelée avec `media="print"` : le navigateur ne l'applique
   qu'à l'impression, et le `@media screen` qui s'y trouvait ne pouvait jamais
   être vrai.

   Conséquence, visible sur TOUS les documents — quittance, récapitulatif,
   bordereau : l'en-tête d'impression (nom de l'agence, adresse, numéro
   d'agrément, objet, date d'édition) s'affichait en clair au-dessus du
   document à l'écran, répétant ce qu'il dit déjà en dessous. Constaté en
   refaisant la quittance de loyer.

   Les trois règles d'impression posent `display:…!important` de leur côté :
   le document imprimé retrouve donc bien son en-tête et son pied. */
.entete-impression,
.pied-impression,
.impression-seulement{ display:none; }
