/* =============================================================================
   RESPONSIVE — couche d'adaptation aux petits ecrans
   =============================================================================

   POURQUOI CE FICHIER EXISTE, ET POURQUOI IL EST PLEIN DE `!important`.

   La mise en page de l'application est ecrite, pour l'essentiel, dans des
   attributs `style=` poses directement dans les vues : 5 070 declarations de
   largeur et 116 vues qui fixent leur `grid-template-columns` a la main. Une
   declaration en ligne l'emporte sur toute regle de feuille de style, quelle
   que soit sa specificite. Les media queries de `header.php`, qui visent des
   classes, n'ont donc AUCUNE prise sur ces vues : c'est la raison pour
   laquelle l'application « s'adapte a moitie » sur telephone — le cadre suit,
   le contenu non. Un tableau de bord declare `repeat(auto-fit, minmax(180px,
   1fr))` en ligne : sur 310 px utiles il ne tient qu'une colonne, et huit
   indicateurs deviennent huit ecrans de defilement.

   Reecrire 1 806 vues n'est pas envisageable. La seule prise qui reste est
   `!important`, pose dans des media queries qui ne s'ouvrent QUE sous 900 px.
   Au-dela — c'est-a-dire sur les postes de travail de l'hopital, qui sont la
   cible principale — ce fichier ne declare rien du tout : l'ecran de bureau
   est strictement inchange.

   ORDRE DE CHARGEMENT : ce fichier doit etre le DERNIER <link> de la page,
   apres `header.php` et son <style> en ligne, sinon les regles de meme
   specificite qui y figurent passeraient devant.

   PALIERS
     <= 900 px  tablette et telephone en paysage. La barre laterale est deja
                hors-champ a ce palier (voir header.php), on aligne le reste.
     <= 640 px  telephone en portrait. C'est la que tout se joue.
     <= 400 px  petits telephones : on serre encore les marges.
   ========================================================================== */


/* =============================================================================
   1. BASES
   ========================================================================== */

@media (max-width: 900px) {

    /* `min-height: 100vh` (header.php) compte la barre d'URL du navigateur
       mobile comme si elle n'existait pas : la page depasse systematiquement
       d'une cinquantaine de pixels et on « rebondit » en bas de chaque ecran.
       `svh` mesure la hauteur reellement visible. La regle `vh` reste en
       premier comme repli pour les navigateurs qui ignorent `svh`. */
    body {
        min-height: 100vh;
        min-height: 100svh;
    }

    /* `background-attachment: fixed` est pose en style en ligne sur <body>.
       Sur iOS il n'est pas implemente (l'image est redimensionnee a la
       hauteur du document entier, donc enorme et floue) et sur Android il
       provoque un repeint a chaque pixel de defilement. On repasse en
       defilement normal. */
    body#bg {
        background-attachment: scroll !important;
    }

    /* Filet de securite : rien ne doit pouvoir pousser la page au-dela de sa
       largeur : un seul element trop large et TOUT l'ecran se met a glisser
       lateralement, ce qui est le defaut le plus desagreable a l'usage. Les
       rares contenus vraiment larges (tableaux) defilent dans leur propre
       cadre.

       `clip` et non `hidden`, et sur `body` seulement. `overflow-x: hidden`
       fait du bloc un conteneur de defilement : les bandeaux d'identite, qui
       sont en `position: sticky`, cessent alors de coller en haut de l'ecran
       et remontent avec le contenu — verifie, la barre partait a -900 px des
       le premier defilement. `clip` coupe le debordement sans creer de
       conteneur de defilement, donc sans toucher au `sticky`. La ou `clip`
       n'est pas connu (navigateurs anterieurs a 2022), la declaration est
       ignoree : on retombe simplement sur le comportement d'avant, sans
       regression. */
    html, body {
        max-width: 100%;
    }
    body {
        overflow-x: clip;
    }

    /* Les references de l'hopital n'ont pas d'espace pour se couper
       (CSJP-20260817-0000010) : sans cette regle elles debordent de leur
       cellule ou etirent la colonne. */
    body .data-table td,
    body .data-table th,
    body .info-value,
    body .info-label {
        /* `break-word` et non `anywhere` : les deux coupent un mot trop long
           plutot que de le laisser deborder, mais `anywhere` le fait aussi
           entrer dans le calcul de la largeur minimale de la colonne. Le
           tableau se tasse alors au maximum et « Amoxycilline » s'affiche sur
           deux lignes dans une colonne de 60 px, sans necessite. */
        overflow-wrap: break-word;
    }
}


