/* COPIE AUTOMATIQUE DE public/base/seuils-retenus.css -- NE PAS EDITER ICI.
   La source est au banc ; `python tools/base/porter_reprise.py` refait
   cette copie, et son mode `verifier` signale toute divergence. */
/* =========================================================================
   LES QUATRE SEUILS
   =========================================================================

   LE PRODUIT EN ECRIT VINGT-NEUF. 822 regles sous `@media`, reparties sur
   vingt-neuf largeurs differentes, dont 720, 760 et 768 -- trois seuils a huit
   pixels d'ecart qui ne decrivent pas trois moments de la mise en page, mais le
   meme, decide trois fois par trois personnes. Idem pour 880, 899 et 900 ;
   idem pour 980 et 1000 ; idem pour 1180 et 1200.

   ON NE LES A PAS FUSIONNES AU JUGEMENT. On a rendu la page a une echelle de
   largeurs, de 320 a 1440, et releve a chacune l'etat des objets que la base
   porte -- afficher ou non, en ligne ou en colonne, combien de colonnes, fixe
   ou dans le flux. Une largeur ou rien ne bascule n'est pas un seuil, quoi
   qu'en dise la feuille. Puis on a resserre a 4 px autour de chaque bascule
   pour en trouver la valeur exacte.

   QUATRE MOMENTS, ET PAS UN DE PLUS :

       640    le telephone
       760    le rail apparait
       900    la disposition large : la barre reprend ses trois colonnes, le
              tableau redevient un tableau
      1200    le rail se deplie et montre ses libelles

   DEUX FAUX SEUILS ECARTES EN CHEMIN. Le releve grossier en donnait six ; deux
   n'existaient pas. Le remplissage horizontal de la barre change bien entre
   1360 et 1440, mais GRADUELLEMENT -- il est deja fluide. Un pas de 40 px fait
   passer une variation continue pour une marche : c'est en resserrant a 4 px
   qu'on voit qu'elle bouge partout, donc nulle part en particulier.

   LE PIEGE DE LA MESURE, paye une fois : la HAUTEUR d'un element change a
   chaque pixel parce que le texte se replie. Gardee dans la signature, elle
   faisait ressembler chaque pas a un palier -- quinze « seuils » dont treize
   n'etaient que du texte changeant de ligne. La marge automatique du pied
   faisait la meme chose. On ne releve que ce qui SAUTE.

   =========================================================================
   LE RAIL A TROIS ETATS, PAS DEUX
   =========================================================================

   C'est le seul objet de la base qui en a trois, et c'est ce qui justifie deux
   de nos quatre seuils :

       sous 760      absent      la place manque, le menu du compte prend le
                                 relais
       760 a 1200    replie      62 px, les icones seules : on sait ou l'on est
                                 sans perdre la largeur du contenu
       au-dela       deploye     232 px, les libelles

   LA COQUE SUIT EXACTEMENT LES MEMES TROIS ETATS, sans quoi le contenu passe
   sous le rail ou laisse une bande vide. C'est ecrit ici, au meme endroit,
   pour qu'on ne puisse pas changer l'un sans voir l'autre.

   =========================================================================
   CE QUE CETTE FEUILLE NE FAIT PAS
   =========================================================================

   SOUS 900 px, LA BARRE PERD SA NAVIGATION et c'est le dessin du produit : les
   six entrees passent dans le menu du compte. La base le reproduit ; savoir si
   ce menu suffit sur telephone est une question de produit, pas de feuille de
   style, et elle reste ouverte.

   Les grilles internes de chaque ecran -- deux colonnes de cartes, paires de
   chiffres cote a cote -- ne sont pas ici : elles appartiennent au fichier de
   leur page. Cette feuille ne porte que ce qui est partage.
   ========================================================================= */


/* -------------------------------------------------------------------------
   AU-DELA DE 1200 — le rail deploye
   -------------------------------------------------------------------------
   C'est l'etat par defaut de la base : on ecrit les largeurs en RETIRANT, pas
   en ajoutant. Une base qui part du telephone et empile les ajouts finit par
   demander trois regles pour comprendre un element ; celle qui part du grand
   et retire n'en demande qu'une par palier.
   ------------------------------------------------------------------------- */


/* -------------------------------------------------------------------------
   LE RAIL REPLIE — un ETAT, pas une largeur
   -------------------------------------------------------------------------
   CE QUI A CHANGE, ET POURQUOI. Le repli etait decide par la seule largeur de
   l'ecran : sous 1200 px les libelles partaient, au-dessus ils revenaient, et
   personne ne pouvait en decider autrement. Or le rail prend 256 px a toutes
   les largeurs, y compris quand on veut la place pour lire un tableau large.
   Le repli devient donc une COMMANDE -- un bouton en tete du rail -- et son
   etat vit sur `<html>` en `data-rail`.

   IL N Y A PLUS DE REQUETE DE MEDIA ICI, et c'est voulu : une meme mise en
   forme ecrite a deux endroits -- une fois pour la largeur, une fois pour le
   bouton -- finit par diverger, et l'on corrige alors la moitie du defaut. Le
   script pose l'etat de depart AVANT le premier rendu, a partir du choix
   memorise ou, a defaut, de la largeur. La largeur decide toujours ; elle ne
   decide simplement plus toute seule.

   SANS SCRIPT, LE RAIL RESTE DEPLOYE. Ce n'est pas un defaut : une colonne de
   256 px sur un ecran de 1100 est large, elle n'est pas cassee. Dupliquer tout
   ce bloc dans un repli de secours couterait plus cher que ce qu'il repare.
   ------------------------------------------------------------------------- */

/* LE REPLI N EXISTE QU AU-DESSUS DE 760 PX, ET C EST LA BONNE PORTE.
   -------------------------------------------------------------------------
   Sous 760, le rail du visualiseur se deroule dans la page : il n'a plus de
   colonne a gagner, donc plus rien a replier. J'avais d'abord ANNULE le repli
   depuis le bloc de 760, regle par regle -- et j'ai perdu la course de poids
   deux fois. `body:has(.viz-rail) { --retrait-rail: 0 }` pese (0,2,0) contre
   (0,3,0) pour `html[data-rail="replie"] body:has(.viz-rail)`, et la
   neutralisation du `display` des enfants ne disait rien de la LARGEUR du rail.

   CE QUE CA DONNAIT EN REEL, a 699 px, vu dans le navigateur : rail large de
   62 px, contenu redevenu visible dedans, libelles debordant de leur boite, et
   le contenu de la page decale de 62 px pour un rail qui n'etait plus une
   colonne. Aucune mesure de banc ne l'avait vu : elles portaient sur 1440,
   1180, 960, 760 et 390 -- le defaut vit entre 640 et 760.

   ON NE CONTRE PAS, ON FAIT RENONCER. Le repli est borne a son domaine, les
   trois regles d'annulation disparaissent, et il n'y a plus de course a
   perdre. Meme geste que pour les cartes a barres : dire la verite sur le
   domaine plutot qu'ajouter du poids.

   LA BORNE PASSE DE 761 A 1025 LE 06/10/2026, ET POUR LE MEME RAISONNEMENT.
   Demande de l'Admin : ajuster la lecture des resultats « pour une
   utilisation mobile et tablette ».

   CE QU'ON A MESURE SUR UNE TABLETTE DE 768 x 1024 : le rail du visualiseur
   etait REPLIE, large de 62 px -- huit pour cent de l'ecran -- et les
   dix-huit planches avaient disparu. Il ne restait qu'un chevron pour toute
   navigation, et rien ne disait qu'il y avait dix-huit sections derriere.
   Le repli n'est pas en cause : il fait ce qu'on lui demande. C'est son
   DOMAINE qui etait faux, parce qu'une colonne de 240 px prend le tiers d'une
   tablette, et qu'un tiers n'est pas un prix qu'on paie pour une liste.

   SOUS 1025, LA LISTE DU VISUALISEUR EST UNE RANGEE QUI DEFILE, et une rangee
   n'a rien a replier. Le repli n'existe donc qu'au-dessus, la ou une colonne a
   vraiment une largeur a rendre.

   ET CE RAISONNEMENT NE VAUT QUE POUR LE RAIL DU VISUALISEUR. Je l'ai applique
   aux DEUX le 06/10, parce qu'ils partageaient un bloc. Le rail de l'espace
   praticien, lui, ne se deroule pas dans la page sous 1025 : il reste une
   colonne `fixed` de 256 px. Sa gouttiere, elle, tombait bien a 62 px --
   `body:has(.prat-rail) { --retrait-rail: var(--rail-replie) }` sous 1200 n'a
   pas de borne basse.

   MESURE DU 16/10/2026, DE 761 A 1024 PX, et c'est la meme que celle du
   commentaire de la gouttiere plus bas, au pixel pres : rail 256, gouttiere 62,
   LE RAIL COUVRE 194 PX DU CONTENU. A 901 px sur « Mes clients », il cachait le
   titre de la page, le champ de recherche et LE NOM DE CHAQUE CLIENT.

   Le defaut avait deja ete trouve une fois, avec une autre cause -- la
   gouttiere qui ne suivait pas -- et repare par le `:not(:has(.viz-rail))`
   ci-dessous. Deux seuils qui se contredisent rendent le meme ecran deux fois.

   LE DOMAINE DE CHAQUE RAIL EST DONC ECRIT SEPAREMENT : 761 pour celui de
   l'espace, qui garde sa colonne jusque-la et doit donc pouvoir la replier ;
   1025 pour celui du visualiseur, dont la liste se deroule en dessous.
   ------------------------------------------------------------------------- */
