/* ===================================================================   Coquille du PRODUIT (socle L01) : contrepartie de production de la coquille du prototype (shell.src.html, « Coquille du
   prototype », hors barre d'outils, scène et cadre d'appareil). La page défile dans le document (pas dans un défileur interne) ;
   .frame reste le conteneur « frame » des container queries de base.css (Vérifier qui repousse la page, compacte) et .o-layer
   la couche des dialogues, fixée à la fenêtre.
   Décision D15 (2026-11-08, constat L00 n° 2) : body{margin:0} fait partie du socle.
   ========================================================================== */
html{scroll-padding-top:calc(var(--header-h) + var(--space-2))}
/* SOCLE-perf (D15 après L05 (1)) : « html:has(.screen .o-localnav) » faisait réévaluer la racine à chaque mutation du document ;
   l'état est posé par le code (data-o-localnav, src/socle/shell/etats.ts), même rendu (garde-fous/e2e/socle-etats.spec.ts). */
html[data-o-localnav]{scroll-padding-top:calc(var(--header-h) + var(--localnav-h) + 1px + var(--space-2))}
body{margin:0;background:var(--bg);color:var(--text-1);font-family:var(--font-ui)}
.frame{container-type:inline-size;container-name:frame;position:relative;min-height:100dvh;background:var(--bg)}
.o-layer{position:fixed;inset:0;z-index:var(--z-layer);pointer-events:none;overflow:hidden}
/* Gabarit Outil (L07, constaté au navigateur) : sans contexte d'empilement, le panneau d'un sélecteur des entrées
   (.o-picker__panel, absolu, z-index 3, dans le <details> des entrées) passait SOUS la réponse qui suit (.o-tool__state, relatif) :
   ses options n'étaient pas cliquables. Les entrées forment leur contexte, au-dessus de l'état de calcul. */
.o-tool__entries{position:relative;z-index:4}
/* Explorateur (lot L05, F §3.0 « Sémantique », X9) : dans la maquette, un écran ; dans le produit, une SURCOUCHE de la fiche ouverte
   par #explorer= (src/explorateur/couche.ts) : section.screen plein écran au-dessus de la fiche inerte, sous la couche des dialogues
   (Vérifier, feuille), sans en-tête de site (--header-h nul pour la hauteur minimale du cadre o-explorer) ; seule la surcouche défile. */
.screen.o-couche{position:fixed;inset:0;z-index:calc(var(--z-layer) - 10);overflow:auto;overscroll-behavior:contain;--header-h:0px}
/* R5-EXP-8 : la fiche, inerte et cachée sous la surcouche opaque, sort du calcul de style et de mise en page (content-visibility) :
   un réglage de l'Explorateur ne recalcule plus la page entière ; classe posée par la couche (jamais :has(), invalidé à chaque
   mutation de la scène) */
html.o-explorer-ouvert{overflow:hidden}
html.o-explorer-ouvert #viewport > .screen:not(.o-couche){content-visibility:hidden}
/* D15 après L05 (1) (C5-062, R5-EXP-8 (1)) : l'attente d'un réglage serveur atténue la scène affichée en UN élément (opacité du corps
   de calcul, après --wait) ; les règles is-busy du socle (couleur de chaque p, li, svg… du corps) recalculaient le style de toute la
   scène, arbre compris (≈ 1 000 éléments, 0,3 s sous CPU ×4). Corps de calcul du cadre : .o-explorer__calcbody (src/explorateur/cadre.ts). */
.o-explorer__calc > .o-explorer__calcbody{position:relative;flex:1;min-height:0;display:flex;flex-direction:column;transition:opacity var(--t-2) var(--ease)}
.o-explorer__calc.is-busy > .o-explorer__calcbody{opacity:.6;transition-delay:var(--wait)}
@media (prefers-reduced-motion: reduce){.o-explorer__calc > .o-explorer__calcbody{transition:none}}
/* I §3.4 bis (R5-EXP-14) : la carte de lecture et la carte d'exploration partagent view-transition-name: map (morph de 480 ms en
   --spring-surface, 320 ms au retour), comme sp-media (base.css §29). */
::view-transition-group(map){animation-duration:var(--t-4);animation-timing-function:var(--spring-surface)}
html[data-nav="back"]::view-transition-group(map){animation-duration:var(--t-3)}
/* Navigation entre documents (A2 du shell, CATALOGUE §9, I §3.1) : fondu de root 200 ms, en-tête immobile, morph carte → fiche
   (view-transition-name posés par le shell : départ pageswap, arrivée pagereveal). Animations : base.css §29.
   SOCLE-perf (2e passe, D15 après L01 (4)) : PAS JOUÉE. Mesuré sur la construction de production sous CPU ×4, le morph tombe pendant
   le chargement de la page d'arrivée (scripts, hydratation) : p95 de 66 à 133 ms pour 16,7 (I §6.2), même avec le shell démarré
   après la transition ; au-delà du budget, la chorégraphie passe sans animation (D15). Le code du départ et de l'arrivée reste en
   place (pageswap, pagereveal, transitions.ts) : rétablir navigation:auto le rejoue tel quel quand l'arrivée tiendra le budget. */
@view-transition{navigation:none}
/* Groupe root d'une navigation entre documents : la VT de l'aller simple par défaut du navigateur (250 ms, ease) est hors jetons ;
   on lui donne le fondu de root de base.css §29 (--t-2, --ease ; I §3.1 et §5.1 : « fondu enchaîné de root en 200 ms »). */
::view-transition-group(root){animation-duration:var(--t-2);animation-timing-function:var(--ease)}
/* Respiration du symbole (I §4.2, §2.2) : un var() n'est pas permis dans animation-timing-function À L'INTÉRIEUR d'une
   @keyframes (le navigateur retombe sur « ease ») ; base.css y écrit var(--ease-inout). Même animation, courbe du jeton
   --ease-inout écrite en clair (égalité avec le jeton vérifiée par src/socle/socle.test.ts). */
@keyframes ont-breath{
  0%{stroke-dasharray:100 110;stroke-dashoffset:0;animation-timing-function:cubic-bezier(.45,0,.55,1)}
  40%{stroke-dasharray:100 110;stroke-dashoffset:75}
  50%{stroke-dasharray:100 110;stroke-dashoffset:75;animation-timing-function:cubic-bezier(.45,0,.55,1)}
  90%,100%{stroke-dasharray:100 110;stroke-dashoffset:0}}
/* ---------- Retours du propriétaire, jet 2 (2026-11-10, agent « theme ») : n° 18, 21, 22, 26 ---------- */
/* n° 21 (capture 23) — Choix du thème dans l'en-tête (src/socle/shell/ChoixTheme.tsx, theme.ts) : bouton-icône tertiaire rond du
   socle, discret (--text-2, --text-1 au survol et menu ouvert), son pictogramme aligné sur le bord droit de la page ; son icône suit
   data-theme de la racine, posé avant le premier rendu (aucun éclair). Montré en bureau ; en compacte, la rangée « Thème » du menu. */
.o-theme__btn{margin-left:calc(var(--space-3) - var(--space-6));margin-right:calc((20px - var(--control-h)) / 2);color:var(--text-2)}
.o-theme__btn:hover,.o-theme__btn[data-ouvert]{color:var(--text-1);background:var(--surface-1)}
.o-theme__btn > .o-icon{width:20px;height:20px}
.o-theme__btn .o-theme__i{display:none}
:root:not([data-theme]) .o-theme__btn .o-theme__i--system,:root[data-theme="light"] .o-theme__btn .o-theme__i--light,:root[data-theme="dark"] .o-theme__btn .o-theme__i--dark{display:inline}
.o-search[hidden] + .o-theme__btn{margin-left:auto}   /* accueil : champ de l'en-tête masqué, le bouton garde sa place à droite */
@container screen (max-width:759.98px){.o-header .o-theme__btn{display:none}}
/* Menu du thème (popover natif, posé par theme.ts sous le bouton, bord droit aligné) : surface flottante du socle (--surface-float,
   --shadow-2, --radius-2), trois options de --control-h, survol en voile de --text-1 (les deux thèmes), coche du choix en cours.
   Entrée : fondu et glissement de --d-1 en --t-2 --ease depuis le bouton ; mouvement réduit : fondu seul (--d-1 et --s-surface nuls). */
.o-theme__pop{position:fixed;inset:auto;margin:0;padding:var(--space-1);min-width:calc(var(--space-9) * 2);border:0;border-radius:var(--radius-2);background:var(--surface-float);box-shadow:var(--shadow-2);color:var(--text-1);opacity:0;transform:translateY(calc(-1 * var(--d-1))) scale(var(--s-surface));transform-origin:top right;transition:opacity var(--t-2) var(--ease),transform var(--t-2) var(--ease),display var(--t-2) allow-discrete,overlay var(--t-2) allow-discrete}
.o-theme__pop:popover-open{opacity:1;transform:none}
@starting-style{.o-theme__pop:popover-open{opacity:0;transform:translateY(calc(-1 * var(--d-1))) scale(var(--s-surface))}}
.o-theme__pop[popover]:not(:popover-open){display:none}
.o-theme__opts{display:grid}
.o-theme__opt{position:relative;display:flex;align-items:center;gap:var(--space-3);min-height:var(--control-h);padding-inline:var(--space-3) var(--space-2);border-radius:var(--radius-inset);font-size:var(--fs-small);line-height:var(--lh-small);letter-spacing:var(--ls-small);color:var(--text-1);cursor:pointer;user-select:none;transition:background-color var(--t-1) var(--ease)}
.o-theme__opt:hover{background:color-mix(in srgb,var(--text-1) 7%,transparent)}
.o-theme__opt > .o-icon{color:var(--text-2)}
.o-theme__in:checked ~ .o-icon{color:var(--text-1)}
.o-theme__t{flex:1;white-space:nowrap}
.o-theme__ok{flex:none;width:16px;height:16px;visibility:hidden}
.o-theme__ok::before{content:"";display:block;width:5px;height:9px;margin:2px auto 0;border:solid currentColor;border-width:0 1.5px 1.5px 0;transform:rotate(45deg)}
.o-theme__in:checked ~ .o-theme__ok{visibility:visible}
/* le champ couvre la case, transparent (sans :has(), garde-fou SOCLE-perf) : il porte lui-même l'anneau du focus clavier */
.o-theme__in{position:absolute;inset:0;width:100%;height:100%;margin:0;appearance:none;background:none;border:0;border-radius:var(--radius-inset);cursor:pointer}
.o-theme__in:focus-visible{outline:2px solid var(--focus);outline-offset:-2px}
@media (forced-colors:active){.o-theme__pop{border:1px solid CanvasText}.o-theme__in:checked ~ .o-theme__t{text-decoration:underline}}
/* Menu (compacte), n° 42 b (capture 34) : la rangée « Thème » (libellé au-dessus d'un segmenté pleine largeur de 50 px) pesait autant
   que la navigation et la recherche. Un réglage, pas une destination : une seule ligne au bas de la feuille, sous « Fermer », séparée
   par un filet ; « Apparence » en petit texte secondaire, segmenté compact du socle à droite (hauteur des puces, 32 px, pictogrammes
   seuls) ; chaque option garde sa cible tactile de 44 px (zone transparente centrée, comme .o-chip::after). Le segmenté des feuilles
   passe à 44 px (socle.css, .o-sheet--bottom .o-seg__opts) : celui-ci reste compact. Bas de la feuille : zone sûre de l'iPhone. */
.o-menu__theme{display:flex;align-items:center;justify-content:space-between;gap:var(--space-3);min-height:var(--target);margin-inline:var(--margin);padding-block:var(--space-3) 0}
.o-menu__theme-l{font-size:var(--fs-small);line-height:var(--lh-small);color:var(--text-2)}
.o-sheet--bottom .o-menu__seg{height:var(--chip-h)}
.o-menu__seg > label{width:var(--target);padding-inline:0}
.o-menu__seg > label::after{content:"";position:absolute;left:0;right:0;top:50%;height:var(--target);transform:translateY(-50%)}
/* n° 18 — À l'ouverture au toucher, le focus va au dialogue lui-même (shell/saisie.ts) : jamais d'anneau sur la feuille, la
   visionneuse ou le menu ; une feuille basse garde son ombre (la règle des cibles de navigation, nav[tabindex="-1"]:focus, l'ôtait). */
.o-layer :is(.o-sheet,.o-viewer)[tabindex="-1"]:focus{outline:none}
.o-layer .o-sheet--bottom[tabindex="-1"]:focus{box-shadow:var(--shadow-2)}
.o-layer .o-viewer[tabindex="-1"]:focus{box-shadow:none}
/* n° 26 (capture 26) — Bulle de glossaire : la ligne du lien « Glossaire › » était plus haute que les autres. Cause : le lien était
   une boîte inline-flex de 44 px de haut (cible tactile, --target) posée dans une ligne de 20 px (--lh-small) ; la marge basse
   négative ne rattrapait que le bas, la ligne grandissait de 12 px au-dessus. Le lien reste dans le texte (inline, interligne
   régulier) ; sa cible de 44 px est une zone transparente centrée sur lui, comme celle d'un terme (.o-term::after, 2.5.8), sans rien
   déplacer. Toutes les bulles (glossaire, Explorateur, mois d'une commune). */
.o-bubble a[href]{position:relative;display:inline;min-height:0;margin-bottom:0}
.o-bubble a[href]::after{content:"";position:absolute;left:50%;top:50%;width:max(100%,var(--target));height:var(--target);transform:translate(-50%,-50%)}
/* n° 40 — Une bulle ouverte restait collée à l'écran pendant le défilement (position fixe, placée une fois). Elle suit son mot : en
   position absolue, une bulle de la couche supérieure se place dans le bloc conteneur initial, qui défile avec le document ; le shell
   la pose en coordonnées du document et la ferme quand son mot sort de la vue (src/socle/shell/composants.ts). Toutes les bulles. */
