/* GRILLES SOUPLES — filet de sécurité pour tous les formats d'écran.
   =================================================================

   POURQUOI CE FICHIER EXISTE

   Un agent a photographié son écran le 19/07/2026 : sur son iPhone 14, le comparateur
   affichait « 412 00 » au lieu de « 412 000 € », et deux cartes étaient coupées à droite.

   La cause n'est pas une largeur d'écran particulière, c'est une règle de CSS que presque
   personne n'a en tête : dans une grille (ou une boîte flexible), une cellule reçoit par
   défaut « min-width: auto ». Autrement dit, elle REFUSE de descendre sous la largeur de
   son propre contenu. Quand la place manque, elle ne s'adapte pas : elle pousse son
   conteneur, et c'est le conteneur parent qui coupe ce qui dépasse.

   MESURÉ : il suffit que le texte grossisse de 15 à 17 px, soit 13 %, pour que la mise en
   page casse. C'est atteint par le réglage « Texte plus grand » d'iOS, par le zoom de
   Safari (menu AA), ou par l'affichage zoomé qui fait passer un iPhone 14 de 390 à 320
   points. À taille normale tout tient, ce qui explique que le défaut soit resté invisible
   pendant des mois : il ne se voit que chez quelqu'un qui a agrandi son texte.

   Le projet comptait 103 grilles déclarées en « fr », et AUCUNE n'était protégée.

   POURQUOI CETTE FORME PLUTÔT QU'UNE AUTRE

   « :where(*) » a une spécificité NULLE. Cette feuille ne peut donc écraser aucun style du
   projet : n'importe quelle règle existante, même la plus banale, garde la priorité. C'est
   ce qui rend ce filet sûr à charger partout, y compris sur des écrans qu'on n'a pas
   relus un par un.

   Une règle « @media » sur la largeur d'écran ne suffirait pas : elle ne verrait pas un
   texte agrandi sur un grand écran, qui est précisément le cas de l'agent.

   MESURÉ sur le simulateur, à 320 px avec le texte agrandi de 30 % :
   éléments sortant de l'écran 18 → 0, pire débordement 76 px → 9 px.

   CE QUE CE FICHIER NE FAIT PAS

   Il empêche la mise en page de casser, mais il ne décide pas à la place du contenu.
   Un bloc où le texte NE DOIT JAMAIS être coupé (un montant, par exemple) doit en plus
   se replier de lui-même. Voir « .resume-grid » dans comparateur-v1.html :

       grid-template-columns: repeat(auto-fit, minmax(96px, 1fr));

   ⚠️ Ne jamais laisser tronquer un montant : « 412 00 » ne se lit pas comme un nombre
   coupé, il se lit comme un AUTRE montant. */

/* 1. Aucune cellule ne peut forcer son conteneur à déborder. */
:where(*) { min-width: 0; }

/* 2. Une image ou un dessin ne dépasse jamais de son cadre. */
:where(img, svg, video, canvas) { max-width: 100%; }

/* 3. Un mot trop long pour la ligne (adresse électronique, nom de commune composé)
      passe à la ligne au lieu de sortir de l'écran. « break-word » ne coupe QUE si le mot
      ne peut vraiment pas tenir : les autres mots gardent une coupure normale. */
:where(body) { overflow-wrap: break-word; }

/* ═══ L'ONGLET DU NOM D'ECRAN (17/08/2026) ══════════════════════════════════════════════════
   ⚠️ J'Lay : « est-ce que le nom de l'onglet on peut le mettre au centre du header avec un fond
   sous forme d'onglet pour bien informer sur quelle page on se trouve ? », puis, après trois
   maquettes : « la 2 » — languette arrondie posée sur un liseré vert qui ferme l'en-tête — et
   « tu le fais sur tous les écrans pour chaque menu ».

   ⚠️ ICI ET NULLE PART AILLEURS. Cinq écrans portent ce nom (accueil, administration, pilotage,
   profil, et l'application), chacun avec son propre <style>. Recopier la règle cinq fois, c'est
   la certitude qu'une retouche n'en atteindra que trois : cette feuille est déjà partagée, elle
   est le seul endroit où « tous les écrans » veut dire quelque chose.

   ⚠️ LES MARGES NEGATIVES SONT CALEES SUR LE REMBOURRAGE DES EN-TETES (14 px sur les côtés,
   10 px en bas) : le liseré doit courir d'un bord à l'autre, sinon il s'arrête avant et ne
   ferme plus rien. Un en-tête au rembourrage différent devra ajuster CES DEUX valeurs, pas
   redéfinir la règle. */