/* =============================================================================
   2. CHROME DE PAGE — barre collante, hamburger, bandeau d'identite
   ========================================================================== */

@media (max-width: 900px) {

    /* Le hamburger est `position: fixed` en haut a gauche (header.php) et se
       posait PAR-DESSUS le bandeau d'identite : « Compte : Gerant » etait
       coupe en deux sur chaque ecran. On reserve sa place dans le bandeau
       plutot que de le faire flotter au-dessus.
       Deux bandeaux coexistent selon l'ecran : `banniere.php` rend
       `#main-wrapper` (814 appels) et `banniere-back.php` `#backoffice-wrapper`
       (447 appels). Les deux sont traites partout dans ce fichier. */
    #main-wrapper,
    #backoffice-wrapper {
        padding-left: 58px;
    }

    /* Menu ouvert, le hamburger se superposait au titre de la barre laterale
       (« :al Hopital »). Le voile suffit a refermer, le bouton n'a plus lieu
       d'etre. */
    body.bl-ouverte .bl-hamburger {
        display: none !important;
    }

    /* Cible tactile : 44 px est le minimum retenu par les guides Apple et
       Google. Le bouton en faisait 38. */
    body.a-barre-laterale .bl-hamburger {
        top: 8px;
        left: 8px;
        min-width: 44px;
        min-height: 44px;
        padding: 0 12px;
        font-size: 1.05rem;
    }

    /* Le bandeau d'identite prenait 10 px de haut et 30 px de cote pour
       afficher deux informations de service. Sur un ecran de 844 px de haut,
       chaque ligne compte. */
    #submenu-main,
    #submenu-back {
        padding: 8px 12px !important;
        font-size: 12px !important;
        margin-bottom: 12px !important;
    }

    /* La barre collante mangeait jusqu'a un quart de la hauteur utile des
       qu'un badge de notification passait a la ligne. On plafonne. */
    #main-wrapper,
    #backoffice-wrapper {
        max-height: 40vh;
        overflow-y: auto;
    }

    /* Replier/deplier la barre laterale n'a pas de sens quand elle est
       hors-champ : le bouton « << » ne faisait que la refermer, en doublon
       du voile. */
    body.bl-ouverte .bl-bascule {
        display: none;
    }

    /* Les entrees du menu : 7 px de padding vertical donnaient des cibles de
       31 px, sous le seuil tactile, et un menu ou l'on se trompe de ligne. */
    .bl-lien {
        padding-top: 11px;
        padding-bottom: 11px;
    }
    .bl-lien.est-actif {
        padding-top: 11px;
        padding-bottom: 11px;
    }
    .bl-section-titre {
        padding-top: 13px;
        padding-bottom: 13px;
    }

    /* La barre laterale hors-champ occupait 258 px fixes, soit les deux tiers
       d'un telephone de 390 px : on voyait a peine le voile derriere, donc
       mal ou refermer. Elle s'arrete maintenant a 82 % de l'ecran. */
    .barre-laterale,
    body.bl-repliee .barre-laterale {
        width: min(82vw, 310px);
    }
}

@media (max-width: 640px) {

    /* Le pied de page tenait sur deux lignes serrees et centrees sur une
       image de fond : illisible. */
    body .page-footer {
        font-size: 11px;
        margin-top: 24px;
        padding: 12px 6px;
        line-height: 1.6;
        background: rgba(255, 255, 255, 0.88);
        border-radius: 6px;
    }
}


/* =============================================================================
   3. CONTENEURS ET FEUILLE
   ========================================================================== */