@media (min-width: 761px) {
    html[data-rail="replie"] .prat-rail {
        width: var(--rail-replie);
        padding-inline: var(--e-5);
    }

    html[data-rail="replie"] .prat-rail__libelle,
    html[data-rail="replie"] .prat-rail__compte {
        display: none;
    }

    /* LE BLOC D IDENTITE SE CACHE SANS PARTIR, pour la meme raison que les
       surtitres : il occupe 56 px en tete du rail, et sans eux les sept onglets
       remontaient d'autant. Replie, le premier onglet tombait 56 px plus haut
       qu'ouvert -- le repli deplacait ce qu'on venait de viser, et deplier le
       remettait ailleurs.

       REPLIE, ON SAIT DEJA DANS QUEL ESPACE ON EST : la barre du haut le dit, et
       l'icone courante le confirme. C'est bien un bloc a cacher ; c'est sa PLACE
       qu'il ne faut pas rendre. */
    html[data-rail="replie"] .prat-rail__qui {
        visibility: hidden;
        overflow: hidden;
        width: 100%;
    }

    /* LE BOUTON, LUI, RESTE VISIBLE. Il est maintenant DANS la tete, et
       `visibility` descend : cache avec le bloc d'identite, il n'y aurait plus rien
       pour deplier le rail -- et un rail qu'on ne peut plus rouvrir n'est pas
       replie, il est perdu. La regle ci-dessus ne vise que le bloc d'identite, mais
       on le dit ici parce que c'est le genre de chose qu'on casse en deplacant un
       element d'un cran. */
    /* LE BOUTON SE POSE SUR LA TETE, IL NE S AJOUTE PAS A ELLE.
       -------------------------------------------------------------------------
       Empile au-dessus du bloc d'identite cache, il rendait sa propre hauteur et
       les sept onglets redescendaient de trente-six pixels : mesure, 165 deploye
       contre 201 replie, donc le repli deplacait a nouveau ce qu'on venait de
       viser -- exactement le defaut qu'on venait de corriger.

       Pose EN ABSOLU dans la tete, il occupe la place que le bloc d'identite
       reserve deja, et la tete garde la hauteur qu'elle a ouverte. `inset: 0` avec
       `margin: auto` le centre dans cette boite : c'est la seule facon de le
       centrer sans connaitre la hauteur, qui depend de la longueur du nom.

       `visibility: visible` PARCE QUE LA TETE EST CACHEE ET QUE CA DESCEND : sans
       cette ligne il disparaitrait avec elle, et un rail qu'on ne peut plus
       rouvrir n'est pas replie, il est perdu. */
    html[data-rail="replie"] .rail-tete {
        position: relative;
    }

    /* CETTE REGLE NE VAUT QUE DANS LA TETE DES RAILS D ESPACE. Ecrite sans
       ancetre, elle attrapait aussi le chevron du visualiseur, dont la rangee n'est
       pas positionnee : son bloc de reference devenait le RAIL, et `inset: 0` plus
       `margin: auto` le centrait au milieu d'une colonne de huit cents pixels --
       mesure, y = 467. Un `position: absolute` cherche son ancetre positionne ; si
       on ne lui en donne pas, il en trouve un beaucoup plus loin. */
    html[data-rail="replie"] .rail-tete .rail-bascule {
        position: absolute;
        inset: 0;
        margin: auto;
        visibility: visible;
    }

    /* ET SON TEXTE RESTE SUR UNE LIGNE, sans quoi la place rendue n'est pas la
       bonne. « Florent Naudin » tient sur une ligne dans 232 px ; dans les 42 px du
       rail replie il se coupait en quatre, et le bloc cache mesurait alors 91 px
       au lieu de 56 -- les onglets descendaient de trente-cinq pixels au lieu de
       rester ou ils etaient. On cache un bloc, on ne le redimensionne pas.

       UN NOM PLUS LONG QUE LE RAIL DEPLOYE ferait l'inverse : deux lignes ouvert,
       une seule repliee, donc vingt pixels d'ecart. Le cas existe et il est petit ;
       le corriger demanderait de mesurer le bloc en JavaScript, ce qui coute plus
       que ce qu'il repare. */
    html[data-rail="replie"] .prat-rail__qui > * {
        white-space: nowrap;
    }

    /* LES SURTITRES SE CACHENT SANS PARTIR, et c'est ce qui aligne les deux etats.
       En `display: none` ils rendaient leur hauteur : les sept onglets remontaient
       de quarante-cinq pixels, donc aucun ne tombait au meme endroit qu'ouvert, et
       le repli deplacait tout ce qu'on venait de viser. En `visibility: hidden` la
       boite reste, l'onglet garde son niveau, et le mot ne se lit plus.

       `overflow: hidden` PARCE QUE LE MOT EST TOUJOURS LA : « Mon activite » fait
       plus de quarante-deux pixels et debordait du rail, invisible mais compte dans
       la largeur defilable du document. */
    html[data-rail="replie"] .prat-rail__groupe {
        visibility: hidden;
        overflow: hidden;
        /* LES MARGES LATERALES PARTENT AVEC LE MOT, et c'est ce qui manquait.
           `width: 100%` prend la largeur du rail -- 41 px -- mais la marge de 10
           pousse la boite a droite : elle courait de 20 a 61 dans un cadre qui
           s'arrete a 51, donc dix pixels dehors et vingt de largeur defilable en
           trop. Le mot etait bien cache ; sa BOITE, non. Une boite de mise en page
           sans encre pese quand meme. */
        margin-inline: 0;
        width: 100%;
    }

    /* LA COLONNE DES ONGLETS PREND TOUTE LA LARGEUR DU RAIL, et sans cette ligne
       rien de ce qui suit ne sert a rien. `align-items: center` sur le rail faisait
       retracter cette colonne sur son contenu : dix-neuf pixels, la largeur d'une
       icone. Les onglets mesuraient donc 21 x 21 dans un rail qui leur en offrait
       42 -- le carre etait ecrit, il n'etait pas rendu. */
    html[data-rail="replie"] .prat-rail__defile {
        width: 100%;
        align-self: stretch;
    }

    /* CARRE, ET DE LA MEME HAUTEUR QU OUVERT. `aspect-ratio` seul redonnerait un
       carre, mais de 42 px, quand l'onglet deploye en fait 40 : les sept onglets
       se decalaient d'un cran de plus a chaque rangee. La hauteur est donc celle de
       l'etat ouvert, et la largeur suit le rail. */
    html[data-rail="replie"] .prat-rail__lien {
        flex: none;
        width: 100%;

        /* `border-box`, SANS QUOI LES QUARANTE DEVIENNENT QUARANTE-DEUX : le filet
           transparent de l'etat au repos s'ajoute a la hauteur, et deux pixels par
           onglet font quatorze sur sept rangees. Mesure : 42 replie contre 40
           ouvert, et le dernier onglet decale de quatorze pixels. */
        box-sizing: border-box;
        height: 40px;
        justify-content: center;
        padding: 0;
    }

    /* LE CREUX RESTE, ET IL EN A PLUS BESOIN QU OUVERT : sans libelle ni gras, il
       est le SEUL signe qui dise ou l'on se trouve. Il vaut la peine d'etre ecrit
       ici plutot que laisse a l'heritage -- la regle deployee pose un remplissage
       et un rayon de controle que le carre replie ne veut pas des deux cotes. */
    html[data-rail="replie"] .prat-rail__lien[aria-current="page"] {
        background: var(--creux-fond);
        box-shadow: var(--creux-relief);
        border-radius: var(--rayon-controle);
    }

    /* LA GOUTTIERE SUIT LE RAIL. Le contenu recule de la largeur du rail ; si elle
       ne suivait pas, le rail passerait par-dessus lui ou laisserait un vide de
       deux cents pixels.

       IL FAUT DIRE « ET PAS DE RAIL DE VISUALISEUR », parce que le rail de
       l'espace est encore DANS LE DOCUMENT quand celui du visualiseur le remplace :
       la coquille le masque (`body:has(.viz-rail) .prat-rail`), elle ne le retire
       pas. `:has(.prat-rail)` matchait donc sur une page de resultats, la gouttiere
       tombait a 62 px pendant que le rail visible en mesurait 256, et le contenu
       passait DESSOUS. Mesure a 900 px : le rail couvrait 194 px de la colonne. */
    html[data-rail="replie"] body:has(.prat-rail):not(:has(.viz-rail)) {
        --retrait-rail: var(--rail-replie);
    }
}


/* -------------------------------------------------------------------------
   LE RAIL DU VISUALISEUR SE REPLIE AUTREMENT : IL S EFFACE
   -------------------------------------------------------------------------
   SON DOMAINE S ARRETE A 1025, et c'est la seule chose qui le separe du bloc
   ci-dessus : sous ce seuil sa liste se deroule dans la page, donc il n'a plus
   de colonne a rendre. Celui de l'espace, lui, reste une colonne jusqu'a 761,
   et c'est pour cela que les deux ne partagent plus le meme bloc.

   IL N A PAS D ETAT « ICONES », et la raison est ecrite depuis l'atelier : ses
       entrees ne peuvent pas devenir des pictogrammes -- neuf notions abstraites
       feraient neuf devinettes. Il est la en entier, ou il n'y est pas.

       REPLIE, IL NE LAISSE DONC QUE SON BOUTON. Une bande de quarante-deux pixels
       ou l'on clique pour le faire revenir, et douze cents pixels rendus a la
       planche qu'on lit -- ce qui est exactement la raison pour laquelle on replie
       un rail devant un resultat.

   CE N EST PAS LA MEME COMMANDE QUE « MASQUER », et c'est pourquoi le bouton
   reste : un rail qu'on ne peut plus rouvrir n'est pas replie, il est perdu.
   ------------------------------------------------------------------------- */