.o-bubble{position:absolute}
/* n° 22 — « Autour de moi » pendant la recherche (shell/autour.ts) : le symbole du socle respire à la place du pictogramme (même
   place, 16 px), le texte dit l'étape ; le bouton reste lisible (--text-1 : un état en cours, pas un bouton désactivé). */
[data-autour][aria-busy="true"]{color:var(--text-1);text-decoration-color:transparent;cursor:progress}   /* un état, pas un lien : jamais souligné (survol resté collé après un toucher) */
[data-autour] > .o-autour__mark{width:16px;height:16px}
/* I §3.2 (décision Q.2 du directeur) : en-tête compact au défilement d'une fiche, posé par src/socle/shell/compact.ts quand le <h1> de
   l'entité passe sous l'en-tête du site ; il reprend son texte, sous l'en-tête, sans capter le pointeur.
   Mêmes jetons que l'en-tête du site (fond, filet, largeur de page).
   Clôture « final » (I §6.2) : mise en page et couche composée une fois ; montrée ou cachée par sa seule visibilité (data-on, posé par
   compact.ts), sans mise en page ni nouvelle couche pendant le défilement.
   Retours du propriétaire (2026-11-10, capture 10) : la barre se pose TOUJOURS contre l'en-tête du site (avant : sous la place de la
   navigation locale, même quand celle-ci, pas encore collée, était 400 px plus bas : la barre flottait sur le contenu, le titre visible
   au-dessus d'elle). Sur une page qui a la barre (html[data-o-compact], shell/etats.ts), la navigation locale se colle sous la barre,
   et la marge des ancres compte l'en-tête, la barre et la navigation locale : un terme visé (#t-…, #section) n'est jamais dessous.
   Hauteur fixe d'une ligne (--compact-h), titre long tronqué d'une ellipse : la place réservée est exacte.
   Retours du propriétaire (jet 2, point 19, capture 21) : une page À ONGLETS n'a plus de barre séparée. La barre du nom et la navigation
   locale faisaient deux bandes (nom, puis 300 px plus bas, les onglets pas encore collés, puis collés sous le nom). Désormais UNE bande :
   la navigation locale, qui, une fois collée sous l'en-tête, montre le nom de la page à gauche (fondu) et ses onglets à droite (voir
   « Bande collante » ci-dessous). La barre .o-compact reste celle des pages SANS onglets (glossaire, méthode…) : html[data-o-compact] n'y
   est posé que sans navigation locale (shell/etats.ts). */