@media (max-width: 640px) {

    /* 15 px de conteneur + 20 px de feuille = 70 px de marges sur 390, soit
       18 % de l'ecran perdus avant d'avoir affiche quoi que ce soit. Et
       plusieurs vues poussent jusqu'a 25 px en style en ligne, d'ou le
       `!important` : sans lui ces ecrans-la gardent leurs marges de bureau. */
    body .invoice-layout,
    body .invoice-layout-small,
    body .invoice-layout-large {
        padding: 0 10px !important;
        margin: 10px auto !important;
    }

    body .paper-sheet {
        padding: 16px 14px;
        border-radius: 8px;

        /* `min-height: 500px` produisait une carte blanche a moitie vide sous
           un formulaire de deux champs. Sur un ecran de bureau c'est une
           respiration ; sur telephone c'est un demi-ecran de vide a franchir
           avant le pied de page. */
        min-height: 0;
    }

    /* Les 410 vues qui portent une largeur en dur sur leur feuille sont deja
       neutralisees dans header.php ; on etend la meme protection a tout
       element fixant une largeur en pixels en ligne, qui autrement force un
       defilement lateral de la page entiere. */
    body .paper-sheet [style*="width:"],
    body .paper-sheet [style*="width :"] {
        max-width: 100% !important;
    }

    /* Mais pas les cellules de tableau : leur `width: 10%` sert au partage
       des colonnes et `max-width` y declencherait des calculs absurdes. */
    body .paper-sheet td[style*="width"],
    body .paper-sheet th[style*="width"] {
        max-width: none !important;
    }

    body .sheet-header {
        margin-bottom: 18px;
        padding-bottom: 10px;
    }
    body .sheet-title {
        font-size: 19px;
        line-height: 1.3;
    }
    body .chapeau-box,
    body .alert-box {
        padding: 12px 14px;
        margin-bottom: 16px;
        font-size: 13px;
    }
}

@media (max-width: 400px) {
    body .invoice-layout,
    body .invoice-layout-small,
    body .invoice-layout-large {
        padding: 0 6px;
    }
    body .paper-sheet {
        padding: 14px 10px;
    }
}


/* =============================================================================
   4. BARRE D'ACTIONS ET RECHERCHE
   ========================================================================== */

@media (max-width: 768px) {

    /* header.php bascule la barre en colonne sous 768 px, mais laisse
       `margin-left: auto` sur la zone de recherche. En colonne, cette marge
       ne pousse plus vers la droite dans le flux : elle DECALE le bloc vers
       la droite. Le champ se retrouvait desaxe, et l'icone de loupe —
       positionnee en absolu a 12 px du conteneur — atterrissait au milieu du
       texte « Rechercher... ». C'est le defaut le plus visible de l'ecran. */
    body .action-bar > .toolbar-right,
    body .action-bar > .search-wrapper {
        margin-left: 0 !important;
        width: 100%;
    }

    body .action-bar {
        padding: 12px;
        gap: 10px;
        margin-bottom: 16px;
        border-left-width: 4px;
    }

    /* Un bouton par ligne, c'etait la regle de header.php
       (`body .btn-action { width: 100% }`). Trois filtres « Actifs /
       Suspendus / Tous » occupaient alors trois lignes pleines : 180 px de
       hauteur pour trois mots, et la liste qu'ils filtrent repoussee sous la
       ligne de flottaison. On rend leur largeur naturelle aux boutons et on
       laisse le conteneur les repartir : deux par ligne quand ils sont
       courts, un seul quand le libelle est long. La hauteur tactile de 44 px,
       elle, est garantie dans tous les cas. */
    body .btn-action {
        width: auto !important;
        flex: 1 1 auto;
        min-width: 132px;
        min-height: 44px;
        padding: 10px 12px;
        justify-content: center;
    }

    /* Un bouton seul n'a aucune raison de s'etaler sur toute la largeur : il
       se lisait comme l'action principale de l'ecran alors qu'il n'est
       souvent qu'un retour a la liste ou une impression. */
    body .action-bar > .btn-action:only-child,
    body .btn-group > .btn-action:only-child {
        flex: 0 1 auto;
    }

    /* Les rangees de boutons, y compris celles que les vues declarent en
       `style="display:flex"` sans prevoir le retour a la ligne. */
    body .toolbar-left,
    body .btn-group,
    body .toolbar-right {
        flex-direction: row !important;
        flex-wrap: wrap;
        gap: 8px;
        width: 100%;
    }

    body .search-wrapper {
        max-width: none !important;
        flex: 1 1 100%;
    }

    /* La loupe est posee en absolu a 12 px du bord du conteneur, en supposant
       que le champ porte la classe `.search-input` et ses 35 px de retrait a
       gauche. Une partie des vues ne pose qu'un `id="search_input"` : le
       champ n'a alors aucun retrait et l'icone se retrouve DANS le mot
       « Rechercher ». On rattrape tout champ vivant sous une loupe.
       (Le meme defaut existe sur poste de travail ; il n'est pas corrige ici,
       ce fichier ne devant rien changer au-dela de 900 px.) */
    body .search-wrapper input {
        padding-left: 36px;
        box-sizing: border-box;
        width: 100%;
        border: 1px solid #ddd;
        border-radius: 6px;
    }
}