@media (min-width: 1025px) {

    html[data-rail="replie"] .viz-rail {
        width: var(--rail-replie);
        padding-inline: var(--e-5);
        align-items: center;
        overflow: visible;

        /* LE CHEVRON RESTE EN HAUT. Seule sa rangee survit au repli, et le rail
           repartit l'espace entre ses enfants : avec un enfant unique, elle se
           retrouvait au MILIEU de la colonne -- mesure, y = 467 dans un rail de
           900. On ne cherche pas un bouton de repli a mi-hauteur d'une bande vide,
           on le cherche la ou le rail commence. */
        justify-content: flex-start;
    }

    /* TOUT SAUF LA RANGEE QUI PORTE LE BOUTON. Nommer ce qui reste plutot que ce
       qui part : le rail du visualiseur porte huit blocs et en gagnera d'autres, et
       une liste de ce qu'on cache serait fausse des le neuvieme.

       CETTE REGLE A FAIT DISPARAITRE LE CHEVRON, et c'est la deuxieme fois que le
       meme geste casse la meme chose. Elle disait « tout sauf le bouton » quand le
       bouton etait un enfant DIRECT du rail ; en le remontant sur la ligne du
       retour, il est devenu petit-fils, donc il est parti avec sa rangee. Le rail
       se repliait et ne se depliait plus : signale sur « Mes resultats », ou il n'y
       a meme pas de lien de retour pour trahir la rangee cachee.

       ON CACHE DONC LA RANGEE PAR SON CONTENU, pas la rangee elle-meme. Un rail
       qu'on ne peut plus rouvrir n'est pas replie, il est perdu -- c'est ecrit deux
       fois dans cette feuille, et ca n'a pas suffi. */
    /* LA LISTE DES PLANCHES SURVIT AU REPLI, DEPUIS LE 08/10/2026.
       -------------------------------------------------------------------------
       Elle partait avec tout le reste, et le rail replie ne portait plus qu'un
       chevron : dix-neuf planches derriere une colonne de 62 px vide, et la
       seule facon d'en changer etait de rouvrir le rail. Releve par l'Admin :
       « ajouter des icones par page de resultats, affiches quand rail replie,
       pour pouvoir continuer a naviguer ».

       C'EST LE MEME GESTE QUE LE RAIL DU PRATICIEN, qui cache ses libelles et
       garde ses icones. Il manquait les icones : elles sont posees par
       `partials/icone-planche.blade.php`, une par planche. */
    html[data-rail="replie"] .viz-rail > *:not(.viz-rail__qui):not(.diagnostic-viewer-nav) {
        display: none;
    }

    /* CE QUI RESTE DANS LA LISTE REPLIEE : l'icone, et rien d'autre.

       LES INTERRUPTEURS DE PARTAGE PARTENT AVEC LES LIBELLES, et ce n'est pas un
       detail de place : une case a cocher large de 36 px dans une colonne de 62,
       sans le nom de la page qu'elle commande, est un interrupteur qu'on actionne
       sans savoir sur quoi. Le partage se decide rail ouvert. */
    html[data-rail="replie"] .viz-rail .viz-rail__libelle,
    html[data-rail="replie"] .viz-rail .partage-interrupteur,
    html[data-rail="replie"] .viz-rail .viz-rail__compte,
    html[data-rail="replie"] .viz-rail .viz-rail__mention,
    /* LE CADENAS AUSSI, ET IL N EST MEME PLUS DANS LE LIEN : depuis le
       03/11/2026 il est le dernier enfant de la RANGEE, dans la colonne du
       temoin de partage, donc l'enveloppe du libelle ne l'emporte pas avec
       elle. Il faut le nommer ici pour qu'il parte au repli. Deux pictos dans
       une colonne de 62 px se disputeraient la place ; c'est l'attenuation du
       lien qui dit « fermee », pas un second dessin. */
    html[data-rail="replie"] .viz-rail .diagnostic-viewer-nav__cadenas {
        display: none;
    }

    /* L ICONE NE SE LAISSE PAS ROGNER. Le lien porte `flex: 1 1 auto;
       min-width: 0` (coquille-retenue), donc il se contracte sous son contenu
       et emporterait l'icone avec lui : mesure du 08/10/2026, 4 x 20 px dans
       une colonne de 62. `flex: none` sur l'icone, pose en permanence dans
       `coquille-retenue.css`, suffit -- c'est le meme reglage que
       `.prat-rail__icone`, et c'est pour cela qu'il n'y a plus rien a redire
       ici de sa taille. */

    /* REPLIE, LA BARRE DE DEFILEMENT NE PREND PLUS DE PLACE DU TOUT.
       -------------------------------------------------------------------------
       TROIS ETATS ESSAYES, ET SEUL LE TROISIEME TIENT. La colonne repliee fait
       62 px, dont 41 pour la liste une fois le retrait du rail enleve.

         `auto` (le depart)   la barre s'ajoute dedans quand ca deborde et
                              decale tout de 10 px vers la gauche -- c'est ce
                              que l'Admin a photographie ;
         `stable both-edges`  elle reserve 9,5 px DE CHAQUE COTE, mesure en
                              ligne : 41 px de liste pour 22 px utiles. Le
                              centre redevenait juste, mais il ne restait que
                              cinq pixels autour d'une icone de dix-sept, et le
                              lien debordait de sa rangee ;
         rien du tout         la liste garde ses 41 px, l'icone de 17 tombe au
                              milieu avec douze pixels de part et d'autre.

       ON MASQUE DONC LA BARRE PLUTOT QUE DE LUI FAIRE DE LA PLACE. Elle ne sert
       a rien ici : dix-huit icones de 40 px tiennent presque dans la hauteur
       d'un ecran, la molette et le clavier defilent toujours, et le rail du
       praticien ne montre pas la sienne non plus. `overflow-y: auto` reste,
       c'est le DESSIN de la barre qu'on retire, pas le defilement. */
    /* LA BARRE MASQUEE A DEMENAGE DANS LA COQUILLE (09/10/2026), hors de tout
       seuil : elle vaut deployee comme repliee, et une recette ecrite a deux
       endroits finit par diverger. Il ne reste rien a dire ici. */
    /* ========================================================================
       LE RAIL REPLIE EST CELUI DE L ESPACE, PAS UN AUTRE

       DEMANDE DE L ADMIN le 09/10/2026 : « reprends ce qu il y a dans
       /partner, c est quoi qui est complique ! on va pas reinventer ce qui
       existe ! » Puis, devant l etat du fichier : « tu me nettoies ca ! un
       seul element correctement configure, pas de rustines dans tous les
       sens ».

       CE QU IL Y AVAIT. Le rail de l espace tient en DEUX regles : le lien
       prend la taille d une case, le lien actif prend le creux. Celui-ci en
       avait accumule SEPT, posees l une apres l autre au fil des captures --
       centrer la rangee, masquer son `::after`, etirer trois niveaux, annuler
       son remplissage, annuler son filet, annuler son creux, retailler
       l ecart. Chacune reparait ce que la precedente laissait voir, et aucune
       ne touchait la cause.

       LA CAUSE EST STRUCTURELLE. Chez le praticien, le lien est enfant DIRECT
       du rail. Ici une rangee s intercale, parce qu elle loge la case de
       partage et le libelle : deux choses qui n existent plus une fois
       replie. Elle ne porte donc plus rien, et continuait pourtant a peser --
       41 x 60 autour d une case de 40, ce que l Admin a vu au survol.

       `display: contents` LA RETIRE DE LA MISE EN PAGE SANS LA RETIRER DU
       DOCUMENT. Le lien devient enfant direct de la liste, exactement comme
       la-bas. Son remplissage, son filet, son creux et son `::after` cessent
       d exister du meme coup : il n y a plus de boite pour les porter. Les
       sept regles tombent, et il ne reste que la recette.

       LA RECETTE EST RECOPIEE DE `.prat-rail__lien`, mot pour mot, y compris
       `box-sizing` -- un filet transparent au repos ajoute deux pixels par
       rangee, soit trente-six sur dix-huit planches. Si elle change la-bas,
       elle doit changer ici : c est le prix d un rail qui n est pas l autre,
       et c est moins cher que sept rustines.

       L ICONE N EST PAS ICI. Sa couleur d accent vaut DEPLOYEE AUSSI, donc
       elle vit dans la coquille, hors de tout seuil, a cote de celle du rail
       de l espace.
       ======================================================================== */
    html[data-rail="replie"] .viz-rail .viz-rail__planche {
        display: contents;
    }

    /* ET SON `::after` CESSE D EXISTER AVEC ELLE, SINON IL SURVIT SEUL.
       `display: contents` retire la boite, PAS les pseudo-elements : le trait
       de dix pixels qui separait les groupes devenait un enfant direct de la
       liste, et l ecart entre deux cases passait de quatre a dix-huit. Mesure
       du 09/10/2026 : pas de 58 px la ou le rail de l espace est a 44. */
    html[data-rail="replie"] .viz-rail .viz-rail__planche::after {
        content: none;
    }

    /* ET SON ATTENUATION CESSE D AGIR AVEC SA BOITE.
       -------------------------------------------------------------------------
       RELEVE PAR LA RELECTURE FABLE DU 03/11/2026, et c'est la suite directe de
       la ligne au-dessus. Une planche fermee est atténuée par
       `.viz-rail__planche.is-ferme { opacity: .5 }` (coquille) ; `display:
       contents` lui retire sa boite, et une opacite sur un element sans boite ne
       peint RIEN. Deployee la regle agit, repliee elle ne fait rien.

       CA NE SE VOYAIT PAS TANT QUE LES PLANCHES FERMEES MONTRAIENT DES MOTS
       ROGNES : elles ne ressemblaient a rien d'autre. Depuis qu'elles ont leur
       icone, elles ressemblent EXACTEMENT a une planche ouverte, et onze icones
       du meme gris ne disent plus laquelle s'ouvre.

       LE LIEN, LUI, GARDE SA BOITE au repli -- la regle juste en dessous lui pose
       une hauteur et une largeur. C'est donc lui qui porte l'attenuation, comme
       il porte deja le `cursor: default` de la planche fermee, et pour la meme
       raison. */
    html[data-rail="replie"] .viz-rail .viz-rail__planche.is-ferme .viz-rail__lien {
        opacity: 0.5;
    }

    html[data-rail="replie"] .viz-rail .viz-rail__lien {
        flex: none;
        width: 100%;
        box-sizing: border-box;
        height: 40px;
        justify-content: center;
        gap: 0;
        padding: 0;
    }

    html[data-rail="replie"] .viz-rail .viz-rail__lien[aria-current="page"] {
        background: var(--creux-fond);
        box-shadow: var(--creux-relief);
        border-radius: var(--rayon-controle);
    }

    /* L ECART ENTRE LES CASES EST CELUI DU RAIL DE L ESPACE. Il venait avant
       du remplissage de la rangee (9 + 9) plus deux pixels de `gap`, soit
       vingt et un ; la rangee effacee, il ne reste que le `gap`, porte a la
       valeur de la-bas. Dix-huit planches passent de 1 098 px a 788. */
    html[data-rail="replie"] .viz-rail .viz-rail__planches {
        gap: 4px;
    }


    /* LES DEUX NIVEAUX S ETIRENT, SINON LA CASE N EN EST PLUS UNE.
       -------------------------------------------------------------------------
       Une colonne flexible se retracte sur son contenu : sans cela la liste se
       reduisait a la largeur d une icone, et la case rendait 17 x 40 -- haute et
       maigre dans un rail de 62. L icone y etait bien centree, mais centree dans
       un rectangle qui, lui, ne l etait pas. Mesure du 08/10/2026 relevee par
       l Admin : rapport largeur sur hauteur de 0,43 la ou le rail praticien est
       a 1,0.

       DEUX NIVEAUX ET PLUS TROIS : la rangee en faisait partie, elle n a plus de
       boite depuis qu elle est en `display: contents`. Il suffit qu un seul de
       ceux qui restent se retracte pour que la case suive. */
    html[data-rail="replie"] .viz-rail .viz-rail__planches,
    html[data-rail="replie"] .viz-rail .diagnostic-viewer-nav {
        width: 100%;
        align-self: stretch;
        box-sizing: border-box;
    }

    /* LE CHEVRON SE CENTRE COMME LES ICONES.
       Il tombait 4,6 px a droite du milieu : sa rangee est centree, mais elle
       porte le retrait qui servait a aligner le lien de retour -- lequel n'existe
       plus au repli. `margin-inline: auto` le pose au milieu de ce qui reste,
       quel que soit ce retrait. */
    html[data-rail="replie"] .viz-rail .viz-rail__qui {
        padding-inline: 0;
    }

    html[data-rail="replie"] .viz-rail .rail-bascule {
        margin-inline: auto;
    }

    /* LE CHEVRON SURVIT AU REPLI, OU LE RAIL EST PERDU.
       -------------------------------------------------------------------------
       CETTE REGLE A CESSE D AGIR LE 02/11/2026, SANS RIEN DIRE. Elle nommait les
       enfants DIRECTS de la rangee, et le chevron en etait un ; ce jour-la il est
       entre dans `.viz-rail__actions` pour voisiner avec l'engrenage des
       resultats. La rangee a donc vu un enfant qui n'etait pas lui, elle l'a
       cache, et le chevron est parti dedans.

       CE QUE CA DONNAIT : replie, le rail du visualiseur n'avait plus AUCUN
       moyen d'etre rouvert. Il fallait passer par une autre page -- l'etat est
       partage, donc le rail du praticien le deplie -- et revenir. L'Admin,
       le 03/11/2026, capture a l'appui : « corrige le bouton qui deplie le rail
       aussi, c'est clairement casse ». « Un rail qu'on ne peut plus rouvrir
       n'est pas replie, il est perdu » etait deja ecrit deux fois dans cette
       feuille, et ca n'a pas suffi : la phrase ne tenait pas le selecteur.

       ON NOMME LE GESTE, PAS LA PEAU. `.rail-bascule` est l'habillage, et
       l'engrenage le porte aussi -- volontairement, « deux gestes voisins, de
       meme poids, qui ne meritent pas deux habillages ». `[data-bascule-rail]`
       est ce que le script branche, et lui seul designe le repli : le gabarit le
       dit deja, « ce qui les distingue est ce qu'ils font, pas ce a quoi ils
       ressemblent ».

       DEUX NIVEAUX, PARCE QU IL Y EN A DEUX. La rangee garde l'enfant qui le
       CONTIENT, et cet enfant ne garde que lui. Si le chevron redescend d'un
       cran demain, la premiere regle le suit toute seule ; la seconde cesse de
       resserrer, elle ne le cache pas. */
    html[data-rail="replie"] .viz-rail__qui > *:not([data-bascule-rail]):not(:has([data-bascule-rail])) {
        display: none;
    }

    /* ET SEULE LA RANGEE DE TETE EST VISEE, parce que `.viz-rail__actions`
       nomme DEUX choses : celle-ci, et la rangee des trois gestes de la fiche
       (`actions-praticien.blade.php` -- consultation, commande, note). Releve
       par la relecture Fable du 03/11/2026. La seconde est deja cachee au repli
       avec la fiche qui la porte, donc rien ne bouge aujourd'hui ; le jour ou un
       de ses gestes devra survivre au repli, il disparaitrait sans un mot, par
       une regle ecrite pour le chevron. On la borne avant que ca arrive. */
    html[data-rail="replie"] .viz-rail__qui > .viz-rail__actions > *:not([data-bascule-rail]) {
        display: none;
    }

    /* Et la rangee des deux gestes n'en porte plus qu'un : elle le centre, et ne
       garde pas l'ecart qui separait les deux. */
    html[data-rail="replie"] .viz-rail__qui > .viz-rail__actions {
        justify-content: center;
        gap: 0;
    }

    /* LE REPLI SANS `:has()`, pour ce qu'il en coute : la regle du dessus est
       rejetee en bloc par un navigateur qui ne connait pas `:has()`, et le
       surtitre et le lien de retour resteraient alors visibles et rognes. Celle-
       ci les nomme, sans rien de neuf. Releve par la revue croisee du
       03/11/2026. */
    html[data-rail="replie"] .viz-rail__qui > .viz-rail__tete {
        display: none;
    }

    /* Et la rangee rend sa place au chevron : sans lien de retour a gauche, il n'a
       plus de raison de tenir le bord droit.

       `flex: none` PARCE QU ELLE EST SEULE. Devenue le dernier enfant visible d'un
       rail qui fait toute la hauteur de l'ecran, elle s'etirait sur huit cents
       pixels et centrait le chevron au MILIEU d'une bande vide -- mesure, y = 467
       dans un rail de 900, alors que la rangee, elle, commencait bien a 83. On ne
       cherche pas un bouton de repli a mi-hauteur, on le cherche la ou le rail
       commence. */
    html[data-rail="replie"] .viz-rail__qui {
        flex: none;
        justify-content: center;
    }

    html[data-rail="replie"] body:has(.viz-rail) {
        --retrait-rail: var(--rail-replie);
    }
}


/* -------------------------------------------------------------------------
   SOUS 900 — la disposition se resserre
   -------------------------------------------------------------------------
   LE SEUIL LE PLUS CHARGE, et le seul ou la barre change de nature : elle
   cesse d'etre une grille de trois colonnes pour devenir une ligne qui se
   replie. Sa navigation passe dans le menu du compte, et le prenom s'efface --
   la pastille suffit a dire de qui il s'agit quand la place manque.

   LE TABLEAU REDEVIENT UNE LISTE DE CARTES. Chaque cellule montre alors
   l'etiquette de sa colonne, qui etait cachee au-dessus : sans en-tete pour
   dire ce qu'on lit, la valeur seule ne veut rien dire.
   ------------------------------------------------------------------------- */