:root{--compact-h:calc(var(--lh-small) + 2 * var(--space-2) + 1px)}
html[data-o-compact]{scroll-padding-top:calc(var(--header-h) + var(--compact-h) + var(--space-2))}
.o-compact{position:fixed;top:var(--header-h);left:0;right:0;z-index:calc(var(--z-header) - 2);box-sizing:border-box;height:var(--compact-h);background:var(--bg);border-bottom:1px solid var(--border-subtle);pointer-events:none;visibility:hidden;will-change:transform,opacity}
.o-compact[data-on]{visibility:visible}
.o-compact__t{max-width:calc(var(--w-full) + 2 * var(--margin));margin:0 auto;padding:var(--space-2) var(--margin);font-size:var(--fs-small);line-height:var(--lh-small);font-weight:600;color:var(--text-1);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.o-compact__t.sci{font-style:italic}
/* La barre est hors de l'écran (enfant de body, hors des conteneurs « screen » et « frame ») : les marges de page des classes de
   largeur (socle.css §2, container queries) ne l'atteignaient pas, et son titre restait à 48 px du bord en compacte (16 px pour la
   page). Mêmes seuils, sur la fenêtre (le cadre en a la largeur) ; la barre est son propre conteneur (largeur de la fenêtre) :
   container query, jamais de media query de largeur (C3). */
.o-compact{container:compact / inline-size}
@container compact (max-width:1023.98px){.o-compact__t{--margin:var(--space-6)}}
@container compact (max-width:599.98px){.o-compact__t{--margin:var(--space-4)}}
/* Bande collante d'une page à onglets (retours du propriétaire, jet 2, point 19 ; I §3.2 : garder le contexte quand le grand en-tête
   sort ; comme la barre de section des pages produit d'Apple). Quand la navigation locale se colle sous l'en-tête du site
   (data-colle, posé par shell/compact.ts : IntersectionObserver, jamais un écouteur de défilement), elle devient la seule bande : le nom
   de la page à gauche (texte du <h1>, aria-hidden : le <h1> reste le titre), en fondu, et les onglets à droite, qui y glissent
   (compact.ts). Avant qu'elle se colle : rien, ni barre, ni vide ; le chapeau et les chiffres de la fiche sont encore sous les yeux.
   Mise en page : grille de deux colonnes, le nom (au plus 40 % de la bande, ellipse) puis la piste des onglets ; les boutons ‹ › se
   posent dans la case de la piste (même cellule, au-dessus, à ses bords) ; l'onglet de tête prend la marge libre (margin-left:auto),
   nulle dès que la piste déborde : les onglets défilent alors depuis le nom, comme avant. */
.o-localnav__nom{display:none}
.o-localnav[data-colle] > .o-localnav__in{display:grid;grid-template-columns:fit-content(40%) minmax(0,1fr);column-gap:var(--space-6)}
.o-localnav[data-colle] .o-localnav__nom{display:block;grid-area:1 / 1;align-self:center;min-width:0;margin:0;font-size:var(--fs-small);line-height:var(--lh-small);font-weight:600;color:var(--text-1);white-space:nowrap}
/* jamais un nom coupé (C1, C5-065) : un nom plus large que sa colonne (40 % de la bande, mesuré par shell/compact.ts) n'est pas
   montré ; avant, l'ellipse cachait la fin d'un nom long (« Vallées du Tarn, de l'Aveyron, … ») et son texte débordait l'écran */
.o-localnav[data-colle] .o-localnav__nom[data-trop-long]{display:none}
.o-localnav[data-colle] .o-localnav__nom.sci{font-style:italic}
.o-localnav[data-colle] ul{grid-area:1 / 2}
.o-localnav[data-colle] li:first-child{margin-left:auto}
.o-localnav[data-colle] .o-localnav__btn{position:relative;inset:auto;grid-area:1 / 2}
.o-localnav[data-colle] .o-localnav__btn--prev{justify-self:start;margin-left:calc(-1 * var(--space-3))}   /* même débord que socle.css §12 */
.o-localnav[data-colle] .o-localnav__btn--next{justify-self:end;margin-right:calc(-1 * var(--space-3))}
@container screen (max-width:599.98px){.o-localnav[data-colle] > .o-localnav__in{column-gap:var(--space-4)}}
/* Clôture « final » (C5-093, BLQ-49b93c ; shell/composants.ts, springTo) : fondu d'entrée d'une feuille basse qui s'ouvre au ressort,
   celui de l'état ouvert (.o-sheet[data-state="open"] : opacity --t-4 --spring-surface), comme avant la suppression du recalcul forcé de
   l'ouverture ; le transform reste piloté par le ressort (aucune transition). is-pending : la feuille qui s'ouvre reste invisible jusqu'à
   la première image du ressort (au cran fermé, hors de l'écran) : le recalcul de son contenu (visibilité héritée) se fait dans le rendu
   de cette image, pas dans la tâche du clic. */
.o-layer .o-sheet.is-springing.is-opening{transition:opacity var(--t-4) var(--spring-surface),visibility 0s}
.o-layer .o-sheet.is-pending{visibility:hidden}
/* ---------- Colonnes écrasées (retours du propriétaire, 2026-11-10, captures 9, 13, 16 et 18) ----------
   Cause commune : une piste de grille ou de flex dont le minimum est nul (minmax(0, …), min-width:0) laissée à côté d'un contenu
   de largeur fixe ou intrinsèque ; la colonne se réduit à quelques pixels et le texte s'y coupe lettre par lettre.
   1. Fiche espèce, section Liens (écran gelé espece-renard : enfants .o-vivant__fig puis .o-vivant__suite, grille de base.css §40 bis
      en placement automatique). Une ouverture du produit placée avant la figure (rang de connectivité ESP-104, bandeau des preuves
      d'Europe ESP-045, alerte de la lentille ESP-099) prenait la première case : la figure tombait dans la colonne de 360 px des
      suites (sablier écrasé), la colonne de lecture restait vide. Toute ouverture tient la largeur de la section, comme la barre de
      lentille (R5-VIV-15) ; figure et suites se placent après elles, côte à côte (order : aucun effet hors de la grille). */
.o-vivant__liens > :not(.o-vivant__fig):not(.o-vivant__suite){grid-column:1 / -1}
.o-vivant__liens > :is(.o-vivant__fig,.o-vivant__suite){order:1}
/* 2. Vérifier, liste de faits compacte (base.css §32 : minmax(0,1fr) auto) : une valeur longue (« non renseigné par la source
      (ventilation par lien en attente) ») prenait toute la largeur à sa taille max-content et réduisait les termes à zéro. Le terme
      garde au moins sa largeur min-content (ses mots entiers) ; la valeur, plus longue, passe à la ligne. */
.o-facts.o-facts--compact{grid-template-columns:minmax(min-content,1fr) auto}
/* 3. Explorateur, arbre : une feuille d'espèce tient sur une ligne avatar, nom, « remarquable », barrettes et « N sources » (largeurs
      fixes, ≈ 323 px avec les retraits de deux niveaux). Dans la colonne latérale du Réseau (--ex-side, 320 px) et sur un téléphone,
      le nom tombait à son minimum (4em) et la ligne débordait (défilement horizontal). Sous 32rem d'arbre (somme des largeurs fixes
      et d'un nom de 12em), la feuille passe sur deux lignes, comme une carte du réseau (.o-explorer__card) : le nom sur toute la
      largeur, puis la mention, les barrettes et les sources ; rien ne déborde. */
.o-explorer__tree{container:ex-arbre / inline-size}
@container ex-arbre (max-width:32rem){
  .o-explorer__leaf > .o-explorer__node{display:grid;grid-template-columns:auto minmax(min-content,1fr) auto auto;column-gap:var(--space-2);row-gap:0;align-items:center}
  .o-explorer__leaf > .o-explorer__node > .o-explorer__av{grid-row:1 / span 2}
  .o-explorer__leaf > .o-explorer__node > :is(.o-explorer__u,.o-explorer__s){grid-column:2 / -1;grid-row:1;min-width:0}
  .o-explorer__leaf > .o-explorer__node > .o-tag{grid-column:2;grid-row:2;justify-self:start}
  .o-explorer__leaf > .o-explorer__node > :is(.o-bars,.o-pot){grid-column:3;grid-row:2;margin-left:0}
  .o-explorer__leaf > .o-explorer__node > .o-explorer__ev{grid-column:4;grid-row:2}
  /* 4. (jet 2, point 16, capture du réseau avec barres de défilement classiques) : rôle et groupe de la colonne latérale, « Ses
        consommateur|s », « Champignon|s » : le libellé tombait à son minimum de 4em et se coupait dans le mot. Comme en compacte
        (socle §Explorateur compact) : le libellé garde ses mots entiers (min-content), le compte passe à la ligne s'il le faut. */
  .o-explorer__node{flex-wrap:wrap}
  .o-explorer__node > :is(.o-explorer__lab,.o-explorer__u){min-width:min-content}
  .o-explorer__node > .o-explorer__n{margin-left:auto}
  /* 5. (jet 2) la colonne de la mention « remarquable » garde sa largeur (min-content) : la pastille ne passe plus sous les barrettes */
}
/* Photo d'une feuille de l'arbre de l'Explorateur (jet 2, points 16 et 28 ; transposer_shell.py) : fond posé SUR le pictogramme, à la
   découpe et au cadrage d'une photo de bulle (.o-avatar img : cover, 50 % 38 %). Jamais chargée tant que la feuille n'est pas affichée
   (groupe replié : aucune requête, aucune observation du navigateur) ; le pictogramme reste visible pendant le chargement et si le
   fichier manque. */
.o-explorer__av[style*="--ph"]::after{content:"";position:absolute;inset:0;border-radius:inherit;background:var(--ph) var(--fx,50%) var(--fy,38%) / cover no-repeat}
/* Barres de défilement de l'Explorateur (colonne latérale, réseau, surcouche) : fines, aux couleurs du thème (pouce --border-control,
   piste transparente), dans les deux thèmes ; scrollbar-color est héritée par les défileurs internes. */
.screen.o-couche,.o-explorer{scrollbar-color:var(--border-control) transparent}
.screen.o-couche,.o-explorer__side,.o-explorer__net{scrollbar-width:thin}
/* Retours du propriétaire (jet 1, Vérifier d'un lien de l'Explorateur) : « Voir sa fiche » et « Voir les preuves » se touchaient ;
   pied du panneau en rangée souple, espacée du jeton --space-3, qui passe à la ligne sur un panneau étroit. */
.o-verify__foot{display:flex;flex-wrap:wrap;gap:var(--space-3)}
/* Retours du directeur (2026-11-11, après « Voir les preuves ») : numéro d'étape des blocs du Vérifier. La base du socle numérote
   chaque titre de bloc (.o-verify__h::before, compteur vblock remis à zéro par .o-sheet__body), même seul : « 1   Preuves », un
   chiffre isolé qui n'apporte rien. Le numéro n'est rendu que si le panneau a PLUSIEURS blocs titrés : état data-o-etapes posé
   par le code sur le corps du panneau (src/socle/shell/etats.ts, tenu à jour à chaque rendu et quand un bloc se remplit à
   l'ouverture, comme « Nature des preuves » ; pas de :has(), garde-fou SOCLE-perf) ; un ::before non rendu n'incrémente pas le
   compteur. Il prend alors la forme d'une pastille d'étape : chiffre tabulaire au corps de légende, centré dans un anneau de
   --border-subtle, à --space-2 du libellé, lisible dans les deux thèmes (en sombre, le fond du panneau est déjà --surface-2 : pas
   de fond plein). */
.o-sheet__body .o-verify__h{align-items:center}
.o-sheet__body .o-verify__h::before{display:none}
.o-sheet__body[data-o-etapes] .o-verify__h::before{display:inline-grid;place-items:center;flex:none;box-sizing:border-box;min-width:calc(var(--space-4) + var(--space-1));height:calc(var(--space-4) + var(--space-1));padding-inline:var(--space-1);border-radius:var(--radius-full);box-shadow:inset 0 0 0 1px var(--border-subtle);font-size:var(--fs-caption);line-height:1;font-weight:600;color:var(--text-2)}
/* Retours du directeur (2026-11-11) : « Terminé » de l'Explorateur en partie caché par le Vérifier ouvert, en bureau. Le panneau
   recouvre la scène sans la recomposer (MOT-R5-N4 (3), D15 après le rattrapage (4)) et part sous la bande d'en-tête (top:
   --header-h, 64 px) ; l'en-tête de l'Explorateur, plus haut que cette bande dès que son sous-titre tient sur deux lignes, centrait
   « Terminé » sur toute sa hauteur : le bas du bouton passait sous le panneau. « Terminé » s'aligne sur le haut de l'en-tête, à
   côté de la première ligne du titre : padding --space-3 + 36 px de bouton, toujours dans la bande, quelle que soit la longueur
   du titre ou du sous-titre. */
.o-explorer__head > [data-explorer-done]{align-self:flex-start}
/* Fil d'Ariane (retours du propriétaire, capture 12 puis jet 2, point 24, capture 25 : « Lieux › Occitanie › Tarn (81) › Lacaze ›
   Espèces » collé à l'en-tête). UN espacement pour tous les fils du site, quelle que soit la page : 24 px sous l'en-tête en bureau,
   8 px en compacte, celui de l'en-tête d'entité (.o-entity : padding-top --space-5, 0 en compacte où le fil prend --space-2). Toute
   autre tête de page (Index, Outil, page de méthode, liste d'un lieu, recherche…) le reçoit sur son fil de tête, sans liste de gabarits.
   Le correctif du jet 1 ne s'appliquait pas : une ligne « ======= » (reste de fusion) le précédait dans cette feuille, et le navigateur
   écartait la règle entière (sélecteur invalide) ; la feuille est désormais contrôlée (src/socle/shell/coquille-retours.test.ts). */
.o-main :not(.o-entity) > .o-crumb:first-child{margin-top:var(--space-5)}
@container screen (max-width:599.98px){.o-main :not(.o-entity) > .o-crumb:first-child{margin-top:var(--space-2)}}
/* En-tête compact (retours du propriétaire, jet 2, points 25 et 27). La maquette (socle.css §7, sous 760 px) retirait le mot-symbole et
   gardait le seul symbole : la marque « Ontologia » n'apparaissait jamais sur un téléphone ; le champ de recherche, masqué sur
   l'accueil, y laissait le bouton Menu collé au logo, à gauche. Désormais, à toute largeur et sur toutes les pages, accueil compris :
   le mot-symbole entier à gauche, et à droite la recherche puis le menu, deux boutons-icônes de 44 px (cible, G §2) ; le nom
   accessible de la recherche reste son libellé « Rechercher » (masqué à l'œil seulement). La marque pousse les boutons à droite :
   le menu y reste même sans recherche. */
@container screen (max-width:759.98px){
  .o-header .o-wordmark{display:block}
  .o-header .o-brand{margin-right:auto}
  .o-header__inner{gap:var(--space-1)}
  .o-header .o-search{flex:none;justify-content:center;width:var(--target);max-width:none;height:var(--target);margin-left:0;padding:0;border:0;border-radius:var(--radius-full);background:none;color:var(--text-1)}
  .o-header .o-search:hover{background:var(--surface-1)}
  .o-header .o-search .o-icon{width:20px;height:20px}
  .o-header .o-search__label{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}
}
/* Accueil (point 27) : la recherche de l'en-tête y est désormais affichée, avec son raccourci ⌘K ; le champ du héros, qui ouvre la même
   palette, ne répète plus le raccourci (un seul ⌘K à l'écran, celui de la recherche de toutes les pages). */
.acc-field__kbd{display:none}
/* Liens d'évitement (socle.css §6) : hors focus, ils attendent au-dessus de la fenêtre, mais leur ombre (--shadow-1) dépassait sous le
   bord haut, en voile gris en haut à gauche de chaque page (constaté sur les captures du jet 2) ; l'ombre n'est portée qu'au focus. */
.o-skip:not(:focus-visible){box-shadow:none}
/* Retours du propriétaire (2026-11-10) : choix du thème (Système, Clair, Sombre ; src/socle/shell/theme.ts), segmenté du socle sur sa
   propre ligne du pied, sous le plan du site, au-dessus de la ligne des sources. */
.o-footer__theme{grid-column:1 / -1;margin-top:var(--space-4)}
/* ---------- Étages de la chaîne alimentaire (retours du propriétaire, 2026-11-10, capture 24, point 23) ----------
   Constat : la barre d'un étage était mise à l'échelle de l'étage le plus peuplé (n / max, C5-087) et alignée à gauche : 374 plantes
   en pleine largeur, 24 espèces de régime mixte en 56 px, segments trop étroits pour porter leur effectif, aucune pyramide dessinée ;
   la ligne des groupes (pictogramme, lien souligné, « · ») passait à la ligne n'importe où.
   Décision (H §1 G1, G3, G6, G9) : la barre répond à « de quoi est fait cet étage ? » : barre de répartition TOUJOURS pleine largeur,
   segments en proportion de l'étage ; le total de l'étage est le nombre écrit dans la colonne du nom (exact, chiffres tabulaires),
   la phrase au-dessus compare les étages. Les groupes forment une légende en colonnes régulières, dans l'ordre des segments :
   pictogramme, nom et effectif dans une même case, jamais séparés ; aucun soulignement au repos, souligné au survol pour un groupe qui
   ouvre sa feuille ; cible de 44 px sur téléphone. Sur téléphone, le total suit le nom sans jamais se couper (« 374 » / « espèces »). */
.o-chain__etages > li > .o-chain__etages-bar{width:100%}
/* Point 39 (jet 3, capture 33) : la légende en colonnes (jet 2) restait illisible : trois colonnes étalées sur toute la largeur, sans
   lien visible avec les segments (« Insectes » au milieu de l'écran, son segment au bout de la barre), une rangée orpheline, chaque
   effectif écrit deux fois (segment et légende), deux encres alternées qui ne désignaient aucun groupe.
   Décision (H §1 G1, G3, G6) : le lien segment ↔ groupe se voit. Chaque segment porte le pictogramme de son groupe, dès qu'il a la
   place (28 px, container query) ; la légende suit, sur une seule rangée qui s'enroule comme une phrase (jamais de colonnes à trous),
   dans l'ordre des segments ; chaque groupe y commence par sa PASTILLE, miniature exacte de son segment (même encre, même
   pictogramme). Les effectifs ne sont écrits qu'une fois, dans la légende ; aucun segment n'est fusionné en « + ». Barre aux
   extrémités arrondies (rayon 1). Un groupe : une barre pleine et sa pastille ; huit groupes : la rangée s'enroule ; un petit effectif
   garde son segment (2 px au moins) et sa place dans la légende. */
.o-chain__etages > li > .o-chain__etages-bar{border-radius:var(--radius-1);overflow:hidden}
/* R4-3 (F §3.3 R4 (1), C25 ; relevé de prod du 2026-11-12) : puce pointillée « + N mentions générales » de l'étage, en fin de légende
   (rangée qui s'enroule : aucune hauteur de plus en général) ; jamais comptée. */
.o-chain__etages-groups > li.o-chain__ment{align-items:center}
@container screen (max-width:599.98px){.o-chain__ment-g{position:absolute;width:1px;height:1px;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}}   /* téléphone : « + N mentions », « générales » lu seulement (plafond de la section) */
.o-chain__etages > li > .o-chain__etages-bar > span{container-type:inline-size;min-width:2px}
.o-chain__etages-bar > span > .o-icon{flex:none;color:var(--bg)}
@container (max-width:27.98px){.o-chain__etages-bar > span > .o-icon{display:none}}
.o-chain__etages > li > .o-chain__etages-groups{display:flex;flex-wrap:wrap;column-gap:var(--space-5);row-gap:0;margin:var(--space-1) 0 0;padding:0;list-style:none}
.o-chain__etages-groups > li{display:flex;min-width:0}
.o-chain__etages-g{display:inline-flex;align-items:center;gap:var(--space-2);padding-block:var(--space-1);color:var(--text-1);font:inherit;text-align:left}
.o-chain__etages-k{display:inline-flex;align-items:center;justify-content:center;flex:none;width:22px;height:22px;border-radius:5px;background:var(--mark);color:var(--bg)}
.o-chain__etages-groups > li:nth-child(even) .o-chain__etages-k{background:var(--seq-7)}   /* l'encre de son segment (R5-LIEU-8 : deux voisins jamais de même encre) */
.o-chain__etages-groups > li > .o-chain__etages-g > .o-chain__etages-k[data-autres]{background:var(--seq-5)}
.o-chain__etages-gt{min-width:0;overflow-wrap:break-word}
.o-chain__etages-gv{color:var(--text-2);font-variant-numeric:tabular-nums;white-space:nowrap}
button.o-chain__etages-g .o-chain__etages-gn{text-decoration:underline;text-decoration-thickness:1px;text-decoration-color:transparent;text-underline-offset:3px;transition:text-decoration-color var(--t-1) var(--ease)}
button.o-chain__etages-g:hover .o-chain__etages-gn{text-decoration-color:currentColor}
@media (prefers-reduced-motion:reduce){button.o-chain__etages-g .o-chain__etages-gn{transition:none}}
@media (forced-colors:active){.o-chain__etages-k{forced-color-adjust:none;background:Canvas!important;color:CanvasText;box-shadow:inset 0 0 0 1.5px CanvasText}.o-chain__etages-bar > span > .o-icon{color:CanvasText}}
@container screen (max-width:599.98px){
  .o-chain__etages > li > .o-chain__etages-groups{column-gap:var(--space-4)}
  button.o-chain__etages-g{min-height:var(--target);padding-block:0}
  .o-chain__etages-n{white-space:nowrap}
}
/* F-§3.3 (3e relevé de prod, 2026-11-12) : section Réseau de Lacaze à 1 471 px en 390 pour un plafond de 1 200 (F §3.10).
   Cause, sur les vraies données : la légende de chaque étage s'enroulait en rangées de 44 px (cible tactile) et les étages réels ont
   8, 4, 4 et 2 groupes (la maquette figée en avait 3, 2, 3 et 2 : 1 197 px) : 13 rangées, 572 px, dont 4 rangées pour la seule puce
   « + N mentions ». Avec des cibles de 44 px qui ne se recouvrent pas, aucun enroulement ne tient 1 200 px (même parfaitement tassée,
   la légende prend 10 rangées : 901 + 440 px).
   Correction (téléphone seulement ; le bureau garde la rangée qui s'enroule du point 39) : la légende d'un étage est UNE rangée qui
   défile à l'horizontale, comme toute rangée défilante en compacte (retour n° 59 : elle va jusqu'au bord de l'écran, l'élément
   suivant dépasse, opaque). Rien ne change dans la légende : même ordre que les segments, pastille, nom et effectif inséparables,
   aucun segment fusionné, barre pleine largeur (n° 23, 39), puce « + N mentions » en fin de rangée ; cibles de 44 px. Hauteur d'un
   étage constante quel que soit le nombre de groupes : 1 077 px à Lacaze. position:relative : les textes « vh » (en position absolue)
   des puces restent dans la rangée (sinon ils élargissaient la page de 750 px). La marge négative est rendue par un retrait intérieur
   de 8 px en haut et en bas : l'anneau de focus n'est pas rogné par la rangée. */
@container screen (max-width:599.98px){
  .o-chain__etages > li > .o-chain__etages-groups{position:relative;flex-wrap:nowrap;overflow-x:auto;overscroll-behavior-x:contain;scrollbar-width:none;margin:calc(var(--space-1) - var(--space-2)) calc(-1 * var(--margin)) calc(-1 * var(--space-2)) 0;padding:var(--space-2) var(--margin) var(--space-2) 0}
  .o-chain__etages > li > .o-chain__etages-groups::-webkit-scrollbar{display:none}
  .o-chain__etages > li > .o-chain__etages-groups > li{flex:none}
  .o-chain__etages > li > .o-chain__etages-groups .o-chain__etages-gt{white-space:nowrap}
}
/* ---------- Fiche espèce, retours du propriétaire (jet 3, 2026-11-10, agent « fiche ») : points 30, 32 et 33 ---------- */
/* n° 30 (capture 27) — Section Liens en bureau : la colonne des suites (« Explorer le réseau », « Toutes les espèces documentées »,
   les outils, « Vu depuis une commune », « Comparer ») reste sous les yeux pendant la lecture du sablier. Elle colle sous la bande de
   l'en-tête et des onglets (--header-h + --localnav-h + son filet ; son padding-top de --space-5 fait l'écart), et s'arrête avec sa
   case de grille, donc au bas de la figure : jamais au-delà de la zone Liens. Toutes les fiches qui ont cette grille (espèce, genre
   replié) ; en compacte, une seule colonne : rien ne colle. Aucun mouvement ajouté (mouvement réduit : rien à retirer). */
@container screen (min-width:1024px){
  .o-vivant__liens > .o-vivant__suite{position:sticky;top:calc(var(--header-h) + var(--localnav-h) + 1px);align-self:start}
}
/* n° 32 (capture 29) — Où et quand : la grille de l'écran gelé espece-renard (carte | listes | figures, 4/4/3) ne garde jamais de
   colonne vide. OuEtQuand (socle/composants/ou.tsx) ne rend que les modules présents et dit leur composition (data-compo : c carte,
   l listes et liens, p figures). Sans carte (espèce sensible partout, outre-mer seul), les figures prennent la place : listes sur
   4/11, figures sur 7/11, côte à côte (calendrier | altitude) ; une figure seule prend toute sa case ; un module seul, toute la
   largeur. Entre 600 et 1 023 px, la grille de deux colonnes du socle n'est gardée qu'avec la carte. */
@container screen (min-width:1024px){
  .screen .o-ou:is([data-compo="lp"],[data-compo="cp"],[data-compo="cl"]){grid-template-columns:minmax(0,4fr) minmax(0,7fr)}
  .screen .o-ou:is([data-compo="l"],[data-compo="p"],[data-compo="c"]){grid-template-columns:minmax(0,1fr)}
  .screen .o-ou:is([data-compo="lp"],[data-compo="cp"],[data-compo="p"]) > .o-ou-petits{grid-template-columns:repeat(auto-fit,minmax(min(100%,18rem),1fr));column-gap:var(--gutter)}
}
@container screen (min-width:600px) and (max-width:1023.98px){
  .screen .o-ou:not([data-compo^="c"]),.screen .o-ou:is([data-compo="c"]){grid-template-columns:minmax(0,1fr)}
  .screen .o-ou[data-compo="cp"] > .o-ou-petits{grid-column:auto;grid-template-columns:minmax(0,1fr)}
  .screen .o-ou > .o-ou-petits{grid-template-columns:repeat(auto-fit,minmax(min(100%,16rem),1fr))}
}
/* n° 33 (capture 30) — Photo de tête : aucune donnée ne dit où est l'espèce dans la photo (pas de point focal) ; le recadrage en
   bandeau (5:2, 10:3 avec une réponse longue) coupait l'oiseau, l'insecte ou la fleur. La photo est montrée ENTIÈRE (contain),
   centrée, sur un fond tiré d'elle-même (--fond-photo, même fichier que l'<img>, déjà chargé), flouté et à peine assombri : les
   bords prolongent la photo, aucune bande vide, à toutes les largeurs et dans les deux thèmes ; une photo au rapport du cadre le
   remplit. En compacte, le cadre passe à 16:9, une seule hauteur pour toutes les fiches (5:2 et 10:3 ne laissaient voir l'espèce
   qu'en vignette). Le filet du cadre (::after) reste au-dessus. Aucune animation. */
.o-entity__media > .o-media--entiere{isolation:isolate}
.o-entity__media > .o-media--entiere::before{content:"";position:absolute;inset:0;z-index:-1;background:var(--fond-photo,none) 50% 50% / cover no-repeat;filter:blur(24px) saturate(1.15) brightness(.82);transform:scale(1.2)}
.o-entity__media > .o-media--entiere img{position:relative;object-fit:contain;object-position:50% 50%}
@container screen (max-width:599.98px){
  .o-vivant > .o-entity:not([data-kind="rang"]) > .o-entity__media > .o-media.o-media--entiere{aspect-ratio:16 / 9}
}
@media (forced-colors:active){.o-entity__media > .o-media--entiere::before{display:none}}
/* n° 32 — Le bouton Vérifier d'une figure (« Quand l'observer ? ») : son pictogramme de 16 px s'aligne sur le bord de la colonne,
   comme le bord droit des barres du calendrier (la cible du bouton, --control-h, déborde dans la gouttière). */
.o-ou-fig__head > .o-btn--icon{margin-right:calc((16px - var(--control-h)) / 2)}
/* F §3.10 (« Où et quand » ≤ 650 px en bureau, 1 200 en compacte) : le bouton reste une cible pleine (--control-h, 44 px en compacte),
   centrée sur la ligne du H3, sans grandir la tête du module (sa hauteur est celle du titre, comme la tête de l'altitude sans bouton) ;
   sa zone déborde de quelques pixels sur la marge du texte qui suit, sans recouvrir de cible. */
.o-ou-fig__head > .o-btn--icon{margin-block:calc((var(--lh-heading) - var(--control-h)) / 2)}
/* ---------- « Filtres » et « Trier » des Index (retours du propriétaire, 2026-11-10, capture 32, point 38) ----------
   Constat : en bureau, ouvrir « Filtres » ou « Trier » dépliait un tiroir pleine largeur SOUS la barre (flex-basis 100 %, order 9) :
   la commande sautait sur sa propre ligne, l'autre commande changeait de place, les deux tiroirs pouvaient s'empiler, Échap ni un clic
   ailleurs ne refermaient rien. Toutes les pages d'Index passent par la même barre (GabaritIndex) : la correction est faite ici, une fois.
   Décision : en bureau, chaque commande ouvre un panneau flottant ANCRÉ à son bouton (le panneau du sélecteur d'entrée du socle,
   .o-picker__panel : surface flottante, bord de contrôle, rayon 2, ombre 2), à gauche pour « Filtres », aligné à droite pour « Trier » ;
   la barre ne bouge plus. Un seul panneau ouvert ; clic ailleurs ou Échap le referment (shell, composants.ts). « Trier » est un menu :
   une option par ligne, coche à gauche, choisir referme. En compacte (téléphone), rien ne change : la feuille basse du socle (portail). */
@container screen (min-width:600px){
  .o-toolbar > .o-filters{position:relative}
  .o-toolbar > .o-filters[open]{flex-basis:auto;order:0;border-color:var(--text-1)}
  .o-toolbar > .o-filters > .o-filters__body{position:absolute;z-index:3;top:calc(100% + var(--space-2));left:-1px;width:calc(var(--space-9) * 6);max-width:calc(100cqi - var(--space-5));padding:var(--space-4);border:1px solid var(--border-control);border-radius:var(--radius-2);background:var(--surface-float);box-shadow:var(--shadow-2)}
  .o-toolbar > .o-filters--sort > .o-filters__body{left:auto;right:-1px;width:max-content;min-width:calc(var(--space-9) * 3);padding:var(--space-1)}
}
/* « Trier » est un menu, en panneau (bureau) comme en feuille basse (téléphone) : une option par ligne, coche à gauche dans une colonne
   fixe (les libellés restent alignés), survol en --surface-1 ; une option choisie au pointeur referme le panneau ou la feuille (shell). */
.o-filters__menu .o-chips{flex-direction:column;flex-wrap:nowrap;gap:0}
.o-filters__menu label.o-chip{min-height:var(--target);padding-inline:var(--space-3) var(--space-5);border:0;border-radius:var(--radius-1);background:none;font-size:var(--fs-body);line-height:var(--lh-body);letter-spacing:normal}
.o-filters__menu label.o-chip::before{content:"";flex:none;width:6px;height:10px;margin-right:var(--space-2);border:solid transparent;border-width:0 1.5px 1.5px 0;transform:rotate(45deg) translate(-1px,-1px)}
.o-filters__menu label.o-chip:has(> input:checked){background:none}
.o-filters__menu label.o-chip:has(> input:checked)::before{margin-right:var(--space-2);border-color:currentColor}   /* même colonne de coche, cochée ou non */
.o-filters__menu label.o-chip:hover{background:var(--surface-1)}
.o-filters__menu label.o-chip:has(> input:focus-visible){outline-offset:-2px;box-shadow:none}
.o-sheet--bottom .o-filters__menu{padding-inline:calc(var(--margin) - var(--space-3))}
/* Retour n° 61 (directeur, 2026-11-11) : le menu est décalé de la marge des puces (space-3) pour que leur colonne de coche tombe sur la
   gouttière ; le pied (texte, « Afficher… », filet) restait sur ce décalage, à 4 px du bord. Il reprend la gouttière : son contenu par
   un retrait space-3 et son filet tracé dans le même retrait ; sa surface et le fondu au-dessus (feuille du socle) gardent toute la
   largeur, pour couvrir les rangées qui défilent dessous jusqu'au bord de leur surbrillance. */
.o-sheet--bottom .o-filters__menu > .o-filters__foot{padding-inline:var(--space-3);border-top-color:transparent;background:linear-gradient(var(--border-subtle),var(--border-subtle)) var(--space-3) 0 / calc(100% - 2 * var(--space-3)) 1px no-repeat border-box,var(--surface-float)}
/* ---------- Choix du département de /fr/communes (retours du propriétaire, jet 3, agent petits) ----------
   Constat : le choix du département (101 départements, en puces) s'ouvrait en tiroir pleine largeur sous la barre, seul Index resté
   ainsi après le point 38 : il n'est pas dans la barre d'outils (.o-toolbar) mais au-dessus de la liste (.o-index__entry).
   Décision : le même panneau flottant ANCRÉ à son bouton (surface, bord, rayon et ombre du panneau de sélecteur du socle), en menu
   comme « Trier » (un département par ligne, coche en colonne fixe, son nombre de communes aligné à droite, choisir referme) ; champ
   « Filtrer les départements » en tête (shell : .o-filters__q, début de mot, sans accents) ; la liste a une hauteur bornée et défile
   seule, d'un défileur fin aux couleurs du socle, le champ restant en haut et le pied en bas. En compacte : la feuille basse du socle. */
.o-filters--choix > summary{white-space:nowrap}
/* le panneau porte ses propres classes (.o-filters__choix) : en compacte, le portail du shell le déplace dans la feuille basse */
.o-filters__choix .o-filters__ql{display:block;margin-bottom:var(--space-2)}
.o-filters__choix .o-filters__q{width:100%}
.o-filters__choix .o-filters__grp{margin-top:var(--space-2)}
.o-filters__choix .o-chips > label.o-chip{align-self:stretch}
.o-filters__choix .o-chips > label.o-chip[hidden]{display:none}
.o-filters__choix label.o-chip > .o-chip__n{margin-left:auto;padding-left:var(--space-4);font-variant-numeric:tabular-nums}
.o-filters__choix .o-filters__vide{padding:var(--space-3);font-size:var(--fs-small);line-height:var(--lh-small);color:var(--text-2)}
.o-filters__choix .o-filters__vide[hidden]{display:none}
/* feuille basse : le menu y est décalé de la marge des puces (.o-sheet--bottom .o-filters__menu) ; libellé et champ gardent la marge */
.o-sheet--bottom .o-filters__choix > :is(.o-filters__ql,.o-filters__q){margin-inline:var(--space-3);width:calc(100% - 2 * var(--space-3))}
@container screen (min-width:600px){
  .o-index__entry > .o-filters--choix{position:relative;width:fit-content;max-width:100%}
  .o-index__entry > .o-filters--choix[open]{border-color:var(--text-1)}
  .o-index__entry > .o-filters--choix > .o-filters__body{position:absolute;z-index:3;top:calc(100% + var(--space-2));left:-1px;width:calc(var(--space-9) * 4);max-width:calc(100cqi - var(--space-5));padding:var(--space-4) var(--space-4) var(--space-3);border:1px solid var(--border-control);border-radius:var(--radius-2);background:var(--surface-float);box-shadow:var(--shadow-2)}
  /* seule la liste défile, de hauteur bornée par la fenêtre ; défileur fin aux couleurs du socle */
  .o-index__entry > .o-filters--choix .o-chips{max-height:min(calc(var(--space-9) * 4), calc(100dvh - var(--header-h) - var(--space-9) * 5));overflow-y:auto;overscroll-behavior:contain;margin-inline:calc(-1 * var(--space-2));padding:var(--space-1) var(--space-2) 0;border-top:1px solid var(--border-subtle);scrollbar-width:thin;scrollbar-color:var(--border-control) transparent}
  .o-index__entry > .o-filters--choix .o-chips::-webkit-scrollbar{width:6px}
  .o-index__entry > .o-filters--choix .o-chips::-webkit-scrollbar-thumb{border-radius:3px;background:var(--border-control)}
  .o-index__entry > .o-filters--choix .o-chips::-webkit-scrollbar-track{background:transparent}
  .o-index__entry > .o-filters--choix .o-filters__foot{margin-top:var(--space-2);padding-top:var(--space-3)}
  .o-index__entry > .o-filters--choix .o-filters__foot > p{flex-basis:100%}
}
/* ---------- Attente d'une recherche servie par l'API (retours du propriétaire, 2026-11-10, point 34) ----------
   Constat : sur /fr/especes (et toute liste d'Index dont le filtre texte est demandé au serveur), la page refiltrait ses 50 rangées à
   la frappe et montrait « Aucune espèce ne correspond » le temps que l'API réponde ; de même pour les sélecteurs dont les options
   viennent de l'API (outils du Labo, Contribuer).
   Décision : le motif d'attente de la palette (C5-023, R5-IDX-13) : les résultats précédents restent, atténués, sous un trait de
   progression fin qui glisse ; rien n'apparaît avant 150 ms (une réponse rapide ne clignote pas) ; « aucun résultat » n'est dit que
   par la réponse. Sous mouvement réduit, le trait est fixe. Le compte de la barre dit « Recherche de « … »… » (shell). */
.o-index__list{position:relative}
.o-index__list > li{transition:opacity var(--t-2) var(--ease)}
.o-index__list[aria-busy="true"] > li{opacity:.4;transition-delay:150ms}
:is(.o-index__list,.o-picker__list)[aria-busy="true"]::before{content:"";position:absolute;z-index:1;top:-1px;left:0;right:0;height:2px;background:linear-gradient(90deg,transparent,var(--text-1),transparent) 0 0 / 40% 100% no-repeat;opacity:0;animation:o-busy 1.2s linear infinite,o-busy-in var(--t-2) var(--ease) 150ms forwards;pointer-events:none}
.o-index__list[aria-busy="true"]::before{left:var(--space-3);right:var(--space-3)}   /* bords des rangées (.o-list : marges de -12 px) */
.o-picker__list{position:relative}
.o-picker__list[aria-busy="true"]{min-height:2px}   /* liste vide en attente : le trait reste visible (défileur de hauteur nulle sinon) */
.o-picker__list[aria-busy="true"]::before{position:sticky;top:0;display:block;margin-bottom:-2px}
.o-picker__list > .o-picker__opt{transition:opacity var(--t-2) var(--ease)}
.o-picker__list[aria-busy="true"] > .o-picker__opt{opacity:.4;transition-delay:150ms}
@keyframes o-busy-in{to{opacity:1}}
@media (prefers-reduced-motion:reduce){:is(.o-index__list,.o-picker__list)[aria-busy="true"]::before{animation:o-busy-in var(--t-2) var(--ease) 150ms forwards;background:var(--text-1)}}
/* ---- Lentille communale de la fiche espèce (#dans=), retours du propriétaire (2026-11-10, points 36 et 41) ----
   Rangée de contexte de la bande collante, SOUS les onglets (src/vivant/choix-commune.tsx) : « Vu depuis {commune} ({dép.}) », « Changer
   de commune », « Voir partout en France » ; visible dès le premier écran (la bande suit l'en-tête de la fiche) et pendant tout le
   défilement (la bande colle). Rendue par le serveur, cachée ; montrée par la lentille (data-o-lentille sur la racine). Fond de surface
   et filet : la rangée se lit comme l'état de la page, pas comme une navigation. */
.o-localnav__lens{border-top:1px solid var(--border-subtle);background:var(--surface-1);transition:opacity var(--t-2) var(--ease)}
@starting-style{.o-localnav__lens{opacity:0}}
.o-localnav__lens[hidden]{display:none}
/* arbitrage du directeur (vague du 2026-11-12) : un seul bloc. « Vu depuis {commune} » et la phrase locale forment un paragraphe ;
   les commandes (Changer, Voir partout en France) flottent à droite de sa première ligne, la phrase les contourne puis prend toute
   la largeur (en compacte, 3 lignes au lieu d'une rangée suivie d'un paragraphe de 3 lignes dans la section Liens). */
.o-localnav__lens-in{display:flow-root;max-width:calc(var(--w-full) + 2 * var(--margin));min-height:var(--target);margin-inline:auto;padding-inline:var(--margin);font-size:var(--fs-small);line-height:var(--lh-small)}
.o-localnav__lens-act{float:right;display:flex;align-items:center;column-gap:var(--space-5);margin-left:var(--space-3);margin-bottom:calc((var(--lh-small) - var(--target)) / 2)}
/* (marge basse négative : les commandes, cibles de 44 px centrées sur la première ligne, n'occupent que cette ligne ; la suite de la
   phrase prend toute la largeur) */
/* la phrase prend la place libre (un paragraphe de l'écran est borné à la mesure de lecture : pas ici) ; un nom long passe à la ligne
   entre les mots, jamais tronqué (le nom de la commune est le contexte : on le lit en entier) */
.o-localnav__lens-t{max-width:var(--measure);margin:0;padding-block:calc((var(--target) - var(--lh-small)) / 2) var(--space-2);color:var(--text-2)}
.o-localnav__lens-t > .o-icon{margin-right:var(--space-2);vertical-align:calc((var(--lh-small) - 16px) / -2);color:var(--text-1)}
.o-localnav__lens-t b{font-weight:600;color:var(--text-1)}
.o-localnav__lens-t [data-lentille-phrase][hidden]{display:none}
/* actions à la taille de la phrase (un bouton du socle passe au corps de texte en compacte : pas dans cette rangée) */
.o-localnav__lens .o-btn{flex:none;min-height:var(--target);font-size:inherit;line-height:inherit;letter-spacing:inherit}
.o-localnav__lens .o-picker__panel{left:auto;right:0}
/* marge de défilement des ancres : la bande compte sa rangée de contexte */
html[data-o-localnav][data-o-lentille]{scroll-padding-top:calc(var(--header-h) + var(--localnav-h) + var(--target) + var(--space-3) + 2px + var(--space-2))}
/* Sélecteur de commune (choix-commune.tsx) : déclencheur au dessin d'un bouton tertiaire, jamais l'encadré d'une puce ouverte */
.o-lens-choix > summary.o-btn{list-style:none}
.o-lens-choix[open] > summary.o-btn--tertiary{border-color:transparent;text-decoration-color:currentColor}
.o-lens-choix__court{display:none}
/* repère de l'onglet Liens : la seule section que la lentille change */
.o-localnav__pin{display:inline-flex;align-items:center;margin-left:var(--space-1);color:var(--text-2)}
.o-localnav__pin[hidden]{display:none}
@media (prefers-reduced-motion:reduce){.o-localnav__lens{transition:none}}
@container screen (max-width:599.98px){
  .o-localnav__lens-act{column-gap:var(--space-3)}
  /* compacte : la phrase finit à 4 px du filet (la rangée reste sous le pli avec le premier rôle du sablier, C8) */
  .o-localnav__lens-t{padding-bottom:var(--space-1)}
  .o-lens-choix__long{display:none}
  .o-lens-choix__court{display:inline}
  .o-localnav__lens-x{width:var(--target);margin-right:calc(-1 * var(--space-3));border-radius:var(--radius-full)}
}
/* le déclencheur de la rangée des suites a le dessin des liens voisins (graisse et cible de la rangée, .o-actions__row > .o-btn) */
.screen .o-actions__row > .o-lens-choix > summary.o-btn{min-height:var(--target);font-weight:400}
/* Retours du propriétaire (jet 3, agent petits) : le panneau du choix de commune de la colonne des suites (bureau) dépassait de la
   colonne et de la marge de la page (24 px) : ancré au bord gauche de son déclencheur avec la largeur du panneau de sélecteur du
   socle (384 px), dans une colonne de 360 px. Il prend la largeur de la colonne, bords alignés sur ceux du contenu ; il reste sous son
   déclencheur (position statique de son <details> : la colonne collante, positionnée, est le bloc de référence). */
@container screen (min-width:1024px){
  .o-vivant__liens > .o-vivant__suite .o-lens-choix{position:static}
  .o-vivant__liens > .o-vivant__suite .o-lens-choix > .o-picker__panel{top:auto;left:0;right:0;width:auto;max-width:none;margin-top:var(--space-2)}
}
/* Sélecteurs et filtres du socle (`details.o-picker`, `details.o-filters`) : à l'ouverture, le champ prend le focus (shell, toggle).
   Cause du focus perdu (constat du 2026-11-10, point 36 des retours, au clic comme par le script) : la transition discrète de
   `content-visibility` du contenu de <details> (socle : fondu de fermeture) le gardait `hidden` pendant --t-1 APRÈS l'ouverture ; un
   champ caché ne reçoit pas le focus, qui restait sur le résumé (la saisie ne tapait nulle part). La transition de la fermeture reste ;
   l'ouverture montre le contenu sur-le-champ (fondu d'opacité seul). Vaut pour tous les sélecteurs et filtres du site. */
.o-picker[open]::details-content,.o-filters[open]::details-content{transition:opacity var(--t-1) var(--ease)}
/* Champ « Filtrer » (R5-IDX-7, retours du 2026-11-11 : « Nom ou nom latin » doit tenir sur iPhone) : la place de la croix d'effacement
   (44 px à droite) n'est réservée que quand le champ a une saisie (la croix n'existe qu'alors) ; vide, le texte indicatif a toute la
   largeur utile. Sur /fr/especes à 390, il tenait dans 151 px mais le champ ne lui en laissait que 119 : TexteIndicatif le retirait. */
.o-qfilter__box > .o-input:placeholder-shown{padding-right:var(--space-3)}
/* Rangée défilante de puces en compacte (/fr/recherche : première rangée 428 > 420 ; /liens : 487 > 480, F §3.4) : la piste gardait
   6 px de marge haute et basse pour ne pas rogner la zone sensible de 44 px empruntée par une puce de 32 px (socle.css §6) ; depuis
   R5-T-30 (socle.css, A11Y-R5-7), une puce mesure 44 px réels en compacte, et la marge grandissait la rangée de 12 px (56 au lieu
   des 44 de l'écran gelé, dont les puces faisaient 32 + 2 × 6). Elle reste pour l'anneau de focus (la piste rogne en hauteur), mais
   hors du flux : marge négative égale, la rangée occupe 44 px. */
@container screen (max-width:599.98px){.o-scroller__track:has(> .o-chip){margin-block:calc((var(--chip-h) - var(--target)) / 2)}}
/* Légende de la carte de « Où et quand » en compacte : même pas que la légende d'une carte de lieu (socle.css, .o-mapcap .o-legend :
   4 px entre rangées, 12 entre entrées) ; à 24 px, la sixième entrée (« jamais notée ») passait seule sur une troisième rangée
   (outarde : « Où et quand » 1 240 > 1 200 en compacte, F §3.10). */
@container screen (max-width:599.98px){.screen .o-carte-lg{gap:var(--space-1) var(--space-3)}}
/* Communes en colonnes (.o-communes) : un nom propre ne se coupe jamais (traits d'union insécables, D12) ; quand le nom et sa valeur
   ne tiennent pas ensemble dans la colonne (« Montredon‑Labessonnié 4 % » dans une colonne de 169 px à 390), la valeur passe sous le
   nom, à droite, au lieu de déborder de l'écran (Natura 2000 FR7301631 : scrollWidth 400 > 390, CI-3). */
.screen .o-communes li{flex-wrap:wrap}
.screen .o-communes li > data,.screen .o-communes li > span:last-child{margin-left:auto}
/* Annuaire d'une longue liste de lieux (retours du propriétaire, jet 4, n° 49, capture 37 : les 797 communes de l'Aisne s'ouvraient
   toutes d'un coup) : champ « Filtrer », état en mots, index du rail A–Z (même dessin que le satellite paginé : 44 px, lettre choisie
   soulignée, lettre sans rangée grisée), 15 rangées (10 en compacte) puis « Afficher N de plus ». Composant :
   src/socle/composants/annuaire.tsx ; comportement : src/socle/shell/annuaire.ts. */
.o-annuaire:not(:first-child){margin-top:var(--space-6)}
.o-annuaire__outils{display:flex;flex-direction:column;gap:var(--space-2);margin-top:var(--space-3)}
/* En bureau, l'état en mots (« 314 communes », « 108 communes en C » et sa sortie) se lit à droite du champ, sur sa ligne : le champ
   n'occupe que la mesure de lecture (680 px) et la ligne d'état sous lui ajoutait une rangée à chaque annuaire (F §3.10 : Autour du
   département ≤ 1 400 px). L'index reste dessous, sur toute la largeur. Sous 1 024 px, l'état reste sous le champ (à 640, le champ
   prend toute la largeur : à côté, l'état débordait). */
@container screen (min-width:1024px){
  .o-annuaire__outils{display:grid;grid-template-columns:minmax(0,var(--measure)) minmax(0,1fr);align-items:center;column-gap:var(--space-4)}
  .o-annuaire__outils > .o-annuaire__index{grid-column:1 / -1}
}
.o-annuaire__etat{display:flex;flex-wrap:wrap;align-items:baseline;gap:0 var(--space-3);margin:0;font-size:var(--fs-small);line-height:var(--lh-small);color:var(--text-2);font-variant-numeric:tabular-nums}
.o-annuaire__etat{min-height:var(--lh-small)}
.o-annuaire__etat > .o-link,.o-annuaire__vide > .o-link{position:relative;padding:0;border:0;background:none;font:inherit;color:var(--text-1);cursor:pointer}
/* cible de 44 px sans hauteur de ligne en plus (la ligne d'état ne bouge pas quand la sortie apparaît) */
.o-annuaire__etat > .o-link::after,.o-annuaire__vide > .o-link::after{content:"";position:absolute;left:50%;top:50%;width:max(100%,var(--target));height:var(--target);transform:translate(-50%,-50%)}
.o-annuaire__index{margin-top:0}
.o-annuaire__index button{display:inline-flex;align-items:center;justify-content:center;min-width:var(--target);min-height:var(--target);padding:0 var(--space-2);white-space:nowrap;border:0;border-radius:var(--radius-1);background:none;font:inherit;color:var(--text-1);cursor:pointer;transition:background-color var(--t-1) var(--ease)}
.o-annuaire__index button:hover{background:var(--surface-1)}
.o-annuaire__index button[aria-pressed="true"]{font-weight:600;box-shadow:inset 0 -2px 0 var(--text-1)}
.o-annuaire__index button:focus-visible{outline:2px solid var(--focus);outline-offset:-2px}
.o-annuaire__l{margin-top:var(--space-2)}
/* colonnes fixes : filtrer ou choisir une lettre ne fait jamais bouger les colonnes */
.o-table--annuaire{table-layout:fixed}
.o-table--annuaire thead th:not(:first-child){width:calc(var(--space-9) + var(--space-8))}
.o-annuaire [data-annuaire-cle].is-revele{animation:o-reveal var(--t-2) var(--ease) backwards}
.o-annuaire__vide{margin-top:var(--space-4);color:var(--text-2)}
.o-annuaire__suite{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-2) var(--space-4);margin-top:var(--space-4)}
.o-annuaire__n{font-size:var(--fs-small);line-height:var(--lh-small);color:var(--text-2);font-variant-numeric:tabular-nums}
.o-annuaire > .o-cap{margin-top:var(--space-3)}
@media (prefers-reduced-motion:reduce){.o-annuaire [data-annuaire-cle].is-revele{animation:none}.o-annuaire__index button{transition:none}}
/* En compacte, une commune tient sur deux lignes (nom, puis espèces observées · surface · habitants), toute la rangée est la cible
   du lien ; l'en-tête du tableau reste lu (tri au clavier et au lecteur d'écran), sans place à l'écran. */