/* =============================================================================
   5. FORMULAIRES ET CIBLES TACTILES
   ========================================================================== */

@media (max-width: 900px) {

    /* Safari iOS zoome automatiquement des qu'un champ recoit le focus avec
       une police inferieure a 16 px — et ne dezoome pas en sortant. C'est
       l'origine de la sensation de page « qui part de travers » au premier
       clic dans un formulaire. Les champs du logiciel sont a 14 px. */
    body input[type="text"],
    body input[type="number"],
    body input[type="password"],
    body input[type="email"],
    body input[type="tel"],
    body input[type="date"],
    body input[type="time"],
    body input[type="search"],
    body select,
    body textarea,
    body .form-control,
    body .search-input {
        font-size: 16px !important;
        min-height: 44px;
        max-width: 100% !important;
    }

    body textarea,
    body .form-control[rows] {
        min-height: 88px;
    }

    /* Les boutons d'action en ligne dans les tableaux faisaient 32 px : on
       vise a cote une fois sur trois au doigt. */
    body .btn-icon {
        width: 40px;
        height: 40px;
        font-size: 15px;
    }

    body .btn-action {
        min-height: 44px;
    }

    /* Les cases a cocher des listes de selection (examens, articles) etaient
       a la taille par defaut, soit 13 px de cible. */
    body input[type="checkbox"],
    body input[type="radio"] {
        width: 20px;
        height: 20px;
        vertical-align: middle;
    }
}

@media (max-width: 640px) {

    body .form-group {
        margin-bottom: 14px;
    }
    body .form-label {
        margin-bottom: 6px;
    }

    /* Les actions de formulaire (Valider / Annuler) se serraient sur une
       ligne en se coupant. Elles s'empilent, l'action principale en premier,
       et restent atteignables au pouce. */
    body .form-actions {
        flex-direction: column;
        gap: 10px;
        margin-top: 24px;
        padding-top: 16px;
    }
    /* `!important` : la regle generique de la section 4 rend leur largeur
       naturelle a tous les boutons, elle aussi en `!important` pour passer
       devant `header.php`. Ici on veut le contraire — une action de
       formulaire se prend a pleine largeur. */
    body .form-actions .btn-action {
        width: 100% !important;
        justify-content: center;
    }
    body .form-actions-modal {
        text-align: stretch;
    }
}


/* =============================================================================
   6. GRILLES POSEES EN LIGNE DANS LES VUES
   =============================================================================
   C'est le coeur du probleme. 116 vues fixent leur grille en attribut
   `style=`, hors d'atteinte des media queries de header.php. Une grille
   `1fr 1fr 1fr` reste a trois colonnes sur 310 px utiles : chaque colonne
   fait 90 px et le texte se casse lettre par lettre.

   Le selecteur d'attribut `[style*="..."]` est la seule facon d'atteindre
   ces elements sans toucher aux vues. Il est volontairement large : sous
   640 px, une grille a plusieurs colonnes n'a jamais de sens, a la seule
   exception des tuiles d'indicateurs (voir plus bas).
   ========================================================================== */

@media (max-width: 640px) {

    /* Toute grille declaree en ligne repasse a une colonne.
       `minmax(0, 1fr)` plutot que `1fr` : `1fr` vaut `minmax(auto, 1fr)`, et
       un contenu insecable (une reference, un tableau) elargit alors la
       colonne au-dela de la grille — le fameux debordement de grille. */
    body [style*="grid-template-columns"] {
        grid-template-columns: minmax(0, 1fr) !important;
        gap: 12px !important;
    }

    /* Exception : les tuiles d'indicateurs des tableaux de bord, ecrites
       `repeat(auto-fit, minmax(180px, 1fr))`. Une tuile porte un chiffre et
       trois mots ; a une par ligne, huit indicateurs demandent 1 200 px de
       defilement pour huit nombres. Deux colonnes les font tenir en un
       ecran, ce qui est exactement ce qu'on attend d'un tableau de bord. */
    body [style*="auto-fit"],
    body [style*="auto-fill"] {
        grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
        gap: 10px !important;
    }

    /* Les conteneurs flex poses en ligne : on autorise le retour a la ligne,
       que la plupart oublient de declarer. */
    body [style*="display:flex"],
    body [style*="display: flex"] {
        flex-wrap: wrap;
    }

    /* Les grilles de formulaire et de fiche, elles, sont deja en classes. */
    body .form-grid,
    body .info-grid,
    body .form-grid-m-2 {
        grid-template-columns: minmax(0, 1fr) !important;
        display: grid !important;
        gap: 12px;
    }

    body .multi-col-grid {
        flex-direction: column;
        gap: 16px;
    }
}

