/* ============================================================
   Guiter Ops · theme.css (chargé en dernier : raffinement global)
   Style épuré moderne, CSS pur. Poppins partout, marque en texte,
   couleurs adoucies, champs nets, densité maîtrisée.
   ============================================================ */

/* --- Typographie : Poppins ----------------------------------- */
body, button, input, select, textarea {
  font-family: "Satoshi", "Segoe UI", system-ui, sans-serif;
}
h1, h2, h3, h4, .topbar-titre, .tuile-kpi-valeur, .valeur-geante {
  font-family: "Satoshi", "Segoe UI", system-ui, sans-serif;
  letter-spacing: -0.01em;
}

/* --- Marque en texte (le logo noir ne va pas sur fond vert) --- */
.marque-texte {
  font-weight: 800; font-size: 19px; letter-spacing: -0.02em;
  color: #fff; text-decoration: none; line-height: 1;
}
.marque-texte .ops { color: var(--g-orange-500); }

/* --- Commutateur de zone ------------------------------------- */
.zone-switch { position: relative; margin: 14px 12px 6px; }
.zone-switch summary {
  list-style: none; cursor: pointer; user-select: none;
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  background: rgba(255,255,255,.07); border: 1px solid rgba(255,255,255,.12);
  color: #fff; border-radius: 12px; padding: 11px 14px;
  font-size: 13px; font-weight: 600; min-height: 44px;
}
.zone-switch summary::-webkit-details-marker { display: none; }
.zone-switch summary .icone { opacity: .7; flex: none; }
.zone-switch[open] summary { border-color: var(--g-orange-500); }
/* LE COMMUTATEUR POUSSE, IL NE RECOUVRE PAS · et c'est vrai À TOUTE
   LARGEUR, pas seulement dans le tiroir.

   Ce panneau était `position: absolute`, posé par-dessus le menu du
   module. Le raisonnement qui l'a rendu statique dans le tiroir (plus bas,
   bloc 900 px) vaut partout, et la mesure le dit : sur un profil de
   Direction, à 1280 x 800, le commutateur liste VINGT-DEUX zones. Le
   panneau fait alors 839 px de haut dans une fenêtre de 800 · il
   descendait à 1009 px pendant que la barre s'arrête à 800, soit 209 px
   coupés net, et il masquait le menu de la zone en dessous. Aucune
   hauteur de fenêtre ne rattrape cela : la liste grandit avec le nombre
   de modules, et le Groupe en ouvre régulièrement.

   Posé dans le flux, il écarte le menu vers le bas et le défilement
   interne de la barre suffit à l'atteindre en entier. On perd le fondu
   d'un panneau flottant ; on gagne de pouvoir cliquer sur la dernière
   zone de la liste. */