@container screen (max-width:599.98px){
  /* Tri en compacte : l'en-tête n'est plus caché visuellement (ses boutons de tri restaient des cibles focalisables invisibles, de
     44 px, sous la première commune : D9 ; une rangée de tableau ignore width, height et overflow). Il devient la rangée de tri, au-
     dessus de la liste : Commune, Surface, Habitants (cibles de 44 px, flèche du sens) ; la colonne sans tri n'y figure pas. */
  .o-table--annuaire thead{display:block}
  .o-table--annuaire thead tr{display:flex;flex-wrap:wrap;align-items:center;column-gap:var(--space-5);border-bottom:1px solid var(--border-subtle)}
  .o-table--annuaire thead th,.o-table--annuaire thead th:not(:first-child){width:auto;padding:0;border:0;font-size:var(--fs-small);line-height:var(--lh-small);font-weight:400;color:var(--text-2);text-align:left}
  .o-table--annuaire thead th[data-sans-tri]{display:none}
  .o-table--annuaire,.o-table--annuaire tbody{display:block}
  .o-table--annuaire tbody tr{position:relative;display:flex;flex-wrap:wrap;align-items:baseline;padding-block:var(--space-2);border-bottom:1px solid var(--border-subtle)}
  .o-table--annuaire tbody th[scope="row"]{flex:1 0 100%;padding:0;border:0;font-size:var(--fs-body);line-height:var(--lh-body)}
  .o-table--annuaire tbody th[scope="row"] a::after{content:"";position:absolute;inset:0}
  .o-table--annuaire tbody td{padding:0;border:0;color:var(--text-2);text-align:start;white-space:nowrap}
  .o-table--annuaire tbody td:empty{display:none}
  .o-table--annuaire tbody td[data-u]::after{content:attr(data-u)}
  .o-table--annuaire tbody td:not(:empty) ~ td:not(:empty)::before{content:"·";padding-inline:var(--space-2);color:var(--text-3)}
}
/* ---------- Feuilles de réglages et de filtres en compacte (retour du propriétaire n° 55, capture 42 ; agent reglages) ----------
   Constat : la feuille « Réglages » de l'Explorateur était posée en vrac — libellés à GAUCHE de segmentés de largeurs inégales,
   « Sources » en segmenté vertical de 4 options (le repli R2-6 d'un segmenté qui ne tient pas), « Liens potentiels » et « Ordre ou
   famille : tous » en puces côte à côte, « Réinitialiser » en gras sous le tout ; les réglages des cartes (calques) en boutons radio
   natifs dans un cadre de fieldset, ceux du réseau d'un lieu sans leurs styles (règles du rendu « #écran .xl-… », que le portail sort
   de l'écran). Cause : la feuille rendait tel quel le balisage de la BARRE de bureau (en ligne, flex-wrap) ; le sélecteur « Ordre ou
   famille », dans la feuille, ne s'ouvrait même pas (shell, n° 55 (2)).
   Décision : une seule grammaire pour toute feuille de réglages ou de filtres (portail du shell, [data-portal]) :
   · en-tête : titre et actions sur UNE ligne, centrés sur la croix ; l'action de remise (« Réinitialiser », « Retirer les filtres »)
     est un texte discret avant la croix (shell : [data-feuille-action]), estompé tant qu'il n'y a rien à remettre ;
   · un réglage = un groupe titré : libellé AU-DESSUS (petit, --text-2), contrôle pleine largeur ; 24 px entre groupes, 8 px du libellé
     au contrôle ; toute cible fait 44 px ;
   · choix exclusif court : segmenté pleine largeur, options égales ; choix exclusif qui n'y tient pas (« Sources », calques des
     cartes) : liste à coche (rangées de 44 px dans un cadre arrondi, coche à droite) ;
   · bascule (« Liens potentiels », « Une seule mention ») : rangée avec interrupteur ;
   · choix dans une longue liste (« Ordre ou famille ») : rangée de navigation « Ordre ou famille   Tous › », qui ouvre sa feuille
     par-dessus (shell) ;
   · rangées consécutives d'un même groupe : un seul cadre, filets entre elles.
   Jetons, deux thèmes, mouvement réduit ; rien ne change en bureau (le portail n'existe qu'en compacte). */