@media (min-width: 641px) and (max-width: 900px) {

    /* Palier intermediaire : trois ou quatre colonnes ne tiennent pas sur une
       tablette en portrait, deux oui. */
    body [style*="repeat(3"],
    body [style*="repeat(4"],
    body [style*="repeat( 3"],
    body [style*="repeat( 4"],
    body [style*="1fr 1fr 1fr"] {
        grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
    }
}


/* =============================================================================
   7. TABLEAUX — bascule en fiches
   =============================================================================
   Un tableau de neuf colonnes dans une fenetre de 310 px est illisible quelle
   que soit la ruse employee. Aujourd'hui il defile lateralement DANS son
   cadre : rien ne l'indique a l'ecran, et les boutons d'action, toujours en
   derniere colonne, sont donc hors d'atteinte pour qui ne devine pas qu'il
   faut glisser. C'est le defaut le plus couteux a l'usage.

   `responsive-tableaux.js` recopie les libelles de l'en-tete dans un attribut
   `data-libelle` sur chaque cellule ; les regles ci-dessous transforment alors
   chaque ligne en une petite fiche « libelle / valeur ». Le script ne marque
   que les tableaux dont la structure s'y prete (voir le fichier) ; les autres
   gardent le defilement lateral, mais signale cette fois.
   ========================================================================== */