/* -------------------------------------------------------------------------
   LA BARRE DU HAUT SE VIDE PAR ETAGES, DANS UN ORDRE
   -------------------------------------------------------------------------
   TROIS COLONNES QUI NE SE CHEVAUCHENT JAMAIS. La barre est une grille
   `auto 1fr auto` : la marque et le compte prennent ce qu'il leur faut, la
   rangee prend le reste. Le chevauchement est donc structurellement impossible
   -- mais la rangee est en `overflow: hidden` et CENTREE : quand le reste ne
   suffit plus, elle se coupe aux DEUX bouts, en silence, et une destination
   disparait sans que rien ne le dise.

   L ORDRE EST UNE DECISION, PAS UN EFFET DE BORD. Partent d'abord les deux
   ESPACES (praticien, administration) : on y va souvent, mais on sait ou ils
   sont, et le rail de l'espace ou l'on se trouve les redit. Puis la BOUTIQUE,
   avec son filet -- un trait qui ne separe plus rien est un defaut, pas une
   economie. Puis la rangee entiere. A chaque etage, tout reste atteignable
   depuis le menu du compte, qui porte les memes liens.

   LES SEUILS SONT MESURES, ET PAR LANGUE. Releve du 12/09/2026 sur la barre
   d'un administrateur (le cas le plus garni), en additionnant la largeur des
   ENFANTS de la rangee : la rangee elle-meme est la colonne `1fr`, elle valait
   857 a 1440 et 1017 a 1600 pour exactement les memes six onglets, donc sa
   largeur ne dit rien de ce qu'ils demandent.

       langue   marque  compte  parcours  boutique  espaces || tout  -esp  -bout
       fr          240     257       369        88      262 || 1307  1045   952
       en          240     257       327        64      264 || 1243   979   910
       ru          265     257       394        87      345 || 1439  1094  1002
       de          240     257       379        64      213 || 1244  1031   962

   UN SEUL SEUIL POUR LES QUATRE AURAIT ETE UN SEUIL RUSSE. « Кабинет
   специалиста » et « Администрирование » demandent 345 la ou
   « Fachbereich » et « Verwaltung » demandent 213 : 132 px d'ecart, et la
   marque russe en ajoute 25. Aligner tout le monde sur le pire aurait retire
   les onglets a un lecteur anglais sur un ecran ou ils tenaient largement.

   LES NOMBRES CI-DESSOUS SONT LE RELEVE + 32, soit seize pixels d'air de chaque
   cote : au seuil nu, les onglets touchent la marque et le compte. Arrondis a
   cinq pixels.

   LES ETATS S EMBOITENT, donc les seuils valent pour tout le monde : un client
   sans espace praticien n'a pas de premier etage, et son « tout » est
   exactement le « -esp » de la table. Rien a recalculer par profil.

   POURQUOI LE DEFAUT PRECEDENT AVAIT SURVECU : les mesures portaient sur 1340,
   900 et 390, et il vivait ENTRE deux de ces largeurs. Trois nombres choisis a
   la main ne couvrent pas une plage.
   ------------------------------------------------------------------------- */

/* LE PRENOM NE POUSSE PLUS LA COLONNE DU COMPTE.

   Sans borne, un prenom long elargit le compte, la colonne `1fr` se resserre
   d'autant, et la rangee se coupe -- a une largeur que les seuils ci-dessus ne
   peuvent pas prevoir, puisqu'elle depend de qui est connecte. Le nom complet
   est dans le menu, juste en dessous : ce qui est ici sert a se reconnaitre,
   pas a se lire. */
/* LA LIGNE DOIT LAISSER PASSER LES JAMBAGES.

   CE QUE L'ADMIN A PHOTOGRAPHIE (14/10/2026) : « Jimmy » dans la barre du
   haut, le jambage du « y » coupe net.

   LA MESURE, sur la page rendue. La boite faisait 14 px de haut pour une
   police de 14 px, parce que la hauteur de ligne valait 1. Un temoin de la
   meme police, pose sans contrainte, demande 18,4 px : il manquait 4,4 px, et
   `overflow: hidden` -- qui est la pour l'ellipsis horizontale -- les coupait
   par le bas. Les lettres sans jambage (Alice, Admin) ne montraient rien :
   c'est un defaut qui depend du prenom.

   `1.4` DONNE 19,6 px. Le premier essai tenait `1.35`, soit 18,9 px : le
   temoin demandait 18,4 px AVANT que la police de la page ne soit chargee, et
   19 px une fois qu'elle l'etait. Un dixieme de pixel de marge n'est pas une
   marge -- la borne depend de la police servie, qui peut changer. On ne passe
   pas par `normal` pour autant : il varie d'une police a l'autre sans qu'on
   sache de combien, et c'est precisement ce qu'on vient de mesurer.

   L'ELLIPSIS RESTE : c'est la largeur qu'on tronque, pas la hauteur. */