/* en-tête des feuilles du portail et de la feuille générique : une ligne, titre centré sur la croix */
.o-sheet--bottom:is([data-portal],#gsheet) .o-sheet__head{display:flex;align-items:center;gap:var(--space-1);min-height:calc(var(--target) + var(--space-2));padding-block:0 var(--space-2)}
.o-sheet--bottom:is([data-portal],#gsheet) .o-sheet__title{flex:1;min-width:0}
/* une feuille plus haute que la fenêtre (liste longue : « Filtres » d'un Index, « Ordre ou famille ») écrasait sa poignée (bloc vide,
   rétrécissable dans la colonne flex de la feuille) : le titre remontait sous la poignée. Poignée et en-tête ne rétrécissent jamais. */
.o-layer .o-sheet--bottom > :is(.o-sheet__grab,.o-sheet__head){flex:none}
.o-sheet--bottom:is([data-portal],#gsheet) .o-sheet__head > .o-btn--icon{flex:none;margin:0}
.o-sheet__head > [data-feuille-action]{flex:none;min-height:var(--target);padding-inline:var(--space-3);font-size:var(--fs-body);line-height:var(--lh-body);letter-spacing:normal;font-weight:400;color:var(--text-1);white-space:nowrap}
.o-sheet__head > [data-feuille-action]:disabled{color:var(--text-3);cursor:default;text-decoration-color:transparent}
.o-sheet__head > [data-feuille-action] :is([data-explorer-n],.xl-reset__n){color:var(--text-2);font-variant-numeric:tabular-nums}
/* corps : rythme vertical régulier, zone sûre de l'iPhone en bas */
.o-sheet[data-portal] .o-explorer__setbody{display:flex;flex-direction:column;align-items:stretch;gap:var(--space-5);padding-block:var(--space-4) calc(var(--space-6) + env(safe-area-inset-bottom, 0px))}
.o-sheet[data-portal] :is(.xl-tools,.xl-more-tools){display:contents}
.o-sheet[data-portal] .o-filters__grp + .o-filters__grp{margin-top:var(--space-5)}
/* groupe titré : libellé au-dessus, contrôle pleine largeur */
.o-sheet[data-portal] :is(.o-seg,.xl-control){display:grid;grid-template-columns:minmax(0,1fr);gap:var(--space-2);width:100%;max-width:none;min-width:0}
.o-sheet[data-portal] :is(.o-seg__label,.xl-control > span:first-child,.xl-control > label:first-child,.mx-calques > legend){font-size:var(--fs-small);line-height:var(--lh-small);letter-spacing:normal;font-weight:400;color:var(--text-2)}
.o-sheet[data-portal] .o-seg__opts{display:grid;width:100%}
/* liste à coche : choix exclusif qui ne tient pas en segmenté (repli du shell, data-overflow) et calques des cartes */
.o-sheet[data-portal] .o-seg__opts[data-overflow]{grid-auto-rows:auto;padding:0;border:1px solid var(--border-subtle);border-radius:var(--radius-2);background:none;overflow:hidden}
.o-sheet[data-portal] .o-seg__opts[data-overflow]::before{display:none}
.o-sheet[data-portal] :is(.o-seg__opts[data-overflow] > label,.mx-calques > .mx-chip){position:relative;display:flex;align-items:center;justify-content:space-between;gap:var(--space-3);min-height:var(--target);padding:var(--space-2) var(--space-4);border-radius:0;background:none;font-size:var(--fs-body);line-height:var(--lh-body);color:var(--text-1);white-space:normal;cursor:pointer;-webkit-tap-highlight-color:transparent;transition:background-color var(--t-1) var(--ease)}
.o-sheet[data-portal] .o-seg__opts[data-overflow] > label + label{border-top:1px solid var(--border-subtle)}
.o-sheet[data-portal] :is(.o-seg__opts[data-overflow] > label,.mx-calques > .mx-chip)::after{content:"";position:static;flex:none;width:6px;height:11px;margin:0 var(--space-1) var(--space-1) 0;border:solid currentColor;border-width:0 2px 2px 0;transform:rotate(45deg);visibility:hidden}
.o-sheet[data-portal] :is(.o-seg__opts[data-overflow] > label,.mx-calques > .mx-chip):has(> input:checked)::after{visibility:visible}
.o-sheet[data-portal] :is(.o-seg__opts[data-overflow] > label,.mx-calques > .mx-chip):active{background:var(--surface-1)}
.o-sheet[data-portal] :is(.o-seg__opts[data-overflow] > label,.mx-calques > .mx-chip):has(> input:focus-visible){outline:2px solid var(--focus);outline-offset:-2px;box-shadow:none}
.o-sheet[data-portal] .mx-calques{display:block;min-width:0;margin:0;padding:0;border:0}
.o-sheet[data-portal] .mx-calques > legend{float:none;margin:0 0 var(--space-2);padding:0}
.o-sheet[data-portal] .mx-calques > .mx-chip{border:1px solid var(--border-subtle)}
.o-sheet[data-portal] .mx-calques > .mx-chip + .mx-chip{margin-top:-1px}
.o-sheet[data-portal] .mx-calques > .mx-chip:first-of-type{border-top-left-radius:var(--radius-2);border-top-right-radius:var(--radius-2)}
.o-sheet[data-portal] .mx-calques > .mx-chip:last-of-type{border-bottom-left-radius:var(--radius-2);border-bottom-right-radius:var(--radius-2)}
.o-sheet[data-portal] .mx-calques > .mx-chip::before{content:none}
.o-sheet[data-portal] .mx-calques > .mx-chip > input{position:absolute;inset:0;width:100%;height:100%;margin:0;opacity:0;cursor:pointer}
.o-sheet[data-portal] .mx-calques > .mx-chip:has(> input:disabled){color:var(--text-3);cursor:not-allowed}
.o-sheet[data-portal] .mx-calques > .mx-chip > input:disabled{cursor:not-allowed}
.o-sheet[data-portal] .mx-why{margin:var(--space-2) 0 0;font-size:var(--fs-small);line-height:var(--lh-small);color:var(--text-2)}
/* bascule : rangée avec interrupteur (piste 48 × 28, pastille 24 ; monochrome du socle : piste --text-1 quand activée) */
.o-sheet[data-portal] :is(.o-explorer__potc,.o-chips > .o-check){position:relative;display:flex;align-items:center;width:100%;min-height:var(--target);margin:0;padding:var(--space-2) calc(var(--space-4) + var(--space-7) + var(--space-3)) var(--space-2) var(--space-4);border:1px solid var(--border-subtle);border-radius:var(--radius-2);background:none;font-size:var(--fs-body);line-height:var(--lh-body);letter-spacing:normal;color:var(--text-1);cursor:pointer;-webkit-tap-highlight-color:transparent}
.o-sheet[data-portal] :is(.o-explorer__potc,.o-chips > .o-check) > input{position:absolute;inset:0;width:100%;height:100%;margin:0;opacity:0;cursor:pointer}
.o-sheet[data-portal] :is(.o-explorer__potc,.o-chips > .o-check)::after{content:"";position:absolute;left:auto;right:var(--space-4);top:50%;width:var(--space-7);height:calc(var(--space-5) + var(--space-1));margin:0;border:0;border-radius:var(--radius-full);background:var(--border-control);transform:translateY(-50%);transition:background-color var(--t-2) var(--ease)}
.o-sheet[data-portal] :is(.o-explorer__potc,.o-chips > .o-check)::before{content:"";position:absolute;z-index:1;right:calc(var(--space-4) + var(--space-7) - var(--space-5) - 2px);top:50%;width:var(--space-5);height:var(--space-5);margin:0;border:0;border-radius:var(--radius-full);background:var(--bg);box-shadow:var(--shadow-1);transform:translateY(-50%);transition:transform var(--t-2) var(--spring-surface)}
.o-sheet[data-portal] :is(.o-explorer__potc,.o-chips > .o-check):has(> input:checked)::after{background:var(--text-1)}
.o-sheet[data-portal] :is(.o-explorer__potc,.o-chips > .o-check):has(> input:checked)::before{width:var(--space-5);height:var(--space-5);margin:0;border:0;transform:translate(calc(var(--space-7) - var(--space-5) - 4px),-50%)}
.o-sheet[data-portal] :is(.o-explorer__potc,.o-chips > .o-check):has(> input:checked){background:none;color:var(--text-1)}
.o-sheet[data-portal] :is(.o-explorer__potc,.o-chips > .o-check):has(> input:focus-visible){outline:2px solid var(--focus);outline-offset:-2px;box-shadow:none}
/* garde-fou SOCLE-perf (aucun :has() à profondeur libre ni sur un frère) : le cadre des cases jointes est porté par leur conteneur
   (:has(> …), enfant direct), « Liens potentiels » suivi d'« Ordre ou famille » par une classe posée au rendu (o-explorer__potc--suivi) */
.o-sheet[data-portal] .o-chips:has(> .o-check){flex-direction:column;flex-wrap:nowrap;gap:0;border:1px solid var(--border-subtle);border-radius:var(--radius-2)}
.o-sheet[data-portal] .o-chips > .o-check{min-height:calc(var(--target) - 2px);border:0;border-radius:0}
.o-sheet[data-portal] .o-chips > .o-check:first-child{border-top-left-radius:var(--radius-2);border-top-right-radius:var(--radius-2)}
.o-sheet[data-portal] .o-chips > .o-check:last-child{border-bottom-left-radius:var(--radius-2);border-bottom-right-radius:var(--radius-2)}
.o-sheet[data-portal] .o-chips > .o-check + .o-check{min-height:calc(var(--target) - 1px);border-top:1px solid var(--border-subtle)}
/* rangée de navigation : un sélecteur dans le panneau d'une feuille (« Ordre ou famille   Tous › ») ouvre sa feuille par-dessus */
.o-sheet[data-portal] .o-filters__body .o-picker{display:block;width:100%;max-width:none}
.o-sheet[data-portal] .o-filters__body .o-picker > summary{display:flex;align-items:center;gap:var(--space-3);width:100%;min-height:var(--target);padding:var(--space-2) var(--space-4);border:1px solid var(--border-subtle);border-radius:var(--radius-2);background:none;font-size:var(--fs-body);line-height:var(--lh-body);letter-spacing:normal;color:var(--text-1);-webkit-tap-highlight-color:transparent}
.o-sheet[data-portal] .o-filters__body .o-picker > summary:active{background:var(--surface-1)}
.o-sheet[data-portal] .o-filters__body .o-picker > summary::before{width:16px;height:16px;color:var(--text-3);transform:rotate(-90deg)}
.o-sheet[data-portal] .o-filters__body .o-picker > summary > .o-picker__k{flex:1;min-width:0}
.o-sheet[data-portal] .o-filters__body .o-picker > summary .o-picker__sep{display:none}
.o-sheet[data-portal] .o-filters__body .o-picker > summary > .o-picker__v{display:inline-block;font-weight:400;color:var(--text-2);text-align:right}
.o-sheet[data-portal] .o-filters__body .o-picker > summary > .o-picker__v::first-letter{text-transform:uppercase}
/* rangées consécutives d'un même groupe : un seul cadre, filet entre elles (« Liens potentiels » puis « Ordre ou famille ») */
.o-sheet[data-portal] .o-explorer__potc.o-explorer__potc--suivi{border-bottom-left-radius:0;border-bottom-right-radius:0}
.o-sheet[data-portal] .o-explorer__potc + .o-picker{margin-top:calc(-1 * var(--space-5) - 1px)}
.o-sheet[data-portal] .o-explorer__potc + .o-picker > summary{border-top-left-radius:0;border-top-right-radius:0}
/* déroulant dans un groupe (« Choisir un ordre ou une famille » des filtres des liens) : même rangée encadrée, chevron vers le bas */
.o-sheet[data-portal] .o-filters__grp > .o-details > summary{justify-content:space-between;padding:var(--space-2) var(--space-4);border:1px solid var(--border-subtle);border-radius:var(--radius-2);font-size:var(--fs-body);line-height:var(--lh-body);font-weight:400;color:var(--text-1);-webkit-tap-highlight-color:transparent}
.o-sheet[data-portal] .o-filters__grp > .o-details > summary::after{color:var(--text-3)}
.o-sheet[data-portal] .o-filters__grp > .o-details > summary:active{background:var(--surface-1)}
.o-sheet[data-portal] .o-filters__grp > .o-details[open] > .o-filters__grp{margin-top:var(--space-3)}
/* réseau d'un lieu : puces des liens et des règnes, recherche d'un ordre ou d'une famille (styles du rendu, restés dans l'écran) */
.o-sheet[data-portal] .xl-chips{display:flex;flex-wrap:wrap;gap:var(--space-2);min-width:0}
.o-sheet[data-portal] .xl-tax{position:relative}
.o-sheet[data-portal] .xl-tax__i{display:block;width:100%;height:var(--target);padding-inline:var(--space-3);border:1px solid var(--border-control);border-radius:var(--radius-1);background:var(--bg);color:var(--text-1);font:inherit;font-size:var(--fs-body);line-height:var(--lh-body)}   /* 16 px : Safari ne zoome pas au focus */
.o-sheet[data-portal] .xl-tax__i::placeholder{color:var(--text-3)}
.o-sheet[data-portal] .xl-tax__l{position:fixed;inset:auto;width:calc(100vw - 2 * var(--margin));margin:0;padding:var(--space-1);border:0;border-radius:var(--radius-2);background:var(--surface-float);color:var(--text-1);box-shadow:var(--shadow-2)}
.o-sheet[data-portal] .xl-tax__o{display:flex;align-items:center;gap:var(--space-2);width:100%;min-height:var(--target);padding-inline:var(--space-3);border-radius:var(--radius-1);font:inherit;font-size:var(--fs-body);line-height:var(--lh-body);color:var(--text-1);text-align:left}
.o-sheet[data-portal] .xl-tax__o:is(:hover,:active){background:var(--surface-2)}
.o-sheet[data-portal] .xl-tax__sel{display:flex;flex-wrap:wrap;gap:var(--space-2)}
.o-sheet[data-portal] .xl-tax__sel:empty{display:none}
/* feuille empilée (« Ordre ou famille » par-dessus « Réglages ») : la feuille du dessous, inerte, s'efface sous un voile, comme le fond */
.o-layer .o-sheet--bottom::after{content:"";position:absolute;inset:0;border-radius:inherit;background:var(--scrim);opacity:0;pointer-events:none;transition:opacity var(--t-2) var(--ease)}
.o-layer .o-sheet--bottom[inert][data-state="open"]::after{opacity:.24}
/* segmenté en feuille : en sombre, la piste du socle (--surface-2) se confond avec la feuille (--surface-float = --surface-2) ; elle
   y prend --bg, en creux, comme le champ de recherche */
/* même cause pour une puce cochée (fond --surface-2) : elle y prend le fond de la pastille du segmenté (--seg-thumb) */
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]) .o-sheet[data-portal] .o-seg__opts:not([data-overflow]){background:var(--bg)}
  :root:not([data-theme="light"]) .o-sheet[data-portal] :is(.o-chip[aria-pressed="true"],label.o-chip:has(> input:checked)):not(.o-explorer__potc,.o-filters__menu .o-chip){background:var(--seg-thumb)}
}
:root[data-theme="dark"] .o-sheet[data-portal] .o-seg__opts:not([data-overflow]){background:var(--bg)}
:root[data-theme="dark"] .o-sheet[data-portal] :is(.o-chip[aria-pressed="true"],label.o-chip:has(> input:checked)):not(.o-explorer__potc,.o-filters__menu .o-chip){background:var(--seg-thumb)}
/* Labo, entrées du calcul en compacte : chaque sélecteur est une rangée pleine largeur (socle) ; sa valeur flottait au milieu
   (« Commune :      Lacaze (81)   ⌄ », trois éléments répartis). Même rangée que « Ordre ou famille   Tous › » : la valeur rejoint le
   chevron, à droite. */