@media (max-width: 640px) {

    /* --- Tableaux convertis en fiches --- */

    body .data-table.tableau-fiches {
        min-width: 0 !important;
        width: 100% !important;
        display: block;
        font-size: 13px;
    }

    body .tableau-fiches thead,
    body .tableau-fiches tr.ligne-entete {
        display: none;
    }

    body .tableau-fiches tbody,
    body .tableau-fiches tfoot {
        display: block;
    }

    body .tableau-fiches tr {
        display: block;
        border: 1px solid #e3e8ee;
        border-left: 3px solid var(--primary, #2c3e50);
        border-radius: 8px;
        background: #fff;
        margin: 0 0 10px;
        padding: 4px 12px;
    }

    body .tableau-fiches tr:hover {
        background: #fff;
    }

    body .tableau-fiches td {
        display: flex;
        align-items: baseline;
        justify-content: space-between;
        gap: 14px;
        width: auto !important;
        max-width: none !important;
        padding: 8px 0;
        border: 0;
        border-bottom: 1px dashed #f0f2f5;
        text-align: right;
    }

    body .tableau-fiches tr td:last-child {
        border-bottom: 0;
    }

    /* Le libelle de colonne, recopie de l'en-tete par le script. */
    body .tableau-fiches td[data-libelle]::before {
        content: attr(data-libelle);
        flex: 0 0 38%;
        text-align: left;
        font-size: 11px;
        font-weight: 600;
        line-height: 1.5;
        letter-spacing: 0.3px;
        text-transform: uppercase;
        color: #7b8794;
    }

    /* Une colonne sans titre (celle des boutons, le plus souvent) n'a pas de
       libelle a afficher : sa cellule prend toute la largeur. */
    body .tableau-fiches td[data-libelle=""],
    body .tableau-fiches td.td-actions {
        display: block;
        text-align: left;
        padding-top: 10px;
    }

    /* Les boutons d'action, jusqu'ici hors champ a droite, deviennent une
       rangee en bas de la fiche. Ils echappent a la largeur minimale de
       132 px accordee aux boutons de barre d'outils : ce sont presque
       toujours des icones seules, qui n'ont besoin que d'une cible tactile
       carree — trois d'entre elles tiennent alors sur une ligne au lieu de
       trois. */
    body .tableau-fiches td.td-actions {
        display: flex;
        flex-wrap: wrap;
        gap: 8px;
        align-items: center;
    }
    body .tableau-fiches td.td-actions .btn-action,
    body .tableau-fiches td.td-actions .btn-icon {
        flex: 0 0 auto;
        min-width: 46px;
        padding: 10px 14px;
    }
    body .tableau-fiches td.td-actions .action-group {
        display: flex;
        flex-wrap: wrap;
        gap: 8px;
        justify-content: flex-start !important;
        width: 100%;
    }

    /* Les lignes pleine largeur : cartouche de titre en tete de tableau,
       « Aucune occurrence trouvee » en l'absence de donnees. Ce ne sont pas
       des fiches, elles ne prennent donc ni cadre ni filet de couleur. */
    body .tableau-fiches tr.ligne-message {
        border: 0;
        border-radius: 0;
        background: none;
        margin-bottom: 4px;
        padding: 0;
    }
    body .tableau-fiches tr.ligne-message td {
        display: block;
        text-align: center;
        color: #7b8794;
        border-bottom: 0;
    }
    body .tableau-fiches tr.ligne-message td::before {
        content: none;
    }

    /* Les totaux gardent leur poids visuel. */
    body .tableau-fiches tfoot tr {
        border-left-color: var(--warning, #f39c12);
        background: #fbfcfd;
        font-weight: 700;
    }

    /* Le cadre a defilement n'a plus lieu d'etre autour d'une pile de fiches :
       il ajoutait une bordure et une ombre a l'interieur d'une carte qui en a
       deja. */
    body .table-container:has(.tableau-fiches) {
        overflow-x: visible;
        border: 0;
        box-shadow: none;
        border-radius: 0;
    }

    /* --- Tableaux restes en defilement lateral --- */

    body .table-container {
        /* Le defilement au doigt, avec inertie, et un arret par colonne. */
        -webkit-overflow-scrolling: touch;
        margin-bottom: 18px;
    }

    /* Rien n'indiquait que ce cadre defile. Une ombre portee a droite, qui
       disparait quand on atteint le bout, est la convention la plus lisible
       sans ajouter de texte. */
    body .table-container.defile-lateralement {
        background:
            linear-gradient(to right, #fff 30%, rgba(255, 255, 255, 0)) left center,
            linear-gradient(to left, #fff 30%, rgba(255, 255, 255, 0)) right center,
            radial-gradient(farthest-side at 0 50%, rgba(44, 62, 80, 0.18), transparent) left center,
            radial-gradient(farthest-side at 100% 50%, rgba(44, 62, 80, 0.18), transparent) right center;
        background-repeat: no-repeat;
        background-size: 30px 100%, 30px 100%, 14px 100%, 14px 100%;
        background-attachment: local, local, scroll, scroll;
    }

    body .data-table:not(.tableau-fiches) {
        min-width: 0;
        font-size: 12.5px;
    }
    body .data-table:not(.tableau-fiches) th {
        padding: 10px 8px;
        font-size: 10.5px;
    }
    body .data-table:not(.tableau-fiches) td {
        padding: 9px 8px;
    }

    /* Les tableaux compacts des postes de service (pharmacie, passation) :
       memes causes, memes effets. */
    .table-large {
        -webkit-overflow-scrolling: touch;
    }
    .table-compacte {
        font-size: 11px;
    }
    .table-compacte th,
    .table-compacte td {
        padding: 4px 5px;
    }
}


/* Ce qui suit vaut des 900 px : un tableau de neuf colonnes est deja coupe
   sur une tablette en portrait, et rien ne le dit non plus a cette taille. */
@media (max-width: 900px) {

    /* La ligne d'explication posee par le script au-dessus d'un tableau qui
       defile. Discrete, mais explicite : c'est la seule indication qu'une
       partie des colonnes est hors champ. */
    body .indice-defilement {
        margin: 0 0 6px;
        font-size: 11.5px;
        line-height: 1.4;
        color: #7b8794;
        font-style: italic;
    }
    body .indice-defilement::before {
        content: "\2194\00a0";
        font-style: normal;
    }

    /* Largeur confortable rendue aux seuls tableaux qui defilent vraiment
       (classe posee par le script apres mesure) : tasse a sa largeur
       minimale, un tableau de six colonnes coupe chaque mot et monte a
       225 px par ligne. */
    body .data-table.tableau-au-large {
        min-width: 560px;
    }

    /* Les boutons d'action a l'interieur d'un tableau echappent a la largeur
       minimale de 132 px accordee aux boutons de barre d'outils : elle
       elargissait la colonne d'actions au point de la faire deborder, et
       empilait ses trois icones l'une sous l'autre — ce qui triplait la
       hauteur de chaque ligne. */
    body .data-table .btn-action,
    body .data-table .btn-icon {
        min-width: 0 !important;
        flex: 0 0 auto;
        width: auto !important;
        padding: 8px 10px;
    }
    /* `!important` : les vues declarent `flex-wrap: wrap` en style en ligne
       sur ce groupe. La colonne d'actions se calant sur la largeur d'UN
       bouton (58 px mesures), les trois icones se mettaient l'une sous
       l'autre et chaque ligne du tableau montait a 169 px. En `nowrap`, la
       largeur minimale du groupe devient celle des trois boutons, dont la
       mise en page du tableau tient compte : la colonne s'elargit d'elle-meme
       et la ligne retombe a une hauteur normale. */
    body .data-table:not(.tableau-fiches) .action-group {
        flex-wrap: nowrap !important;
        justify-content: flex-start !important;
    }
    /* En fiches, au contraire, la rangee d'actions occupe toute la largeur de
       la carte : elle peut et doit revenir a la ligne s'il y a plus de trois
       boutons. */
    body .tableau-fiches td.td-actions .action-group {
        flex-wrap: wrap !important;
    }
    body .data-table td .btn-action,
    body .data-table td .btn-icon {
        white-space: nowrap;
    }
}


/* =============================================================================
   8. MODALES
   ========================================================================== */

@media (max-width: 640px) {

    /* `margin: 15% auto` sur un ecran de 844 px pousse la modale a 126 px du
       haut, puis son contenu deborde en bas sans que le pied soit
       atteignable. On la colle en bas de l'ecran — le geste attendu sur
       telephone — et on lui donne une hauteur bornee avec un corps qui
       defile. */
    body .modal-overlay {
        display: none;
    }
    body .modal-overlay[style*="block"],
    body .modal-overlay.est-ouverte {
        display: flex !important;
        align-items: flex-end;
    }

    body .modal-content,
    body .modal-small,
    body .modal-extra-small {
        width: 100% !important;
        max-width: none !important;
        margin: 0 !important;
        border: 0;
        border-radius: 14px 14px 0 0;
        max-height: 92vh;
        max-height: 92svh;
        display: flex;
        flex-direction: column;
        animation-name: none;
    }

    body .modal-header {
        border-radius: 14px 14px 0 0;
        padding: 14px 16px;
    }
    body .modal-title {
        font-size: 16px;
    }

    /* La croix de fermeture : 28 px de police, mais une cible reelle de
       22 px de large. */
    body .modal-close {
        min-width: 44px;
        min-height: 44px;
        display: inline-flex;
        align-items: center;
        justify-content: center;
    }

    body .modal-body {
        padding: 16px;
        overflow-y: auto;
        flex: 1;
    }

    /* Toutes les modales ne suivent pas le gabarit header/body/footer : une
       bonne partie pose son formulaire directement dans `.modal-content`.
       Sur grand ecran la modale etant etroite et centree, l'absence de marge
       laterale ne se voyait pas ; en feuille pleine largeur, les libelles se
       collent au bord de l'ecran. On donne donc une marge aux enfants directs
       qui n'en ont pas deja une par leur classe. */
    body .modal-content > form,
    body .modal-content > div:not(.modal-header):not(.modal-body):not(.modal-footer) {
        padding-left: 14px;
        padding-right: 14px;
    }

    body .modal-footer {
        padding: 12px 16px;
        border-radius: 0;
        display: flex;
        flex-direction: column;
        gap: 8px;
    }
    /* Le bouton de fermeture ne porte pas toujours `.btn-action`. */
    body .modal-footer .btn-action,
    body .modal-footer button,
    body .modal-footer input[type="submit"],
    body .modal-footer input[type="button"],
    body .modal-footer > a {
        width: 100% !important;
        justify-content: center;
        text-align: center;
    }
    /* Les deux div de calage que certaines modales interposent entre le pied
       et son bouton empechaient le bouton de s'etendre. */
    body .modal-footer > div {
        width: 100%;
    }
}


/* =============================================================================
   9. FICHES, ENCADRES ET POSTES DE SERVICE
   ========================================================================== */

@media (max-width: 640px) {

    body .info-box .box-body,
    body .info-grid-simple {
        padding: 14px;
    }
    body .info-box .box-header {
        padding: 12px 14px;
        font-size: 14px;
    }

    /* header.php empile deja libelle et valeur sous 992 px, mais laisse la
       valeur alignee a gauche sous son libelle : les deux se confondent. Un
       libelle gris en petites capitales au-dessus d'une valeur en gras se
       distingue sans ambiguite. */
    body .info-label {
        font-size: 11px;
        text-transform: uppercase;
        letter-spacing: 0.3px;
        color: #7b8794;
        margin-bottom: 2px;
    }
    body .info-value {
        font-weight: 600;
    }
    body .info-row {
        padding: 8px 0;
    }

    /* postes.css : etiquette de 120 px fixes a cote d'une valeur, sur 310 px
       utiles il reste 190 px pour un montant et sa devise. */
    .poste-ligne {
        flex-direction: column;
        gap: 2px;
        padding: 6px 0;
        border-bottom: 1px dashed #eef1f5;
    }
    .poste-etiquette {
        width: auto;
        font-size: 11px;
        text-transform: uppercase;
        letter-spacing: 0.3px;
    }

    .poste-filtre {
        flex-direction: column;
        align-items: stretch;
        gap: 10px;
    }

    .poste-encadre {
        padding: 10px;
    }

    /* Trois cartouches de signature cote a cote font 95 px chacun. */
    .signatures {
        flex-direction: column;
        gap: 12px;
    }

    .table-chapeau,
    .table-chapeau tbody,
    .table-chapeau tr {
        display: block;
    }
    .table-chapeau th,
    .table-chapeau td {
        display: block;
        width: auto;
        border: 0;
        padding: 2px 0;
    }
    .table-chapeau th {
        background: none;
        font-size: 10.5px;
        text-transform: uppercase;
        color: #7b8794;
    }
    .table-chapeau tr {
        border-bottom: 1px dashed #eef1f5;
        padding: 6px 0;
    }
}


/* =============================================================================
   10. GREFFONS TIERS
   ========================================================================== */

@media (max-width: 900px) {

    /* jQuery UI pose ses calendriers en absolu a la position du champ, sans
       jamais verifier qu'ils tiennent : sur telephone la moitie du mois
       sortait de l'ecran a droite. */
    .ui-datepicker {
        max-width: calc(100vw - 20px);
        font-size: 15px;
    }
    .ui-datepicker td a,
    .ui-datepicker td span {
        padding: 8px 4px;
        text-align: center;
    }

    /* Idem pour l'autocompletion (recherche de patient, d'article). */
    .ui-autocomplete {
        max-width: calc(100vw - 20px);
        max-height: 50vh;
        overflow-y: auto;
    }
    .ui-menu .ui-menu-item {
        padding: 10px 8px;
        line-height: 1.4;
    }

    /* DataTables : sa barre d'outils (longueur, recherche, pagination) est
       construite en flottants qui se chevauchent sous 500 px. */
    .dataTables_wrapper .dataTables_length,
    .dataTables_wrapper .dataTables_filter,
    .dataTables_wrapper .dataTables_info,
    .dataTables_wrapper .dataTables_paginate {
        float: none !important;
        text-align: left !important;
        width: 100%;
        margin-bottom: 8px;
    }
    .dataTables_wrapper .dataTables_filter input {
        width: 100%;
        margin-left: 0;
    }
    .dataTables_wrapper .dataTables_paginate .paginate_button {
        padding: 8px 12px;
    }

    /* La pagination maison. */
    .pagination-a4 a,
    .pagination-a4 span {
        min-width: 40px;
        min-height: 40px;
        display: inline-flex;
        align-items: center;
        justify-content: center;
    }
}


/* =============================================================================
   11. IMPRESSION
   =============================================================================
   Tout ce qui precede est cantonne a l'ecran : la mise en page papier est
   deja traitee dans header.php, print.css et les trois feuilles d'impression
   (A4, matriciel, thermique). On se contente d'annuler la bascule en fiches,
   qui n'aurait aucun sens sur une feuille A4 : un utilisateur qui imprime
   depuis son telephone doit obtenir le meme tableau que depuis un poste.
   ========================================================================== */

@media print {
    body .data-table.tableau-fiches,
    body .tableau-fiches thead,
    body .tableau-fiches tbody,
    body .tableau-fiches tfoot,
    body .tableau-fiches tr,
    body .tableau-fiches td {
        display: revert !important;
    }
    body .tableau-fiches td::before {
        content: none !important;
    }
    body .table-container.defile-lateralement {
        background: none !important;
    }
}