.zone-switch .zone-menu {
  position: static;
  margin-top: 6px;
  background: var(--g-vert-900); border: 1px solid rgba(255,255,255,.14);
  border-radius: 12px; padding: 6px;
}
.zone-switch .zone-menu a {
  display: flex; align-items: center; gap: 10px;
  color: rgba(255,255,255,.85); text-decoration: none;
  border-radius: 8px; padding: 9px 10px; font-size: 13px;
}
.zone-switch .zone-menu a:hover { background: rgba(255,255,255,.08); color: #fff; }
.zone-switch .zone-menu a.actuelle { background: var(--g-vert-800); color: #fff; }

/* --- Sidebar : plus sobre ------------------------------------ */
.sidebar-section { opacity: .55; }
.sidebar-badge { background: rgba(240,160,40,.9); }

/* --- Champs nets (formulaires) ------------------------------- */
input[type="text"], input[type="email"], input[type="password"],
input[type="search"], input[type="number"], select, textarea {
  border-radius: 10px;
}
input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: 2px solid var(--g-vert-600); outline-offset: 1px;
  border-color: var(--g-vert-600);
}

/* --- Couleurs adoucies --------------------------------------- */
.hero-verte {
  background: #0F5C0D; /* aplat vert profond, aucun dégradé */
}
.pastille-delta { background: rgba(255,255,255,.12); font-weight: 600; }
.badge-hero { background: rgba(0,0,0,.18); border-color: rgba(255,255,255,.14);
  font-weight: 600; }
.badge-priorite.critique { background: #F9ECEC; color: #A03636; }
.badge-priorite.haute { background: #FBF1DE; color: #96610E; }
.chip-etat.panne { background: #F9ECEC; color: #A03636; }
.encart-preventif { background: #FCF6EB; border-left-width: 3px; }

/* --- Cartes : moins de bruit --------------------------------- */
.carte-page { border-color: #EAE8E1; box-shadow: 0 1px 2px rgba(0,0,0,.05); }
.carte-page > h2 { font-size: 16px; }

/* --- Densité : moins de texte décoratif ---------------------- */
.kicker { margin-bottom: 2px; }

/* --- Connexion : carte pleine, nette, sans flou de verre ------ */
.carte-verre {
  backdrop-filter: none !important; -webkit-backdrop-filter: none !important;
  background: #FFFFFF !important; border: none !important;
  box-shadow: 0 24px 60px rgba(7, 26, 16, .35);
}
.public-plateforme { color: var(--g-vert-800) !important; }

/* --- Mur Direction : lisible et apaisé ----------------------- */
.mur, .scene { background: #0B1F14 !important; }
.mur .pastille { box-shadow: none !important; width: 18px; height: 18px; }
.mur .carte-m {
  background: rgba(255,255,255,.045) !important;
  border: 1px solid rgba(255,255,255,.09) !important;
}
.mur .kpi-ligne b, .mur .kpi-ligne strong { font-size: 30px; }
.mur .filiale-nom { font-size: 17px; font-weight: 700; }
.mur .titre { letter-spacing: .14em; opacity: .8; }
.mur .ticker { background: rgba(0,0,0,.35) !important; font-size: 15px; }
.mur .horloge { font-weight: 700; }

/* La carte publique passe AU-DESSUS du voile dégradé (fini le faux verre). */
.public-contenu, .public-carte, .signature-concepteur { position: relative; z-index: 2; }
.voile-degrade { z-index: 1; }

/* Tableaux de bord : chiffres plus GRANDS et plus lisibles.
   La valeur SUIT la largeur de sa colonne · une rangée de six vignettes
   n'a pas la place d'une rangée de trois, et c'est là qu'une date se
   faisait couper. Le plancher garde la lisibilité, le plafond garde
   l'ancien corps 30 quand la carte est large.

   L'UNITÉ EST « cqw », PAS « vw ». La règle dit de suivre la COLONNE ;
   « 2vw » suit la fenêtre, et une vignette de 251 px recevait donc un
   corps 30 calculé sur un écran de 1 500 px · « 428 089 524 418 » y
   mesurait 327 px et sortait de sa carte. La vignette déclare déjà
   container-type: inline-size ; 8 cqw de 251 px font 20 px, et le même
   montant tient en 218 px. Le facteur se CALCULE, il ne se choisit pas. */
.fiche-kpi b { font-size: clamp(12px, 8cqw, 30px); }
.fiche-kpi b.mot { font-size: 15px; }
.fiche-kpi { padding: 16px; min-width: 0; }
.tuile-kpi-valeur { font-size: 38px; }
.carte-page > h2 { font-size: 17px; }

/* ============================================================
   IDENTITÉ GUITER RÉELLE (couleurs du logo : vert #168212,
   soleil #FDB63B) + rigueur Logika (fond neutre, transitions
   courtes, rayons 10px). Police : Satoshi.
   ============================================================ */
:root {
  --g-vert-600: #168212;
  --g-vert-800: #0F5C0D;
  --g-vert-900: #0C3E0B;
  --g-vert-950: #082B08;
  --g-vert-100: #E8F5E7;
  --g-orange-500: #FDB63B;
  --g-orange-600: #E9A222;
  --g-creme: #F5F6F8;          /* fond de travail neutre, fini le crème */
  --g-filet: #E0E0E0;
  --t-rapide: 150ms ease;
}
body, button, input, select, textarea,
h1, h2, h3, h4, .topbar-titre, .tuile-kpi-valeur, .valeur-geante {
  font-family: "Satoshi", "Segoe UI", system-ui, sans-serif;
}
h1, h2, h3, h4 { font-weight: 800; letter-spacing: -0.03em; }
.carte-page, .carte, .fiche-kpi { border-radius: 10px; }
.btn { border-radius: 10px; transition: all .15s ease; }
.sidebar { background: var(--g-vert-950); }
.sidebar-item.est-actif { border-left-color: var(--g-orange-500); }

/* Le VRAI logo Guiter, version blanche, dans la sidebar. */
.sidebar-logo img { display: block !important; height: 34px; width: auto; }

/* Boutons orange : texte lisible sur le jaune-orangé du soleil. */
.btn-orange { background: var(--g-orange-500); color: #1A1A18; }
.btn-orange:hover { background: var(--g-orange-600); }
/* LE TEXTE BLANC EST POSÉ ICI AUSSI · theme.css est chargé APRÈS
   components.css et redéfinit le fond du bouton primaire. En ne reposant
   pas la couleur, il laissait le texte hériter du vert des liens du
   contenu → « Ouvrir le dossier » vert sur vert, illisible (14/09/2026).
   On rend la règle complète, comme .btn-orange juste au-dessus. */
.btn-primaire { background: var(--g-vert-600); color: var(--g-blanc); }
.btn-primaire:hover { background: var(--g-vert-800); }

/* Formulaires de création · motif Logika (étiquettes, grille 2 colonnes). */
.form-grille {
  display: grid; gap: 16px 20px;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}
.form-groupe { display: flex; flex-direction: column; gap: 6px; }
.form-label { font-size: 13px; font-weight: 700; color: var(--g-encre); }
.form-label .requis { color: #C23A3A; }
/* `:not([type="checkbox"])` · le champ de saisie fait 42 px de haut et
   toute la largeur, ce qu'une CASE À COCHER ne doit surtout pas devenir.
   Sans cette exclusion, une case posée dans un .form-groupe s'étirait à
   100 % de la ligne et écrasait son libellé contre le bord · défaut vu à
   l'écran sur le bloc « Rattachement ». La famille .creer-champ portait
   déjà l'exclusion ; celle-ci ne l'avait pas, et .form-case ne faisait que
   rattraper le cas au coup par coup. */
.form-groupe input:not([type="checkbox"]):not([type="radio"]),
.form-groupe select, .form-groupe textarea {
  width: 100%; box-sizing: border-box; font: inherit;
  height: 42px; padding: 0 12px;
  border: 1px solid var(--g-filet); border-radius: 10px; background: #fff;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.form-groupe textarea { height: auto; min-height: 90px; padding: 10px 12px; }
.form-groupe input:not([type="checkbox"]):not([type="radio"]):focus,
.form-groupe select:focus, .form-groupe textarea:focus {
  border-color: var(--g-vert-600); outline: none;
  box-shadow: 0 0 0 3px var(--g-vert-100);
}
.form-aide { font-size: 12px; color: var(--g-muet); }
.form-erreur { font-size: 12.5px; color: #C23A3A; font-weight: 600; margin-top: 4px; }
.form-case { flex-direction: row; align-items: center; gap: 10px; }
.form-case input { width: 20px; height: 20px; }

/* En-tête de liste avec action « Nouveau » (motif Logika). */
.page-actions {
  display: flex; align-items: center; justify-content: space-between;
  gap: 14px; flex-wrap: wrap; margin: 4px 0 4px;
}

/* ============================================================
   Plateforme vivante : les courbes se tracent, les barres
   grandissent. Motion douce, entièrement neutralisée dès que
   l'utilisateur préfère réduire les animations.
   ============================================================ */
@media (prefers-reduced-motion: no-preference) {
  @keyframes tracer { to { stroke-dashoffset: 0; } }
  .trace-vivante {
    stroke-dasharray: 1600;
    stroke-dashoffset: 1600;
    animation: tracer 1.1s ease-out .15s forwards;
  }
  @keyframes grandir { from { transform: scaleX(0); } }
  .barre-vivante { animation: grandir .6s ease-out backwards; }
}

/* ============================================================
   GABARIT DE CRÉATION (ui/creer.html) · esprit Modulix/Curelo :
   carte centrée 760px, grille sémantique demi / pleine largeur,
   étiquettes au-dessus, pied d'actions séparé par un filet.
   ============================================================ */
.creer-carte {
  max-width: 760px;
  margin: 18px auto 36px;
  padding: 28px;
}

/* En-tête de carte : titre + sous-titre gris. */
.creer-entete { margin-bottom: 24px; }
.creer-titre {
  margin: 0;
  font-size: 20px; font-weight: 800; letter-spacing: -0.02em;
  color: var(--g-encre);
}
.creer-sous-titre { margin: 5px 0 0; font-size: 13px; color: var(--g-muet); }

/* Erreur globale du formulaire : sobre, jamais criarde. */
.creer-alerte {
  margin-bottom: 18px; padding: 11px 14px;
  background: #FBF1F1; border: 1px solid #EAC9C9; border-radius: 10px;
  color: #A03636; font-size: 13px; font-weight: 600;
}

/* Grille : 2 colonnes ; un champ est pleine largeur par défaut,
   la classe .demi le ramène à une colonne (champs courts). */
.creer-grille {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 18px 20px;
}
.creer-champ {
  grid-column: 1 / -1;
  display: flex; flex-direction: column; gap: 6px;
  min-width: 0;
}
.creer-champ.demi { grid-column: auto / span 1; }
@media (max-width: 640px) {
  .creer-champ.demi { grid-column: 1 / -1; }
}
/* ATTENTION · le `display: flex` ci-dessus est posé par une CLASSE, donc
   il bat le `display: none` que le navigateur attache à [hidden]. Un champ
   marqué caché restait affiché. La réparation est unique et vit dans
   tokens.css (« CACHÉ VEUT DIRE CACHÉ ») · ne pas la recopier ici. */

/* Étiquette au-dessus, astérisque orange soleil (pas rouge agressif). */
.creer-label { font-size: 13px; font-weight: 600; color: var(--g-encre); }
.creer-label .requis {
  color: var(--g-orange-600); font-weight: 700; margin-left: 3px;
}

/* Champs : 44px, bordure douce, fond blanc, anneau vert au focus. */
.creer-champ input:not([type="checkbox"]),
.creer-champ select,
.creer-champ textarea {
  width: 100%; box-sizing: border-box;
  font: inherit; font-size: 14px; color: var(--g-encre);
  height: 44px; padding: 0 12px;
  background: #FFFFFF;
  border: 1px solid var(--g-filet); border-radius: 10px;
  transition: border-color var(--t-rapide), box-shadow var(--t-rapide);
}
.creer-champ textarea {
  height: auto; min-height: 96px; padding: 10px 12px; resize: vertical;
}
.creer-champ input::placeholder,
.creer-champ textarea::placeholder { color: #B9B8B3; }
.creer-champ input:not([type="checkbox"]):focus,
.creer-champ select:focus,
.creer-champ textarea:focus,
.creer-champ input:not([type="checkbox"]):focus-visible,
.creer-champ select:focus-visible,
.creer-champ textarea:focus-visible {
  outline: none;
  border-color: var(--g-vert-600);
  box-shadow: 0 0 0 3px rgba(22, 130, 18, .13);
}

/* Select : chevron dessiné (aucune apparence native). */
.creer-champ select {
  appearance: none; -webkit-appearance: none; -moz-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2352514E' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 16px 16px;
  padding-right: 38px;
}

/* Liste à choix MULTIPLES : elle vaut par sa hauteur.
   « height: 44px » ci-dessus écrasait l'attribut ``size`` · un champ où
   l'on désigne huit destinataires n'en montrait qu'un, dans une boîte
   d'une ligne coiffée d'un chevron qui n'ouvre rien. C'est ce qui a fait
   croire, sur l'écran des règles de notification, qu'on ne pouvait pas
   ajouter de destinataire. */
.creer-champ select[multiple] {
  height: auto;
  min-height: 184px;
  padding: 6px;
  background-image: none;
}
.creer-champ select[multiple] option {
  padding: 6px 8px;
  border-radius: 6px;
}

/* Champ figé : il se lit, il ne s'écrit pas · et ça se voit. */
.creer-champ input[readonly] {
  background: var(--g-creme, #F7F6F1);
  color: var(--g-muet);
  cursor: default;
}

/* Case à cocher : rangée alignée sur la ligne des champs voisins. */
.creer-champ.avec-case { justify-content: flex-end; }
.creer-case {
  display: flex; align-items: center; gap: 10px; min-height: 44px;
}
.creer-case input[type="checkbox"] {
  width: 18px; height: 18px; margin: 0; flex: none;
  accent-color: var(--g-vert-600);
}
.creer-case .creer-label { margin: 0; }

/* Champ fichier : aperçu de l'image actuelle à côté du WIDGET Django
   (« Actuellement : … » + case Effacer + sélecteur), pas à la place. */
.creer-fichier {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
}
.creer-apercu {
  width: 64px; height: 64px; flex: none;
  border-radius: 50%; object-fit: cover; border: 1px solid var(--g-filet);
}
/* Le widget rend un lien vers la pièce déposée, une case « Effacer » et le
   sélecteur : on lui donne de l'air sans lui imposer une mise en page. */
.creer-fichier-widget {
  flex: 1 1 240px; min-width: 0;
  font-size: 13px; color: var(--g-encre-2); line-height: 1.7;
}
.creer-fichier-widget a { color: var(--g-vert-600); }
.creer-fichier-widget input[type="file"] {
  display: block; margin-top: 6px; max-width: 100%;
  font: inherit; font-size: 13px; color: var(--g-encre);
  background: var(--g-blanc);
  border: 1px solid var(--g-filet); border-radius: 10px; padding: 9px 12px;
}
.creer-fichier-widget input[type="checkbox"] {
  width: 16px; height: 16px; margin: 0 6px 0 0;
  accent-color: var(--g-vert-600); vertical-align: -2px;
}

/* Aide grise sous le champ, erreur rouge sobre. */
.creer-aide { font-size: 12px; color: var(--g-muet); line-height: 1.45; }
.creer-erreur { font-size: 12px; font-weight: 600; color: #A03636; }
.creer-champ.en-erreur input:not([type="checkbox"]),
.creer-champ.en-erreur select,
.creer-champ.en-erreur textarea { border-color: #C86B6B; }

/* Pied : Annuler fantôme à gauche, Enregistrer vert à droite,
   séparés du formulaire par un filet. */
.creer-pied {
  display: flex; align-items: center; justify-content: space-between;
  margin-top: 26px; padding-top: 20px;
  border-top: 1px solid var(--g-filet);
}

/* ============================================================
   PIÈCES COMMUNES SORTIES DES GABARITS
   ------------------------------------------------------------
   Ces classes étaient redéfinies dans un <style> local page après
   page (jusqu'à trois variantes de la même chose). Elles vivent
   ici, une fois, pour que la charte cesse de se disperser.
   ============================================================ */

/* Paragraphe d'explication sous un titre · employé dans 30 gabarits
   sans avoir jamais été défini : il héritait du corps de texte. */
.note {
  margin: 6px 0 0; font-size: 13px; color: var(--g-muet);
  line-height: 1.5; max-width: 74ch;
}

/* État vide honnête d'une collection · dit ce qui manque et pourquoi. */
.etat-vide {
  margin-top: 16px; padding: 28px 20px; text-align: center;
  background: var(--g-blanc); border: 1px dashed var(--g-filet);
  border-radius: 10px; color: var(--g-muet); font-size: 13.5px;
}
.etat-vide b { display: block; color: var(--g-encre); margin-bottom: 4px; }

/* Cartes de collection (fiches en cotation, files de travail). */
.grille-collection {
  display: grid; gap: 16px; margin-top: 14px;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 430px), 1fr));
}
.collection-entete {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 12px; flex-wrap: wrap; margin-bottom: 12px;
}
.collection-titre { margin: 0; font-size: 16px; }
/* LE SUJET D'UNE CARTE · ce que la pièce demande, sous son numéro. Un
   numéro est une adresse, pas un sujet : sans cette ligne, une file de
   huit fiches s'ouvre huit fois pour retrouver la bonne. */
.collection-sujet {
  margin: 2px 0 0; font-weight: 600; line-height: 1.35;
  color: var(--c-texte, #1B1D1B);
}
.collection-pied {
  display: flex; gap: 8px; flex-wrap: wrap; margin-top: 14px;
  padding-top: 12px; border-top: 1px solid var(--g-filet);
}

/* Étape SAUTÉE du circuit (les cotations d'un achat direct) : barrée et
   grise · elle n'a pas eu lieu, elle ne se montre pas comme faite. */
.stepper-etape.est-sautee { opacity: .75; }
.stepper-etape.est-sautee .stepper-libelle {
  text-decoration: line-through; color: var(--g-muet);
}
.stepper-etape.est-sautee .stepper-point {
  background: var(--g-blanc);
  border: 1px dashed var(--g-muet);
  box-shadow: none;
}

/* Encart d'honnêteté · remplace un bouton que l'utilisateur n'a pas le
   droit d'actionner. Était recopié dans quatre gabarits (flux, compta,
   magasin) : il vit ici, une fois. */
.encart-reserve {
  display: inline-flex; align-items: center; gap: 8px;
  color: var(--g-muet); font-size: 12.5px;
  border: 1px dashed var(--g-filet); border-radius: 10px;
  padding: 8px 12px; background: var(--g-blanc);
}

/* File de travail dont les éléments sont des liens (dossier, fiche). */
.liste-file a.element {
  display: block; text-decoration: none; color: inherit; cursor: pointer;
  transition: background var(--t-rapide);
}
.liste-file a.element:hover { background: #FAFBFA; }

/* Alertes de l'intelligence N1 · aplats, jamais décoratives.
   Rouge = à vérifier avant d'engager · orange = à savoir. */
.liste-alertes { list-style: none; margin: 14px 0 0; padding: 0; }
.liste-alertes li {
  padding: 10px 12px; border-radius: 10px; margin-bottom: 8px;
  border-left: 3px solid transparent; font-size: 13px;
}
.liste-alertes li b { display: block; margin-bottom: 2px; }
.liste-alertes li span { color: var(--g-encre-2); }
.liste-alertes .alerte-rouge {
  background: #FBEAEA; border-left-color: #D64545; color: #A02020;
}
.liste-alertes .alerte-orange {
  background: #FCF6EB; border-left-color: var(--g-orange-500); color: #96610E;
}

/* ============================================================
   FORMULAIRES · SECTIONS, SÉLECTION, RÉCAPITULATIF
   ------------------------------------------------------------
   Un formulaire n'est pas une pile de champs devinés : c'est une
   suite de SECTIONS nommées, chacune avec sa question en clair.
   Trois briques, réutilisables partout :

     .form-section   un bloc de sens (titre + explication + champs)
     .selection      choisir dans une liste réelle, jamais ressaisir
     .form-recap     ce qui est choisi, le total, l'action · collant

   Règles du dépôt respectées : aplats seulement, rayon 10px,
   transitions 150 ms, aucune couleur hors variables, aucun style
   en dur dans les gabarits.
   ============================================================ */

/* Carte large : formulaires à sélection (file + récapitulatif). */
.form-carte-large { max-width: 1180px; }

/* Deux colonnes : le formulaire, puis le récapitulatif qui suit
   le défilement. En dessous de 1040px le récapitulatif redescend
   en pied collant (règle mobile : action principale d'abord). */
.form-colonnes {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: 22px;
  align-items: start;
}
@media (max-width: 1040px) {
  .form-colonnes { grid-template-columns: minmax(0, 1fr); }
}

/* --- Section ------------------------------------------------- */
.form-section { border-top: 1px solid var(--g-filet); padding-top: 20px; }
.form-section + .form-section { margin-top: 24px; }
.form-section:first-of-type { border-top: 0; padding-top: 0; }
.form-section-entete { margin-bottom: 14px; }
.form-section-titre {
  margin: 0; font-size: 15px; font-weight: 700; color: var(--g-encre);
  display: flex; align-items: baseline; gap: 8px;
}
.form-section-rang {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; flex: none;
  border-radius: 999px; background: var(--g-vert-100);
  color: var(--g-vert-600); font-size: 12px; font-weight: 700;
}
.form-section-aide {
  margin: 4px 0 0; font-size: 13px; color: var(--g-muet); line-height: 1.5;
}

/* --- Résumé d'erreurs cliquable en tête de formulaire -------- */
.form-resume {
  margin-bottom: 18px; padding: 12px 14px;
  background: #FBF1F1; border: 1px solid #EAC9C9; border-radius: 10px;
}
.form-resume-titre {
  margin: 0 0 6px; font-size: 13px; font-weight: 700; color: #A03636;
}
.form-resume ul { margin: 0; padding-left: 18px; }
.form-resume li { font-size: 13px; color: #A03636; }
.form-resume a { color: #A03636; }

/* --- Liste de sélection ------------------------------------- */
.selection {
  border: 1px solid var(--g-filet); border-radius: 10px;
  background: var(--g-blanc); overflow: hidden;
}
.selection-barre {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 12px 14px; border-bottom: 1px solid var(--g-filet);
  background: #FAFAF8;
}
.selection-recherche { position: relative; flex: 1 1 220px; min-width: 0; }
.selection-recherche input {
  width: 100%; box-sizing: border-box; font: inherit; font-size: 14px;
  height: 40px; padding: 0 12px;
  background: var(--g-blanc); color: var(--g-encre);
  border: 1px solid var(--g-filet); border-radius: 10px;
  transition: border-color var(--t-rapide), box-shadow var(--t-rapide);
}
.selection-recherche input:focus {
  outline: none; border-color: var(--g-vert-600);
  box-shadow: 0 0 0 3px rgba(22, 130, 18, .13);
}
.selection-actions { display: flex; gap: 6px; flex: none; }
.selection-lien {
  border: 1px solid var(--g-filet); background: var(--g-blanc);
  color: var(--g-encre-2); font: inherit; font-size: 12.5px; font-weight: 600;
  border-radius: 999px; padding: 7px 12px; cursor: pointer; min-height: 34px;
  transition: border-color var(--t-rapide), color var(--t-rapide);
}
.selection-lien:hover { border-color: var(--g-vert-600); color: var(--g-vert-600); }
.selection-compte {
  margin: 0; flex: none; font-size: 12.5px; font-weight: 600;
  color: var(--g-muet);
}
.selection-compte.actif { color: var(--g-vert-600); }

/* Groupe (une demande, un site…) : un intertitre discret. */
.selection-groupe + .selection-groupe { border-top: 1px solid var(--g-filet); }
.selection-groupe-entete {
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  padding: 10px 14px 6px;
}
.selection-groupe-titre {
  margin: 0; font-size: 13px; font-weight: 700; color: var(--g-encre);
}
.selection-groupe-aide { margin: 0; font-size: 12px; color: var(--g-muet); }
/* « Voir le détail » du groupe · poussé à droite de l'intertitre. Il prend
   la marge auto, donc c'est LUI qui repousse les contrôles à droite ; le
   « Tout cocher » qui le suit se range juste à côté (règle ci-dessous)
   plutôt que de réclamer sa propre marge auto et d'ouvrir un trou entre
   les deux. */
.selection-groupe-lien { margin-left: auto; font-size: 12px; white-space: nowrap; }
/* « Tout cocher » du groupe · poussé à droite de l'intertitre pour ne pas
   se confondre avec celui de la barre, qui prend la liste entière. */
.selection-groupe-tout {
  margin-left: auto; font-size: 12px; padding: 5px 10px; min-height: 30px;
}
/* Quand un lien de détail précède le bouton, c'est le lien qui porte la
   marge auto · le bouton se colle à lui au lieu d'en réclamer une seconde,
   qui séparerait les deux contrôles. */
.selection-groupe-lien + .selection-groupe-tout { margin-left: 10px; }

/* Ligne cochable : toute la surface est la cible (gants, tablette). */
.selection-ligne {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 12px 14px; cursor: pointer;
  border-top: 1px solid #F1F0EB;
  transition: background var(--t-rapide);
}
.selection-groupe-entete + .selection-ligne { border-top: 0; }
.selection-ligne:hover { background: #FAFBFA; }
/* Ligne qui contient une saisie : seuls la case et le titre basculent
   la sélection · viser un champ ne doit pas décocher la ligne. */
.selection-ligne.avec-saisie { cursor: default; }
.selection-ligne.avec-saisie .selection-titre { cursor: pointer; }
.selection-ligne input[type="checkbox"] {
  width: 20px; height: 20px; margin: 2px 0 0; flex: none;
  accent-color: var(--g-vert-600);
}
/* Ligne cochée · la classe est posée par selection.js, le :has()
   couvre le cas sans JavaScript. Les deux disent la même chose. */
.selection-ligne.est-cochee,
.selection-ligne:has(input:checked) {
  background: var(--g-vert-100);
  box-shadow: inset 3px 0 0 var(--g-vert-600);
}
.selection-ligne:has(input:focus-visible) {
  outline: 2px solid var(--g-vert-600); outline-offset: -2px;
}
.selection-corps { flex: 1 1 auto; min-width: 0; }
.selection-titre {
  display: block; font-size: 14px; font-weight: 600; color: var(--g-encre);
}
.selection-detail {
  display: block; margin-top: 2px; font-size: 12.5px; color: var(--g-muet);
}
.selection-metas {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-top: 6px;
}
.selection-chiffre {
  flex: none; text-align: right; font-size: 14px; font-weight: 700;
  color: var(--g-encre); font-variant-numeric: tabular-nums;
}
.selection-chiffre small {
  display: block; font-size: 11.5px; font-weight: 500; color: var(--g-muet);
}
.selection-vignette {
  width: 44px; height: 44px; flex: none; border-radius: 8px;
  object-fit: cover; border: 1px solid var(--g-filet); background: #F5F5F2;
}

/* Saisie posée DANS une ligne de sélection (prix unitaire d'un achat
   direct) : étiquette au-dessus comme partout, champ court. */
.ligne-prix {
  display: flex; flex-direction: column; gap: 4px; margin-top: 8px;
  max-width: 220px;
}
.ligne-prix input {
  width: 100%; box-sizing: border-box; font: inherit; font-size: 14px;
  height: 40px; padding: 0 12px; color: var(--g-encre);
  background: var(--g-blanc);
  border: 1px solid var(--g-filet); border-radius: 10px;
  transition: border-color var(--t-rapide), box-shadow var(--t-rapide);
}
.ligne-prix input:focus {
  outline: none; border-color: var(--g-vert-600);
  box-shadow: 0 0 0 3px rgba(22, 130, 18, .13);
}

/* États vides : deux messages DIFFÉRENTS · rien en file, ou rien
   qui corresponde à la recherche. Ne jamais confondre les deux. */
.selection-vide {
  margin: 0; padding: 26px 16px; text-align: center;
  font-size: 13.5px; color: var(--g-muet);
}
.selection-vide b { display: block; color: var(--g-encre-2); margin-bottom: 3px; }

/* --- Récapitulatif ------------------------------------------ */
.form-recap {
  position: sticky; top: 18px;
  border: 1px solid var(--g-filet); border-radius: 10px;
  background: var(--g-blanc); padding: 16px;
  /* MIN-WIDTH ZÉRO · signalé par l'utilisateur le 02/09/2026, capture à
     l'appui : « ce design est trop scroller sur le côté ».

     La colonne du récapitulatif est une piste FIXE de 320 px, mais un
     élément de grille garde `min-width: auto` : son contenu peut donc le
     pousser PLUS LARGE que sa piste, et il déborde alors hors de la
     carte en emportant la page entière dans un défilement horizontal.
     C'est arrivé sur la file des besoins, où un <select> nu se
     dimensionnait sur son option la plus longue (« Prénoms NOM ·
     poste »).

     Même famille que la leçon du 19/08/2026 sur « 1fr » sans minmax(0),
     et même remède : on autorise la colonne à se rétrécir, donc son
     contenu à se plier. */
  min-width: 0;
  /* ET PLUS HAUT QUE L'ÉCRAN, IL DÉFILE EN DEDANS · le repli mobile
     (media 1040px) rendait déjà ce service à la barre du bas, mais le
     panneau LATÉRAL du bureau restait sans borne : collé à 18 px du
     haut, un récapitulatif plus grand que la fenêtre poussait ses
     derniers gestes (Attribuer, Refuser) sous le bord de l'écran,
     injoignables, la page ne défilant plus une fois le panneau collé
     (03/09/2026 · « un endroit sans scroll, on peut rien faire »). On
     borne sa hauteur à la fenêtre et on lui rend son défilement. */
  max-height: calc(100vh - 36px);
  overflow-y: auto;
}
/* Un champ du récapitulatif ne dépasse jamais sa carte · filet posé pour
   TOUT le panneau, et pas seulement pour le sélecteur du jour. Un select
   se dimensionne sur son option la plus longue tant qu'on ne le borne
   pas · le prochain qu'on y posera sera borné d'avance. */
.form-recap select,
.form-recap input:not([type="checkbox"]),
.form-recap textarea { max-width: 100%; box-sizing: border-box; }
.form-recap-titre {
  margin: 0 0 10px; font-size: 13px; font-weight: 700; color: var(--g-encre);
}
.form-recap-ligne {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 10px; padding: 7px 0; font-size: 13px; color: var(--g-encre-2);
  border-bottom: 1px solid #F1F0EB;
}
.form-recap-ligne:last-of-type { border-bottom: 0; }
.form-recap-ligne b { font-size: 14px; color: var(--g-encre); font-weight: 700; }
.form-recap-total {
  margin-top: 10px; padding-top: 12px; border-top: 1px solid var(--g-filet);
}
.form-recap-total .valeur {
  display: block; font-size: 22px; font-weight: 800; letter-spacing: -0.02em;
  color: var(--g-encre); font-variant-numeric: tabular-nums;
}
.form-recap-total .libelle { font-size: 12px; color: var(--g-muet); }
.form-recap-actions { margin-top: 14px; display: grid; gap: 8px; }
.form-recap-actions .btn { width: 100%; justify-content: center; }
.form-recap-note { margin: 10px 0 0; font-size: 12px; color: var(--g-muet); }

/* Bouton d'action qui refuse honnêtement : rien de coché, rien à
   faire · l'interface le DIT au lieu de laisser cliquer dans le vide. */
.btn[aria-disabled="true"] {
  opacity: .5; cursor: not-allowed; pointer-events: none;
}

@media (max-width: 1040px) {
  /* LE RÉCAPITULATIF DESCEND SOUS LA LISTE · en flux normal, jamais collé.
     Signalé le 06/09/2026, capture à l'appui : collé au bas de l'écran, ce
     panneau RECOUVRAIT la liste des besoins (elle disparaissait derrière lui).
     Le 03/09 l'avait rendu défilant pour que le bouton « Refuser » ne tombe
     pas hors cadre · en flux normal, tous les gestes restent joignables par
     le défilement de la page, ET la liste reste entièrement visible. */
  .form-recap {
    position: static;
    max-height: none;
    overflow: visible;
    margin-top: 18px;
    box-shadow: none;
  }
  .form-recap-actions { grid-auto-flow: column; }
}
@media (max-width: 480px) {
  .selection-barre { padding: 10px; }
  .selection-ligne { padding: 11px 10px; gap: 10px; }
  .form-recap-actions { grid-auto-flow: row; }
}

/* ============================================================
   RIGUEUR LOGIKA (référence ERPLDProject/static/css/logika.css) :
   aplats stricts, ombre de carte légère, rayon 10px partout,
   transitions 150 ms, tables sobres. AUCUN dégradé décoratif ·
   seule la jauge de cuve carburant (liquide) y a droit.
   ============================================================ */
:root {
  --rayon-carte: 10px;
  --rayon-champ: 10px;
  --rayon-bouton: 10px;
  --ombre-douce: 0 1px 2px rgba(0, 0, 0, .05);
}

/* Rayon 10px harmonisé sur toutes les surfaces de contenu. */
.carte-page, .carte, .fiche-kpi, .kpi-mod,
.carte-cotation, .carte-dossier, .carte-fournisseur,
.etape, .hero-verte, .zone-nfc, .encart-preventif,
.kpi-mod-pastille, .hist-pastille {
  border-radius: 10px;
}
.encart-preventif { border-radius: 0 10px 10px 0; }

/* Ombre de carte unique, façon Logika. */
.carte-page, .carte, .tuile-kpi { box-shadow: 0 1px 2px rgba(0, 0, 0, .05); }

/* Boutons : aplats nets, hover simplement plus foncé.
   Ni halo coloré, ni soulèvement, ni reflet. */
.btn-primaire:hover, .btn-orange:hover, .btn-fantome:hover {
  box-shadow: none; transform: none;
}

/* Tables : en-têtes discrets, survol de ligne neutre. */
.table-metier th, .table-guiter th, .table-compacte th {
  font-size: 11px; font-weight: 600; color: #777;
  text-transform: uppercase; letter-spacing: .04em;
}
.table-metier tr:hover td,
.table-guiter tbody tr:hover { background: #FAFAF8; }

/* ============================================================
   POLISSAGE GLOBAL DES CHAMPS · uniformisation de la saisie.
   Tous les champs de la zone de travail (.zone-contenu) :
   42px de haut, filet #E0E0E0, rayon 10px, fond blanc,
   anneau vert doux au focus, placeholder #ADABA6.
   La topbar (recherche en pilule) et les écrans publics
   (connexion, OTP, réinitialisation) gardent leurs formes.
   ============================================================ */
.zone-contenu input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not([type="range"]):not([type="color"]):not([type="submit"]):not([type="button"]):not([type="reset"]):not([type="hidden"]),
.zone-contenu select,
.zone-contenu textarea {
  height: 42px;
  box-sizing: border-box;
  font: inherit; font-size: 14px; color: var(--g-encre);
  background: #FFFFFF;
  border: 1px solid #E0E0E0;
  border-radius: 10px;
  padding: 0 12px;
  transition: border-color var(--t-rapide), box-shadow var(--t-rapide);
}
.zone-contenu textarea {
  height: auto; min-height: 90px; padding: 10px 12px; resize: vertical;
}

/* ------------------------------------------------------------
   CHAMPS FICHIER · ils étaient EXCLUS de l'uniformisation
   ci-dessus (`:not([type="file"])`), et le bouton natif ·
   la seule partie que le navigateur peint vraiment · n'était
   stylé nulle part dans le dépôt. D'où le « Choose File · No
   file chosen » gris signalé par l'utilisateur : ce n'était pas
   une impression, c'était une exclusion écrite en toutes lettres.
   Les 14 champs de dépôt de la plateforme sont rattrapés ici,
   sans toucher un seul gabarit.
   ------------------------------------------------------------ */
.zone-contenu input[type="file"] {
  box-sizing: border-box;
  width: 100%;
  min-height: 48px;              /* cible tactile · gants sur site */
  padding: 7px 12px 7px 7px;
  font: inherit; font-size: 14px; color: var(--g-encre-2);
  background: #FFFFFF;
  border: 1px dashed #CFCFC9;    /* pointillé : « déposez ici », pas « saisissez » */
  border-radius: 10px;
  cursor: pointer;
  transition: border-color var(--t-rapide), background var(--t-rapide),
              box-shadow var(--t-rapide);
}
.zone-contenu input[type="file"]:hover {
  border-color: var(--g-vert-600);
  background: var(--g-vert-100);
}
.zone-contenu input[type="file"]:focus-visible {
  outline: none;
  border-color: var(--g-vert-600);
  box-shadow: 0 0 0 3px rgba(22, 130, 18, .13);
}
/* Le bouton natif prend la forme d'un bouton Guiter. Son LIBELLÉ reste
   celui du navigateur (« Choose File », « Parcourir ») : un pseudo-élément
   ne peut pas le remplacer, et mentir sur ce point demanderait de masquer
   le contrôle réel · ce que le projet interdit. L'étiquette et l'aide
   au-dessus du champ portent le sens en français. */
.zone-contenu input[type="file"]::file-selector-button {
  margin-right: 12px;
  padding: 0 14px;
  height: 32px;
  font: inherit; font-size: 13px; font-weight: 600;
  color: #FFFFFF;
  background: var(--g-vert-600);
  border: 0; border-radius: 8px;
  cursor: pointer;
  transition: background var(--t-rapide);
}
.zone-contenu input[type="file"]:hover::file-selector-button {
  background: var(--g-vert-700);
}
.zone-contenu input[type="file"]:disabled,
.zone-contenu input[type="file"]:disabled::file-selector-button {
  cursor: not-allowed; opacity: .55;
}
.zone-contenu input::placeholder,
.zone-contenu textarea::placeholder { color: #ADABA6; }
.zone-contenu input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not([type="range"]):not([type="color"]):not([type="submit"]):not([type="button"]):not([type="reset"]):not([type="hidden"]):focus,
.zone-contenu select:focus,
.zone-contenu textarea:focus,
.zone-contenu input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not([type="range"]):not([type="color"]):not([type="submit"]):not([type="button"]):not([type="reset"]):not([type="hidden"]):focus-visible,
.zone-contenu select:focus-visible,
.zone-contenu textarea:focus-visible {
  outline: none;
  border-color: var(--g-vert-600);
  box-shadow: 0 0 0 3px rgba(22, 130, 18, .13);
}
/* .filtre-select hérite du même style que tous les champs. */
.zone-contenu .filtre-select,
.filtre-select {
  height: 42px; min-height: 42px; padding: 0 12px;
  border: 1px solid #E0E0E0; border-radius: 10px; background: #FFFFFF;
}
/* Le select du gabarit de création garde la place de son chevron dessiné. */
.zone-contenu .creer-champ select { padding-right: 38px; }

/* ============================================================
   FORMULAIRES EN LIGNE (terminal pompiste, pesée, filtres…) :
   étiquette AU-DESSUS du champ, gap 12/14px, bouton aligné en
   bas, retours à la ligne propres sous 900px.
   ============================================================ */
.form-ligne { gap: 12px; }
.form-inline {
  display: flex; flex-wrap: wrap;
  gap: 12px 14px;
  align-items: flex-end;
}
.inline-champ {
  display: flex; flex-direction: column; gap: 5px; min-width: 0;
}
.inline-libelle {
  font-size: 12px; font-weight: 600; color: var(--g-muet);
  letter-spacing: .01em;
}
.form-inline .btn { height: 42px; min-height: 42px; }
@media (max-width: 900px) {
  .form-inline .inline-champ { flex: 1 1 100% !important; width: auto !important; min-width: 0 !important; }
  .form-inline .inline-champ input,
  .form-inline .inline-champ select { width: 100%; }
  .form-inline > .btn { width: 100%; }
  .form-ligne > input:not([type="hidden"]),
  .form-ligne > select { flex: 1 1 100%; }
}

/* ============================================================
   RESPONSIVE · du portable 14 pouces au très grand écran.
   - Très grands écrans : la zone de travail plafonne à 1440px,
     centrée · plus de lignes kilométriques.
   - ≤ 1400px (portables 14") : rangées de KPI moins denses,
     les cartes gardent une largeur lisible.
   - ≤ 760px : les grilles de formulaire passent en 1 colonne,
     les actions de page s'empilent en pleine largeur.
   ============================================================ */
.zone-contenu { max-width: 1440px; margin: 0 auto; }

@media (max-width: 1400px) {
  /* LA BORNE DE 240 px SUIT · sans elle, cette règle-ci rendait le `1fr`
     à toutes les fenêtres de portable (1366 px en est une), et les deux
     vignettes d'« Effectifs » se remettaient à s'étirer sur la largeur.
     Voir pages.css, où la règle de base explique le défaut. */
  .fiche-kpis { grid-template-columns: repeat(auto-fit, minmax(150px, 240px)); }
  .kpi-modulix { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }
}

@media (max-width: 760px) {
  .form-grille,
  .creer-grille { grid-template-columns: minmax(0, 1fr); }
  .creer-champ.demi { grid-column: 1 / -1; }
  .form-inline .inline-champ { flex: 1 1 100%; }
  .page-actions { flex-direction: column; align-items: stretch; }
  .page-actions .btn {
    width: 100%; justify-content: center; box-sizing: border-box;
  }
}

/* ============================================================
   PORTÉE DE LECTURE · Groupe, filiale, site.
   Sélecteur de la topbar et fil d'Ariane de la zone de travail.
   Aplats stricts, aucune ombre portée, aucun dégradé.
   ============================================================ */
.portee-form {
  display: flex; align-items: center; gap: 8px;
  padding: 3px 4px 3px 10px;
  border: 1px solid var(--g-filet); border-radius: 999px;
  background: var(--g-blanc);
}
.portee-form .portee-picto { display: inline-flex; color: var(--g-muet); }
.portee-form .topbar-select {
  min-height: 34px; height: 34px; border: none; background: transparent;
  padding: 0 6px; font-size: 13.5px;
}
.portee-form .topbar-select:focus-visible {
  outline: none; box-shadow: 0 0 0 3px rgba(22, 130, 18, .13);
  border-radius: 8px;
}

/* Périmètre BORNÉ : la personne est affectée à un site, elle n'a rien à
   choisir. Même galet que le sélecteur pour que la topbar reste alignée,
   mais sans menu · un contrôle qui ne contrôle rien est interdit. */
.portee-fixe {
  display: inline-flex; align-items: center; gap: 8px;
  min-height: 40px; padding: 3px 14px;
  border: 1px solid var(--g-filet); border-radius: 999px;
  background: var(--g-blanc); color: var(--g-encre);
  font-size: 13.5px; font-weight: 500; white-space: nowrap;
}
.portee-fixe .portee-picto { display: inline-flex; color: var(--g-vert-700); }
/* Périmètre non renseigné : c'est une donnée manquante, pas une alerte.
   Ton soleil, jamais rouge · la personne n'a rien fait de mal. */
.portee-fixe.est-a-definir {
  border-color: #F0D08A; background: #FDF6E6; color: #7A5A12;
}
.portee-fixe.est-a-definir .portee-picto { color: #B07C15; }
@media (max-width: 760px) {
  .portee-fixe { white-space: normal; }
}

/* PLUSIEURS SOCIÉTÉS · la liste remplace la pastille · 16/09/2026.
   Même hauteur et même pastille arrondie que `.portee-fixe` · ce n'est
   pas un autre objet, c'est le même qui a plusieurs valeurs. Celle qui
   est active se remplit : une liste où rien ne ressort ne dit pas où
   l'on est. */
.portee-liste {
  display: inline-flex; align-items: center; flex-wrap: wrap; gap: 4px;
  min-height: 40px; padding: 3px 6px 3px 12px;
  border: 1px solid var(--g-filet); border-radius: 999px;
  background: var(--g-blanc);
}
.portee-liste .portee-picto { display: inline-flex; color: var(--g-vert-700); }
.portee-choix {
  min-height: 30px; padding: 0 12px;
  border: 1px solid transparent; border-radius: 999px;
  background: transparent; color: var(--g-encre-2);
  font-family: var(--police); font-size: 13px; font-weight: 600;
  cursor: pointer; white-space: nowrap;
}
.portee-choix:hover { background: var(--g-vert-100); color: var(--g-vert-900); }
.portee-choix.est-actif {
  background: var(--g-vert-900); border-color: var(--g-vert-900);
  color: var(--g-blanc);
}
.portee-choix:focus-visible { outline: none; box-shadow: var(--anneau-focus); }
@media (max-width: 760px) {
  .portee-liste { border-radius: 14px; }
  .portee-choix { white-space: normal; }
}

.portee-fil {
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px;
  margin: 0 0 16px; padding: 9px 14px;
  background: var(--g-vert-100); border: 1px solid #CFE6CD;
  border-radius: 10px; font-size: 13px;
}
.portee-fil-picto { display: inline-flex; color: var(--g-vert-800); }
.portee-fil nav { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.portee-niveau { color: var(--g-vert-800); }
.portee-niveau.est-courant { font-weight: 700; color: var(--g-vert-900); }
.portee-sep { color: #8FB88C; }
.portee-fil-retrait { margin-left: auto; }
.portee-retrait {
  display: inline-flex; align-items: center; gap: 5px;
  border: 1px solid #CFE6CD; border-radius: 999px;
  background: var(--g-blanc); color: var(--g-vert-800);
  font: inherit; font-size: 12.5px; font-weight: 600;
  padding: 4px 11px 4px 8px; cursor: pointer;
  transition: border-color var(--t-rapide), color var(--t-rapide);
}
.portee-retrait:hover { border-color: var(--g-vert-600); color: var(--g-vert-900); }
/* Profil borné à son site : à la place du bouton de retrait · qu'il n'a pas
   le droit d'exercer · le fil dit simplement à quoi correspond ce périmètre.
   Discret à dessein : c'est une légende, pas une action, et le site nommé
   juste à gauche doit rester ce qu'on lit en premier. */
.portee-mention {
  margin-left: auto; color: var(--g-vert-800); opacity: .75;
  font-size: 12.5px; font-style: italic;
}

.portee-inactive {
  display: flex; align-items: center; gap: 8px;
  margin: 0 0 16px; padding: 9px 14px;
  background: #FDF4E3; border: 1px solid #F0DCB0; border-radius: 10px;
  color: #8A6218; font-size: 13px;
}
.portee-inactive svg { flex: none; }

@media (max-width: 900px) {
  .portee-form { flex-wrap: wrap; border-radius: 12px; }
  .portee-form .topbar-select { flex: 1 1 120px; }
}

/* ============================================================
   COQUILLE MOBILE · plainte terrain : « le design n'est pas
   adapté sur téléphone ». Cible : Android modeste 360×640.
   - ≤900px : sidebar en tiroir (off-canvas) + bouton hamburger,
     voile sombre cliquable, état body.menu-ouvert posé par app.js.
   - ≤760px : topbar compacte (titre ellipsé, portée SOUS le
     titre), contenu densifié, KPI 2 colonnes.
   - ≤480px : KPI en 1 colonne.
   Aplats stricts, transitions courtes. AUCUN défilement
   horizontal de page : seules les .table-defilante défilent
   DANS leur carte (déjà câblé dans pages.css).
   ============================================================ */

/* Le hamburger et le voile n'existent visuellement qu'en mobile. */
.bouton-menu { display: none; }
.voile-menu { display: none; }

/* La coquille couvre l'écran réel de Chrome Android (barre d'URL
   comprise) : repli 100vh AVANT la ligne dvh. */
.app-coquille { min-height: 100vh; min-height: 100dvh; }

@media (max-width: 900px) {
  /* --- La grille perd sa colonne sidebar : le contenu respire. --- */
  .app-coquille { grid-template-columns: minmax(0, 1fr); }

  /* --- Sidebar en tiroir : hors écran, glisse par-dessus. --- */
  .sidebar {
    position: fixed;
    top: 0; bottom: 0; left: 0;
    z-index: 80;
    width: min(280px, 84vw);
    height: 100vh;   /* repli */
    height: 100dvh;  /* Chrome Android moderne */
    transform: translateX(-100%);
    transition: transform .2s ease;
  }
  body.menu-ouvert .sidebar { transform: translateX(0); }

  /* Le tiroir montre la sidebar COMPLÈTE : le rail d'icônes
     (≤1023px · components.css) n'a plus de sens hors écran. */
  .sidebar-libelle { display: inline; }
  /* SAUF LES PASTILLES DE COMPTAGE · elles portent les DEUX classes
     (« sidebar-badge sidebar-libelle », ui_compteurs.py:14), si bien que
     la ligne ci-dessus les aplatissait en texte : la pastille ronde
     orange redevenait un chiffre collé au libellé, et on lisait
     « Besoins 3 » au lieu de voir un compteur aligné à droite. Elles
     reprennent ici la grille centrée de pages.css:286. */
  .sidebar-badge {
    display: inline-grid;
    place-items: center;
    margin-left: auto;
  }
  /* Le commutateur est posé dans le flux À TOUTE LARGEUR depuis le
     23/08/2026 · la règle et son pourquoi ont remonté au bloc de base,
     en tête de cette feuille. Il n'y a plus rien à corriger ici. */
  .sidebar-section { display: block; }
  .sidebar-pied { display: block; }
  .sidebar-item { justify-content: flex-start; padding: 0 var(--esp-3); }
  .sidebar-logo { justify-content: flex-start; padding: var(--esp-5) var(--esp-4); }
  .sidebar-logo img { height: 34px; }

  /* --- Voile sombre : un aplat cliquable pour refermer. --- */
  .voile-menu {
    display: block;
    /* Quatre ancrages en toutes lettres : `inset` demande Chrome 87 et les
       WebView de terrain sont plus vieilles · le voile s'y réduisait à un
       carré en haut à gauche, laissant le fond cliquable. */
    position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 70;
    background: rgba(8, 43, 8, .55);
    opacity: 0; pointer-events: none;
    transition: opacity .2s ease;
  }
  body.menu-ouvert .voile-menu { opacity: 1; pointer-events: auto; }

  /* Tiroir ouvert : le fond ne défile plus derrière. */
  body.menu-ouvert { overflow: hidden; }

  /* --- Hamburger : à gauche de la topbar, cible 44px. --- */
  .bouton-menu {
    display: inline-flex; align-items: center; justify-content: center;
    flex: none;
    width: 44px; height: 44px; margin-left: -8px;
    border: none; border-radius: 10px;
    background: transparent; color: var(--g-encre);
    cursor: pointer;
    transition: background-color var(--t-rapide);
  }
  .bouton-menu:active { background: var(--g-vert-100); }
  .bouton-menu:focus-visible {
    outline: 2px solid var(--g-vert-600); outline-offset: 1px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .sidebar, .voile-menu, .bouton-menu { transition: none; }
}

/* --- Topbar compacte ≤760px : titre ellipsé, portée dessous. --- */
@media (max-width: 760px) {
  .topbar {
    flex-wrap: wrap;
    gap: 4px 10px;
    min-height: 56px;
    padding: 8px 14px;
  }
  .topbar-titre {
    flex: 1 1 0;
    min-width: 0;   /* l'ellipse (déjà posée) agit dans le flex */
    font-size: clamp(15px, 4.8vw, 18px);
  }
  /* Les outils passent SOUS le titre, pleine largeur : plus rien
     ne pousse la page en défilement horizontal.

     RIEN DE PLUS N'ENTRE DANS CETTE RANGÉE · elle tient déjà tout juste
     sur un écran de 360 px avec la portée, la messagerie et la cloche.
     Le sélecteur de langue, essayé ici le 30/08/2026, la faisait passer
     à la ligne et laissait une bande presque vide sous la portée : il est
     remonté sur la ligne du TITRE, qui a de la place puisqu'il s'ellipse
     (voir base.html). Toute nouvelle icône se posera la même question :
     la place manque ici, et l'écraser se voit. */
  .topbar-outils {
    flex: 1 1 100%;
    min-width: 0;
    gap: 8px;
  }
  /* Le titre rend sa marge automatique : sur cette ligne il n'a plus à
     pousser les outils (ils sont passés dessous), seulement à laisser sa
     place au sélecteur de langue qui le suit. */
  .topbar-titre { margin-right: 8px; }
  .portee-form {
    flex: 1 1 0;
    min-width: 0;
    padding: 3px 6px;
  }
  .portee-form .topbar-select {
    flex: 1 1 110px;
    min-width: 0;
    max-width: 100%;
    font-size: 13px;
  }
  .topbar-lien-icone {
    min-width: 44px; min-height: 44px;
    justify-content: center;
    flex: none;
  }

  /* --- Contenu densifié : padding réduits, cartes sobres. --- */
  .zone-contenu { padding: 14px; }
  .carte-page { padding: 16px 14px; }
  .creer-carte { padding: 18px 14px; }

  /* --- KPI : 2 colonnes nettes (complète l'auto-fit existant). --- */
  .fiche-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .kpi-modulix { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }

  /* Chiffres géants : clamp, jamais de débordement latéral. */
  .tuile-kpi-valeur { font-size: clamp(28px, 9vw, 38px); }
  .fiche-kpi b { font-size: clamp(12px, 8cqw, 26px); }
  .fiche-kpi b.mot { font-size: 14px; }
}

/* --- Très petits écrans (≤480px) : KPI en 1 colonne. --- */
@media (max-width: 480px) {
  .fiche-kpis { grid-template-columns: minmax(0, 1fr); }
  .kpi-modulix { grid-template-columns: minmax(0, 1fr); }
  .zone-contenu { padding: 14px 12px; }

  /* Pied de formulaire : l'action principale en premier, pleine
     largeur · le pouce la trouve sans viser. */
  .creer-pied { flex-direction: column-reverse; gap: 10px; }
  .creer-pied .btn {
    width: 100%; justify-content: center; box-sizing: border-box;
    min-height: 46px;
  }
}

/* ============================================================
   TABLES SUR TÉLÉPHONE · plainte terrain : « les colonnes sont
   coupées ». Chaque table métier vit dans .table-defilante
   (gabarits) : elle défile DANS sa carte, la page ne bouge pas.
   Ombres de bord (fond blanc des cartes) : on VOIT qu'il reste
   des colonnes à droite · l'indice remplace la barre de
   défilement invisible au doigt.
   ============================================================ */
.table-defilante {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
  max-width: 100%;
  /* Ombres de défilement : deux voiles blancs qui suivent le contenu
     (attachment local) masquent les ombres quand le bord est atteint. */
  background:
    linear-gradient(to right, #fff 30%, rgba(255, 255, 255, 0)) left / 40px 100%,
    linear-gradient(to left, #fff 30%, rgba(255, 255, 255, 0)) right / 40px 100%,
    radial-gradient(farthest-side at 0 50%, rgba(12, 62, 11, .16), transparent) left / 14px 100%,
    radial-gradient(farthest-side at 100% 50%, rgba(12, 62, 11, .16), transparent) right / 14px 100%;
  background-repeat: no-repeat;
  background-attachment: local, local, scroll, scroll;
}
/* Une table étroite continue d'occuper toute la largeur de sa carte. */
.table-defilante > .table-metier,
.table-defilante > .table-guiter,
.table-defilante > .table-compacte { min-width: 100%; }

/* ET ELLE NE SE PEINT PAS PAR-DESSUS L'INDICE DE DÉFILEMENT.
   Le cadre porte quatre dégradés (deux voiles blancs en attachement
   local, deux ombres de bord) qui sont la SEULE chose disant qu'il reste
   du contenu à droite. Mais la table posée dedans a un fond blanc opaque
   et occupe 100 % de la largeur par la règle ci-dessus : elle recouvrait
   les quatre. Le cadre travaillait pour rien, et l'utilisateur n'avait
   aucun moyen de deviner qu'il pouvait pousser · c'est la moitié du
   « scroll merdique ». La carte hôte est déjà blanche, donc rien ne
   change à l'oeil sinon l'ombre qui réapparaît au bord. */
.table-defilante > .table-metier,
.table-defilante > .table-guiter,
.table-defilante > .table-compacte { background: transparent; }

@media (max-width: 900px) {
  /* Garde-fou : la page elle-même ne défile JAMAIS latéralement.
     `hidden` d'abord (compris partout), `clip` ensuite pour les moteurs
     récents · sur une WebView ancienne la seconde ligne est ignorée et le
     garde-fou tient quand même. */
  body { overflow-x: hidden; overflow-x: clip; }

  /* ET SUR <html> AUSSI · le garde-fou ne tenait que la moitié.
     Mesuré le 19/08/2026 : sur /console/notifications/, la page
     continuait de glisser de 18px alors que `body` était bien clos ·
     c'est l'élément racine qui porte le défilement du document, pas le
     corps. Uniquement `clip`, jamais `hidden` : `hidden` ferait de
     <html> un conteneur de défilement et casserait le `position:
     sticky` de la topbar. Un moteur qui ne connaît pas `clip` ignore
     simplement la ligne et retrouve le comportement d'avant. */
  html { overflow-x: clip; }

  /* FILET DE SÉCURITÉ · TOUTE table orpheline, pas seulement les deux
     classes du socle.

     Le filet ne connaissait que .table-metier et .table-guiter. Tout ce
     qui porte une autre classe passait au travers et se faisait rogner
     en silence par sa carte · .pc-passages du pointage détaillé,
     .colonnes-attendues de l'écran d'import commun aux dix-neuf
     imports, .dir-table de la vue consolidée. Une table sans enveloppe
     est un accident, quel que soit son nom : le filet doit donc être
     nommé par ce qu'il rattrape, pas par une liste tenue à la main.

     L'exception de la ligne suivante reste indispensable : une table
     DÉJÀ dans un cadre défilant doit redevenir une vraie table, sinon
     deux défilements s'emboîtent. */
  .zone-contenu table {
    display: block;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
  }
  .zone-contenu .table-defilante table { display: table; overflow: visible; }

  /* Les cellules gardent une respiration tactile et ne s'écrasent pas. */
  .table-metier th, .table-metier td,
  .table-guiter th, .table-guiter td { padding-top: 10px; padding-bottom: 10px; }

  /* Les médias ne poussent jamais la page. */
  .zone-contenu img, .zone-contenu video, .zone-contenu canvas {
    max-width: 100%; height: auto;
  }
}

/* ============================================================
   TABLES EMPILÉES EN FICHES · téléphone (≤760px)
   ------------------------------------------------------------
   Posé par app.js (empilerLesTablesLarges) et UNIQUEMENT sur les
   tables qui débordent réellement de leur carte · celles qui
   tiennent gardent leur forme de table, plus dense et plus
   lisible quand elle rentre.

   Mesure du 19/08/2026 : 80 écrans sur 127 obligeaient à pousser
   un tableau de côté à 375px, jusqu'à 854px de course. Le
   garde-fou `body { overflow-x: hidden }` ci-dessus empêchait la
   PAGE de glisser, mais ne rendait pas les colonnes de droite
   atteignables pour autant · elles étaient simplement coupées.

   La sélectivité est volontairement élevée (.zone-contenu ...) :
   les règles ≤900px au-dessus posent `display: block` ou
   `display: table` avec cette même portée, et une règle plus
   faible ne les emporterait pas.
   ============================================================ */
@media (max-width: 760px) {
  .zone-contenu table.est-empilee,
  .zone-contenu .table-defilante table.est-empilee {
    display: block;
    overflow: visible;
    min-width: 0;
    background: transparent;
  }

  /* L'EN-TÊTE DISPARAÎT VRAIMENT.
     Première version : sortie de l'oeil par « position: absolute » et
     un rognage de 1px, pour la laisser dans l'arbre d'accessibilité.
     Mesuré ensuite : sa rangée continuait d'être mise en page à 609px
     et de peser dans la largeur · /console/utilisateurs/ défilait
     encore de 28px pour une ligne que personne ne voyait. Un en-tête
     seulement rogné n'est pas un en-tête retiré.
     Rien n'est perdu pour autant : chaque cellule porte désormais son
     intitulé À CÔTÉ de sa valeur, ce qui est mieux qu'un en-tête placé
     à dix lignes de là · c'est tout l'objet de la mise en fiches. */
  .zone-contenu table.est-empilee thead { display: none; }

  .zone-contenu table.est-empilee tbody { display: block; }

  /* UNE LIGNE DEVIENT UNE FICHE. */
  .zone-contenu table.est-empilee tbody tr {
    display: block;
    margin: 0 0 10px;
    padding: 2px 13px;
    background: #fff;
    border: 1px solid var(--g-filet);
    border-radius: 12px;
  }
  .zone-contenu table.est-empilee tbody tr:last-child { margin-bottom: 0; }
  .zone-contenu table.est-empilee tbody tr:hover td { background: transparent; }

  /* UNE CELLULE DEVIENT UN COUPLE « intitulé · valeur ».
     text-align est forcé : des dizaines de gabarits posent un
     style="text-align:right" en ligne, aligné sur une colonne qui
     n'existe plus une fois la table dépliée. */
  .zone-contenu table.est-empilee tbody td {
    display: grid;
    grid-template-columns: minmax(0, 12ch) minmax(0, 1fr);
    gap: 12px;
    align-items: baseline;
    padding: 10px 0;
    border: 0;
    border-top: 1px solid var(--g-filet);
    text-align: left !important;
    overflow-wrap: anywhere;
  }
  .zone-contenu table.est-empilee tbody tr > td:first-child { border-top: 0; }

  .zone-contenu table.est-empilee tbody td::before {
    content: attr(data-intitule);
    color: var(--g-muet);
    font-size: 12px;
    font-weight: 700;
    line-height: 1.35;
  }

  /* CE QUE LA CELLULE CONTIENT NE PEUT PLUS LA DÉBORDER.
     Dernier débordement mesuré, sur /console/utilisateurs/ : un
     .badge-statut porte « white-space: nowrap » (components.css) et
     « min-width: auto » comme tout enfant flex · sa largeur minimale
     est donc son texte ENTIER. Dans une fiche de 323px il en réclamait
     237 pour un libellé de vues, et poussait la carte de 28px. Une
     étiquette qui tient sur deux lignes reste une étiquette ; une
     carte qui déborde n'est plus une carte. */
  .zone-contenu table.est-empilee tbody td > * {
    min-width: 0;
    max-width: 100%;
  }
  .zone-contenu table.est-empilee tbody td .badge-statut,
  .zone-contenu table.est-empilee tbody td .chip-etat,
  .zone-contenu table.est-empilee tbody td .badge-priorite {
    white-space: normal;
    text-align: left;
  }

  /* Une colonne sans titre (boutons d'action, case à cocher) n'a
     rien à annoncer : la cellule reprend toute la largeur plutôt
     que de laisser une colonne d'intitulé vide. */
  .zone-contenu table.est-empilee tbody td[data-intitule=""],
  .zone-contenu table.est-empilee tbody td[data-pleine-ligne] {
    display: block;
    text-align: left !important;
  }
  .zone-contenu table.est-empilee tbody td[data-pleine-ligne] {
    color: var(--g-muet);
  }

  /* La carte ne dessine plus d'ombre de défilement ni de coupe :
     il n'y a plus rien à pousser. */
  .zone-contenu .table-defilante.contient-empilee {
    overflow: visible;
    background: none;
  }
}

/* ============================================================
   16 PX DANS LES CHAMPS SUR TÉLÉPHONE · CE N'EST PAS UN CHOIX
   DE TYPOGRAPHIE, C'EST CE QUI EMPÊCHE L'ÉCRAN DE PARTIR.
   ------------------------------------------------------------
   Safari sur iPhone ZOOME de lui-même dès qu'on touche un champ
   dont le texte fait moins de 16px. La page grossit, sort de
   son cadre, la barre du haut disparaît · et rien ne la remet
   en place : le zoom ne se défait pas tout seul en quittant le
   champ. C'est très exactement le « c'est toujours bizarre »
   rapporté le 19/08/2026, et cela frappait TOUS les champs de
   la plateforme, qui sont uniformément à 14px (ligne 744).

   La règle ne descend qu'en dessous de 900px · sur un écran de
   bureau les 14px restent, la densité des formulaires longs ne
   change pas d'un pixel.

   Les champs de DATE sont visés nommément en plus : iOS leur
   applique la même règle, et ce sont eux qu'on ouvre le plus
   souvent au doigt.
   ============================================================ */
@media (max-width: 900px) {
  .zone-contenu input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not([type="range"]):not([type="color"]):not([type="submit"]):not([type="button"]):not([type="reset"]):not([type="hidden"]),
  .zone-contenu select,
  .zone-contenu textarea,
  .zone-contenu input[type="date"],
  .zone-contenu input[type="time"],
  .zone-contenu input[type="datetime-local"] {
    font-size: 16px;
    height: 46px;
  }
  .zone-contenu textarea { height: auto; }

  /* Une cible tactile se prend au doigt · 44px est le plancher
     reconnu, et plusieurs boutons du dépôt descendaient à 34. */
  .zone-contenu .btn,
  .zone-contenu button:not(.bouton-menu),
  .zone-contenu input[type="submit"],
  .zone-contenu input[type="button"] {
    min-height: 44px;
  }
  /* « Petit » veut dire ÉTROIT, jamais bas · le jeton --cible-min
     existe (tokens.css) et c'est la classe de bouton la plus employée
     du dépôt qui l'annulait, en descendant à 40px depuis pages.css,
     chargée après components.css à spécificité égale. */
  .zone-contenu .btn-petit {
    min-height: var(--cible-min);
    padding: 10px 16px;
  }
}

/* ============================================================
   CIBLES TACTILES DES COMPOSANTS · téléphone (≤760px)
   ------------------------------------------------------------
   Quatre composants du socle descendaient sous les seuils, chacun
   pour son compte, et aucun ne se voyait depuis un grand écran :
   la barre de portée (34px de haut, 13,5px de texte), le composant
   de sélection d'achat (40px et 14px), les boutons du panneau de
   choix multiple (32px), et le bouton natif des champs fichier.
   Deux seuils, toujours les mêmes : 44px pour le doigt, 16px pour
   empêcher Safari iOS de zoomer au premier appui.
   ============================================================ */
@media (max-width: 760px) {
  /* LA PORTÉE PREND SA PROPRE LIGNE · coincée dans la rangée d'icônes
     de la topbar, il ne lui restait qu'une centaine de pixels pour
     nommer un site. Elle a la place en dessous. */
  .portee-form { flex: 1 1 100%; }
  .portee-form .topbar-select {
    min-height: 44px; height: 44px;
    font-size: 16px;
    flex: 1 1 40%;
  }

  .selection-recherche input { height: 46px; font-size: 16px; }
  .selection-actions { gap: 10px; flex-wrap: wrap; }
  .selection-lien { min-height: 44px; padding: 0 14px; font-size: 13.5px; }

  .choix-multiple-vider,
  .choix-multiple-terminer {
    min-height: 46px; padding: 0 18px; font-size: 14px;
  }
  /* Le panneau occupe tout l'écran et se pose AU-DESSUS de son voile :
     le clic de fermeture posé sur le voile ne peut jamais être atteint,
     et ces deux boutons étaient la seule sortie. On les sépare pour
     qu'aucun doigt ne vide une sélection en croyant la terminer. */
  .choix-multiple-terminer { flex: 1 1 100%; order: 2; }
  .choix-multiple-vider { order: 1; }

  .zone-contenu input[type="file"]::file-selector-button { min-height: 44px; }
  .zone-contenu input[type="file"] { max-width: 100%; font-size: 16px; }
}

/* ============================================================
   ZONE DE SÉCURITÉ iOS · encoche, coins arrondis, barre d'accueil
   ------------------------------------------------------------
   Relevé le 19/08/2026 : env(safe-area-inset-*) n'apparaissait NULLE
   PART dans le dépôt, et le meta viewport ne portait pas
   viewport-fit=cover · les deux manques allaient ensemble, puisque
   sans le second les variables valent zéro et ne servent à rien.

   Le meta est posé depuis (base.html). Il fait occuper tout l'écran
   à la page, encoche comprise : chaque bord doit donc être bordé ici,
   sinon on aurait remplacé un bandeau blanc par du texte illisible
   sous la barre d'accueil.

   Les valeurs de repli à 0px sont indispensables : sur un appareil
   sans encoche, et sur tout moteur qui ignore env(), la déclaration
   doit rester valide et rendre exactement la mise en page d'avant.
   ============================================================ */
.topbar {
  padding-top: env(safe-area-inset-top, 0px);
  padding-left: max(var(--esp-5), env(safe-area-inset-left, 0px));
  padding-right: max(var(--esp-5), env(safe-area-inset-right, 0px));
}

.zone-contenu {
  padding-left: max(var(--esp-5), env(safe-area-inset-left, 0px));
  padding-right: max(var(--esp-5), env(safe-area-inset-right, 0px));
  padding-bottom: max(var(--esp-5), env(safe-area-inset-bottom, 0px));
}

/* Les deux paliers existants gardent LEUR retrait · 14px puis 12px.
   Le max() ne fait que relever le plancher quand l'encoche l'exige : la
   mise en page ne bouge pas d'un pixel sur un appareil sans encoche. */
@media (max-width: 900px) {
  .zone-contenu {
    padding-left: max(14px, env(safe-area-inset-left, 0px));
    padding-right: max(14px, env(safe-area-inset-right, 0px));
    padding-bottom: max(14px, env(safe-area-inset-bottom, 0px));
  }

  /* LE TIROIR · « Se déconnecter » est la dernière entrée de son pied.
     Sans cette marge elle tombait à moitié sous la barre d'accueil de
     l'iPhone, qui prend environ 34px · on la voyait sans pouvoir la
     toucher. Le retrait gauche vaut pour le mode paysage, où l'encoche
     mord sur le bord du tiroir. */
  .sidebar {
    padding-bottom: env(safe-area-inset-bottom, 0px);
    padding-left: env(safe-area-inset-left, 0px);
  }
}

/* Les boutons flottants remontent au-dessus de la barre d'accueil. */
.retour-essai {
  bottom: max(16px, env(safe-area-inset-bottom, 0px)) !important;
  right: max(16px, env(safe-area-inset-right, 0px)) !important;
}

@media (max-width: 760px) {
  .zone-contenu {
    padding-left: max(12px, env(safe-area-inset-left, 0px));
    padding-right: max(12px, env(safe-area-inset-right, 0px));
  }
}