/* ⚠️ LE LISERE EST LA BORDURE DE L'EN-TETE, PAS CELLE DE CETTE LIGNE (corrigé le 17/08).
   Ma première version portait le trait ici, avec des marges négatives de -14 px calées sur
   l'administration. Or le rembourrage des en-têtes VARIE : 14 px sur l'administration, 16 px sur
   le profil, 28 px sur l'accueil et le pilotage. Le liseré s'arrêtait donc avant les bords sur
   trois écrans — J'Lay : « manque le liseré ». Posé sur l'en-tête lui-même, il couvre toujours
   toute sa largeur, quel que soit son rembourrage : plus rien à caler écran par écran.
   ⚠️ ET ON NE DEVINE PLUS LE REMBOURRAGE BAS : on l'ANNULE. Ma deuxième version le rattrapait
   par une marge négative, avec une variable par écran — mesuré ensuite dans le navigateur, le
   rembourrage RÉEL de l'accueil est de 8 px, pas les 14 px que sa feuille annonce : une autre
   règle l'écrase. Lire une valeur dans le CSS ne dit pas ce que le navigateur applique. En le
   mettant à zéro ici, la languette se pose au bas de l'en-tête sans qu'aucun écran n'ait à
   déclarer quoi que ce soit — et l'espace au-dessus vient du « margin-top » de la ligne.
   ⚠️ SPECIFICITE SUFFISANTE, PAS DE « !important » : « .header:has(…) » l'emporte sur « .header ». */
/* ⚠️ DEUX CONTENEURS, PAS UN. Quatre écrans nomment leur en-tête « .header » ; l'application
   l'appelle « .user-bar ». Ma règle ne visait que le premier : dans l'application, il n'y avait
   donc NI liseré ni remontée — et c'est pourtant l'écran que J'Lay donne pour référence
   (« la position idéale serait celle de l'onglet estimation »). Les deux sélecteurs, une seule
   recette. */
/* ⚠️ UN TRAIT FIN, DE LA COULEUR DES PASTILLES (J'Lay, 17/08 : « le liseré, il le faudrait
   beaucoup plus fin comme sur les pastilles du menu du header »). Ses valeurs, reprises telles
   quelles de « .p-nav-btn » : 1 px, « rgba(46,125,50,0.30) ». Un trait vert plein de 2 px pesait
   plus lourd que tout le reste de l'en-tête. */
/* ⚠️ ET LE HAUT AUSSI, ICI ET NULLE PART AILLEURS (17/08). J'Lay : « la hauteur du header est un
   peu moins haut que les autres, c'est vraiment léger mais il faut corriger, je veux que ce soit
   parfait » — référence : l'écran d'accueil. Mesuré écran par écran, le compte n'y était pas :

                     téléphone   grand écran
       accueil            8           12
       administration    10        (aucune règle → 10)
       pilotage          10           12
       coque             10           10

   Sur son Mac — donc en grand écran — l'accueil monte à 12 pendant que l'administration et la
   coque restent à 10. Quatre pixels, exactement ce qu'il voyait. Le « 8 » de l'accueil vient d'un
   resserrage demandé le 14/08 et appliqué à UN SEUL écran ; les surcharges grand écran ont été
   ajoutées à deux écrans sur quatre. Chaque valeur, prise isolément, se défendait : c'est la
   comparaison qui manquait.

   ⚠️ UNE SEULE DEFINITION, PAS QUATRE. Ce bandeau a déjà dérivé deux fois — le 14/08 par ce
   resserrage, le 16/08 par un bloc vide laissé dans l'administration. Quatre valeurs dans quatre
   fichiers finissent toujours par s'écarter. La règle vit donc avec celle de l'onglet, et vise
   exactement les écrans qui le portent.
   ⚠️ « var(--safe-haut) » EST REPRIS TEL QUEL : c'est la zone de l'heure et de la batterie sur
   iPhone, que le bandeau d'accès neutralise quand il occupe le haut. La retirer reposerait
   l'heure sur le texte — le défaut du 13/08. */