@container screen (max-width:599.98px){.o-tool__inputs .o-picker > summary > .o-picker__v{margin-left:auto;text-align:right}}
/* pied des filtres d'Index : l'action principale (« Afficher N espèces ») pleine largeur ; « Retirer les filtres » est dans l'en-tête */
.o-sheet[data-portal] .o-filters__foot > .o-filters__show{flex:1 1 100%}
@media (prefers-reduced-motion:reduce){
  .o-layer .o-sheet--bottom::after{transition:none}
  .o-sheet[data-portal] :is(.o-explorer__potc,.o-chips > .o-check)::before,.o-sheet[data-portal] :is(.o-explorer__potc,.o-chips > .o-check)::after{transition:none}
}
@media (forced-colors:active){
  .o-sheet[data-portal] :is(.o-explorer__potc,.o-chips > .o-check)::after{forced-color-adjust:none;background:Canvas;border:1px solid CanvasText}
  .o-sheet[data-portal] :is(.o-explorer__potc,.o-chips > .o-check)::before{forced-color-adjust:none;background:CanvasText}
  .o-sheet[data-portal] :is(.o-explorer__potc,.o-chips > .o-check):has(> input:checked)::after{background:Highlight;border-color:Highlight}
  .o-sheet[data-portal] :is(.o-explorer__potc,.o-chips > .o-check):has(> input:checked)::before{background:HighlightText}
  .o-sheet[data-portal] :is(.o-seg__opts[data-overflow] > label,.mx-calques > .mx-chip)::after{forced-color-adjust:none;border-color:CanvasText}
}
/* Diagrammes de flux `.o-chain__bip` (Alliances d'une commune, bipartite de l'outil Pollinisateurs) : retours du propriétaire
   (2026-11-11, point 47). Survol, toucher ou focus clavier d'un flux ou d'une famille (shell/flux.ts) : le voisinage reste net,
   ailleurs les marques passent à --dim et le texte des nœuds à --text-2 (la règle de l'Explorateur, C5-005 ; jamais de texte à
   demi-opacité). Fondus de 100 ms (--t-1), seuls gardés en mouvement réduit (I §5.1). Info-bulle : celle de l'Explorateur
   (.o-explorer__tip), au pointeur ou au milieu du flux, jamais hors de la figure. */