.lk-top-bar__prenom {
    max-width: 12ch;
    line-height: 1.4;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* --- Premier etage : les deux espaces ------------------------------------- */
@media (max-width: 1340px) {
    html[lang="fr"] .lk-top-bar__travail { display: none; }
    html[lang="fr"] .lk-top-bar__filet:not(:has(+ .lk-top-bar__link--boutique)) { display: none; }
}

@media (max-width: 1280px) {
    html[lang="en"] .lk-top-bar__travail,
    html[lang="de"] .lk-top-bar__travail { display: none; }

    /* LE FILET PART AVEC EUX S IL N A PLUS RIEN A SEPARER. Une personne sans
       boutique n'a que les espaces a droite du trait : les espaces partis, il
       pendrait apres le dernier onglet du parcours. On teste la PRESENCE de la
       boutique dans le balisage et non son rendu -- `:has()` lit la structure,
       et la structure, elle, ne bouge pas avec la largeur. */
    html[lang="en"] .lk-top-bar__filet:not(:has(+ .lk-top-bar__link--boutique)),
    html[lang="de"] .lk-top-bar__filet:not(:has(+ .lk-top-bar__link--boutique)) {
        display: none;
    }
}

@media (max-width: 1475px) {
    html[lang="ru"] .lk-top-bar__travail { display: none; }
    html[lang="ru"] .lk-top-bar__filet:not(:has(+ .lk-top-bar__link--boutique)) { display: none; }
}

/* --- Deuxieme etage : la boutique, et le filet avec elle ------------------ */
@media (max-width: 1080px) {
    html[lang="fr"] .lk-top-bar__link--boutique,
    html[lang="fr"] .lk-top-bar__filet { display: none; }
}

@media (max-width: 1015px) {
    html[lang="en"] .lk-top-bar__link--boutique,
    html[lang="en"] .lk-top-bar__filet { display: none; }
}

@media (max-width: 1130px) {
    html[lang="ru"] .lk-top-bar__link--boutique,
    html[lang="ru"] .lk-top-bar__filet { display: none; }
}

@media (max-width: 1065px) {
    html[lang="de"] .lk-top-bar__link--boutique,
    html[lang="de"] .lk-top-bar__filet { display: none; }
}

/* --- Troisieme etage : la rangee entiere ---------------------------------- */
@media (max-width: 985px) {
    html[lang="fr"] .lk-top-bar__nav { display: none; }
}

@media (max-width: 945px) {
    html[lang="en"] .lk-top-bar__nav { display: none; }
}

@media (max-width: 1035px) {
    html[lang="ru"] .lk-top-bar__nav { display: none; }
}

@media (max-width: 995px) {
    html[lang="de"] .lk-top-bar__nav { display: none; }
}

/* -------------------------------------------------------------------------
   SOUS 1200 — LE RAIL DEVIENT UN TIROIR : IL PASSE PAR-DESSUS, IL NE POUSSE PLUS
   -------------------------------------------------------------------------
   CE QUE LE PRODUIT FAISAIT. Sous 1200 px le rail se repliait tout seul, et
   l'ouvrir repoussait la page de 256 px. Sur une tablette, c'est un quart de
   la largeur pris a la lecture. Et pour le rail du VISUALISEUR c'etait pire
   que genant : ses entrees n'ont pas d'icone (contrairement aux rails praticien
   et administration), donc replie il ne restait rien -- mesure du 12/09/2026 a
   900, 760 et 390 px : zero onglet visible sur neuf, et la rangee du haut
   cachee elle aussi. Un client ouvrait ses resultats et ne pouvait atteindre
   aucune des huit autres planches.

   LA MESURE QUI FIXE LA REGLE. La matrice des interconnexions ne descend pas
   sous 620 px : elle se lit dans les deux sens, donc elle ne se replie pas en
   cartes comme une liste, il n'y a pas d'ordre de lecture unique a retrouver.
   Avec le remplissage de page il lui faut 684, et le rail deploye en prend 256.
   EN DESSOUS DE 940 PX, OUVRIR LE RAIL EN POUSSANT LA PAGE CASSE LA MATRICE.
   Le tiroir n'est donc pas un confort sous ce seuil, il est la seule facon
   d'ouvrir le rail sans rien perdre.

   ON PART DE 1200 ET NON DE 940, parce que c'est la que le rail se replie deja
   de lui-meme : entre les deux, ne pas pousser ne coute rien, et deux seuils
   pour un seul comportement finissent par diverger.

   COMMENT. Le rail est deja `position: fixed` : il ne pousse rien par
   lui-meme. Ce qui pousse, c'est `--retrait-rail`, le retrait que la coque et
   le pied se donnent pour lui faire de la place. On le fige donc a la largeur
   REPLIEE, quel que soit l'etat du rail. Ouvert, celui-ci s'elargit par-dessus
   le contenu, qui ne bouge pas d'un pixel.

   PAS DE VOILE derriere le tiroir, c'est une decision de l'Admin : on l'ouvre
   pour choisir un onglet en gardant la matrice sous les yeux, et l'assombrir
   reviendrait a cacher ce qu'on est venu lire. Une ombre portee suffit a dire
   qu'il flotte au-dessus.
   ------------------------------------------------------------------------- */

@media (max-width: 1200px) {
    body:has(.prat-rail),
    body:has(.viz-rail) {
        --retrait-rail: var(--rail-replie);
    }

    /* IL FLOTTE, DONC IL PORTE UNE OMBRE. Sans voile, c'est la seule chose qui
       distingue un tiroir pose sur la page d'une colonne qui l'a repoussee.

       ET IL CESSE D ETRE TRANSPARENT, PARCE QU IL N A PLUS RIEN DERRIERE LUI
       QUI LUI APPARTIENNE. Le rail est translucide a 0,28 avec un flou de
       14 px : en colonne c'est juste, il laisse passer la lumiere du fond de
       page, qui est SON fond. Pose sur le contenu, il laisse passer le contenu
       -- on lit la matrice a travers les onglets. Le voile monte donc au
       barreau 12, « l'opacite pleine sans la durete du 1 ».

       LE JETON SE REECRIT, LA COULEUR NON : `--surface-sombre-rgb` se retourne
       avec le theme (5 8 13 en sombre, 244 246 249 en clair). Ecrire la teinte
       en dur aurait donne un panneau noir sur une page claire. */
    html[data-rail="ouvert"] .prat-rail,
    html[data-rail="ouvert"] .viz-rail {
        background: rgba(var(--surface-sombre-rgb), var(--voile-12));
        box-shadow: 0 0 0 1px var(--filet-rail, transparent),
                    18px 0 44px rgba(var(--black-rgb), 0.42);
    }
}

@media (max-width: 900px) {
    /* ELLE RESTE COLLEE EN HAUT, A TOUTES LES LARGEURS.
       -------------------------------------------------------------------------
       L'ADMIN, LE 04/11/2026, capture a l'appui : « la barre n'est pas fixe en
       haut ». Sous 900 px elle repassait en `position: relative` et partait avec
       le defilement : sur un ecran etroit, c'est precisement la ou le compte, le
       theme et le bouton du rail sont le plus difficiles a retrouver.

       LE `relative` NE SERVAIT PAS LA BARRE, IL SERVAIT SON EMPILEMENT -- le
       voile du rail passe dessous, a 1400 contre 1500. `sticky` cree le meme
       contexte d'empilement avec le meme `z-index`, donc rien ne change de ce
       cote. */
    .lk-top-bar {
        display: flex;
        flex-wrap: wrap;
        position: sticky;
        top: 0;
        padding-inline: var(--e-9);
    }

    .lk-top-bar__nav,
    .lk-top-bar__prenom {
        display: none;
    }

    .lk-content {
        padding: var(--e-9) var(--e-9) var(--e-11);
    }

    /* Le tableau se replie en cartes : chaque ligne devient un bloc, et chaque
       cellule reprend le nom de sa colonne.

       SAUF LA LISTE DES CLIENTS, QUI DECIDE PAR SON CONTENEUR.
       -------------------------------------------------------------------
       L'Admin, le 16/10/2026 : « il ne devrait pas y avoir autant de
       dimensions, c'est le meilleur moyen de faire des rafistolages ». Il
       avait raison, et le compte le dit : DOUZE seuils touchaient cette seule
       liste (640, 720, 760, 761, 768, 780, 880, 900, 901, 1025, 1040, 1180,
       1200), dont TROIS repondaient a la meme question -- tableau ou carte ?

       UNE LARGEUR DE FENETRE NE SAIT PAS DE COMBIEN DE PLACE UN TABLEAU
       DISPOSE. C'est la cause de tout ce qui a ete rafistole cette nuit : le
       rempart de 901 a 1040 n'existait que pour compenser un rail, et sa
       premisse est devenue fausse le jour ou la grille a change. La liste des
       clients demande donc a SON CONTENEUR, dans
       `composants/liste-clients.css`, et plus rien ici ne la concerne. */
    /* SAUF LES LISTES QUI ONT UN CONTENEUR : c'est lui qui decide du pli,
       donc de leurs etiquettes. Mesure du 04/11/2026 a 900 px de fenetre : le
       tableau des clients etait en LIGNES (son cadre faisait 760, son seuil
       740) et chaque cellule ecrivait en plus le nom de sa colonne.

       LA LISTE DES COMPTES LES REJOINT LE 06/11/2026, avec son propre
       conteneur et son seuil a 850. Le commentaire qui disait cela vivait
       A L INTERIEUR du selecteur, entre `:has(` et son argument : valide,
       puisque les commentaires sont retires avant l'analyse, mais illisible
       -- et c'est la qu'on ajoute une exclusion sans la voir. */
    .liste-carte:not(:has(.partner-client-row)):not(:has(.admin-user-row)),
    .liste-carte:not(:has(.partner-client-row)):not(:has(.admin-user-row)) tbody,
    .liste-carte:not(:has(.partner-client-row)):not(:has(.admin-user-row)) tr,
    .liste-carte:not(:has(.partner-client-row)):not(:has(.admin-user-row)) td,
    table.responsive-table:has(.responsive-table__label):not(:has(.partner-client-row)):not(:has(.admin-user-row)),
    table.responsive-table:has(.responsive-table__label):not(:has(.partner-client-row)):not(:has(.admin-user-row)) tbody,
    table.responsive-table:has(.responsive-table__label):not(:has(.partner-client-row)):not(:has(.admin-user-row)) tr,
    table.responsive-table:has(.responsive-table__label):not(:has(.partner-client-row)):not(:has(.admin-user-row)) td {
        display: block;
        width: 100%;
        /* `border-box`, SINON LA CELLULE EST PLUS LARGE QUE SA CARTE.
           En bloc, `width: 100%` est 100 % du parent, et le remplissage de 12 a
           14 px s'AJOUTE de chaque cote. Mesure du 16/10/2026 a 901 px sur la
           page reelle : cellules de 762 px dans une carte de 738, donc 24 px
           dehors -- une barre de defilement dans la carte du tableau de bord, et
           des bandes qui depassent du cadre sur la page pleine. */
        box-sizing: border-box;
    }

    /* ET LA LISTE QUI A UN CONTENEUR GARDE SES ETIQUETTES POUR LUI : c'est
       lui qui decide du pli, donc de leur affichage. Mesure du 04/11/2026 a
       900 px de fenetre : le tableau etait en LIGNES (cadre 760, seuil 740)
       et chaque cellule ecrivait en plus le nom de sa colonne. Quatrieme et
       dernier palier de fenetre a lui laisser la main ; la regle de carte,
       dans `liste-clients.css`, pese plus lourd et les rallume au pli. */
    .partner-clients-table .responsive-table__label {
        display: none;
    }

    .liste-carte:not(:has(.partner-client-row)):not(:has(.admin-user-row)) thead,
    table.responsive-table:has(.responsive-table__label):not(:has(.partner-client-row)):not(:has(.admin-user-row)) thead {
        display: none;
    }

    .responsive-table__label {
        display: block;
    }
}


/* -------------------------------------------------------------------------
   UNE PAGE A RAIL REPLIE SES TABLEAUX PLUS TOT, DE LA LARGEUR DU RAIL
   -------------------------------------------------------------------------
   LE SEUIL DE 900 MESURE LA FENETRE, PAS LA PLACE. Un tableau ne deborde pas
   d'une fenetre, il deborde de la COLONNE qu'on lui laisse -- et sur une page a
   rail cette colonne fait 126 px de moins. Releve a 960 : la page dispose de
   834 px de contenu, c'est-a-dire exactement ce qu'une page sans rail offre a
   826. Le tableau de l'aide en demande 933, celui des clients 858 : tous deux
   debordaient dans une bande ou la regle les croyait au large.

   LE SEUIL SE DEDUIT, IL NE SE CHOISIT PAS : 900 + 126 = 1026, arrondi a 1040
   pour les langues aux entetes plus longs. En dessous, la page a rail se replie
   comme une page etroite se replie deja.

   NE SE REPLIE QUE CE QUI SAIT SE REPLIER. `:has(.responsive-table__label)`
   demande au tableau s'il porte le nom de ses colonnes dans ses cellules : sans
   ces etiquettes, replier le tableau efface l'entete et ne le remplace par
   rien. Deux tableaux du produit n'en ont pas -- ceux des traitements, qui
   defilent dans leur propre cadre et n'ont donc rien a se faire pardonner.
   La regle se maintient toute seule : le jour ou quelqu'un ajoute les
   etiquettes, le repli suit, et pas avant.
   ------------------------------------------------------------------------- */

/* CE QUI TIENT NE SE REPLIE PAS, ET LE TABLEAU DE BORD TIENT.

   La regle ci-dessus vaut pour les tableaux de PLEINE PAGE : `/partner/clients`
   demande 857 px pour 802 disponibles, l'aide en demande 932. Ceux-la debordent
   vraiment, et se replier est la bonne reponse.

   La carte du tableau de bord, elle, montre une version REDUITE de la meme
   liste : cinq colonnes au lieu de six, « Programmes » en moins. Mesure de 901
   a 1040 px, de vingt en vingt : elle demande exactement la place dont elle
   dispose, 736 a 876 px, et ne deborde d'aucun pixel. Elle etait donc empilee
   en cinq bandes etiquetees sans en avoir besoin, sur toute une bande de
   largeurs d'ordinateur portable.

   POURQUOI CETTE BANDE ET PAS UNE AUTRE. Le seuil se deduisait de la largeur du
   rail, 126 px, a l'epoque ou le rail POUSSAIT la page. Il est devenu un tiroir
   sous 1200 px : replie il fait 62 px, et deplie il passe PAR-DESSUS le contenu
   sans rien lui prendre. La compensation vaut donc toujours pour les grands
   tableaux, qui debordaient deja avant elle, mais elle n'a plus de raison
   d'atteindre celui-ci. */
/* NE SE REPLIE QUE CE QUI SAIT SE REPLIER -- LA PREMIERE BRANCHE L AVAIT OUBLIE.

   L'ADMIN, LE 28/10/2026 : « j'en ai juste assez de voir ces lignes cassees ».

   LA CONDITION EXISTE DEJA DANS CE BLOC, sur la seconde branche :
   `:has(.responsive-table__label)` demande au tableau s'il porte le nom de ses
   colonnes dans ses cellules. Le commentaire du haut l'explique en toutes
   lettres -- « sans ces etiquettes, replier le tableau efface l'entete et ne le
   remplace par rien » -- et nomme meme les deux tableaux concernes, ceux des
   traitements.

   LA BRANCHE `.liste-carte` NE LA PORTAIT PAS. Elle les attrapait donc quand
   meme, et le resultat tenait du pire des deux mondes : les rangees passaient
   en bloc pendant que l'entete, lui, etait rendu par le palier du rail replie.

   MESURE SUR LA PAGE REELLE, `/admin/processing`, les deux tableaux :

       1000 px   entete visible / rangees block   -> incoherent
        940 px   entete visible / rangees block   -> incoherent
        910 px   entete visible / rangees block   -> incoherent

   Avec la condition, les trois rendent `entete visible / rangees table-row`.

   C EST LE MIROIR DU DEFAUT DE `/admin/users`, corrige le meme jour : la-bas
   l'entete disparaissait au-dessus de rangees restees en tableau, ici les
   rangees se replient sous un entete reste en place. Deux moities du meme
   defaut, une regle qui agit sur un ensemble plus large que celui dont elle
   repare le cas. */
@media (max-width: 1040px) and (min-width: 901px) {
    /* Meme exclusion qu'au palier du dessous : la liste des clients decide par
       son conteneur et pas par la fenetre.

       ET LA LISTE DES COMPTES AVEC ELLE, le 06/11/2026. Le palier du dessous
       l'excluait deja par `:not(:has(.admin-user-row))`, celui-ci ne l'avait
       pas suivi : a 940 px de fenetre, son cadre en fait 804, son conteneur
       la laissait en tableau et cette bande la repliait quand meme. Elle
       tient maintenant jusqu'a 748 px de cadre -- voir `liste-clients.css`,
       l'adresse de courriel se coupe -- donc c'est a son conteneur de dire
       quand elle plie, ici comme ailleurs. */
    body:has(.prat-rail) .liste-carte:has(.responsive-table__label):not(:has(.partner-client-row)):not(:has(.admin-user-row)),
    body:has(.prat-rail) .liste-carte:has(.responsive-table__label):not(:has(.partner-client-row)):not(:has(.admin-user-row)) tbody,
    body:has(.prat-rail) .liste-carte:has(.responsive-table__label):not(:has(.partner-client-row)):not(:has(.admin-user-row)) tr,
    body:has(.prat-rail) .liste-carte:has(.responsive-table__label):not(:has(.partner-client-row)):not(:has(.admin-user-row)) td,
    body:has(.prat-rail) table.responsive-table:has(.responsive-table__label):not(:has(.partner-client-row)):not(:has(.admin-user-row)),
    body:has(.prat-rail) table.responsive-table:has(.responsive-table__label):not(:has(.partner-client-row)):not(:has(.admin-user-row)) tbody,
    body:has(.prat-rail) table.responsive-table:has(.responsive-table__label):not(:has(.partner-client-row)):not(:has(.admin-user-row)) tr,
    body:has(.prat-rail) table.responsive-table:has(.responsive-table__label):not(:has(.partner-client-row)):not(:has(.admin-user-row)) td {
        display: block;
        width: 100%;
        /* Meme raison qu'au palier d'en dessous : en bloc, le remplissage
           s'ajoute a la largeur. */
        box-sizing: border-box;
    }

    body:has(.prat-rail) .liste-carte:has(.responsive-table__label):not(:has(.partner-client-row)):not(:has(.admin-user-row)) thead,
    body:has(.prat-rail) table.responsive-table:has(.responsive-table__label):not(:has(.partner-client-row)):not(:has(.admin-user-row)) thead {
        display: none;
    }

    body:has(.prat-rail) .responsive-table__label {
        display: block;
    }

    /* L EXCEPTION DE LA CARTE DU TABLEAU DE BORD EST RETIREE : SA PREMISSE
       EST DEVENUE FAUSSE.

       Elle disait, et c'etait vrai le jour ou elle a ete ecrite : « mesure de
       901 a 1040 px, de vingt en vingt, elle demande exactement la place dont
       elle dispose, 736 a 876 px, et ne deborde d'aucun pixel ». Elle rendait
       donc sa mise en tableau a une liste qui n'avait pas besoin d'etre
       empilee.

       LA GRILLE A CHANGE DEPUIS. `.prat-grille-trois` repartit en flex,
       60 % pour la carte double et 30 % pour les autres : la carte des clients
       ne dispose plus que de 472 a 571 px dans cette bande.

       MESURE DU 16/10/2026, SUR LA PAGE REELLE :

           largeur   cadre   table   hors cadre   entete
           1040      571     845     274 px       desaligne
           1000      544     845     301 px       desaligne
            901      472     815     343 px       desaligne

       ET CE N EST PAS UNE AFFAIRE DE NOMS LONGS : les quatre colonnes autres
       que le nom pesent 153 + 99 + 122 + 94 = 468 px de minimum, pour 472
       disponibles a 901. Meme avec un nom d'une lettre, la table ne tient pas.

       L entete etait desaligne par-dessus le marche : l'exception rendait
       `tbody tr` a `table-row` et oubliait `thead tr`, reste en `block`. Les
       cinq titres se tassaient a gauche a leur largeur naturelle, aucun
       au-dessus de sa colonne. Une rangee en bloc au milieu d'un tableau defait
       tout le reste.

       LA CARTE SE REPLIE DONC COMME TOUTES LES AUTRES dans cette bande. Rendre
       la mise en tableau demanderait de rendre a la carte la largeur sur
       laquelle l'exception avait ete decidee, c'est-a-dire de toucher a la
       grille : c'est un choix de mise en page, pas une reparation. */
}


/* -------------------------------------------------------------------------
   SOUS 760 — le rail s efface
   -------------------------------------------------------------------------
   Meme replie, il prendrait 62 px sur 700 : un dixieme de la largeur pour une
   colonne d'icones. Le menu du compte porte alors toute la navigation.
   ------------------------------------------------------------------------- */

/* -------------------------------------------------------------------------
   SOUS 1025 — la tablette et le telephone : le rail du visualiseur se deroule
   -------------------------------------------------------------------------
   CE PALIER EST SEPARE DE CELUI DU PRATICIEN, ET C'EST VOULU. Le rail
   `.prat-rail` disparait sous 760 parce que la barre du haut reprend sa
   navigation ; le rail du visualiseur, lui, porte la seance, la consultation,
   le partage, les programmes et la note -- rien ne les reprend ailleurs. Les
   deux rails n'ont donc pas le meme seuil, et leur donner le meme reviendrait
   a faire disparaitre sur tablette ce qu'aucun autre ecran ne rend.
   ------------------------------------------------------------------------- */

@media (max-width: 1024px) {
    /* LE RAIL DU VISUALISEUR NE DISPARAIT PAS : IL SE DEROULE DANS LA PAGE.
       Quand il ne portait que neuf liens, l'effacer ne coutait rien -- la
       rangee d'onglets revenait et la navigation etait sauve. Il porte
       maintenant la seance, la consultation, le partage, les programmes et la
       note : l'effacer les emporterait tous, et la rangee d'onglets ne les
       rendrait pas, ils n'y ont jamais ete.

       Il cesse donc d'etre fixe et devient un bloc en tete de page, sur toute
       la largeur. Rien n'est perdu, rien n'est range derriere un bouton, et la
       page reprend ses 100 % pour les resultats. */
    /* LE RAIL DU VISUALISEUR EST UN TIROIR DES ICI, PLUS UNE BANDE.
       -------------------------------------------------------------------
       IL SE DEROULAIT EN TETE DE PAGE entre 761 et 1024 px : une bande
       horizontale portant la fiche, le bouton de commande, les onglets en
       rangee et le pied du rail.

       CE QUE CA DONNAIT, mesure le 26/10/2026 a 800, 900 et 1000 px : les
       onglets DEBORDAIENT (la rangee est plus large que la page), le bouton
       « Commander des programmes » s'etalait sur toute la largeur, et le
       pied -- « Tous les services fonctionnent », le copyright -- venait se
       poser AU MILIEU de la page, entre les onglets et les resultats.
       L'Admin : « il ne devrait jamais y avoir ca ici et comme ca ».

       LE TIROIR VAUT DONC JUSQU A 1024, et non jusqu'a 760. C'est le seul
       dessin qui tienne pour un rail de onze entrees plus une fiche : il
       sort du flux, on l'ouvre quand on en a besoin, et la page garde sa
       largeur pour les resultats.

       LE RAIL DU PRATICIEN GARDE SON SEUIL A 760 : entre les deux il reste
       une colonne, ce qu'il peut se permettre -- ses entrees sont courtes et
       il a un repli en icones. Meme traitement ne veut pas dire memes
       valeurs. */
    .viz-rail {
        position: fixed;
        inset-block: 0;
        block-size: 100dvh;
        max-block-size: 100dvh;
        /* LA MEME LARGEUR QUE SUR GRAND ECRAN, ET PAR LE MEME JETON.

           L'ADMIN, LE 04/11/2026 : « le rail en responsive tablette ou reduit
           n'a pas le meme rendu visuel que le rail PC, verifie et ajuste.
           Version PC parfaite. »

           MESURE A 820 PX, TIROIR OUVERT : le rail faisait 280 px et ses
           rangees 248, contre 256 et 227 sur grand ecran -- vingt-quatre
           pixels d'ecart, ecrits ici en dur pendant que la colonne lisait
           `--rail`. Tout le reste tenait deja : meme hauteur de rangee, meme
           icone, meme cadenas au bord droit, et le fond plus dense est celui
           d'un panneau qui flotte, pas un ecart.

           LE PLAFOND EN `vw` RESTE : sous 300 px de fenetre, un tiroir de
           256 ne laisserait rien voir de la page derriere. */
        width: min(var(--rail), 82vw);
        transform: translateX(-100%);
        transition: transform 180ms ease;
        z-index: 1600;
        margin-bottom: 0;
        border-right: 0;
        border-bottom: 0;
        overflow: auto;
        animation: none;
        box-shadow: none;
    }

    html[data-rail-mobile="ouvert"] .viz-rail {
        transform: none;
        box-shadow: 0 0 40px rgba(0, 0, 0, 0.45);
    }

    /* LA PAGE NE RECULE PAS DE SA LARGEUR : il passe par-dessus. */
    body:has(.viz-rail) {
        --retrait-rail: 0px;
    }

    /* ET IL SORT DE SA BOITE LE TEMPS QU IL EST OUVERT. `.lk-content` et
       `.lk-wrapper` sont en `position: relative; z-index: 1` : chacun ouvre
       un contexte d'empilement, et vu du dehors tout le bloc pese 1 -- le
       voile et la barre passaient donc par-dessus le panneau. */
    html[data-rail-mobile="ouvert"] .lk-wrapper,
    html[data-rail-mobile="ouvert"] .lk-content {
        z-index: auto;
    }

    /* LES DIX-HUIT PLANCHES PASSENT EN RANGEE QUI DEFILE.

       MESURE AVANT DE TOUCHER, sur un telephone de 375 x 812 : le rail deroule
       occupait 711 px a lui seul, et le premier resultat commencait a 1192 px.
       Une page et demie de navigation avant la premiere valeur. Ce n'est pas
       une question de gout : c'est le temps qu'il faut pour voir ce qu'on est
       venu lire.

       RIEN N'EST CACHE, ET C'EST LA MEME REGLE QU'AU-DESSUS. Les dix-huit
       planches restent toutes la, avec leur case de partage ; elles se
       rangent en LARGEUR au lieu de la hauteur, et le pouce les fait defiler.
       On ne gagne pas la place en retirant des choses, on la gagne en
       changeant leur sens de rangement : 711 px deviennent environ 56.

       `overflow-x: auto` REMPLACE LE `overflow: visible` D'AVANT, et il faut
       dire pourquoi il etait la. Il defaisait la chaine de defilement
       verticale du rail en colonne (voir la regle du `<nav>` plus bas) : une
       liste flexible a `min-height: 0` dans un conteneur sans hauteur se
       comprimait jusqu'a zero. En rangee, la hauteur ne se comprime plus --
       c'est la largeur qui deborde, et c'est elle qu'on laisse defiler.
       `overflow-y: hidden` ferme l'autre axe : sans lui, un conteneur qui
       defile sur un axe defile sur les deux, et la rangee se mettrait a
       sauter verticalement d'un demi-pixel sous le doigt.

       L'ACCROCHE EST EN `proximity`, PAS EN `mandatory`. Avec `mandatory`, un
       petit geste de lecture est ramene de force sur une planche et la rangee
       paraIt collante ; `proximity` n'aide que quand on s'arrete pres d'une
       borne. */
    .viz-rail__planches {
        flex-direction: column;

        /* LE MEME ECART QUE DANS LA COLONNE, ET PAS UN DE PLUS.

           L'ADMIN, LE 04/11/2026, capture a l'appui : « a corriger, compare au
           rail PC ». Mesure a 390 px, tiroir ouvert : les onze rangees etaient
           separees de 6 px au lieu de 2, et la liste portait deux pixels de
           remplissage que la colonne n'a pas. Rien d'autre ne differait --
           meme largeur depuis le jeton, meme rangee de 38, meme icone, meme
           police -- mais six pixels onze fois font soixante-six pixels d'air,
           et c'est ce qui se voyait.

           L ECART DE TOUCHE NE SE PREND PAS SUR LE VIDE : la rangee fait
           38 px de haut dans les deux dessins, c'est elle qui porte le doigt.
           Ecarter les rangees n'agrandit pas la cible, ca allonge la liste. */
        gap: 2px;
        overflow-x: hidden;
        overflow-y: auto;
        scroll-snap-type: none;
        -webkit-overflow-scrolling: touch;

        /* LA GOUTTIERE NE MANGE PAS LA RANGEE. Sous le doigt elle ne
           s'affiche pas ; a la souris, sur une tablette branchee a un clavier,
           elle prendrait 15 px sur 38 de hauteur. */
        scrollbar-width: none;

        /* DE L'AIR EN BAS SEULEMENT, pour que la derniere planche ne colle
           pas au bord -- un element colle au bord se lit comme un element
           coupe. Le remplissage LATERAL est parti avec le reste : la colonne
           n'en a pas, et il decalait les rangees de deux pixels par rapport a
           la fiche au-dessus. */
        padding-bottom: 2px;
    }

    .viz-rail__planches::-webkit-scrollbar {
        display: none;
    }

    /* LA PLANCHE NE SE COMPRIME PAS, ET C EST TOUT CE QUI RESTE D UNE RANGEE.

       `flex: 0 0 auto` : la liste defile, et sans lui les planches se
       tassent pour tenir dans la hauteur au lieu de deborder -- il n'y a
       alors plus rien a faire defiler.

       LE CONTOUR EST PARTI, le 04/11/2026. L'Admin : « le design n'est pas
       celui valide (grand ecran) ». Il avait ete pose quand ce palier
       dessinait une RANGEE de pastilles cote a cote, ou un bord separait ce
       que l'empilement ne separait plus. Le palier est un TIROIR depuis le
       26/10 : les planches y sont empilees comme dans la colonne, donc elles
       se lisent deja comme une liste, et le bord n'etait plus qu'un ecart de
       dessin. Mesure a 390 contre 1440, tiroir ouvert : meme rangee de 38,
       meme rayon, meme ombre, meme police -- `rgba(255,255,255,0.09)` d'un
       cote, transparent de l'autre.

       LA COULEUR SEULE PART, pas la declaration de la coquille : le bord
       transparent y porte la largeur, et la retirer decalerait la rangee
       d'un pixel. */
    .viz-rail__planche {
        flex: 0 0 auto;
        white-space: normal;
    }

    /* LE LIEN CESSE DE REMPLIR SA RANGEE. En colonne il prenait toute la
       largeur (`flex: 1 1 auto`) pour que la case de partage se pose a droite ;
       en rangee, cela etirerait chaque pastille sur toute l'ecran. */
    .viz-rail__planche .viz-rail__lien {
        flex: 1 1 auto;
    }


    /* ET LA CHAINE DE DEFILEMENT SE DEFAIT AVEC LUI.
     *
     * `coquille-retenue` fait du `<nav>` un element flexible qui se comprime
     * (`flex: 1 1 auto`, `min-height: 0`) : c'est ce qui permet a la liste des
     * planches de defiler quand le rail est une COLONNE FIXE de hauteur
     * imposee. Deroule dans la page, le rail n'a plus de hauteur imposee, et
     * un enfant flexible a `min-height: 0` dans un conteneur de hauteur
     * indeterminee se comprime jusqu'a zero : mesure a 760 comme a 390, les
     * planches tombaient de 538 px a 0. La liste disparaissait entierement,
     * sans erreur et sans trace.
     *
     * C'est le meme piege que `1fr` dans une cellule de tableau : la valeur
     * qui autorise la compression devient la valeur qui l'impose des que la
     * reference de hauteur s'en va. Le remede d'un defaut en fabrique un
     * autre ; ici on le rend au moment exact ou il cesse de servir. */
    .viz-rail > .diagnostic-viewer-nav {
        display: flex;
        flex: 1 1 auto;
        min-height: 0;
    }

    /* LE REPLI N ARRIVE PLUS JUSQU ICI : il est borne a `min-width: 1025px`,
       en tete de feuille. Trois regles d'annulation vivaient a cet endroit et
       perdaient la course de poids contre lui ; les retirer etait le vrai
       remede. Le bouton de repli reste affiche, et il reste sans effet ici :
       c'est un choix qui n'a plus de colonne a gagner. */
    body:has(.viz-rail) {
        --retrait-rail: 0px;
    }
}


/* -------------------------------------------------------------------------
   SOUS 760 — le rail sort du cote au lieu de disparaitre
   -------------------------------------------------------------------------
   CE QUI ETAIT ECRIT ICI, ET QUI ETAIT FAUX : « Lui peut disparaitre : la barre
   du haut porte la meme navigation, et sous 900 px elle est deja repliee en
   menu. Rien n'est perdu. »

   TOUT ETAIT PERDU, AU CONTRAIRE. La barre du haut porte SIX entrees de premier
   niveau -- mon parcours, mes resultats, les programmes, la boutique, l'espace
   praticien, l'administration. Le rail en porte SEPT chez le praticien et
   DIX-SEPT chez l'administrateur, et aucune n'est ailleurs. Une fois arrive sur
   `/partner`, plus aucune section n'etait atteignable. Remonte par l'Admin le
   06/10/2026 : « le rail disparait en version mobile ou etroite donc pas de
   navigation possible, par exemple /partner et tout rail ».

   IL RESTE `fixed`, IL SE DEPLACE SEULEMENT. Le rendre `static` le ferait
   dérouler en tete de chaque page : sept a dix-sept entrees a franchir avant
   d'arriver au contenu, a chaque fois. Hors champ, il ne coute rien tant qu'on
   ne le demande pas.

   LE RAIL DU VISUALISEUR N'EST PAS CONCERNE : lui se deroule DANS la page sous
   1024 px (plus haut dans cette feuille), et ses planches restent atteignables.
   ------------------------------------------------------------------------- */

@media (max-width: 760px) {
    /* LE RAIL DU VISUALISEUR SUIT LE MEME TIROIR QUE CELUI DU PRATICIEN.
       -------------------------------------------------------------------
       L'ADMIN, LE 26/10/2026 : « le visualiseur doit avoir le meme traitement
       pour son rail que les rails /partner en responsive. La ce n'est pas
       accessible ».

       TOUT CE MECANISME N ETAIT ECRIT QUE POUR `.prat-rail` : le panneau qui
       sort du cote, le voile, la page qui ne recule pas. `.viz-rail` gardait
       donc son dessin de colonne permanente sur un telephone -- il mangeait
       la largeur ou sortait du champ, et rien ne le rappelait.

       ET LE BOUTON N ETAIT MEME PAS EMIS : `Navigation::laPageAUnRail()` ne
       connaissait que les deux espaces. Les deux moities se corrigent
       ensemble, sinon le rail s'ouvre sans qu'on puisse le demander. */

    /*
     * HORS CHAMP, PAS CACHE. `transform` plutot que `display: none` pour trois
     * raisons : la bascule se joue, le rail garde sa taille calculee -- donc il
     * ne se remet pas en page a chaque ouverture -- et il garde sa place dans
     * l'ordre de lecture, ce qu'un `display: none` lui retirerait.
     */
    .prat-rail,
    .viz-rail {
        /* ET LE RAIL DU VISUALISEUR REPASSE EN `fixed`, PARCE QU IL N Y EST
           PLUS A CE STADE. Sous 1024 px, plus haut dans cette feuille, il
           devient `static` : il cesse d'etre une colonne et se DEROULE en
           tete de page, ce qui est son dessin de tablette.

           SOUS 760 PX CE DESSIN NE VAUT PLUS, puisqu'il devient un tiroir.
           Le laisser `static` le sortait du champ par `transform` -- donc
           invisible -- tout en lui gardant sa PLACE dans le flux : mesure a
           390 px, 736 px de vide entre la barre du haut et le premier bloc
           de resultats. L'Admin, le 26/10/2026 : « il y a juste un tres
           grand espace ».

           LES TROIS AUTRES DECLARATIONS DE 1024 PARTENT AVEC, pour la meme
           raison : la largeur `auto`, la marge sous le bloc et le filet du
           bas dessinent une bande horizontale, pas un panneau. */
        position: fixed;
        margin-bottom: 0;
        border-bottom: 0;
        overflow: auto;

        /* MEME JETON QUE LA COLONNE, comme le tiroir du visualiseur
           au-dessus : la largeur d'un rail ne se reecrit pas par palier. */
        width: min(var(--rail), 82vw);
        transform: translateX(-100%);
        transition: transform 180ms ease;
        box-shadow: none;

        /*
         * AU-DESSUS DE LA BARRE DU HAUT, qui est a `z-index: 1500` -- mesure a
         * l'ecran le 06/10/2026. A 1200 le rail passait DESSOUS : il couvrait
         * bien toute la hauteur, et la barre lui mangeait ses cent douze
         * premiers pixels, donc l'entree « Mode presentiel ». Un panneau qui
         * couvre doit couvrir tout, sinon il vaut mieux qu'il ne couvre rien.
         */
        z-index: 1600;

        /*
         * IL PART DU HAUT DE L'ECRAN ET VA JUSQU'EN BAS.
         *
         * Il commencait sous la barre du haut, a `61px` : une valeur juste
         * tant que la barre tient sur UNE rangee. Sous 760 px elle passe a
         * DEUX -- mesure a 375 px le 06/10/2026, 112 px de haut -- et les
         * cinquante premiers pixels du rail glissaient dessous. Le bloc
         * d'identite s'affichait coupe en deux.
         *
         * ON NE CHERCHE PAS A SUIVRE LA HAUTEUR DE LA BARRE : elle depend de
         * ce qu'elle porte et de la largeur, donc toute valeur ecrite ici
         * serait fausse a une autre taille. Un panneau qui sort du cote
         * COUVRE, c'est sa nature ; le voile se charge du reste, et le
         * refermer rend la barre.
         */
        inset-block: 0;
        block-size: 100dvh;
        max-block-size: 100dvh;
    }

    /* ET IL REDEVIENT UNE COLONNE, pas une bande.
       -------------------------------------------------------------------
       Le seuil de 1024 px, plus haut, deroule `.viz-rail` en tete de page :
       ses planches passent en RANGEE qui defile de cote, ses pastilles
       cessent de remplir leur ligne, et sa navigation perd la chaine de
       compression qui fait defiler la liste.

       CES TROIS CHOIX VONT ENSEMBLE AVEC UNE BANDE HORIZONTALE. Dans un
       tiroir de 280 px de large et de pleine hauteur, ils donnent une liste
       qui sort par la droite : mesure a 390 px, les onglets « Organisme » et
       « Organes et systemes » coupes au bord, et le reste hors de portee.

       ON LES REND DONC ICI, au moment exact ou le dessin change de nature.
       C'est la meme precaution que le bloc de 1024 prend pour la chaine de
       defilement, et pour la meme raison : une valeur qui sert a une forme
       nuit a l'autre. */
    .viz-rail__planches {
        flex-direction: column;
        overflow-x: hidden;
        overflow-y: auto;
        scroll-snap-type: none;
    }

    .viz-rail__planche {
        white-space: normal;
    }

    .viz-rail__planche .viz-rail__lien {
        flex: 1 1 auto;
    }

    /* LA CHAINE DE DEFILEMENT REVIENT AVEC LA HAUTEUR IMPOSEE. Le tiroir fait
       `100dvh` : la liste a de nouveau une reference, donc elle peut se
       comprimer pour defiler au lieu de pousser le panneau. */
    .viz-rail > .diagnostic-viewer-nav {
        display: flex;
        flex: 1 1 auto;
        min-height: 0;
    }

    /* ET LE TIROIR SORT DE SA BOITE, le temps qu'il est ouvert.
       -------------------------------------------------------------------
       `.viz-rail` vit DANS `.page-shell`, donc dans `.lk-content` et
       `.lk-wrapper` -- deux conteneurs en `position: relative; z-index: 1`.
       Chacun ouvre un contexte d'empilement, et un contexte enferme ce qu'il
       contient : le `z-index: 1600` du rail ne vaut qu'a l'INTERIEUR, et vu
       du dehors tout ce bloc pese 1.

       CE QUE CA DONNAIT, mesure a 390 px le 26/10/2026 : le voile du tiroir
       (1590, enfant direct de `body`) et la barre du haut (1500) passaient
       PAR-DESSUS le panneau ouvert. L'Admin : « il y a un voile sombre par
       dessus », et le nom en tete du rail arrivait coupe sous la barre.

       LE RAIL DU PRATICIEN N A JAMAIS EU CE DEFAUT parce qu'il n'est pas
       dans le wrapper : c'est la meme feuille, le meme z-index, et un
       endroit different dans l'arbre. Un `z-index` ne se lit jamais seul.

       `z-index: auto` PLUTOT QU UNE VALEUR PLUS HAUTE : on ne veut pas
       hisser ces conteneurs au-dessus du voile -- le contenu doit rester
       dessous, c'est tout l'objet du voile -- on veut qu'ils cessent
       d'enfermer. Sans contexte, le rail reprend sa place dans celui de la
       racine, avec son 1600, et l'ordre voulu revient : contenu, voile,
       rail.

       SEULEMENT PENDANT L OUVERTURE : refermee, la page retrouve exactement
       la pile qu'elle avait. */
    html[data-rail-mobile="ouvert"] .lk-wrapper,
    html[data-rail-mobile="ouvert"] .lk-content {
        z-index: auto;
    }

    html[data-rail-mobile="ouvert"] .prat-rail,
    html[data-rail-mobile="ouvert"] .viz-rail {
        transform: none;
        box-shadow: 0 0 40px rgba(0, 0, 0, 0.45);
    }

    /* LA PAGE NE RECULE PAS DE LA LARGEUR DU RAIL : il passe PAR-DESSUS, il ne
       prend pas de colonne. Sur 375 px, lui en donner une ne laisserait rien au
       contenu. */
    body:has(.prat-rail),
    body:has(.viz-rail) {
        --retrait-rail: 0px;
    }

    /* LA BASCULE DE REPLI N'A PLUS D'OBJET ICI : elle choisit entre un rail
       large et un rail etroit, et sous 760 px il n'y a plus de colonne a
       gagner -- le repli est d'ailleurs borne a `min-width: 1025px` en tete de
       feuille. Un bouton sans effet dans un panneau qu'on vient d'ouvrir se lit
       comme une panne. */
    .prat-rail .rail-bascule,
    .viz-rail .rail-bascule {
        display: none;
    }
}

/* ==========================================================================
   LE BOUTON D OUVERTURE ET LE VOILE : LEUR DESSIN NE DEPEND D AUCUNE LARGEUR
   --------------------------------------------------------------------------
   CES REGLES VIVAIENT DANS `@media (max-width: 760px)`, et c'etait juste tant
   que le bouton ne servait que sous 760. Le rail du visualiseur en a fait un
   tiroir jusqu'a 1024 : entre 761 et 1024 le bouton etait AFFICHE et n'avait
   plus une seule regle. Il retombait donc sur les defauts du navigateur, et
   son icone, un SVG sans dimensions, prenait la place qu'elle voulait.
   Mesure a 1008 px sur la page reelle : bouton 123 x 116, icone 107 x 107,
   un bloc gris en haut a gauche de l'ecran.

   C EST LE MEME PIEGE QUE CELUI RACONTE JUSTE EN DESSOUS, par une autre
   porte : la-bas des jetons inconnus rendaient les declarations invalides,
   ici c'est leur portee qui ne couvrait plus l'affichage. Dans les deux cas
   le bouton tombe sur les defauts du navigateur, et dans les deux cas rien
   ne le dit.

   LA REGLE A EN TIRER : on elargit l'affichage d'un element, on elargit son
   habillage dans le meme geste. Ici on va au plus simple -- l'apparence ne
   depend d'aucune largeur, seule la VISIBILITE en depend, et ce sont les
   deux regles de masquage juste en dessous qui la portent.
   ========================================================================== */
/*
 * LE BOUTON EST DANS LA BARRE DU HAUT, EN TETE.
 *
 * Demande de l'Admin le 06/10/2026 : « dans la barre de navigation en haut
 * pour le bouton menu de navigation ». Il flottait en bas a gauche, ou il
 * se posait sur la derniere ligne de chaque page -- sur `/partner`, le lien
 * d'invitation client.
 *
 * IL N'EST DONC PLUS `fixed` : il prend sa place dans la rangee, et c'est
 * la barre qui le porte. Rien a reserver sous le contenu, rien a effacer
 * quand le rail s'ouvre -- le rail passe au-dessus de la barre et le
 * recouvre de lui-meme.
 */

/*
 * IL SE DESSINE COMME SON VOISIN, LE BOUTON DE THEME.
 *
 * CE QUE J'AVAIS ECRIT, ET POURQUOI C'ETAIT FAUX : `var(--bordure)` et
 * `var(--texte)`. CES DEUX JETONS N'EXISTENT PAS dans cette interface --
 * elle les nomme `--trait`, `--texte-calme`, `--texte-vif`,
 * `--surface-effleuree`. Une variable inconnue rend la declaration
 * invalide, et le bouton tombait sur les DEFAUTS DU NAVIGATEUR : mesure a
 * l'ecran en theme clair, `color: rgb(0,0,0)`, `background:
 * rgb(240,240,240)`, `border: rgb(0,0,0)`. Un carre gris a bord noir dans
 * une barre qui n'en a aucun -- exactement « bouton/menu pas lisible ».
 *
 * ON NE REINVENTE DONC PAS SON APPARENCE : on reprend celle de
 * `.lk-top-bar__theme`, qui est a deux centimetres de lui dans la meme
 * barre. Deux boutons voisins qui ne se ressemblent pas se lisent comme
 * une erreur, et les jetons sont deja justes dans les deux themes.
 */
.rail-ouverture {
    display: inline-grid;
    place-items: center;
    flex: none;
    inline-size: 36px;
    block-size: 36px;
    margin-inline-end: var(--e-2, 4px);
    padding: 0;
    background: none;
    border: var(--filet-epaisseur) solid transparent;
    border-radius: 999px;
    color: var(--texte-calme);
    cursor: pointer;
    transition: color var(--duree-effleurement, .16s) ease,
                background var(--duree-effleurement, .16s) ease;
}

.rail-ouverture:hover,
.rail-ouverture:focus-visible {
    background: var(--surface-effleuree);
    color: var(--texte-vif);
}

.rail-ouverture__icone {
    inline-size: 20px;
    block-size: 20px;
}

.rail-voile {
    position: fixed;
    inset: 0;

    /* SOUS LA BARRE DU HAUT ET SOUS LE RAIL, pas au-dessus.
       ---------------------------------------------------------------
       Il valait 1590, entre la barre (1500) et le rail (1600) : il
       assombrissait donc la barre en meme temps que le contenu, et --
       le rail etant enferme dans le contexte de `.lk-wrapper` -- il
       passait aussi sur le panneau ouvert. L'Admin, le 26/10/2026 :
       « il y a un voile sombre par dessus », puis « ca ne doit pas etre
       au dessus de la barre en haut ni du rail ».

       A 1400 l'ordre se lit de lui-meme : le contenu est voile, la
       barre et le rail restent nets. Le voile sert a eteindre CE QU ON
       QUITTE, pas ce avec quoi on est en train d'agir. */
    z-index: 1400;
    border: 0;
    padding: 0;
    background: rgba(0, 0, 0, 0.5);
    opacity: 0;
    pointer-events: none;
    transition: opacity 180ms ease;
    cursor: pointer;
}

html[data-rail-mobile="ouvert"] .rail-voile {
    opacity: 1;
    pointer-events: auto;
}

/* EN THEME CLAIR, LE RAIL OUVERT DEVIENT OPAQUE.

   L'ADMIN, LE 28/10/2026 : « Le rail en theme clair des resultats est
   sombre », puis, devant ma capture : « tu vois pas que c'est sombre a
   gauche ?? ». En mode tablette, rail deplie.

   MESURE SUR LA PAGE REELLE, a 934 px, theme clair, tiroir ouvert :

       .viz-rail     fond rgba(244, 246, 249, 0.28)
       .rail-voile   fond rgba(0, 0, 0, 0.5)
       enfants du rail : transparents, SAUF la fiche du client,
                         opaque a 0,76 -- la seule partie qui restait blanche

   LE VOILE COUVRE TOUTE LA FENETRE, `inset: 0`, donc AUSSI la bande du
   rail. Il passe bien DESSOUS (1400 contre 1600, corrige le 26/10 a la
   demande de l'Admin), mais passer dessous ne suffit pas quand ce qui est
   au-dessus n'est opaque qu'a 28 % : le noir traverse. Le rail ne paraissait
   clair que la ou un bloc opaque le couvrait.

   LA TEINTE BASCULAIT, PAS L OPACITE. `--surface-rail` vaut
   `rgba(var(--surface-sombre-rgb), 0.28)` : en clair la couleur devient bien
   claire, mais les 28 % restent -- une valeur choisie pour un rail sombre
   sur une page sombre, ou ce qui transparait est sombre de toute facon.

   BORNE AU TIROIR OUVERT, et c'est volontaire : c'est le seul etat ou un
   voile est peint. Rail ancre, il n'y a rien de sombre derriere et la
   translucidite garde son effet. */
html[data-theme="clair"][data-rail-mobile="ouvert"] {
    --surface-rail: rgb(var(--surface-sombre-rgb));
}

/* ==========================================================================
   LA BARRE DU HAUT GAGNE SA QUATRIEME COLONNE QUAND LE BOUTON PARAIT
   --------------------------------------------------------------------------
   L'Admin, le 26/10/2026 : « la barre en haut ne devrait JAMAIS avoir de
   retour a la ligne comme ca ».

   CE N EST PAS UN REPLI, C EST UNE COLONNE QUI MANQUE. `.lk-top-bar` est une
   grille, pas une rangee : `grid-template-columns: auto 1fr auto`, trois
   colonnes pour la marque, la navigation et le compte. Le bouton d'ouverture
   du rail est un QUATRIEME enfant. Il prend la premiere colonne, decale les
   trois autres d'un cran, et le compte, qui n'a plus de piste, descend en
   deuxieme ligne. Mesure a 1008 px sur la page reelle : barre de 113 px de
   haut au lieu de 61, bloc du compte a y = 65.

   SEULEMENT ENTRE 901 ET 1024, et seulement sur une page a rail de
   visualiseur. En dessous de 901 la barre repasse en `flex` et ne connait
   plus de colonnes ; au-dessus de 1024 le bouton est masque et la grille
   retrouve ses trois enfants. Le trou est exactement la bande ou le tiroir du
   visualiseur a etendu l'affichage du bouton sans que la grille le sache.

   `:has()` PLUTOT QU UNE CLASSE : la page sait deja quel rail elle porte,
   comme pour les deux regles de masquage juste en dessous.
   ========================================================================== */
@media (min-width: 901px) and (max-width: 1024px) {
    body:has(.viz-rail) .lk-top-bar {
        grid-template-columns: auto auto 1fr auto;
    }
}

/* HORS DU PALIER, LE BOUTON ET LE VOILE N'EXISTENT PAS. Ils sont emis a toutes
   les largeurs -- un bouton cree par script n'existerait pas pour un lecteur
   d'ecran avant qu'on tourne le telephone -- et c'est ici qu'ils se taisent. */
/* LE BOUTON ET LE VOILE SUIVENT LE SEUIL DE LEUR RAIL.
   -------------------------------------------------------------------------
   Ils disparaissaient a 761 px pour tout le monde. Le rail du visualiseur
   etant un tiroir jusqu'a 1024, il perdait sa commande a 761 : panneau hors
   champ, et rien pour le rappeler.

   `:has()` PLUTOT QU UNE CLASSE SUR LE CORPS : la page sait deja quel rail
   elle porte, elle n'a pas a le redire. */
@media (min-width: 761px) {
    body:not(:has(.viz-rail)) .rail-ouverture,
    body:not(:has(.viz-rail)) .rail-voile {
        display: none;
    }
}

@media (min-width: 1025px) {
    .rail-ouverture,
    .rail-voile {
        display: none;
    }
}


/* -------------------------------------------------------------------------
   SOUS 640 — le telephone
   -------------------------------------------------------------------------
   La marge du contenu tombe a un cran : sur 375 px, 20 px de chaque cote
   coutent un dixieme de la largeur utile.
   ------------------------------------------------------------------------- */

@media (max-width: 640px) {
    .lk-top-bar {
        padding-inline: var(--e-6);

        /* 10 PX ET NON 20, ET C EST CE QUI FAIT TENIR LA LIGNE.
           -------------------------------------------------------------------
           La barre passe en `flex-wrap: wrap` sous 900 px (plus haut dans
           cette feuille), donc des que son contenu depasse, le dernier bloc
           TOMBE : l'Admin a vu, le 25/10/2026, l'avatar et le theme sur une
           seconde ligne sous le brule-parfum, et le menu du compte sortir de
           l'ecran a gauche.

           LE COMPTE, mesure a 360 px et avec le theme parti dans le menu :
           36 px pour le rail, 232 pour la marque, 40 pour le compte, plus
           deux ecarts. A 20 px d'ecart il faut 348 px pour 336 d'utile, donc
           ca tombe ; a 10 px il en faut 328, et la ligne tient.

           L ECART N EST PAS DU VIDE A ECONOMISER AILLEURS : il separe trois
           objets dont deux sont des cibles tactiles. 10 px les tient
           distincts, au-dessous ils se liraient comme un seul bloc. */
        gap: var(--e-5);
    }

    .lk-content {
        padding: var(--e-8) var(--e-6) var(--e-9);
    }

    .lk-app-footer {
        padding-inline: var(--e-5);
        text-align: center;
    }

    .lk-app-footer__links {
        justify-content: center;
    }
}

/* -----------------------------------------------------------------------
   LE CADRE DES RESULTATS NE DEFILE PLUS AVEC LA PAGE : IL EST LA PAGE.

   Demande de l'Admin le 08/10/2026 : « je pense a un cadre et un visuel comme
   ce qu'il y a sur expert., les blocs fixes, les blocs scrollables, les pages
   scrollables ».

   MESURE SUR expert. EN LIGNE, a 1536 x 730 : `html` et `body` y sont en
   `overflow: hidden` et `scrollHeight` vaut exactement `innerHeight`. Sa page
   ne defile PAS. Chaque ecran se borne a la fenetre (`calc(100vh - 54px)` pour
   les emotions, `- 84px` pour les interconnexions) et ce sont ses panneaux qui
   defilent. Le visualiseur Online faisait l'inverse : 3 290 px de document pour
   730 de fenetre, barre comprise.

   CE QUE CA CHANGE, ET POURQUOI CA COMPTE ICI : l'air demande sous la barre et
   en bas de page (20 px, pose avec `--espace-page` sur la coquille) n'existe
   qu'a condition que le bas de page soit VISIBLE. Dans une page qui defile, le
   remplissage du bas ne se voit qu'une fois arrive en bas, c'est-a-dire
   presque jamais. Borne a la fenetre, il encadre en permanence.

   LE SEUIL EST CELUI DU RAIL, PAS UN NOMBRE CHOISI. En dessous de 1025 px le
   rail cesse d'etre une colonne fixe et se deroule en tete de page (voir
   `@media (max-width: 1024px)` plus haut) : la page redevient alors un
   document qu'on fait defiler, et lui imposer la hauteur de la fenetre
   enfermerait la navigation ET les resultats dans une boite de 700 px.

   `dvh` ET NON `vh` : sur un telephone la barre d'adresse se retracte, et
   `100vh` laisse alors depasser de sa hauteur. Le seuil met ce cas hors de
   portee, mais une tablette en paysage y entre.
   ----------------------------------------------------------------------- */
@media (min-width: 1025px) {
    /* LE CREUX DE LA ZONE SURE N A PLUS RIEN A PROTEGER ICI. `.lk-body` pose
       `padding-bottom: calc(15px + env(safe-area-inset-bottom))` pour que la
       fin d'un document passe au-dessus de l'encoche basse d'un telephone.
       Dans un cadre borne a la fenetre, ces quinze pixels ne protegent rien et
       DEBORDENT : mesure a 1536 x 730, le document rendait 746 pour 730 de
       fenetre, soit une barre de defilement de page qui ne menait nulle part. */
    body:has(.viz-rail) {
        padding-bottom: 0;
    }

    body:has(.viz-rail) .lk-content {
        /* LA LARGEUR DE CONFORT DE LECTURE NE S APPLIQUE PAS A UN TABLEAU DE
           BORD. `--large-page` (1400) borne les pages de texte ; sur les
           resultats, combinee a `margin: 0 auto`, elle AJOUTE des marges
           automatiques par-dessus les 32 px demandes -- 64 au total -- et,
           pire, elle les fait varier avec l'etat du rail : zone utile de 1280
           rail deploye (marges nulles, ecart 32), de 1474 rail replie (marges
           de 37, ecart 69). Le bord du contenu SAUTAIT au pli. Les resultats
           prennent donc toute la largeur offerte, comme les ecrans d'expert. */
        max-width: none;

        height: calc(100dvh - var(--haut-barre));

        /* `overscroll-behavior` ARRETE LA CHAINE AU CADRE. Sans lui, arriver en
           bas des resultats continue le geste sur la fenetre -- qui ne defile
           pas, donc rien ne bouge, mais le navigateur rend quand meme le rebond
           de fin de page. */
        overflow-y: auto;
        overscroll-behavior: contain;
    }
}