.header:has(.ecran-onglet-ligne),
.user-bar:has(.ecran-onglet-ligne) {
  border-bottom: 1px solid rgba(46,125,50,0.30);
  padding-top: calc(var(--safe-haut, env(safe-area-inset-top)) + 10px);
  padding-bottom: 0;
}
@media (min-width: 768px) {
  /* ⚠️ LES QUATRE MONTENT ENSEMBLE. C'est en grand écran que l'écart se voyait — sur le Mac de
     J'Lay, deux écrans passaient à 12 px et deux restaient à 10. */
  .header:has(.ecran-onglet-ligne),
  .user-bar:has(.ecran-onglet-ligne) {
    padding-top: calc(var(--safe-haut, env(safe-area-inset-top)) + 12px);
  }
}
/* ⚠️ « 4px », PAS 8 : J'Lay — « il y a trop d'espace perdu entre le bas du header et les
   contenus ». La languette n'a pas besoin de respirer au-dessus, elle a déjà sa propre hauteur. */
/* ⚠️ A GAUCHE, PAS AU CENTRE (J'Lay, 17/08, après comparaison). Deux raisons, et la seconde est
   la vraie : la languette s'aligne sur le nom de l'agence et sur le bord du contenu — on lit
   « efficity », puis juste dessous où l'on se trouve ; et surtout SA POSITION NE DEPEND PLUS DU
   LIBELLE. Au centre, « Accueil » et « Calcul des honoraires » ne commençaient pas au même
   endroit : l'onglet se déplaçait à chaque changement d'écran, et l'œil devait le retrouver.
   ⚠️ « 14px » N'EST PAS UN NOMBRE CHOISI A L'ŒIL : c'est le rembourrage latéral des en-têtes, le
   même que celui du contenu. La languette démarre donc exactement là où commence le texte en
   dessous. Si ce rembourrage change, celui-ci doit suivre. */
.ecran-onglet-ligne {
  display: flex;
  justify-content: flex-start;
  padding-left: 14px;
  margin-top: 4px;
}
.ecran-onglet {
  background: #E7F1E7;
  color: #1F5423;
  border: 1px solid rgba(46,125,50,0.30);
  /* ⚠️ LA BORDURE BASSE PREND LA COULEUR DU FOND, elle ne disparaît pas (J'Lay, 17/08 : « le
     dessous du texte de l'onglet ne doit pas avoir de liseré »). Avec « border-bottom:none », la
     languette perdait 2 px de hauteur et le liseré du conteneur réapparaissait dessous : le trait
     traversait la languette, qui cessait de se lire comme l'onglet ACTIF. En lui donnant la
     couleur du fond, elle recouvre le liseré exactement sur sa largeur — c'est ce trait
     interrompu qui fait tout l'effet d'onglet. */
  /* ⚠️ AUCUNE BORDURE BASSE — ET PAS NON PLUS « de la couleur du fond ». J'avais posé
     « 1px solid #E7F1E7 » en croyant masquer le liseré : mais cette bordure se dessine SOUS la
     languette, sur le blanc de l'en-tête, où le vert pâle se voit. J'Lay : « l'onglet accueil est
     le seul qui a le petit liseré dessous le texte ». Mesuré ensuite sur deux écrans : les valeurs
     étaient identiques — ce n'était donc pas l'accueil qui différait, c'était ce trait pâle,
     visible partout mais remarqué là.
     Sans bordure, et descendue d'un pixel, c'est le FOND de la languette qui recouvre le liseré :
     un aplat, pas un trait de plus. */
  border-bottom: none;
  border-radius: 9px 9px 0 0;
  /* ⚠️ MEME GABARIT QUE LE BANDEAU « PRÉ-PRODUCTION » (J'Lay, 17/08 : « mets-les à la même taille
     que celui de la préprod, ils tiendront moins de place sur le header »). Ses valeurs, reprises
     telles quelles depuis preprod.js : « font:700 10px », « letter-spacing:1.2px »,
     « padding:4px 10px ». Deux étiquettes qui cohabitent dans le même en-tête doivent avoir le
     même poids — sinon l'une écrase l'autre, et c'est la mention d'essai qui l'emportait. */
  /* ⚠️ MEME HAUTEUR QUE LE BANDEAU « PRÉ-PRODUCTION » (J'Lay : « il y a un problème de hauteur
     entre le bandeau préproduction et les autres, c'est trop haut »). Le bandeau fait 18 px :
     10 px de texte sur une interligne de 1, plus 4 px de rembourrage en haut et en bas. On reprend
     « font: 700 10px/1 » — c'est l'INTERLIGNE qui faisait toute la différence, pas le corps. */
  padding: 4px 14px;
  /* ⚠️ PROPRIETES SEPAREES, PAS LE RACCOURCI « font ». J'avais écrit « font: 700 10px/1 inherit » :
     « inherit » n'est pas une famille valide dans ce raccourci, et le navigateur rejette alors la
     déclaration ENTIERE — mesuré, il appliquait 16 px en graisse 400, soit tout le contraire.
     Une règle invalide ne prévient pas : elle est simplement ignorée. */
  font-size: 10px;
  line-height: 1;
  font-weight: 700;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  white-space: nowrap;
  /* Descend d'un pixel : son fond recouvre le liseré, qui fait 1 px. */
  margin-bottom: -1px;
  position: relative;
  z-index: 2;
  /* ⚠️ Sur un iPhone, un nom long ne doit pas pousser la languette hors de l'écran. */
  max-width: calc(100% - 20px);
  overflow: hidden;
  text-overflow: ellipsis;
}
/* ⚠️ SANS NOM, PAS DE LANGUETTE. Dans l'application, le titre est posé par le script au
   changement d'écran : avant qu'il ne s'exécute, l'élément est VIDE, et une languette vide se
   lirait comme un défaut d'affichage. Le liseré reste : c'est lui qui ferme l'en-tête. */