.o-chain__bip{position:relative;border-radius:var(--radius-1)}
.o-chain__bip svg > path,.o-chain__bip-node::after{transition:opacity var(--t-1) var(--ease)}
.o-chain__bip-node{transition:color var(--t-1) var(--ease)}
.o-chain__bip[data-hover] svg > path:not(.is-near){opacity:var(--dim)}
.o-chain__bip[data-hover] .o-chain__bip-node:not(.is-near){color:var(--text-2)}
.o-chain__bip[data-hover] .o-chain__bip-node:not(.is-near)::after{opacity:var(--dim)}
.o-chain__bip .o-flux__hit path{fill:transparent;stroke:transparent;stroke-width:10px;vector-effect:non-scaling-stroke;stroke-linejoin:round}
.o-flux__tip{position:absolute;z-index:3;left:0;top:0;width:max-content;max-width:min(calc(var(--space-9) * 4),100%);padding:var(--space-1) var(--space-2);border-radius:var(--radius-1);background:var(--text-1);color:var(--bg);font-size:var(--fs-caption);line-height:var(--lh-caption);letter-spacing:var(--ls-caption);text-align:left;pointer-events:none;transform:translate(-50%,calc(-100% - var(--space-3)));opacity:1;transition:opacity var(--t-1) var(--ease)}
.o-flux__tip[data-dessous]{transform:translate(-50%,var(--space-4))}
@starting-style{.o-flux__tip{opacity:0}}
@media (forced-colors:active){
  .o-chain__bip .o-flux__hit path{fill:transparent;stroke:transparent}
  .o-chain__bip[data-hover] .o-chain__bip-node:not(.is-near){color:GrayText}
  .o-flux__tip{border:1px solid CanvasText}
}
/* Carte centrale du sablier (retours du propriétaire, 2026-11-11, point 48) : quand elle mène quelque part (Explorateur de la fiche,
   fiche de l'exemple de l'accueil), TOUTE la carte est la cible, avec le survol et l'appui d'une carte (.o-card--text : surface-2 au
   survol, échelle --s-press à l'appui) ; le compte « espèces liées » (bouton Vérifier, terme du glossaire) reste au-dessus de la zone. À l'accueil, le lien
   de la carte double le « Voir la fiche » de la légende : il est retiré de la tabulation et des lecteurs d'écran (Sablier, prop fiche). */
.o-hg__center:has(> :is(.o-hg__center-link,.o-hg__center-fiche)){transition:background-color var(--t-1) var(--ease),transform var(--t-2) var(--ease)}
.o-hg__center:has(> :is(.o-hg__center-link,.o-hg__center-fiche)):hover{background:var(--surface-2)}
.o-hg__center:has(> :is(.o-hg__center-link,.o-hg__center-fiche)):active{transform:scale(var(--s-press));transition-duration:var(--t-1)}
:is(.o-hg__center-link,.o-hg__center-fiche)::after{content:"";position:absolute;inset:0;border-radius:var(--radius-2)}
.o-hg__center-link,.o-hg__center-fiche{cursor:pointer}
.o-hg__center-fiche{display:block;border-radius:var(--radius-2)}
.o-hg__center-link:focus-visible{outline:none;box-shadow:none}
.o-hg__center-link:focus-visible::after{outline:2px solid var(--focus);outline-offset:2px;box-shadow:0 0 0 4px var(--focus-halo)}
.o-hg__center:hover > .o-hg__center-fiche + .o-hg__center-name{text-decoration:underline;text-underline-offset:3px;text-decoration-thickness:1px}
/* ce qui se touche dans la carte (compte « espèces liées » : bouton Vérifier ou terme du glossaire) reste au-dessus de la zone */
.o-hg__center-count :is(button,[href]){position:relative;z-index:1}
/* Tuile par défaut (socle/composants/tuile.tsx ; retours du propriétaire, 2026-11-11, point 50 ; décision :
   docs/refonte/implementation/DECISION_TUILE_DEFAUT.md) : planche gravée de ce qui n'a pas d'image. Surface du socle et filet des
   photos, motif au trait fin encré dans la rampe (--seq-2, accents --seq-3 : les deux thèmes suivent les jetons), effacé vers le coin
   du texte ; code en grand (graisse et approche du titre d'écran, chiffres alignés), typologie au-dessus, grand milieu dessous. Même
   cadre que la plaque (4:3, rayon 12, marges 16 ; 12 en compacte), sans couleur de marque : la marque reste au vivant (G §7.2). */
.o-tuile{position:relative;isolation:isolate;display:flex;flex-direction:column;justify-content:space-between;gap:var(--space-4);aspect-ratio:4 / 3;padding:var(--space-4);overflow:hidden;border-radius:var(--radius-2);background:var(--surface-1);box-shadow:inset 0 0 0 1px var(--photo-hairline);color:var(--text-1);container-type:inline-size;container-name:tuile}
/* vague du 2026-11-12 (poids) : le tracé est un fichier SVG immuable (app/tuiles), posé en masque sur un aplat encré au jeton ;
   même cadrage que l'ancien SVG en ligne (xMidYMid slice : center / cover), mêmes traits (1 px, 1,5 px, dans le fichier) */
.o-tuile__motif{position:absolute;inset:0;z-index:-1;-webkit-mask-image:linear-gradient(to top right,transparent 0,transparent 22%,currentColor 62%);mask-image:linear-gradient(to top right,transparent 0,transparent 22%,currentColor 62%)}
.o-tuile__fin,.o-tuile__accent{position:absolute;inset:0;-webkit-mask-image:var(--motif);mask-image:var(--motif);-webkit-mask-size:cover;mask-size:cover;-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat}
.o-tuile__fin{background:var(--seq-2)}
.o-tuile__accent{background:var(--seq-3)}
.o-tuile__picto{color:var(--text-2)}
.o-tuile__texte{min-width:0}
.o-tuile__sur,.o-tuile__sous{font-size:var(--fs-small);line-height:var(--lh-small);letter-spacing:var(--ls-small);color:var(--text-2)}
/* un code plus large que la tuile passe à la ligne au lieu de déborder : break-word (la boîte du texte a une largeur fixée par la
   tuile, c'est donc équivalent à anywhere ici) ; anywhere est interdit au lint C6 (jamais de coupe en plein mot, socle.css C5-065) */
.o-tuile__code,.o-tuile__nom{margin-block:var(--space-1);font-size:var(--fs-display);line-height:var(--lh-display);letter-spacing:var(--ls-display);font-weight:600;font-variant-numeric:lining-nums tabular-nums;overflow-wrap:break-word}
.o-tuile__nom{font-size:var(--fs-title);line-height:var(--lh-title);letter-spacing:var(--ls-title)}
@container tuile (max-width:359.98px){
  .o-tuile__code{font-size:var(--fs-title);line-height:var(--lh-title);letter-spacing:var(--ls-title)}
  .o-tuile__nom{font-size:var(--fs-heading);line-height:var(--lh-heading);letter-spacing:var(--ls-heading)}
}
@container screen (max-width:599.98px){.o-tuile{padding:var(--space-3)}}
@media (forced-colors:active){.o-tuile{border:1px solid CanvasText}.o-tuile__motif{display:none}}
/* Retours du propriétaire, points 54 et 56 (captures 41 et 43, iPhone) : sous le doigt, la barre des onglets d'une fiche défilait aussi
   de haut en bas, son contenu bougeait librement. Cause : `overflow-x:auto` seul donne aussi `overflow-y:auto` (CSS Overflow 3 : un axe
   non « visible » rend l'autre défilant) ; l'onglet courant (trait de 2 px à bottom:-1px) dépasse la piste d'1 px, qui devient défilable
   en hauteur : un glissement vertical commencé sur la barre la faisait rebondir au lieu de faire défiler la page. Toute rangée défilante
   horizontale du site (onglets, défileurs de puces et de cartes, galeries, rail A–Z en compacte, tableaux larges, segmentés) défile
   désormais en LARGEUR SEULE : `overflow-y:hidden` (rien n'est rogné de plus : l'axe vertical rognait déjà), et son bord ne déclenche
   ni le défilement de la page ni le retour arrière du navigateur (`overscroll-behavior-x:contain`). `touch-action` reste `auto` : un
   `pan-x` ferait de la barre une zone morte pour le défilement vertical de la page (mesuré au toucher : la page ne bouge plus quand le
   doigt part de la barre) ; sans axe vertical défilable, le geste vertical passe à la page, comme une rangée défilante native. */
.o-localnav ul,.o-scroller__track,.o-table-wrap,.lc-segscroll{overflow-y:hidden;overscroll-behavior-x:contain}
@container screen (max-width:599.98px){.o-rail ol{overflow-y:hidden;overscroll-behavior-x:contain}}

/* ---------- Défileur en compacte : la suite se VOIT (retours du propriétaire, 2026-11-11, point 59) ----------
   Constat (iPhone, accueil, « Par quelles espèces commencer ? ») : une seule carte, « Oiseaux 699 », et rien d'autre ; même défaut
   sur les piliers d'une commune, les régions de l'accueil, les puces de statut, de portée, de rôle et « Agir ici ». Cause : la règle
   « jamais un mot coupé » (R2-11) du défileur rend TRANSPARENT (mask-image, --clip-r posé par le shell) l'élément coupé au bord
   droit ; sans boutons ‹ › (accueil) il reste un vide, avec eux un chevron isolé : rien ne dit qu'il y a d'autres cartes.
   Correction, pour TOUT défileur .o-scroller en compacte (la règle du bureau ne change pas) : la rangée va jusqu'au bord de l'écran
   (marge du cadre reprise en retrait intérieur, comme le rail A–Z du socle) et l'élément suivant DÉPASSE, opaque, coupé par le bord
   de l'écran : environ 20 % de la largeur. Les cartes mesurent 80 % de la colonne (--o-defile) ; les grands groupes et les régions
   (variante grille) passent en étagère de trois rangées égales, qui défile par colonnes. L'accroche (scroll-snap) cale chaque carte sur la
   marge du cadre. Au doigt, plus de boutons ‹ › : la carte qui dépasse les remplace ; au pointeur fin (fenêtre étroite), ils restent.
   Aucun mouvement ajouté (défilement de l'utilisateur ; les boutons suivent déjà le mouvement réduit), couleurs du socle. */
@container screen (max-width:599.98px){
  .o-scroller{--o-defile:80%;margin-inline:calc(-1 * var(--margin))}
  .o-scroller__track{padding-inline:var(--margin);scroll-padding-inline:var(--margin);-webkit-mask-image:none;mask-image:none}
  .o-scroller[data-more-start] .o-scroller__track,.o-scroller[data-more-end] .o-scroller__track{margin-inline:0}
  /* « Agir ici » : le libellé tient la gauche ; la rangée ne déborde qu'à droite */
  .o-agir > .o-scroller{margin-left:0}
  .o-agir > .o-scroller > .o-scroller__track{padding-left:0;scroll-padding-left:0}
  /* cartes d'une rangée (piliers d'une commune) : 80 % de la colonne, la suivante dépasse */
  .o-row2 .o-scroller__track > *{flex:0 0 var(--o-defile)}
  /* grille en bureau → étagère de trois rangées (grands groupes, régions) : colonnes de 80 %, la colonne suivante dépasse */
  .o-scroller--grille .o-scroller__track{display:grid;grid-auto-flow:column;grid-template-rows:repeat(3,1fr);grid-auto-columns:var(--o-defile);gap:var(--space-3)}
  /* au-dessus d'une liste d'Index (12 grands groupes de /fr/especes), une seule rangée : la carte suivante dépasse comme dans toute
     rangée défilante (n° 59) ; l'étagère de trois rangées (222 px) poussait la première rangée de la liste à 636 px, au-delà de la
     cote du premier écran d'un Index (F §3.4 : 480 px à 390) */
  .o-index__entry .o-scroller--grille .o-scroller__track{grid-template-rows:auto}
  .o-scroller--grille .o-card--group{width:auto}
  .o-scroller--grille .o-card__name{white-space:normal}
}
@media (pointer:coarse){@container screen (max-width:599.98px){
  .o-scroller[data-more-start] .o-localnav__btn,.o-scroller[data-more-end] .o-localnav__btn{display:none}
}}
@media (pointer:fine){@container screen (max-width:599.98px){
  .o-scroller__track{scroll-padding-inline:var(--target)}   /* R5-T-14 : un élément focalisé n'est jamais sous ‹ › */
}}
/* ---------- Rangée des piliers d'une commune en compacte (F §3.3 et §7.4, 3e relevé de prod du 2026-11-12) ----------
   Constat : cartes de 286 × 148 (80 % de la colonne, n° 59 ; vignette de 64 px à gauche), soit 1,2 carte visible ; F §7.4 demande
   des cartes de 160 × 180, 2,2 visibles, et le premier pilier entier avant 760 px.
   Correction : cartes de 160 px, écart de 12 px (16 + 160 + 12 + 160 + 12 = 360 : la 3e carte dépasse du bord, opaque, n° 59) ;
   carte verticale comme le croquis de F §7.4 et la carte du bureau : photo en tête (bandeau 10:3, 160 × 48 : la photo allégée du
   srcset, sizesCartePilier), nom, mesure, « seule ressource » et crédit en dernière ligne (G §7.3), rien de retiré ; Lacaze : 192 px
   de haut. Pour que le premier pilier reste entier avant 760, l'en-tête de la rangée tient une ligne de 44 px à 390 (elle passe à la ligne à 320) : « Vérifier » en
   pictogramme, son nom accessible inchangé, comme le Vérifier d'un en-tête de section en compacte (socle.css), collé au titre
   (D14 T10) ; « Les 8 piliers › » garde son texte. */
@container screen (max-width:599.98px){
  .o-row2__head{align-items:center;column-gap:var(--space-2)}
  .o-row2__head > div{column-gap:var(--space-2)}
  .o-row2__head > div > .o-btn--verify{width:var(--target);padding-inline:0}
  .o-row2__head > div > .o-btn--verify .o-btn__label{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
  .o-row2 .o-scroller__track{--gap:var(--space-3)}
  .o-row2 .o-scroller__track > *{flex:0 0 160px}
  .o-row2 .o-card:not(.o-card--text){display:flex;flex-direction:column;align-items:stretch;align-content:normal;gap:0;padding:0;background:none}
  .o-row2 .o-card:not(.o-card--text) > .o-media{width:100%;aspect-ratio:10 / 3;margin-bottom:var(--space-1);border-radius:var(--radius-1)}
  .o-row2 .o-card .o-card__name{font-size:var(--fs-small);line-height:var(--lh-small);font-weight:600}
  .o-row2 .o-card :is(.o-card__qual,.o-credit){font-size:var(--fs-caption);line-height:var(--lh-caption);letter-spacing:var(--ls-caption)}
}

/* ---------- Rail A–Z d'un Index (retours du propriétaire, 2026-11-11, point 43) ----------
   La lettre mène à SA première entrée (index/client/RailLettres.tsx) : la rangée atteinte reçoit un voile bref, la teinte du survol,
   tenu un instant puis effacé (I : --t-4, --ease) ; mouvement réduit : aucun voile animé (--t-4 vaut 0). */
.o-row[data-cible]{animation:o-cible calc(var(--t-4) * 3) var(--ease)}
@keyframes o-cible{0%,40%{background:var(--surface-1)}100%{background:transparent}}
@media (prefers-reduced-motion:reduce){.o-row[data-cible]{animation:none}}

/* retours du propriétaire n° 64 : étiquettes de statut d’une rangée (Protégée en France, DH II…) séparées du nom latin qui les précède */
.o-row__sub > * + .o-tags{margin-inline-start:var(--space-2)}
/* Écran d'erreur (retour du directeur, 2026-11-11 ; src/socle/shell/EcranErreur.tsx) : page 404 du socle, 404 de dernier recours,
   erreur globale. Avant : titre, texte et boutons collés au coin haut-gauche, sans en-tête ni gouttière. En-tête réduit à la marque
   (lien d'accueil) et à la recherche ; dessous, la colonne du socle (.o-page : largeur et gouttières de chaque classe de largeur) porte
   un bloc centré, placé un peu au-dessus du milieu de la hauteur restante (repère optique : plus d'air dessous que dessus). */
.o-erreur-ecran{display:flex;flex-direction:column;min-height:100dvh}
.o-erreur-ecran > .o-main{flex:1;display:flex;flex-direction:column;padding-block-end:0}
.o-erreur-ecran > .o-main > .o-page{flex:1;display:flex;width:100%;box-sizing:border-box}
.o-erreur{display:flex;flex-direction:column;align-items:center;max-width:var(--w-read);margin:auto;padding-block:var(--space-8) calc(var(--space-9) + var(--space-7));text-align:center}
.o-erreur__mark{width:var(--space-7);height:var(--space-7);margin-bottom:var(--space-5);color:var(--text-1)}
.o-erreur .o-title{text-wrap:balance}
.o-erreur .o-empty{display:flex;flex-direction:column;align-items:center;margin-top:var(--space-3)}
.o-erreur .o-empty__text p{margin-inline:auto;font-size:var(--fs-lead);line-height:var(--lh-lead);letter-spacing:var(--ls-lead);color:var(--text-2);text-wrap:balance}
.o-erreur .o-empty__actions{justify-content:center;margin-top:var(--space-6)}
@container screen (max-width:599.98px){
  .o-erreur{padding-block:var(--space-7) var(--space-9)}
  .o-erreur__mark{width:var(--space-6);height:var(--space-6);margin-bottom:var(--space-4)}
}
/* Règle des 8 lignes (retours du propriétaire n° 73, 2026-11-11 ; socle/composants/lieu.tsx, ListeBornee) : une liste de page montre au
   plus 8 lignes. Les rangées au-delà du repli d'une liste [data-plier] sont cachées dès le HTML servi ; le shell pose ensuite son repli
   (.o-fold) et « Afficher les N suivantes » : la page ne montre jamais toute la liste pour la replier ensuite (aucun saut). */
[data-plier="8"]:not(.o-fold) > :is(ul,ol) > li:nth-child(n+9):not(.o-more,.o-more-c),
[data-plier="8"]:not(.o-fold) tbody > tr:nth-child(n+9),
[data-plier="6"]:not(.o-fold) > :is(ul,ol) > li:nth-child(n+7):not(.o-more,.o-more-c),
[data-plier="6"]:not(.o-fold) tbody > tr:nth-child(n+7){display:none}
@container screen (max-width:599.98px){
  [data-plier-compact="4"]:not(.o-fold) > :is(ul,ol) > li:nth-child(n+5):not(.o-more,.o-more-c){display:none}
}
/* n° 73 : une liste de communes repliée (ZNIEFF, site de 9 à 20 communes) garde ses 4 colonnes de bureau (règle du socle « lot final »
   pour .o-section__body > .o-communes--1), le repli [data-plier] s'intercalant entre le corps et la liste */
@container screen (min-width:1024px){.screen .o-section__body > [data-plier] > .o-communes--1{columns:10rem 4}}