.ecran-onglet:empty { display: none; }

/* ═══ SUR GRAND ECRAN, LE MENU « ⋯ » SE DEPLIE EN PASTILLES (17/08/2026) ═════════════════════
   ⚠️ J'Lay : « sur écran large je voudrais avoir toutes les pastilles visibles, et tu ne changes
   rien sur le menu actuel sur les téléphones ».

   ⚠️ CE MENU N'A JAMAIS ETE UN CHOIX DE DESIGN, C'EST UNE CONTRAINTE DE PLACE. Le code le dit
   déjà : « 6 boutons ne tenaient pas dans les 358 px utiles d'un iPhone de 390 ». Sur une
   tablette ou un ordinateur, cette contrainte n'existe plus — on rend donc visible ce qui n'avait
   été replié que faute de largeur.

   ⚠️ ON DEPLIE LE MENU LUI-MEME, ON NE RECOPIE PAS SES ENTREES EN PASTILLES. Cinq écrans le
   portent : dupliquer, c'était dix endroits à tenir d'accord, et la certitude qu'une entrée
   ajoutée n'apparaîtrait que d'un côté. Le panneau change de forme, son contenu ne bouge pas.

   ⚠️ ET ON NE TOUCHE PAS AU « display » DES BOUTONS. « p-menu-admin » porte « display:none » en
   attribut, levé par le script pour le seul Editeur : le forcer ici afficherait l'Administration
   à tout le monde. C'est le PANNEAU qu'on affiche, pas ses entrées.
   ⚠️ « font-size:0 » MASQUE LE LIBELLE sans toucher au balisage : le texte est un nœud direct du
   bouton, sans balise autour. Le <svg> garde sa taille, fixée par ses attributs. */
@media (min-width: 768px) {
  /* Le « ⋯ » n'a plus d'objet : ce qu'il cachait est désormais à côté. */
  #p-btn-plus { display: none !important; }

  /* Le panneau flottant redevient une simple rangée, dans le flux de la barre.
     « !important » sur la position : le script en pose une en ligne à l'ouverture. */
  #p-menu {
    display: flex !important;
    position: static !important;
    inset: auto !important;
    gap: 6px;
    background: none;
    border: none;
    box-shadow: none;
    min-width: 0;
    overflow: visible;
  }
  /* ⚠️ L'ETAT ACTIF SUIT LES AUTRES PASTILLES : « .p-nav-btn.actif » ne s'applique pas ici,
     puisque ces boutons vivent dans le menu, pas dans la barre. On reprend ses valeurs. */
  #p-menu button.actif {
    background: #2E7D32 !important;
    border-color: #2E7D32 !important;
    color: #fff !important;
  }
  #p-menu button {
    width: 44px; height: 44px; padding: 0;
    border-radius: 50%;
    background: rgba(46,125,50,0.12);
    border: 1px solid rgba(46,125,50,0.30);
    color: #2E7D32;
    justify-content: center;
    /* ⚠️ « gap: 0 » AUSSI. Le bouton porte « gap:10px » pour séparer son icône de son libellé ;
       le libellé passe à 0 px mais reste PRESENT, et l'écart subsiste — l'icône était donc
       poussée de 5 px vers la gauche. J'Lay : « les icônes à l'intérieur des pastilles ne sont
       pas centrées ». Ce qu'on ne voit plus occupe encore de la place. */
    gap: 0;
    /* Le libellé disparaît, l'icône reste. */
    font-size: 0;
  }
  /* ⚠️ MEME TAILLE QUE LES PASTILLES D'ORIGINE (J'Lay : « la taille des pictogrammes dans les
     pastilles, elles sont peut-être un peu petites pour certaines, il faudrait que tu sois très
     uniforme »). Mesuré dans la barre : 19 px pour les pastilles de navigation, 16 px pour les
     entrées du menu — un écart de 3 px, assez petit pour qu'on ne le nomme pas, assez grand pour
     qu'on le voie. Le CSS l'emporte sur les attributs « width »/« height » des <svg>. */
  #p-menu button svg { width: 19px; height: 19px; flex-shrink: 0; }
  /* La déconnexion garde sa couleur d'avertissement — elle ne se confond pas avec le reste. */
  #p-menu button[onclick*="econnexion"] {
    background: rgba(192,57,43,0.10);
    border-color: rgba(192,57,43,0.32);
    color: #C0392B;
  }
}

/* ═══════════════════════════════════════════════════════════════════════════════════════════
   LE CHEVRON DE CE QUI S'OUVRE ET SE FERME — UNE SEULE FORME POUR TOUTE L'APPLICATION
   ─────────────────────────────────────────────────────────────────────────────────────────
   ⚠️ J'LAY, 30/08/2026 : « les chevrons d'ouverture et de fermeture sont trop petits. On en a
      utilisé qui vont très bien dans Mycompétence. Tu pourrais prendre le modèle et faire les
      mêmes pour l'application MyEstim. »

   ⚠️ LE MODÈLE VIENT DE MYCOMPÉTENCE, où il avait été posé le 27/08 pour la même raison : six
      écrans y affichaient trois apparences différentes pour un seul geste. Une pastille ronde
      de 26 px, un chevron épais de 13 px qui PIVOTE d'un quart de tour — jamais deux dessins
      pour dire « ouvert » et « fermé ».

   ⚠️ ET LA CIBLE FAIT 26 PX, PAS 16 : c'est ce que J'Lay reprochait. Un chevron de 16 px dans
      un coin se rate au doigt, et se voit mal sur un écran au soleil. La pastille donne au geste
      une surface franche, et son fond dit où appuyer sans qu'on ait à deviner.

   ⚠️ L'ÉTAT OUVERT SE DIT PAR LA CLASSE « deplie », JAMAIS par un sélecteur de contexte : c'est
      exactement ce qui avait produit six apparences différentes dans Mycompétence, chaque écran
      écrivant sa propre règle de rotation.
      Garde-fou : tests/un-seul-chevron-pour-tout-ouvrir.mjs
   ═══════════════════════════════════════════════════════════════════════════════════════════ */
.chevron-repli {
  width: 26px; height: 26px; border-radius: 50%; border: none; padding: 0;
  display: grid; place-items: center; flex: none;
  color: #8E8E93; background: #F2F2F7; cursor: pointer;
  transition: background .12s, color .12s, transform .18s ease;
}
.chevron-repli svg {
  width: 13px; height: 13px; fill: none; stroke: currentColor;
  stroke-width: 2.8; stroke-linecap: round; stroke-linejoin: round;
}
.chevron-repli:hover { background: #E5E5EA; color: #3C3C43; }
/* Ouvert : le chevron pointe vers le bas, et la pastille passe au vert de l'application. */
.chevron-repli.deplie { transform: rotate(90deg); background: #E8F5E9; color: #2E7D32; }

/* ⚠️ LA VARIANTE AMBRE, ET POURQUOI ELLE EXISTE (31/08/2026). J'Lay a demande que TOUS les
   chevrons prennent ce dessin, puis, mis devant le cas : « garde l'ambre ». Le chevron des
   « ventes ecartees du calcul » est ambre depuis le 18/07 — vert pour ce qui ENTRE dans le
   calcul, ambre pour ce qui en SORT. Le passer au vert lui ferait dire le contraire de ce
   qu'il annonce. La FORME est donc commune, la COULEUR reste porteuse de sens. */
.chevron-repli.ambre { color: #B26A00; background: #FFF6E8; }
.chevron-repli.ambre:hover { background: #FDECD2; color: #8A5200; }
.chevron-repli.ambre.deplie { background: #FDECD2; color: #B26A00; }

@media (prefers-reduced-motion: reduce) {
  .chevron-repli { transition: none; }
}
