/* =========================================================================
   UST — vocabulaire des composants
   Aucune valeur littérale : tout vient de tokens.css. Aucun survol non gardé.
   Aucune translation, aucun changement d'échelle au survol (§8).
   ========================================================================= */

/* =========================================================================
   1. LA GRADUATION — l'élément signature (ARBITRAGE §7)
   Une piste tracée au seuil de visibilité (--filet-haut), un segment allumé
   dont la longueur est √(minutes), un index de 2 px --lampe posé sur la
   valeur lue, et LES SEUILS IMPRIMÉS SOUS LA PISTE (G4).

   Elle ne mesure QUE du temps d'intégration, jamais autre chose.

   Deux instruments, deux axes, jamais confondus (C4). L'épaisseur de piste
   les sépare avant même la lecture : 3 px pour l'objet, 6 px pour l'appareil.

   L'état vide est un état de premier rang : piste tracée jusqu'au bout,
   segment de longueur nulle, index parqué à zéro en --gradue. Jamais une
   ligne masquée, jamais une carte absente, jamais une astérisque.
   ========================================================================= */
.grad {
  --grad-piste: var(--grad-piste-objet);
  --grad-boite: var(--grad-boite-objet);
  display: flex; flex-direction: column; gap: var(--e-2);
  /* La graduation est son propre contexte de requête (voir .grad__seuils).
     Le confinement en ligne annule sa largeur intrinsèque : sans ce
     width:100%, une graduation posée en enfant d'une rangée flex se
     réduirait à zéro — une piste invisible, exactement ce que §7 interdit.
     Mesuré : 0 px sans, la largeur disponible avec.                       */
  container-type: inline-size;
  width: 100%; min-width: 0;
}
.grad--appareil {
  --grad-piste: var(--grad-piste-appareil);
  --grad-boite: var(--grad-boite-appareil);
}

/* La valeur, en toutes lettres : la forme annonce, le texte confirme.
   Ni l'un ni l'autre ne porte seul l'information (§7). */
.grad__ligne {
  display: flex; flex-wrap: wrap; justify-content: space-between;
  align-items: baseline; gap: var(--e-1) var(--e-3);
  max-width: none;
}
.grad__valeur { color: var(--texte); font-weight: var(--g-mono-fort); letter-spacing: 0; }
.grad__note   { color: var(--label); letter-spacing: 0; }

.grad__piste {
  position: relative; display: block; width: 100%;
  height: var(--grad-boite);
}
/* La piste, tracée jusqu'au bout — y compris à zéro. */
.grad__piste::before {
  content: ""; position: absolute; left: 0; right: 0;
  top: calc((var(--grad-boite) - var(--grad-piste)) / 2);
  height: var(--grad-piste);
  background: var(--filet-haut); border-radius: 1px;
}
/* Le segment allumé : longueur = √(min) / √(axe), calculée à la construction
   et servie en --part. Le scaleX n'est qu'une animation : la géométrie est
   déjà juste au premier rendu, sans JavaScript. */
.grad__lu {
  position: absolute; left: 0;
  top: calc((var(--grad-boite) - var(--grad-piste)) / 2);
  height: var(--grad-piste);
  width: calc(var(--part, 0) * 100%);
  background: var(--texte); border-radius: 1px;
  transform-origin: left center;
  transition: transform var(--t-pose) var(--courbe) var(--t-retard-pose);
}
/* Les traits de seuil (G4) : ils sont sous la piste ET traversent le puits. */
.grad__seuil {
  position: absolute; top: 0; height: var(--grad-boite); width: 1px;
  left: calc(var(--x) * 100%);
  transform: translateX(calc(var(--x) * -100%));
  background: var(--gradue);
}
/* L'index : 2 px de lampe posés sur la valeur lue, avec son halo. */
.grad__index {
  position: absolute; top: 0; height: var(--grad-boite); width: var(--grad-index);
  left: calc(var(--part, 0) * 100%);
  transform: translateX(calc(var(--part, 0) * -100%));
  background: var(--lampe); box-shadow: var(--ombre-index);
  transition: opacity var(--t-ui) ease var(--t-retard-index);
}
/* Les valeurs des seuils, imprimées sous la piste. L'ancrage glisse de
   gauche à droite avec la position : aucune étiquette ne déborde du puits. */
.grad__seuils {
  position: relative; display: block; width: 100%;
  min-height: var(--grad-ligne);
  color: var(--gradue); max-width: none;
}
.grad__seuils span {
  position: absolute; top: 0; white-space: nowrap;
  left: calc(var(--x) * 100%);
  transform: translateX(calc(var(--x) * -100%));
}
/* Sur l'échelle objet, les deux premiers seuils sont à 11,9 % et 23,8 % :
   sous ~455 px de piste, « 15 min » et « 1 h » se toucheraient. Aucune valeur
   n'est pour autant retirée — l'axe se lit alors sur deux lignes, chaque
   étiquette restant sous son trait. Mesuré : plus aucun chevauchement à 300 px
   de piste, la largeur d'une carte à 390.                                   */
@container (max-width: 30rem) {
  .grad--objet .grad__seuils { min-height: calc(2 * var(--grad-ligne)); }
  .grad--objet .grad__seuils span:nth-child(2n) { top: var(--grad-ligne); }
}
/* Garde-fou. Sous 15 rem de piste aucune étiquette intermédiaire ne tient,
   même sur deux lignes : seule l'extrémité de l'axe reste imprimée. Les traits
   restent tracés et la légende porte l'axe en toutes lettres, donc rien n'est
   perdu — mais une graduation n'a pas sa place dans une colonne aussi étroite.
   Ce n'est pas une mise en page prévue, c'est un filet de sécurité.         */
@container (max-width: 15rem) {
  .grad__seuils span:not(:last-child) { display: none; }
  .grad--objet .grad__seuils { min-height: var(--grad-ligne); }
  .grad--objet .grad__seuils span { top: 0; }
}
/* L'axe écrit en toutes lettres (C4, C5). */
.grad__axe { color: var(--label); max-width: none; }

/* --- L'état vide, état de premier rang ---------------------------------- */
.grad.est-vide .grad__lu    { background: var(--filet-haut); }
.grad.est-vide .grad__index { background: var(--gradue); box-shadow: none; }
.grad.est-vide .grad__valeur{ color: var(--label); font-weight: var(--g-mono); }

/* --- Le tracé : 400 ms, 120 ms de retard ; l'index : 200 ms, 420 ms ------
   Conditionné à .js ET à [data-grad]. Sans JavaScript, sans observateur, ou
   sur une graduation déclarée immobile (le hero), tout est peint d'emblée. */
.js [data-grad] .grad__lu    { transform: scaleX(0); }
.js [data-grad] .grad__index { opacity: 0; }
.js [data-grad].vu .grad__lu    { transform: none; }
.js [data-grad].vu .grad__index { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .js [data-grad] .grad__lu    { transform: none; }
  .js [data-grad] .grad__index { opacity: 1; }
}

/* --- Filet de surtitre ---------------------------------------------------
   LE MÊME TRAIT ÉTAIT DESSINÉ DEUX FOIS, SOUS DEUX NOMS, DANS DEUX FEUILLES.
   .integ-marque vivait ici, .filet-brow dans pages.css : trois rem sur un
   pixel de --filet, à l'identique, et vingt poses réparties entre les deux
   noms au hasard des lots. C'est la faute de .bande, recommencée.
   LE NOM RETENU EST .filet-brow, parce qu'il dit ce que la chose est — le
   filet du surtitre — quand .integ nommait la graduation d'intégration
   qu'elle n'est plus. .integ et .integ-marque restent en alias tant que les
   gabarits les portent ; aucune règle nouvelle ne doit les employer.
   TRANSITION : .integ / .integ-marque étaient la signature de la direction
   précédente. Une graduation ne décore jamais et ne mesure rien d'autre que
   du temps (§7) : ces marques ne sont plus qu'un filet. À remplacer par
   <Graduation> là où il y a une donnée, par .filet-brow partout ailleurs. */
.integ, .integ-marque, .filet-brow {
  display: block; height: 1px; background: var(--filet); border: 0;
}
.integ-marque, .filet-brow { width: 3rem; flex: none; }

/* =========================================================================
   2. EN-TÊTE
   C7 : aucun backdrop-filter. Le fond est tokenisé et n'apparaît qu'à 80 px
   de défilement — un seul écouteur passif, 300 ms (§8).
   ========================================================================= */
.nav {
  position: sticky; top: 0; z-index: 50;
  background: transparent; border-bottom: 1px solid transparent;
  transition: background-color var(--t-panneau) ease, border-color var(--t-panneau) ease;
}
.nav[data-collee="oui"] {
  background: var(--voile-entete);
  border-bottom-color: var(--filet);
}
/* LE BLOC DE MARQUE RESPIRE. La barre portait padding 0 et min-height
   4,5rem pour un sceau de 64 px : 4 px au-dessus, 4 en dessous, le logo
   collé au filet. L'air est posé ICI, sur la barre, et non sur .marque :
   le bouton et les liens sont centrés sur la même boîte, ils gagnent le
   même air et la barre reste un seul rythme.
   La hauteur ne saute pas à la bascule data-collee : elle vaut --h-entete
   dans les deux états, et le filet du bas est déjà là au repos, en
   transparent. Seuls le fond et la couleur du filet changent, en 300 ms. */
.nav__barre {
  display: flex; align-items: center; gap: var(--e-4);
  padding-block: var(--air-entete);
  min-height: var(--h-entete); max-width: var(--contenu); margin-inline: auto;
}
.nav__liens { display: flex; align-items: center; gap: var(--e-4); margin-left: auto; }
.nav__lien {
  position: relative; display: inline-block;
  font-size: var(--d-petit); font-weight: var(--g-corps-moyen);
  text-decoration: none; color: var(--champ);
  padding-block: var(--e-2); min-height: 1.5rem;
  transition: color var(--t-micro) ease;
}
/* Le soulignement de nav est le seul autre emploi de la lampe dans le chrome. */
.nav__lien::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: .15rem; height: 2px;
  background: var(--lampe); transform: scaleX(0); transform-origin: left;
  transition: transform var(--t-ui) var(--courbe);
}
.nav__lien[aria-current="page"] { color: var(--texte); }
.nav__lien[aria-current="page"]::after, .nav__lien:focus-visible::after { transform: scaleX(1); }
@media (hover: hover) {
  .nav__lien:hover { color: var(--texte); }
  .nav__lien:hover::after { transform: scaleX(1); }
}
/* LES DEUX ICÔNES DE LA BARRE : LA LOUPE ET LA PORTE DU FORUM.
   Des glyphes, pas des mots : la barre n'a pas la place de deux libellés de
   plus, et la mesure est au §5 de _design/RECHERCHE-ETAT.md. Les icônes sont
   décoratives, le nom accessible est le .u-sr que chaque lien porte.
   ELLES SONT LE DERNIER ENFANT DE LA BARRE, ET AUCUNE PROPRIÉTÉ order NE LES
   DÉPLACE : l'ordre du clavier suit donc l'ordre de l'oeil aux deux tailles,
   ce qu'order aurait cassé au large (les icônes auraient été atteintes avant
   les liens tout en s'affichant après eux). Au large, .nav__liens prend la
   marge automatique et le groupe la suit, à l'extrémité droite après le
   bouton ; au serré, .nav__liens quitte le flux, c'est le burger qui prend la
   marge et le groupe le suit.
   L'ÉCART INTERNE EST --e-1 ET C'EST LÀ QUE LA PLACE A ÉTÉ TROUVÉE. Posée à
   plat dans la barre, la loupe aurait coûté sa largeur PLUS une gouttière de
   barre entière, soit 60 px au large ; dans le groupe elle coûte 36 + 8 = 44.
   Les 16 px gagnés sont exactement ce qui sépare le portugais du débordement.
   La cible fait 2,25rem au large et 2,75rem au serré, la taille du burger :
   au-dessus des 24 px de la 2.5.8 partout, à 44 px là où on vise du doigt. */
.nav__outils { display: flex; align-items: center; gap: var(--e-1); flex: none; }
.nav__icone {
  display: grid; place-items: center;
  width: 2.25rem; height: 2.25rem;
  color: var(--champ);
  transition: color var(--t-micro) ease;
}
.nav__buste, .nav__loupe-icone { width: 1.375rem; height: 1.375rem; }
@media (hover: hover) { .nav__icone:hover { color: var(--texte); } }

/* =========================================================================
   LE SEUIL DU BURGER PASSE DE 61,99rem À 74,99rem. C'EST D25, ET C'EST UNE
   RÉPARATION AUTANT QU'UNE PLACE FAITE.

   CE QUI ÉTAIT CASSÉ AVANT CE LOT, MESURÉ À L'OUTIL ET NON SUPPOSÉ : entre 992
   et 1016 px, la barre FRANÇAISE faisait 94,8 px et non 88, parce que « Les
   télescopes » et « À propos » se repliaient chacun sur deux lignes. En
   espagnol la casse allait jusqu'à 1040 px, en italien jusqu'à 1012. Le
   resserrement d'écart de la pose du buste avait réparé la marque, pas les
   liens. Le tableau des 14 largeurs, avant et après, est au §5 de
   _design/RECHERCHE-ETAT.md.

   POURQUOI 75rem ET PAS LE MINIMUM QUI PASSE. C'est la valeur de D25
   (_design/MULTILINGUE.md §7.8), décidée avant ce lot et pour une autre
   raison : le russe s'allonge de 15 à 30 % sur des libellés courts. Le minimum
   qui passe en français serait plus bas, et il retomberait à la première
   traduction relue. On prend la valeur décidée.

   CE QUE ÇA CHANGE POUR LE CLIENT, ET IL FAUT LE LUI DIRE : entre 992 et
   1199 px, toutes les langues, français compris, ont maintenant le menu
   burger. C'est un changement visible, annoncé comme tel au §5, avec ses
   captures avant et après.

   LA BANDE À ÉCART RESSERRÉ SUIT LE SEUIL. Elle valait 62 à 72rem ; elle vaut
   maintenant 75 à 80rem, c'est à dire le premier pouce au-dessus du burger, où
   sept éléments se disputent encore la ligne. Au-delà de 80rem, la gouttière
   reprend --e-4 : à 1280 px le contenu utile plafonne à 1160 px et le pire cas
   mesuré, le portugais, en demande 1099. */
@media (min-width: 75rem) and (max-width: 79.99rem) {
  .nav__barre, .nav__liens { gap: var(--e-3); }
  /* Même reprise qu'au plateau (§13), sur la gouttière de cette bande. */
  .nav__outils { margin-inline-start: calc(var(--e-1) - var(--e-3)); }
}
.marque { flex: none; }

.nav__burger { display: none; }

/* LE PANNEAU DE RECHERCHE DE LA BARRE, ouvert par le script du pied et par lui
   seul : sans JavaScript il reste `hidden` et la loupe est un lien vers
   /recherche/. Il est en absolu SOUS la barre, et non dans son flux : dans le
   flux il aurait poussé la page de sa hauteur à chaque ouverture, c'est à dire
   un saut de contenu sur un clic. La barre garde donc ses 88 px ouverte comme
   fermée, et le panneau ne recouvre que le haut du contenu, comme le panneau
   du burger.
   `[hidden]` EST REDIT ICI PARCE QUE display: flex L'ÉCRASERAIT : l'attribut
   ne vaut `display: none` que par la feuille par défaut du navigateur, qu'une
   règle d'auteur bat. Sans cette ligne, le panneau serait ouvert pour tout le
   monde, JavaScript ou non. */
.nav__chercher {
  position: absolute; top: 100%; left: 0; right: 0;
  display: flex; align-items: center; gap: var(--e-2);
  padding-block: var(--e-3);
  background: var(--ciel); border-bottom: 1px solid var(--filet);
}
.nav__chercher[hidden] { display: none; }
.nav__saisie {
  flex: 1 1 auto; min-width: 0;
  background: var(--saisie-fond); border: 1px solid var(--saisie-bord);
  border-radius: var(--r-s);
  padding: var(--e-2) var(--e-3); color: var(--texte); font-size: var(--d-corps);
  transition: border-color var(--t-ui) ease;
}
.nav__saisie:focus { outline: 0; border-color: var(--saisie-bord-actif); }
.nav__saisie:focus-visible {
  outline: var(--focus-l) solid var(--focus-couleur); outline-offset: var(--focus-o);
}
@media (hover: hover) { .nav__saisie:hover { border-color: var(--lampe-haute); } }

@media (max-width: 74.99rem) {
  .nav__liens {
    /* Le panneau s'ouvre SOUS la barre : il lit sa hauteur, il ne la recopie
       plus. Avec 4,5rem en dur il recouvrait le bas de l'en-tête dès que la
       barre gagnait un pixel. */
    position: fixed; inset: var(--h-entete) 0 auto 0;
    flex-direction: column; align-items: stretch; gap: 0;
    background: var(--ciel); border-bottom: 1px solid var(--filet);
    padding: var(--e-3) var(--marge) var(--e-5);
    clip-path: inset(0 0 100% 0); transition: clip-path var(--t-pose) ease-in-out;
    /* IL DÉFILE, ET C'EST LE MÉGA MENU QUI L'EXIGE (§13). Le panneau portait
       sept rangées courtes et tenait toujours dans la fenêtre ; il porte
       maintenant un déclencheur qui déplie 81 liens. inset pose son bord haut
       et laisse son bord bas libre : sans max-height le contenu sortait sous
       la fenêtre, hors d'atteinte, parce que body est déjà en overflow: hidden
       quand le burger est ouvert. */
    max-height: calc(100svh - var(--h-entete));
    overflow-y: auto; overscroll-behavior: contain;
  }
  body:has(.nav__burger[aria-expanded="true"]) .nav__liens { clip-path: inset(0 0 0 0); }
  body:has(.nav__burger[aria-expanded="true"]) { overflow: hidden; }
  .nav__lien { padding-block: var(--e-3); border-bottom: 1px solid var(--filet); font-size: 1rem; }
  .nav__lien::after { display: none; }
  .nav__liens .btn { margin-top: var(--e-3); justify-content: center; }
  .nav__icone { width: 2.75rem; height: 2.75rem; color: var(--texte); }
  .nav__burger {
    display: grid; place-items: center; margin-left: auto;
    width: 2.75rem; height: 2.75rem; color: var(--texte);
  }
  .nav__burger span, .nav__burger span::before, .nav__burger span::after {
    content: ""; display: block; width: 20px; height: 1.5px;
    background: currentColor; transition: transform var(--t-panneau) ease, opacity var(--t-ui) ease;
  }
  .nav__burger span::before { transform: translateY(-6px); }
  .nav__burger span::after  { transform: translateY(4.5px); }
  .nav__burger[aria-expanded="true"] span { background: transparent; }
  .nav__burger[aria-expanded="true"] span::before { transform: rotate(45deg); }
  .nav__burger[aria-expanded="true"] span::after  { transform: rotate(-45deg) translateY(0); }

  /* ========================================================================
     L'ORDRE DANS LEQUEL LA BARRE CÈDE QUAND L'ÉCRAN MANQUE. RÉPARATION DU
     DÉBORDEMENT DE 300 À 383 px, ET DE LA CIBLE DU BURGER.

     CE QUI ÉTAIT CASSÉ, MESURÉ AU PAS DE 1 px ET NON SUPPOSÉ. La pose du
     groupe d'icônes lui avait donné `flex: none` : le groupe ne cédait donc
     jamais, et sous 384 px c'était LE DOCUMENT qui débordait. À 375 px
     (iPhone SE, mini, 6 à 8) scrollWidth valait 384 pour 375 de fenêtre ; à
     360 px (la largeur Android la plus répandue) la page défilait réellement,
     window.scrollX atteignant 23. 84 largeurs sur 121 débordaient, de 300 à
     383 sur l'accueil français. Aux neuf largeurs de téléphone, sur 5 routes
     et 7 langues : 175 débordements sur 315 mesures, là où le commit d'avant
     le lot en comptait 13 et la reprise en compte 13, les MÊMES, qui viennent
     du contenu de /telescopes/ et non de la barre. Les trois relevés sont
     .recette/recherche/sorties/balayage-etroit-{avant,lot,apres}.txt.

     LA CIBLE DU BURGER, MÊME CAUSE. Le groupe ne cédant pas, c'est le burger
     qui absorbait : 32 x 44 px de 300 à 414, là où il valait 44 x 44 avant le
     lot. Le burger est LE contrôle principal du téléphone ; la règle de la
     maison lui doit 44 px.

     L'ORDRE DE CESSION EST DONC ÉCRIT, ET IL EST CELUI-CI :
     1. l'écart de barre tombe à --e-1 sous 27rem (§ ci-dessous) ;
     2. le bloc de marque se replie, son nom passant de deux à trois puis
        quatre lignes : une ligne de plus est un coût d'oeil, pas un coût
        d'usage, et quatre lignes tiennent sous les 64 px du sceau, si bien
        que la barre garde ses 88 px ;
     3. le groupe d'icônes se resserre, mais JAMAIS sous --cible-min, les
        24 px de la 2.5.8. Avant ce lot, l'icône unique était écrasée à
        14,4 px de large à 320 px : c'était déjà un manquement, il est réparé
        du même geste ;
     4. le burger ne cède rien, jamais.
     MESURÉ APRÈS, de 300 à 991 px : aucun débordement, burger 44 x 44 partout,
     barre 88 px partout, nom sur deux lignes dès 384 px. Les icônes valent 30,
     34, 40, 42 et 44 px à 300, 320, 360, 375 et 384 px. */
  .nav__burger { flex: none; }
  .marque { flex: 0 1 auto; min-width: 0; }
  .nav__outils { flex: 0 1 auto; min-width: 0; }
  .nav__icone { min-width: var(--cible-min); }

  /* SANS JAVASCRIPT, LE PANNEAU EST DÉPLIÉ ET LE BURGER DISPARAÎT.
     CE N'EST PAS UN ORNEMENT, C'EST CE QUI REND LE MÉGA MENU HONNÊTE AU SERRÉ.

     LE DIAGNOSTIC D'ORIGINE ÉTAIT INEXACT, ET IL EST RECTIFIÉ ICI. Il disait
     « le burger est un bouton mort » et « les cinq liens sont INATTEIGNABLES ».
     Remesuré à 390 px, page.setJavaScriptEnabled(false), sur le commit d'avant
     le lot (.recette/megamenu/sorties/sansjs-cout.txt) : le burger s'affiche
     (display: grid) et se focalise, il ne fait simplement rien ; .nav__liens
     est en position fixe, rectangle [0, 88, 390, 462], et ses cinq liens sont
     FOCALISABLES. Le défaut réel n'est donc pas l'absence, c'est pire dans un
     sens et moins dans l'autre : le panneau est ÉCRÊTÉ par clip-path à zéro
     hauteur, si bien que cinq liens vivent dans l'ordre de tabulation sans
     jamais être peints (2.4.7, focus visible), et que le pointeur, lui, tombe
     sur .hero__voile. Zéro accès au doigt, un accès aveugle au clavier.
     La réparation reste justifiée, et le méga menu la rend obligatoire :
     il vit DANS ce panneau, et « un panneau qui n'existe qu'en JavaScript »
     n'est pas recevable. On le répare donc ici, pour les cinq liens comme
     pour lui.

     CE QU'ELLE COÛTE, ET C'EST DIT PARCE QUE ÇA NE L'ÉTAIT PAS. Sans
     JavaScript, à 390 px, l'en-tête mesurait 89 px avant le lot ; déplié, il
     en mesure 616, et le contenu commence d'autant plus bas. C'est 527 px de
     chrome au-dessus du héros, pour le seul visiteur sans JavaScript. Le lot
     refusé en coûtait 632 : les 16 px rendus sont l'écart de barre qui tombe
     d'un cran sous 27rem (§ plus haut). Le marché est celui-ci : une page
     longue où tout se lit, plutôt qu'une page courte où cinq liens se
     tabulent sans se voir.
     LA CLASSE .js EST POSÉE DANS LE <head>, avant le premier rendu : la règle
     ne s'applique jamais à un visiteur qui a JavaScript, exactement comme
     « .js [data-rev] » de base.css, qui repose sur le même fait.
     LE PANNEAU PASSE EN DEUXIÈME RANGÉE DE LA BARRE, dans le flux : en absolu
     il recouvrirait le haut de chaque page en permanence, et en fixe il
     resterait à l'écran. La barre s'allonge d'autant, et c'est la dégradation
     qu'on veut : tout est lisible, rien n'est caché derrière un bouton mort. */
  html:not(.js) .nav__burger { display: none; }
  html:not(.js) .nav__barre { flex-wrap: wrap; }
  html:not(.js) .nav__liens {
    position: static; flex: 1 0 100%;
    clip-path: none; transition: none;
    max-height: none; overflow: visible;
    padding-inline: 0; border-bottom: 0;
    /* LA SEULE PROPRIÉTÉ order DE LA BARRE, ET ELLE NE VIT QUE SANS
       JAVASCRIPT. Sans elle, la rangée dépliée se glisse ENTRE la marque et le
       groupe d'icônes : la loupe et le buste passent en troisième rangée,
       c'est-à-dire 4 200 px sous le haut de page une fois le méga menu ouvert.
       Regardé sur planche avant correction
       (.recette/megamenu/planches/sansjs-390-fr.png du premier jet).
       CE QU'ELLE COÛTE, ET C'EST DIT : dans ce mode dégradé seulement, l'oeil
       voit les icônes avant la liste et le clavier les atteint après. La
       doctrine de la barre (composants.css §2) refuse order pour cette raison
       exacte ; elle la refuse au nominal, où le choix se paie sur tous les
       visiteurs. Ici l'autre branche met deux commandes hors d'atteinte. */
    order: 1;
  }
}

/* L'ÉCART DE BARRE SOUS 27rem. À 24 px, la barre demande 421,3 px de contenu
   pour les deux gouttières, le bloc de marque, le burger et les deux icônes ;
   elle les a jusqu'à 422 px de fenêtre, marge de --marge comprise, et plus en
   dessous. L'écart tombe donc d'un cran sous 27rem (432 px), le premier pouce
   au-dessus du besoin mesuré, et il rend 32 px à la ligne. C'est le même geste
   qu'aux bandes 75-80rem et 80rem+, et pour la même raison : quand les
   éléments se disputent la ligne, c'est l'écart qui part le premier. */
@media (max-width: 26.99rem) {
  .nav__barre { gap: var(--e-1); }
}

/* --- Marque -------------------------------------------------------------- */
/* LE MÉDAILLON N'ÉCRIT PAS « UST », ET C'EST POUR CELA QUE LE NOM EST ÉCRIT À
   CÔTÉ. Son troisième glyphe est le pied de la lunette, sans barre horizontale :
   on y lit « USI », à 48 comme à 1254 px. Le nom en toutes lettres n'est donc
   pas un confort de lecture, c'est ce qui nomme la marque ; le sigle, lui, n'est
   répété nulle part. Voir sceau() dans inc/composants.php et MEMOIRE.md n° 6. */
/* LE SCEAU N'A NI CERNE NI HALO, ET C'EST UNE DÉCISION MESURÉE.
   Le champ marine du médaillon vaut #000714 en haut : 1,02:1 sur --nuit et
   1,25:1 sur --ciel au maître, et l'intérieur du disque une fois rendu reste
   entre 1,08 et 1,17:1 sur --nuit à toutes les tailles servies. Le haut du
   disque est donc bien indistinguable du fond, et la tentation est d'ajouter un
   cerne or ou un halo pour lui rendre sa silhouette. On ne le fait pas, pour
   trois raisons chiffrées.
   D'abord ce n'est pas la marque qui disparaît, c'est le vide autour d'elle :
   l'anneau, lui, tient. MESURE REFAITE À LA RECETTE, sur les pixels que le
   navigateur compose et non sur un hexadécimal supposé, médiane du pic radial
   relevé sur 1 440 angles, le tube blanc qui traverse l'anneau écarté :
                        48     64     80     96    132
     sur --nuit, d1    3,77   4,40   8,07   9,03   9,74
     sur --nuit, d2    8,69   9,34  11,10  11,35  11,20
   Le seuil d'un objet graphique est 3:1 : l'anneau le tient partout où le site
   le pose. La pose annonçait 8,10:1 à 64 px en densité 1 ; c'est le 99e centile
   de l'anneau, pas sa médiane, qui vaut 4,40:1. La conclusion ne bouge pas, le
   chiffre si. Ce qu'on perdrait à cerner, c'est la seule chose qui marche déjà.
   Ensuite un cerne demanderait un or, et il n'y a pas d'or dans la palette :
   les dix jetons sont mesurés sur 219 029 pixels des astrophotos et l'or
   « reste à l'intérieur de son médaillon » (MEMOIRE.md, décision 4). En poser
   un ici, ce serait écrire une valeur littérale et changer la DA pour le logo.
   Enfin un halo n'a qu'une couleur disponible, la lampe : un halo rose derrière
   le sceau du client, c'est l'accent qui commente la marque. Non.
   Le sceau est donc posé nu, et le seul geste porté sur lui est le détourage. */
.marque { display: inline-flex; align-items: center; gap: var(--e-2); text-decoration: none; }
.marque--pied { flex-direction: column; align-items: flex-start; gap: var(--e-3); }
.marque__nom {
  font-family: var(--f-display); font-weight: var(--g-display);
  font-size: 1.0625rem; line-height: 1.12; letter-spacing: -.01em; color: var(--texte);
}
.marque--pied .marque__nom { font-size: 1.375rem; }
@media (max-width: 34rem) { .marque__nom { font-size: .9375rem; } }
/* L'INTERLIGNE DU NOM SOUS 24rem, ET C'EST UNE MESURE DE HAUTEUR DE BARRE.
   Replié à quatre lignes, le nom mesure 4 x 16,8 = 67,2 px à l'interligne
   1,12 : il dépasse alors les 64 px du sceau et la barre monte à 91,2 px, ce
   qui décale le héros, dont la hauteur se calcule depuis --h-entete. À 1,04 il
   mesure 62,4 px, il repasse sous le sceau, et la barre garde ses 88 px. Le
   corps du nom, lui, ne bouge pas : c'est le plomb qui se resserre, pas la
   lettre. Mesuré à 300 et 320 px, les deux seules largeurs où le nom atteint
   quatre lignes. */
@media (max-width: 23.99rem) {
  .marque__nom { line-height: 1.04; }
}

/* =========================================================================
   3. BOUTONS — trois niveaux, un seul accent
   ========================================================================= */
.btn {
  display: inline-flex; align-items: center; gap: var(--e-1);
  padding: .7rem 1.2rem; border-radius: var(--r-pill);
  font-size: var(--d-petit); font-weight: var(--g-corps-fort); text-decoration: none;
  border: 1px solid transparent; white-space: nowrap;
  transition: background-color var(--t-ui) ease, color var(--t-ui) ease,
              border-color var(--t-ui) ease, box-shadow var(--t-ui) ease;
}
/* LE BOUTON PRINCIPAL EST BLANC SUR UN FOND DÉDIÉ, ET C'EST UNE CONTRAINTE
   D'ACCESSIBILITÉ, PAS UN GOÛT. Son libellé fait 14 à 15 px en graisse 600 :
   ce n'est pas du grand texte au sens WCAG, le seuil est 4,5:1, et le blanc
   sur --lampe ne donne que 3,51:1. Le fond descend donc à --lampe-bouton
   (blanc 5,60:1), la lampe elle-même ne bouge nulle part ailleurs.
   LE FILET N'EST PAS UN ORNEMENT. --lampe-bouton sur une carte --ciel ne vaut
   que 2,88:1, sous le plancher 3:1 de WCAG 1.4.11 : posé sur un panneau
   d'appel ou une carte produit, l'aplat seul ne suffirait plus à dire qu'il y
   a là un bouton. Le filet de 1 px, déjà réservé par .btn, prend la lampe et
   porte la limite : 5,61:1 sur --nuit, 4,58:1 sur --ciel. La boîte ne bouge
   pas d'un pixel, la bordure était déjà là, en transparent. */
.btn--1 {
  background: var(--lampe-bouton); color: var(--encre-bouton);
  border-color: var(--lampe); box-shadow: var(--ombre-bouton);
}
.btn--2 { border-color: var(--filet-haut); color: var(--texte); }
.btn--3 { padding-inline: 0; color: var(--lampe); }
@media (hover: hover) {
  /* Le survol monte la lampe, mais d'un pas borné : --lampe-bouton-haute est
     un pas du fond vers l'accent, et il s'arrête là où le blanc tomberait
     sous 4,5:1. Mesuré : 4,86:1. L'ancien survol --lampe-haute #FFB3BF
     aurait donné 1,69:1 en blanc, soit un bouton illisible. */
  .btn--1:hover { background: var(--lampe-bouton-haute); box-shadow: var(--ombre-bouton-haute); }
  .btn--2:hover { border-color: var(--texte); }
  .btn--3:hover { color: var(--lampe-haute); }
}
.btn__fleche { width: 14px; height: 14px; flex: none; }

/* =========================================================================
   4. CARTES
   Parade du §5 : la hiérarchie ne repose jamais sur le seul contraste de
   surface (1,22:1). Chaque carte porte EN PLUS un filet 1 px et un
   espacement franc.
   ========================================================================= */
/* LE FILET AU REPOS EST À --filet-haut, ET CE N'EST PAS UN CHOIX D'HUMEUR.
   La carte entière est une cible de lien (.carte__lien::after { inset: 0 }) :
   sa limite est fonctionnelle, pas décorative, et relève du plancher 3:1 de
   WCAG 1.4.11. Mesure : les vignettes du catalogue, même recadrées, plafonnent
   au niveau du fond de page (liserés relevés entre 1,0 et 6,5 pour un --nuit à
   13). La carte ne peut donc pas se détacher par ses propres pixels, et le
   contour doit venir d'ici. --filet #353032 sur --nuit vaut 1,52:1, soit la
   moitié du plancher ; --filet-haut #534648 vaut 2,19:1.
   IL RESTE SOUS 3:1, et ce n'est pas caché : seul --gradue #867678 (4,58:1)
   l'atteindrait, mais un filet de ce poids sur quarante cartes change
   l'équilibre de la page. Cet arbitrage appartient au donneur d'ordre.
   Conséquence obligatoire, les deux règles bougent ensemble : --filet-haut
   était la couleur de survol ; le survol monte donc à --gradue, sans quoi
   l'état de survol cesse d'exister. Aucune valeur littérale n'est ajoutée. */
.carte {
  position: relative;
  background: var(--ciel); border: 1px solid var(--filet-haut);
  border-radius: var(--r); overflow: hidden;
  display: flex; flex-direction: column;
  transition: border-color var(--t-ui) ease, box-shadow var(--t-ui) ease;
}
/* G7 : le cadre garde le format de son capteur. La carte reçoit le ratio
   natif de la prise via --ratio ; aucun recadrage n'est décidé par le CSS. */
.carte__media {
  position: relative; overflow: hidden; background: var(--nuit);
  aspect-ratio: var(--ratio, 3 / 2);
}
.carte__media img, .carte__media picture { width: 100%; height: 100%; }
.carte__media img { object-fit: cover; }
.carte__corps { padding: var(--e-4); display: flex; flex-direction: column; gap: var(--e-2); flex: 1; }
.carte__titre {
  font-family: var(--f-corps); font-size: var(--d-h4);
  font-weight: var(--g-corps-fort); letter-spacing: -.01em; line-height: var(--i-titre);
}
.carte__lien::after { content: ""; position: absolute; inset: 0; }
@media (hover: hover) {
  .carte:has(a:hover) { border-color: var(--gradue); box-shadow: var(--ombre-carte); }
}
.carte:has(a:focus-visible) {
  outline: var(--focus-l) solid var(--focus-couleur); outline-offset: var(--focus-o);
}

/* -------------------------------------------------------------------------
   4 bis. LE PACKSHOT ET LA CARTE DE CATALOGUE

   LA BOÎTE CARRÉE EST L'EXCEPTION ASSUMÉE À LA RÈGLE DE .cadre. Partout
   ailleurs sur ce site, une image garde le format de son capteur et rien
   n'est recadré par le CSS. Le catalogue mélange neuf appareils
   photographiés par cinq marques : des carrés 2000 x 2000, des portraits
   1066 x 2000, des paysages. À format libre, les neuf cartes ne s'alignent
   plus et la page se lit comme une liste d'accidents.

   La réserve est donc commune, et l'image posée dedans en `contain` :
   centrée, jamais recadrée, jamais déformée. C'est le contraire de
   .carte__media, qui recadre en `cover` parce qu'une astrophotographie est
   un plein cadre et qu'un packshot détouré est un objet dans du vide.

   Le fond est un dégradé de --ciel vers --nuit, tokens seuls : la
   profondeur d'un fond de studio, sans une seule surface claire (loi n° 3).
   ------------------------------------------------------------------------- */
.pack {
  position: relative; display: block;
  aspect-ratio: var(--pack, 1 / 1); overflow: hidden;
  background: radial-gradient(115% 92% at 50% 8%, var(--ciel), var(--nuit) 76%);
  border-bottom: 1px solid var(--filet);
}
/* La réserve est posée en absolu, et c'est ce qui la rend HAUTE de façon
   définie. En flux, `height: 100 %` sur le <picture> ne résout rien : le
   parent n'a pas de hauteur définie pour lui, l'image reprend son format
   natif, et un portrait 1066 x 2000 déborde d'une boîte carrée au lieu d'y
   tenir. Posée en `inset`, elle hérite d'une largeur ET d'une hauteur, et
   `contain` fait enfin son travail. Le retrait remplace le padding. */
.pack picture { position: absolute; inset: var(--e-4); display: block; }
.pack img {
  display: block; width: 100%; height: 100%;
  object-fit: contain; object-position: center;
}
/* Un visuel de constructeur pris de jour est le seul du lot à porter du
   ciel clair. Il ne se pose pas nu sur la page : il reste dans sa boîte,
   qui l'encadre, et il est le seul à recevoir un filet complet. */
.pack[data-fond="clair"] { border: 1px solid var(--filet); border-radius: var(--r-s); }

.carte-produit .carte__corps { gap: var(--e-3); }
.carte-produit__marque { display: flex; flex-wrap: wrap; align-items: center; gap: var(--e-2); }
.carte-produit__vitre { display: block; }
.carte-produit__lien {
  color: var(--texte); text-decoration: none;
  transition: color var(--t-ui) ease;
}
@media (hover: hover) { .carte-produit__lien:hover { color: var(--lampe); } }

/* LE PRIX EST LA DEUXIÈME CHOSE QU'ON LIT APRÈS LE NOM. Martian Mono porte
   la donnée, et un prix en est une ; il monte à l'échelle du titre parce
   qu'un catalogue qui cache son prix ne vend pas. */
.carte-produit__prix {
  font-size: var(--d-h3); font-weight: var(--g-mono-fort); color: var(--texte);
  letter-spacing: -.01em;
}
/* La nuance de prix : offre de lancement, déstockage, pack. Elle reste
   sourde, mais elle reste, entière. */
.carte-produit__nuance { color: var(--label); max-width: none; }
.carte-produit__phrase { color: var(--champ); font-size: var(--d-petit); }
/* LE RELEVÉ ET LE PIED SONT POUSSÉS EN BAS ENSEMBLE, et c'est le relevé qui
   porte la poussée : neuf cartes de longueurs inégales alignent ainsi leurs
   neuf filets et leurs neuf boutons, au lieu de laisser le relevé flotter au
   milieu d'une carte courte. */
.carte-produit__releve {
  margin-top: auto;
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--e-2);
  color: var(--label); max-width: none;
  padding-top: var(--e-3); border-top: 1px solid var(--filet);
}
.carte-produit__pied {
  padding-top: var(--e-1);
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--e-2) var(--e-4);
}
/* La carte de catalogue n'a pas de lien étendu : elle porte deux actions
   distinctes, et le halo de focus doit désigner celle qui a le focus, pas
   la carte entière. */
.carte-produit:has(a:focus-visible) { outline: none; }

/* =========================================================================
   5. DONNÉES
   ========================================================================= */
.donnee {
  display: flex; justify-content: space-between; gap: var(--e-3);
  padding-block: var(--e-1); border-bottom: 1px solid var(--filet);
}
.donnee:last-child { border-bottom: 0; }
.donnee dt { color: var(--label); font-size: var(--d-petit); }
.donnee dd {
  font-family: var(--f-data); font-size: var(--d-mono); font-weight: var(--g-mono);
  text-align: right; font-variant-numeric: tabular-nums;
}
/* Grille de caractéristiques : le label en mono, la valeur en corps. */
.specs {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--e-2) var(--e-3); margin: 0; padding-top: var(--e-3);
  border-top: 1px solid var(--filet);
}
.specs div { display: flex; flex-direction: column; gap: .1rem; min-width: 0; }
.specs dt {
  font-family: var(--f-data); font-size: var(--d-mono); font-weight: var(--g-mono);
  color: var(--label); text-transform: uppercase; letter-spacing: .09em;
}
.specs dd { font-size: var(--d-petit); font-weight: var(--g-corps-moyen); }

/* --- Puce ---------------------------------------------------------------- */
.puce {
  /* align-self : sans lui, la puce s'étire sur toute la largeur dès qu'elle est
     enfant d'une pile flex (align-items: stretch l'emporte sur inline-flex). */
  display: inline-flex; align-self: flex-start; align-items: center; gap: .375rem;
  padding: .1875rem .625rem; border-radius: var(--r-pill);
  border: 1px solid var(--lampe-bord); color: var(--lampe);
  font-family: var(--f-data); font-size: var(--d-mono); font-weight: var(--g-mono);
  text-transform: uppercase; letter-spacing: .1em;
}
.puce--sourde { border-color: var(--filet-haut); color: var(--label); }

/* --- En-tête de section -------------------------------------------------- */
.tete { display: flex; flex-direction: column; gap: var(--e-3); max-width: 62ch; align-items: flex-start; }
.tete__brow { display: flex; align-items: center; gap: var(--e-3); }
.tete p { color: var(--champ); font-size: var(--d-lead); line-height: 1.55; max-width: 44ch; }

/* =========================================================================
   6. ACCORDÉON
   ========================================================================= */
.acc { border-top: 1px solid var(--filet); }
.acc__item { border-bottom: 1px solid var(--filet); }
.acc__q {
  width: 100%; display: flex; align-items: center; justify-content: space-between;
  gap: var(--e-4); padding: var(--e-4) 0; text-align: left;
  font-size: var(--d-h4); font-weight: var(--g-corps-moyen); color: var(--texte);
}
.acc__plus { position: relative; width: 16px; height: 16px; flex: none; }
.acc__plus::before, .acc__plus::after {
  content: ""; position: absolute; inset: 50% 0 auto 0; height: 1.5px;
  background: var(--lampe); transition: transform var(--t-ui) ease;
}
.acc__plus::after { transform: rotate(90deg); }
.acc__q[aria-expanded="true"] .acc__plus::after { transform: rotate(0deg); }
.acc__r { display: grid; grid-template-rows: 0fr; transition: grid-template-rows var(--t-panneau) var(--courbe); }
.acc__q[aria-expanded="true"] + .acc__r { grid-template-rows: 1fr; }
.acc__r > div { overflow: hidden; }
.acc__r p { padding-bottom: var(--e-4); color: var(--champ); }

/* =========================================================================
   7. PANNEAU D'APPEL — le bord porte le palier sombre de la lampe, décor seul
   ========================================================================= */
.appel {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--e-4) var(--e-5);
  background: var(--ciel); border: 1px solid var(--lampe-nuit);
  border-radius: var(--r); padding: clamp(1.5rem, 1rem + 2vw, 2.25rem);
}
/* L'APPEL FINAL RESPIRE DES DEUX CÔTÉS. La section qui le porte écrivait son
   air en style en ligne, par le bas seulement : padding-bottom --section,
   padding-top 0. Le panneau se collait donc au bas de la bande qui le
   précède, et tout le vide partait sous lui.
   LA RÈGLE EST ICI, PAS DANS LES GABARITS, et c'est délibéré : l'accueil est
   réécrit en parallèle par un autre lot, et le même panneau ferme aussi
   /telescopes/. Une seule règle les traite tous les deux, et le jour où le
   style en ligne disparaîtra du gabarit elle fournira les deux côtés au lieu
   d'un seul. Le style en ligne, tant qu'il est là, gagne sur le bas et pose
   exactement la même valeur : rien à forcer, aucun !important. */
.section:has(> .contenu > .appel),
.enveloppe:has(> .contenu > .appel) { padding-block: var(--section); }

.appel p { color: var(--champ); max-width: 46ch; }
.appel strong { color: var(--texte); font-weight: var(--g-corps-moyen); }

/* =========================================================================
   8. PIED DE PAGE
   ========================================================================= */
/* L'AIR AU-DESSUS DU PIED ÉTAIT COMPTÉ DEUX FOIS, SUR LES 61 PAGES.
   Chaque page se termine par une section qui porte déjà --section de padding
   bas (150 px à 1440). Le pied ajoutait --section de marge haute par-dessus :
   300 px mesurés entre le dernier bouton et le filet du pied, sur l'accueil
   comme sur À propos. C'est « l'énorme espace entre le CTA et le footer ».
   La marge tombe donc à zéro : l'air appartient à la section qui précède, une
   fois, et le rythme entre le dernier bloc et le pied redevient le rythme
   commun de --section. */
.pied {
  border-radius: var(--r-pied);
  border-top: 1px solid var(--filet);
  margin-top: 0;
}
/* LA GOUTTIÈRE DES COLONNES DESCEND À --e-5, ET SEULE ELLE : mesuré le
   21/09/2026 à 1440 x 900, la grille du pied dispose de 1 240 px de contenu.
   Six colonnes de 11rem (176 px) avec --e-6 (40 px) entre elles en demandent
   6 x 176 + 5 x 40 = 1 256 px : il manque 16 px, auto-fit n'en pose que cinq,
   et la sixième colonne (Ailleurs) tombait seule sur une deuxième rangée, sous
   le bloc de marque, où elle se lisait comme une suite de « by Gus ». Avec
   --e-5 (32 px) : 6 x 176 + 5 x 32 = 1 216 px, les six tiennent sur une rangée
   de 180 px chacune.
   CE QUE CE COMMENTAIRE AFFIRMAIT DE FAUX, ET QUI EST CORRIGÉ LE 21/09/2026 :
   il écrivait « le pied perd 139 px de hauteur (600 -> 461) ». C'est faux. Le
   dépôt à l'état 9dc7ab7^ a été extrait par git archive, servi tel quel et
   balayé de 860 à 1 460 px par pas de 4 : à 1 440 px le pied d'AVANT mesurait
   déjà 461,3 px, sur cinq pistes de 216 px et une seule rangée. Les 600 px
   étaient l'état intermédiaire de ce lot, pas l'état d'avant. Le pied n'a donc
   pas maigri de 139 px : il est revenu à la hauteur qu'il avait.
   LA GOUTTIÈRE VERTICALE NE BOUGE PAS. row-gap reste à --e-6 : à 390, 768 et
   1024 px la grille a deux rangées ou plus, et le rythme vertical du pied n'a
   pas de raison de changer parce qu'une colonne s'est ajoutée. Mesuré : 1 track
   à 390, 3 à 768, 4 à 1024, avant comme après.
   CE QUE ÇA COÛTE, ET C'EST DIT : à 180 px, « Catalogue et Smart Photos »
   (203 px) passe sur deux lignes à 1440. C'est le seul libellé du pied dans ce
   cas, regardé sur planche. */
.pied__grille { display: grid; row-gap: var(--e-6); column-gap: var(--e-5); grid-template-columns: repeat(auto-fit, minmax(min(100%, 11rem), 1fr)); }
/* LA BANDE DES CINQ PISTES EST FERMÉE, ET C'EST LA VRAIE CORRECTION.
   Changer la gouttière n'avait pas supprimé la colonne seule, il l'avait
   déplacée. auto-fit compte les pistes par paliers ; avec six enfants un seul
   compte isole, le cinq : 5 + 1, et le 1 est « Ailleurs », seul en rangée 2
   colonne 1, sous le bloc de marque, où il se lit comme une suite de
   « by Gus ». Mesuré sur l'état 9dc7ab7, balayage de 1 040 à 1 340 px par pas
   de 4 : le défaut court de 1 088 à 1 292 px inclus, 52 largeurs sur 76, et il
   contient 1 152, 1 200 et 1 280. Quatre pistes donnent 4 + 2, trois donnent
   3 + 3, deux donnent 2 + 2 + 2, six donnent une rangée : aucun de ces comptes
   n'isole personne. Il n'y a donc qu'un trou à boucher, et c'est le cinq.
   LES DEUX BORNES NE SONT PAS CHOISIES, ELLES SE CALCULENT, en rem, sans un
   seul pixel littéral, et c'est ce qui les rend justes à toute taille de police
   par défaut. Au-delà de 55,7rem de fenêtre, --marge est à son plafond de
   2,5rem : le contenu vaut donc la fenêtre moins 5rem. auto-fit pose cinq
   pistes tant que le contenu tient entre 5 x 11rem + 4 x 2rem = 63rem et
   6 x 11rem + 5 x 2rem = 76rem, soit une fenêtre de 68rem à 81rem. La requête
   reprend ces deux nombres et rien d'autre ; le .99 est la convention de la
   maison (47.99rem, 61.99rem, 71.99rem plus haut dans cette feuille).
   CE QUE ÇA DONNE, MESURÉ APRÈS CORRECTION : sur la bande, six pistes en une
   rangée, de 141,3 px de large à 68rem à 176 px à 81rem ; zéro colonne seule
   de 320 à 1 920 px par pas de 4 ; zéro débordement en X ; le pied passe de
   597,2 px à 504,9 px à 1 088, à 480,8 px à 1 280, et retrouve 461,3 px dès
   1 292. Ce que ça coûte est dit plus haut : à 141 px, les libellés longs
   passent sur trois lignes au lieu de deux, et c'est ce qui sépare les 504,9 px
   du bas de la bande des 461,3 px du haut. */
@media (min-width: 68rem) and (max-width: 80.99rem) {
  .pied__grille { grid-template-columns: repeat(6, minmax(0, 1fr)); }
}
.pied__titre {
  font-family: var(--f-data); font-size: var(--d-mono); font-weight: var(--g-mono);
  text-transform: uppercase; letter-spacing: var(--l-brow);
  color: var(--label); margin-bottom: var(--e-3);
}
.pied ul { list-style: none; padding: 0; display: flex; flex-direction: column; gap: .25rem; }
.pied a {
  font-size: var(--d-petit); text-decoration: none; color: var(--champ);
  transition: color var(--t-micro) ease;
  /* WCAG 2.2 (2.5.8) : 24 px de cible minimum. Un lien de pied à 21 px échoue. */
  display: inline-flex; align-items: center; min-height: 1.5rem; padding-block: 2px;
}
@media (hover: hover) { .pied a:hover { color: var(--texte); } }
.pied__bas {
  display: flex; flex-wrap: wrap; gap: var(--e-3) var(--e-5);
  justify-content: space-between; align-items: center;
  padding-top: var(--e-5); margin-top: var(--e-7); border-top: 1px solid var(--filet);
  color: var(--label);
}

/* --- Média encadré ------------------------------------------------------- */
.cadre { border-radius: var(--r-media); overflow: hidden; background: var(--nuit); border: 1px solid var(--filet); }
.cadre img { width: 100%; }

/* =========================================================================
   9. L'ENTRÉE EN TROIS TEMPS (demande client du 14/09/2026, carnet §2.1, piste 1)
   « Le logo est frappé par des étoiles qui s'accélèrent de plus en plus, et
   finit sur l'éclipse totale. » Une fois par session, 3 000 ms, dur. Toutes
   les durées, courbes et tailles sont les jetons du bloc ENTRÉE de tokens.css,
   la dérogation nommée au barème ; ici aucune valeur littérale, et les seuls
   nombres sont ceux de la partition elle-même (une échelle, une opacité, un
   pourcentage d'image-clé).

   TROIS ÉTATS DU DOCUMENT, décidés par le script de tête d'inc/entete.php
   avant que cette feuille ne soit lue :
     html sans classe   sans JavaScript. Le calque n'existe pas : la règle de
                        base est display: none, la page est là.
     html.entree-non    session déjà entrée, ou prefers-reduced-motion. Le
                        calque n'existe pas non plus, et PAS UN OCTET de sprite
                        n'est demandé : le calque du HTML est un div vide, la
                        scène n'est construite (inc/pied.php) que sous
                        .entree-joue. Aucun preload, nulle part.
     html.entree-joue   la scène est construite en JavaScript : le sceau (le
                        même fichier que sceau() sert), les étoiles, les éclats,
                        le disque. Tout est décoratif (alt vide, aria-hidden
                        sur le calque entier), rien n'est focalisable, rien ne
                        prend le pointeur, le calque ne porte aucun texte.

   TEMPS 1, 0 -> 1 600 : quatorze étoiles partent de --x / --y, à 140 % de la
   demi-diagonale de la fenêtre, et convergent sur le centre du médaillon en
   ease-in PUR : la vitesse monte jusqu'au contact. Échelle .5 -> 1, opacité
   montée sur les 15 premiers pour cent, mort au contact sur --entree-mort.
   Le sceau ne tourne pas : il encaisse trois fois (--c1, --c2, --c3, les
   instants des trois gros impacts), 1 -> .985 -> 1.008 -> 1 en --entree-choc,
   et rien d'autre.
   TEMPS 2, 1 450 -> 2 350 : gerbes ancrées par leur bord gauche au point de
   choc (elles poussent puis s'éteignent), brisures et étincelles qui partent
   selon la normale sur --dx / --dy et tournent de --r ; toutes DÉCÉLÈRENT,
   à l'inverse des étoiles : l'énergie est dépensée.
   TEMPS 3, 2 250 -> 3 000, RÉÉCRIT LE 15/09/2026 : le disque, une photographie
   de l'auteur (éclipse totale du 12/08/2026), à 155 % du médaillon, entre par
   la gauche, FREINE en --entree-courbe-eclat et S'ARRÊTE centré sur le sceau
   à --entree-t3-arret ; il y tient --entree-t3-tenue à pleine opacité. C'est
   pendant cette tenue, et seulement là, que le FOND du calque (le
   pseudo-élément ::before) et le SCEAU s'effacent : le disque, lui, ne fond
   pas, et la page se découvre AUTOUR d'un cercle noir immobile. Le disque
   seul s'efface ensuite en --entree-eclipse-fin, et le script retire le
   calque à --entree-duree. L'ancienne version (traversée continue, fondu du
   calque entier de 2 700 à 2 900) ne montrait l'éclipse totale que 12 ms, et
   à 13 % d'opacité : mesuré, refusé, remplacé. Le pourquoi et les nombres
   sont dans le bloc ENTRÉE de tokens.css.
   LE FOND EST UN PSEUDO-ÉLÉMENT ET NON LE FOND DU CALQUE parce qu'il doit
   s'effacer sans emporter le disque ; et un pseudo-élément et non un nœud du
   script parce qu'il est peint dès la première image, avant que le script
   n'ait construit quoi que ce soit : pas un éclair de page nue.

   LES DÉCALAGES ET LES POSITIONS SONT DES PROPRIÉTÉS PERSONNALISÉES POSÉES EN
   LIGNE PAR LE SCRIPT : --d (le départ), --x / --y (la position), --a
   (l'angle), --dx / --dy / --r (la course d'un éclat), --c1..3 (les chocs),
   comme --i pour la cadence du site. Les tailles rendues sont les attributs
   width et height des images (la moitié du natif, densité 2). L'invisibilité
   avant le départ n'est pas un fill-mode backwards, qui montrerait la
   première image-clé à sa position de départ : c'est l'opacité de base, 0,
   que la première animation prend en charge dès son départ.

   L'INTERRUPTION (clavier, pointeur, toucher, défilement) est un état du
   calque, .entree-fin : tout à zéro en --t-ui, puis le script le retire.
   ========================================================================= */
#rideau { display: none; }
.entree-joue #rideau {
  display: block; position: fixed; inset: 0; z-index: 900;
  overflow: hidden; pointer-events: none;
}
.entree-joue #rideau::before {
  content: ""; position: absolute; inset: 0; background: var(--nuit);
  animation: entree-meurt var(--entree-t3-tenue) var(--courbe) var(--entree-t3-arret) forwards;
}
.entree-joue #rideau.entree-fin { transition: opacity var(--t-ui) var(--courbe); opacity: 0; }
/* Tout est posé au centre du calque, qui est le centre du médaillon ; la
   propriété translate centre la boîte, la propriété transform est laissée
   entière aux images-clés. */
#rideau .entree__sceau, #rideau .entree__astre, #rideau .entree__eclat,
#rideau .entree__gerbe, #rideau .entree__eclipse {
  position: absolute; top: 50%; left: 50%; translate: -50% -50%; max-width: none;
}
/* Le sceau encaisse trois fois, puis s'efface sous le disque arrêté : les
   trois premières animations tiennent la transformation, la dernière tient
   l'opacité, elles ne se disputent rien. */
#rideau .entree__sceau {
  width: var(--entree-medaillon);
  animation:
    entree-encaisse var(--entree-choc) var(--courbe) var(--c1) none,
    entree-encaisse var(--entree-choc) var(--courbe) var(--c2) none,
    entree-encaisse var(--entree-choc) var(--courbe) var(--c3) none,
    entree-meurt var(--entree-t3-tenue) var(--courbe) var(--entree-t3-arret) forwards;
}
#rideau .entree__astre {
  opacity: 0;
  animation:
    entree-vole var(--entree-vol) var(--entree-courbe-choc) var(--d) forwards,
    entree-meurt var(--entree-mort) linear calc(var(--d) + var(--entree-vol) - var(--entree-mort)) forwards;
}
/* La gerbe est ancrée par son bord gauche : c'est lui qui est au point de
   choc, et c'est autour de lui qu'elle pousse et tourne. */
#rideau .entree__gerbe {
  opacity: 0; translate: 0 -50%; transform-origin: left center;
  animation:
    entree-gerbe var(--entree-gerbe-pousse) var(--entree-courbe-eclat) var(--d) forwards,
    entree-meurt var(--entree-gerbe-eteint) linear calc(var(--d) + var(--entree-gerbe-pousse)) forwards;
}
#rideau .entree__eclat {
  opacity: 0;
  animation: entree-eclate var(--entree-eclat-vol) var(--entree-courbe-eclat) var(--d) forwards;
}
/* Le disque attend hors champ, à gauche, jusqu'à --entree-t3-debut ; il court,
   freine, s'arrête sur le sceau, tient, puis s'efface seul. Les deux
   animations portent l'une la position, l'autre l'opacité. */
#rideau .entree__eclipse {
  width: calc(var(--entree-medaillon) * var(--entree-eclipse));
  transform: translateX(var(--entree-eclipse-de));
  animation:
    entree-passe var(--entree-t3-course) var(--entree-courbe-eclat) var(--entree-t3-debut) forwards,
    entree-meurt var(--entree-eclipse-fin) var(--courbe) calc(var(--entree-t3-arret) + var(--entree-t3-tenue)) forwards;
}
@keyframes entree-vole {
  from { opacity: 0; transform: translate(var(--x), var(--y)) rotate(var(--a)) scale(.5); }
  15%  { opacity: 1; }
  to   { opacity: 1; transform: translate(0, 0) rotate(var(--a)) scale(1); }
}
@keyframes entree-meurt { from { opacity: 1; } to { opacity: 0; } }
@keyframes entree-encaisse {
  from { transform: scale(1); }
  33%  { transform: scale(.985); }
  66%  { transform: scale(1.008); }
  to   { transform: scale(1); }
}
@keyframes entree-gerbe {
  from { opacity: 1; transform: translate(var(--x), var(--y)) rotate(var(--a)) scaleX(.2); }
  to   { opacity: 1; transform: translate(var(--x), var(--y)) rotate(var(--a)) scaleX(1); }
}
@keyframes entree-eclate {
  from { opacity: 1; transform: translate(var(--x), var(--y)) rotate(var(--a)); }
  70%  { opacity: 1; }
  to   { opacity: 0; transform: translate(calc(var(--x) + var(--dx)), calc(var(--y) + var(--dy))) rotate(calc(var(--a) + var(--r))); }
}
/* L'arrivée du disque est translateX(0) : le zéro n'est pas un réglage, c'est
   le centre du médaillon, où la boîte est déjà posée. */
@keyframes entree-passe {
  from { transform: translateX(var(--entree-eclipse-de)); }
  to   { transform: translateX(0); }
}

/* =========================================================================
   10. LA VUE — une photographie de l'auteur, et sa légende
   Aucune valeur littérale : hauteurs, gouttières et couleurs viennent des
   jetons. Aucune photo en fond, aucune opacité réduite : la loi n° 3 et les
   onze contrastes de la recette sont calculés contre --nuit et --ciel PLEINS.

   AUCUN FORMAT N'EST IMPOSÉ AU CADRE. Ce qui est borné, c'est la HAUTEUR
   RENDUE, par l'idiome déjà employé sur .planche : la largeur suit le format
   du capteur, l'image reste entière, on change l'échelle et jamais le
   cadrage. Sans cette borne, le portrait 1 800 × 4 000 servait 2 808 px de
   haut, mesurés au navigateur. Sur un paysage, la borne calculée dépasse
   toujours la colonne : elle n'a aucun effet, et c'est voulu.
   ========================================================================= */
.vue {
  --vue-h: clamp(30rem, 20rem + 30vw, 40rem);   /* 480 -> 640 px */
  margin: 0;
  max-width: calc(var(--vue-h) * var(--ratio, 3 / 2));
}
.vue .cadre { display: block; }
.vue picture { display: block; }
.vue img { display: block; width: 100%; height: auto; }

.vue__legende { margin-top: var(--e-3); display: flex; flex-direction: column; gap: var(--e-1); }
.vue__ligne {
  display: flex; flex-wrap: wrap; justify-content: space-between;
  gap: var(--e-1) var(--e-3); max-width: none;
}
.vue__sujet  { color: var(--texte); }
.vue__date   { color: var(--champ); font-variant-numeric: tabular-nums; }
.vue__source { color: var(--label); max-width: none; }

/* Le bandeau. Un panorama de 8 640 px n'a pas à tenir dans une colonne de
   lecture : il prend toute la largeur du contenu, et sa borne de hauteur
   saute avec lui. */
.vue--bandeau { max-width: none; }

/* Deux vues de formats différents sur une rangée. Chacune reçoit une part de
   largeur proportionnelle à SON format (--fr, servi par vue()), ce qui leur
   donne exactement la même hauteur sans qu'aucune ne soit recadrée : mesuré
   1 009 × 454 et 203 × 451 à 1 440 px. Sous 48 rem elles s'empilent, chacune
   reprenant sa borne de hauteur propre. */
.vues-deux { display: grid; gap: var(--gouttiere); align-items: start; }
@media (min-width: 48rem) {
  .vues-deux { display: flex; align-items: flex-start; }
  .vues-deux > .vue { flex: var(--fr, 1) 1 0; min-width: 0; max-width: none; }
}

/* =========================================================================
   11. L'ABSENCE D'IMAGE, DESSINÉE
   Même grammaire que la graduation vide, et les mêmes jetons : le cadre est
   tracé jusqu'au bout en --filet-haut, rien ne le remplit, l'index reste
   parqué à zéro en --gradue. Jamais une section escamotée, jamais une
   astérisque, et surtout jamais la photo d'un autre appareil pour meubler.

   Ce n'est pas une graduation : une graduation ne mesure que du temps
   d'intégration (§7). C'est un emplacement d'image, vide, à la place et à la
   taille qu'aurait prises la galerie.
   ========================================================================= */
.vide {
  display: grid; align-content: space-between; gap: var(--e-6);
  min-height: clamp(11rem, 6rem + 14vw, 17rem);
  padding: var(--e-5);
  background: var(--nuit);
  border: 1px solid var(--filet-haut); border-radius: var(--r-media);
}
.vide__mot { color: var(--label); max-width: none; }
.vide__piste { position: relative; display: block; width: 100%; height: var(--grad-boite-appareil); }
.vide__piste::before {
  content: ""; position: absolute; left: 0; right: 0;
  top: calc((var(--grad-boite-appareil) - var(--grad-piste-appareil)) / 2);
  height: var(--grad-piste-appareil);
  background: var(--filet-haut); border-radius: 1px;
}
.vide__index {
  position: absolute; left: 0; top: 0;
  width: var(--grad-index); height: var(--grad-boite-appareil);
  background: var(--gradue);
}

/* =========================================================================
   12. LA RONDE DES CONSTRUCTEURS, QUI PORTE LES APPAREILS
   Les cinq marques dont UST est revendeur agréé, chacune avec un ou deux de
   ses télescopes, leur photographie et leur prix public. Demande client du
   14/09/2026 (« en cercle, en mouvement ») puis du 21/09/2026 (« beaucoup
   plus gros, que ça prenne à peu près l'écran [...] un ou deux télescopes par
   marque [...] un CTA en dessous »). Posée en tête de la section des
   télescopes de l'accueil par ronde_constructeurs().

   DEUX FORMES, ET LA BASCULE EST MESURÉE SUR DEUX CÔTÉS, PAS CHOISIE.

   Au large ET AU HAUT, une ORBITE : cinq postes sur un cercle, chacun une
   carte de marque portant ses tuiles d'appareil. Partout ailleurs, une
   GRILLE : les mêmes cinq cartes, en colonnes, immobiles.

   --r-ronde est CALCULÉ (tokens.css) pour que deux cartes voisines ne se
   croisent jamais, à aucun angle de rotation : il majore au plus juste la
   diagonale d'une carte divisée par 2 sin 36°. L'emprise de la ronde vaut
   alors deux rayons plus une carte sur chaque axe, et ce sont ces deux
   nombres qui décident des deux bornes.

   LA BORNE DE LARGEUR, 64rem. L'emprise horizontale doit tenir dans la
   fenêtre.
     à 768 de large, avec la plus petite tuile lisible (6,5rem = 104 px,
       sous quoi « Seestar S30 Pro » ne tient plus en deux lignes),
       l'emprise horizontale vaut 817 px pour 768 de fenêtre et 697 de
       colonne. IL N'Y A PAS DE CERCLE À 768.
     à 1024, elle vaut 817 px pour 944 de colonne : 127 px d'air. C'est la
       première largeur qui tient.

   LA BORNE DE HAUTEUR, 48rem, ET ELLE A ÉTÉ 56rem PENDANT UN LOT. La
   première passe du 21/09 ne posait aucune borne de hauteur et mesurait la
   ronde contre 100vh. Or l'entête du site est `sticky` et haute de --h-nav
   (89 px à toutes les largeurs) : elle est posée SUR le premier écran et ne
   s'en va pas. Mesurée contre --h-utile, l'emprise valait 929 px pour 811 à
   1440 x 900, et 199 à 204 px de la ronde restaient sous l'entête à
   1024 x 768 comme à 1366 x 768. La seconde passe a donc posé 56rem, et
   c'était 896 px de fenêtre : AUCUN PORTABLE COURANT N'EST AU-DESSUS. Le
   donneur d'ordre a vu une grille immobile et a demandé que « ça tourne
   comme le premier ».
   LA TROISIÈME PASSE A RENDU LA CARTE ASSEZ PETITE POUR QUE LA BORNE
   DESCENDE, au lieu d'effacer la borne. Trois mesures l'ont permise : le
   lien d'appareil perd son retrait (le plancher de tuile tombe de 97,2 px,
   fixé par la largeur du prix plus 16, à 84 px, la largeur du prix nue),
   l'air de la carte passe à --air-carte-ronde, et la diagonale se prend par
   hypot() au lieu de se majorer. Emprise à la tuile plancher : 797 px avant,
   660,6 px après, pour 679 px utiles sur un écran de 768. La borne est le
   premier cran rond au-dessus des 749,6 px de fenêtre que 660,6 px
   d'emprise réclament. Sous elle, il n'y a toujours rien à sauver en
   rétrécissant : la tuile est déjà sur la largeur du prix.
   La grille, elle, tient jusqu'en bas : à 390 la colonne fait 345 px, la
   carte de groupe en laisse 311 d'utiles, et deux tuiles de 148 plus leur
   gouttière en font 308. Elle reste la forme du téléphone, et celle de toute
   fenêtre plus basse que 768 px.

   CE QUI NE SE FIGE PAS NE S'ATTRAPE PAS. Un lien qui tourne est un lien
   qu'on rate : l'orbite s'arrête au SURVOL (derrière (hover: hover)) et au
   FOCUS CLAVIER (:focus-within), en plus du bouton de pause, qui reste et
   garde son état en session (WCAG 2.2.2). Le focus suffit donc à figer la
   ronde avant même d'atteindre le bouton : c'est pourquoi celui-ci peut
   rester après la scène dans l'ordre du document.

   LA GÉOMÉTRIE VIENT DE DEUX JETONS ET DE LA DONNÉE. --r-ronde est le rayon ;
   chaque poste reçoit son angle (--a, 72° entre voisins) et son facteur
   d'égalisation de logo (--f, facteurStrict de logos-constructeurs.json) par
   son attribut style, écrits par le composant depuis la donnée, jamais ici.
   Le poste est placé par une transformation FIXE : au centre, tourné de --a,
   poussé d'un rayon, remis droit. L'orbite tourne ; la carte tourne à
   l'envers à la même vitesse, et son contenu reste droit. Deux animations,
   une seule durée, --t-ronde, la dérogation nommée dans tokens.css.

   LA PAUSE EST UN ÉTAT DE LA RONDE, data-pause, posé par le script du pied :
   elle fige l'orbite ET les cinq contre-rotations, sans quoi les cartes se
   coucheraient. Sous prefers-reduced-motion il n'y a rien à figer : aucune
   animation, et le bouton n'est pas rendu. En grille non plus : rien ne
   bouge, et un bouton de pause qui ne met rien en pause serait un mensonge
   d'interface. Sans JavaScript non plus : un bouton qui ne fait rien n'est
   pas rendu.

   LE CENTRE NE PREND PAS LES CLICS : il couvre la scène, et les cartes qui
   entrent dans son carré resteraient sous lui.
   ========================================================================= */
.ronde { display: flex; flex-direction: column; align-items: center; gap: var(--e-4); width: 100%; }

/* ----------------------------------------------- la forme au serré, la grille
   C'est la forme de base : elle est écrite sans requête de média, elle ne
   dépend d'aucun jeton de rayon, et c'est elle qui sert sous 64rem. */
.ronde__scene { position: relative; width: 100%; }
/* LA GRILLE SERT ENCORE LES FENÊTRES BASSES, mais plus les portables : la
   borne de hauteur est passée à 48rem, et 1366 x 768, 1536 x 864, 1280 x 800
   et 1024 x 768 sont en orbite depuis le 21/09/2026. Ce qui suit vaut donc
   pour le téléphone, la tablette, et toute fenêtre de moins de 768 px de
   haut. Le gabarit de colonnes ne bouge pas, et c'est MESURÉ : à 1366 x 768
   (avant la bascule) la colonne faisait 1 238 px
   et tient quatre cartes de 292 px, la cinquième passant à la ligne. Une
   borne à 15rem n'en tiendrait toujours que quatre là (1 238 + 24 pour
   240 + 24 fait 4,78) ; il faudrait descendre à 14rem, et les deux tuiles
   d'une carte tomberaient alors à 89 px, sous le plancher de lisibilité.
   Cinq cartes de front demandent 1 300 px de colonne, que 1366 n'a pas.
   Le 4 + 1 est donc le prix de cartes lisibles, pas un oubli. */
.ronde__orbite {
  display: grid; gap: var(--gouttiere);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
  margin: 0; padding: 0; list-style: none;
}
.ronde__groupe {
  height: 100%;
  display: flex; flex-direction: column; align-items: center; gap: var(--e-3);
  padding: var(--e-3);
  background: var(--ciel); border: 1px solid var(--filet-haut); border-radius: var(--r);
}
/* LE LOGO ET SON LIBELLÉ SONT SUR UNE LIGNE, ET C'EST DE LA GÉOMÉTRIE.
   En colonne, la carte de marque montait de 24 px, et 24 px de hauteur de
   carte se paient 29 px de rayon (le rayon majore la diagonale de la carte,
   tokens.css) et 55 px d'emprise horizontale : la ronde ne tenait plus dans
   une colonne de 1024. Mesuré : carte la plus haute 312 px en colonne,
   289 en ligne. Le libellé reste visible, il n'est pas escamoté. */
.ronde__marque {
  display: flex; flex-direction: row; align-items: center; justify-content: center;
  gap: var(--e-2); padding: var(--e-1); border-radius: var(--r-s);
  color: var(--texte); text-decoration: none;
}
.ronde__logo {
  display: block; width: calc(var(--logo-ronde) * var(--f)); height: auto;
  transition: transform var(--t-ui) var(--courbe);
}
/* DwarfLab n'a pas de couleur propre (fill=currentColor, posé en ligne) : il
   prend l'encre de la page. */
.ronde__logo--encre { color: var(--texte); }
.ronde__nom { font-size: var(--d-petit); line-height: var(--i-titre); color: var(--champ); white-space: nowrap; }

/* Les tuiles d'appareil. justify-content: center pour que la marque qui n'a
   qu'un appareil (Celestron) le pose au milieu de sa carte et non contre un
   bord ; flex-wrap est le filet de sécurité d'une colonne plus étroite que
   deux tuiles au plancher, cas qu'aucune des douze largeurs relevées n'a
   produit. */
.ronde__appareils {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: var(--e-2); margin: 0; padding: 0; list-style: none; width: 100%;
}
/* flex-basis 0 ET NON --tuile-ronde, ET C'EST MESURÉ. Avec la tuile pour
   base, deux tuiles de 152 px plus leur gouttière en demandaient 316 dans
   les 304 px utiles d'une carte à 768 de large : elles passaient à la ligne
   et la carte montait à 522 px de haut. Base zéro, les deux tuiles se
   partagent la rangée (146 px chacune à 768, 148 à 390) et --tuile-ronde
   redevient ce qu'elle est, un PLAFOND : sans lui, la marque qui n'a qu'un
   appareil (Celestron) l'étirerait sur toute la largeur de sa carte. */
.ronde__appareil { flex: 1 1 0; min-width: 0; max-width: var(--tuile-ronde); }
/* LE SÉLECTEUR EST DESCENDANT, ET C'EST MESURÉ. base.css pose
   « li > a:only-child { display: inline-flex; align-items: center;
   min-height: 1.5rem } », la règle de cible de 24 px du site : le lien
   d'appareil est le seul enfant de son <li> et la prenait, spécificité
   (0,1,2) contre (0,1,0). Il passait alors en inline-flex, cessait de
   remplir sa tuile, et la boîte de packshot qui s'étire sur sa largeur
   tombait à 0 x 0 : les neuf photographies ne se rendaient pas. Le lien
   passe devant avec deux classes, et la cible qu'il visait est tenue
   largement : 157 à 199 px de haut, mesurés à 1440, 1024, 768 et 390. */
.ronde__appareil > .ronde__vers {
  display: flex; flex-direction: column; align-items: center; gap: 0;
  padding: var(--e-1); border-radius: var(--r-s); text-align: center;
  color: var(--texte); text-decoration: none;
}
/* La boîte de packshot du site, en petit : le retrait de --e-4 y mangerait la
   moitié de la réserve, et le fond de la carte est déjà --ciel, donc la
   vitre se pose en --nuit pour que l'appareil détouré ait un fond à lui.
   width: 100% rend sa largeur DÉFINIE (le lien est une pile flex, et une
   boîte à aspect-ratio qui n'a qu'une largeur étirée n'y résout pas sa
   hauteur : elle vaut 0). */
.ronde__pack { width: 100%; background: var(--nuit); border: 0; border-radius: var(--r-s); }
.ronde__pack picture { inset: var(--e-1); }
/* DEUX LIGNES RÉSERVÉES AU NOM DE MODÈLE, ET C'EST DE LA GÉOMÉTRIE.
   Des neuf noms rendus, un seul passe à deux lignes à la tuile plancher
   (« Seestar S30 Pro », et « Seestar S50 Pro » avec lui) : sa carte était
   alors 18 px plus haute que les quatre autres, et --carte-ronde-h devait
   majorer ce cas. Un majorant qu'une carte sur cinq atteint fait grandir le
   rayon des cinq. Les deux lignes sont donc réservées pour tous : les cartes
   ont la même hauteur, le jeton la dit exactement, et le rayon ne paie plus
   la carte la plus haute. L'unité est l'em du nom, pas une longueur : la
   réserve suit la police si elle change.
   LE PRIX SE COLLE AU NOM, un seul écart dans la tuile : ils forment un
   bloc, et la photographie est ce dont il faut les séparer. 8 px de moins
   par carte, 14 px de moins d'emprise. */
.ronde__modele {
  font-size: var(--d-petit); line-height: var(--i-titre);
  min-height: calc(2em * var(--i-titre)); margin-top: var(--e-1);
}
.ronde__prix { color: var(--champ); }

.ronde__centre {
  max-width: none; text-align: center;
  font-size: var(--d-mono); line-height: var(--i-mono); color: var(--champ);
}
.ronde__centre .nombre { color: var(--texte); font-weight: var(--g-mono-fort); }
.ronde__fait { display: block; }
.ronde__pause { display: none; }

/* ------------------------------------------------- la forme au large, l'orbite
   Tout ce qui suit ne vaut qu'à partir de 64rem : au-dessous, les règles
   ci-dessus tiennent seules et la ronde est une grille immobile. */
@media (min-width: 64rem) and (min-height: 48rem) {
  /* LA CARTE MAIGRIT EN ORBITE, ET SEULEMENT LÀ. En grille, un pixel de
     hauteur de carte coûte un pixel de page ; en orbite il en coûte 2,12,
     et un pixel de largeur 1,30, mesurés à 1024x768 en grossissant la boîte
     de jeton de 10 px, parce que la carte pousse le rayon par sa diagonale
     avant de s'ajouter au diamètre. La grille garde son aération : elle n'a
     rien à payer.
     TROISIÈME PASSE DU 21/09/2026 : L'AIR DE LA CARTE PASSE À
     --air-carte-ronde. À --e-1 partout, l'emprise à la tuile plancher vaut
     714,4 px pour les 679 px utiles d'un écran de 768 : l'orbite ne tenait
     pas, et c'est ce qui la condamnait à la grille sur tous les portables.
     À --air-carte-ronde elle vaut 660,6 px. Les deux retraits de la carte,
     l'écart entre la rangée de marque et les tuiles, et l'écart entre la
     photographie et son nom sont les quatre emplois du jeton, et
     --carte-ronde-h les compte un par un. */
  .ronde__groupe { padding: var(--air-carte-ronde); gap: var(--air-carte-ronde); }
  /* LA RANGÉE DE MARQUE PERD SON DERNIER RETRAIT, ET C'EST ELLE QUI TIENT LA
     CARTE. Mesuré : sous 97,2 px de tuile, la largeur de la carte ne suit
     plus ses tuiles, elle se bloque sur cette rangée (logo Unistellar
     122,34 px + écart + libellé 71 px). Les 16 px de retrait horizontal et
     les 4 px repris sur l'écart valent donc 20 px de carte, pour un air que
     le retrait de la carte donne déjà. Mesuré à 1024x768 en remettant la
     règle d'avant ET son jeton : 686,9 px d'emprise contre 660,6, soit
     26,3 px, et 13,2 px de rayon.
     Sans retrait vertical, la rangée vaut la hauteur du plus haut des cinq
     logos, 23,9 px pour ZWO à --logo-ronde. --cible-min la remonte à 24 et
     la tient là pour les cinq : la cible de WCAG 2.5.8 est tenue au pixel
     près, et la carte ne paie pas un retrait qu'elle ne voit pas. */
  .ronde__marque { padding: 0; gap: var(--e-1); min-height: var(--cible-min); }
  .ronde__scene {
    width: calc(2 * var(--r-ronde)); height: calc(2 * var(--r-ronde));
    /* UNE DEMI-CARTE DE RÉSERVE DE CHAQUE CÔTÉ, et la première passe s'était
       trompée ici : elle retranchait 0,191 r en bas au motif que les deux
       postes du bas sont à sin 54° du centre. C'est vrai d'une ronde
       ARRÊTÉE ; celle-ci tourne, et chaque poste passe par le point le plus
       bas du cercle une fois par tour. La réserve manquait donc de 56 px en
       bas. */
    margin-block: var(--debord-ronde);
  }
  .ronde__orbite {
    position: absolute; inset: 0; display: block;
    border: 1px solid var(--filet); border-radius: 50%;
    animation: ronde-tourne var(--t-ronde) linear infinite;
  }
  /* LE POSTE N'A PAS DE TAILLE, ET C'EST MESURÉ. Un poste qui aurait la boîte
     de sa carte tournerait avec l'orbite, et sa boîte tournée déborderait de
     la carte restée droite : la page prenait 396 px de défilement à 390 de
     large, pour une boîte invisible. Le poste est donc un point sur l'orbite ;
     c'est la carte, posée sur ce point, qui a une boîte. Elle se centre sur le
     point par la propriété translate, qui se compose AVANT la rotation de son
     animation : elle tourne autour de son propre centre, puis se pose.
     contain: layout N'EST PAS UN CONFORT, C'EST MESURÉ : le navigateur calcule
     le débordement du poste en boîte englobante à chaque étage, et deux
     englobantes d'un rectangle tourné font dépasser la fenêtre. Avec le
     confinement de mise en page, ce débordement est traité comme de l'encre. */
  .ronde__poste {
    position: absolute; top: 50%; left: 50%; width: 0; height: 0;
    contain: layout;
    transform: rotate(var(--a)) translate(var(--r-ronde)) rotate(calc(-1 * var(--a)));
  }
  .ronde__groupe {
    position: absolute; top: 0; left: 0; width: max-content; height: auto;
    translate: -50% -50%;
    animation: ronde-contre var(--t-ronde) linear infinite;
  }
  /* En orbite la carte est en max-content : une base zéro n'y contribuerait
     rien et les tuiles disparaîtraient. La tuile redevient la base. L'écart
     entre les deux tuiles passe de --e-2 à --e-1 : il entre dans la largeur
     de carte, donc dans le rayon. Mesuré à 1920x1080, où les tuiles
     commandent la largeur : 955,8 px d'emprise contre 950,4, soit 5,4 px.
     À la tuile plancher il ne vaut rien, la rangée de marque commandant
     alors la largeur, et c'est pour les grands écrans qu'il est pris. */
  .ronde__appareils { flex-wrap: nowrap; width: auto; gap: var(--e-1); }
  .ronde__appareil { flex: 0 0 var(--tuile-ronde); max-width: none; }
  /* LE LIEN D'APPAREIL PERD SON RETRAIT EN ORBITE, ET C'EST LE LEVIER LE PLUS
     RENTABLE DU LOT. Ses deux --e-1 horizontaux ne coûtaient pas de hauteur
     (la vitre les rendait), mais ils levaient le PLANCHER de la tuile : le
     prix le plus large mesure 81,17 px, et avec 16 px de retrait la tuile ne
     pouvait pas descendre sous 97,2 px sans que le prix se replie sur deux
     lignes. Sans retrait, le plancher tombe à 84 px (5,25rem) ET la
     photographie grandit : la vitre vaut la tuile entière au lieu de la
     tuile moins 16. Relevé à 1440x900 : vitre 88 px avant, 109,8 après.
     Mesuré à 1024x768 en remettant le retrait ET le plancher de tuile qu'il
     impose : 690,8 px d'emprise contre 660,6, soit 30,2 px, pour une vitre
     qui tombait à 81,2 px. C'est le levier le plus rentable du lot, et le
     seul qui rende l'image plus grande en rendant la ronde plus petite.
     L'air visuel ne disparaît pas, il est déjà dans la vitre, dont l'image
     est encartée de --e-1 (.ronde__pack picture). */
  .ronde__appareil > .ronde__vers { padding: 0; }
  /* L'écart entre la photographie et son nom passe à --air-carte-ronde :
     c'est le quatrième emploi du jeton, et --carte-ronde-h le compte. */
  .ronde__modele { margin-top: var(--air-carte-ronde); }
  .ronde__centre {
    position: absolute; inset: 0; display: grid; place-content: center;
    pointer-events: none;
  }
  /* LE BOUTON DE PAUSE ENTRE DANS LE CERCLE, ET C'EST UNE MESURE QUI L'Y MET.
     Posé sous la scène, il ajoutait sa hauteur et sa gouttière (71 px) à
     l'emprise de la ronde : à 1440 x 900, la ronde tenait dans les 811 px
     utiles et son bouton tombait 59 px sous le bord de la fenêtre. Or le
     disque intérieur est vide : les deux faits du centre n'en occupent que
     deux lignes. Le bouton s'y pose, 40 px sous les faits, hors flux : il ne
     coûte plus un pixel de hauteur, il est toujours à l'écran quand la ronde
     y est, et il est au milieu de ce qu'il commande. .ronde__centre le
     laisse passer (pointer-events: none) et le bouton lui est postérieur
     dans le document, donc au-dessus.
     LE DÉGAGEMENT SE MESURE AUX SEPT TAILLES ET SUR LE TOUR, PAS À UNE SEULE
     POSITION : le « 176 px du centre » qu'écrivait ici la deuxième passe ne
     se reproduit à aucune taille. Balayage de 144 angles, point de carte le
     plus proche du centre : 147,4 px à 1920x1080, 142,0 à 1680x1050, 115,2 à
     1440x900, 108,9 à 1536x864, 103,1 à 1280x800, 102,8 à 1366x768 comme à
     1024x768. Le coin le plus lointain de la boîte du bouton, lui, est à
     108,4 jusqu'à 109,4 px du centre.
     LES DEUX BOÎTES SE CROISENT DONC AUX TROIS PLUS PETITES TAILLES, et le
     balayage au quart de degré le chiffre : de 135,50 à 295,75 deg, au pire
     3,18 x 3,19 px (1366x768, angle 136,5). L'ENCRE, ELLE, NE SE TOUCHE PAS,
     et c'est pourquoi rien n'est déplacé : le bouton est une pilule de texte
     et la carte a 16 px de rayon. Sur la zone de croisement, elementFromPoint
     rend .ronde__orbite en ses seize points ; au demi-pixel, la plus courte
     distance entre un point qui rend le bouton et un point qui rend une carte
     vaut 10,61 px à 1366x768, 11,31 à 1280x800, 12,38 à 1024x768. Capture à
     la densité 3 regardée. */
  .ronde { position: relative; }
  .js .ronde__pause {
    display: inline-flex; position: absolute; left: 50%;
    top: calc(var(--debord-ronde) + var(--r-ronde) + var(--e-6));
    translate: -50% 0;
  }
}

@keyframes ronde-tourne { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
@keyframes ronde-contre { from { transform: rotate(360deg); } to { transform: rotate(0deg); } }

/* LES TROIS ARRÊTS. Le bouton pose data-pause sur la ronde ; le focus clavier
   et le survol figent sans rien poser, et sans toucher l'état du bouton : on
   quitte la ronde, elle repart où le bouton l'a laissée. */
.ronde[data-pause="oui"] .ronde__orbite,
.ronde[data-pause="oui"] .ronde__groupe,
.ronde__scene:focus-within .ronde__orbite,
.ronde__scene:focus-within .ronde__groupe { animation-play-state: paused; }

/* Le survol est léger et ne touche que le logo survolé : une échelle de 4 %,
   en --t-ui. Ni couleur, ni opacité : un logo ne se teinte pas. Le survol de
   la scène, lui, arrête tout : le pointeur entre dans la ronde, la ronde
   s'arrête, et la cible ne se dérobe plus. */
@media (hover: hover) {
  .ronde__scene:hover .ronde__orbite,
  .ronde__scene:hover .ronde__groupe { animation-play-state: paused; }
  .ronde__marque:hover .ronde__logo { transform: scale(1.04); }
  /* AU SURVOL D'UNE TUILE, LE NOM S'ALLUME ET SE SOULIGNE. La couleur seule
     tenait, mais de justesse : --lampe sur --ciel vaut 4,58:1 pour un seuil
     de 4,5. Le soulignement ne dépend d'aucune marge de contraste et c'est
     l'affordance de lien du site ; la couleur reste, mesurée, elle n'est
     plus seule à porter l'état. */
  .ronde__vers:hover .ronde__modele { color: var(--lampe); text-decoration: underline; }
}

@media (prefers-reduced-motion: reduce) {
  .ronde__orbite, .ronde__groupe { animation: none; }
  .ronde__logo { transition: none; }
  .js .ronde__pause { display: none; }
}

/* =========================================================================
   13. LE MÉGA MENU (demande client du 22/09/2026 : « mise en place d'un méga
   menu afin de pouvoir optimiser la recherche d'éléments »)

   C'EST UN <details>, ET AUCUNE LIGNE DE CETTE RUBRIQUE NE L'OUVRE. Le
   navigateur tient l'état, l'annonce, et retire le contenu de la séquence de
   tabulation quand il est replié. Sans JavaScript, tout fonctionne. Les
   26 lignes du pied n'ajoutent que trois courtoisies (Échap, et l'exclusion
   mutuelle avec les deux autres panneaux), jamais l'ouverture elle-même.

   CE QUI EST ÉCRIT AU SERRÉ EST LE DÉFAUT, ET C'EST VOULU. Sous 75rem le
   déclencheur est une rangée du panneau du burger, parce que .nav__liens y
   quitte la barre : le méga menu descend avec lui et ne coûte RIEN à la barre.
   Le large est la surcharge, dans @media (min-width: 75rem) plus bas.

   LE PANNEAU EST EN POSITION ABSOLUE SOUS LA BARRE, jamais dans son flux : la
   barre garde ses 88 px ouverte comme fermée. C'est ce que le motif retiré de
   D26 croyait impossible ; le relevé aux 14 largeurs et dans les 7 langues est
   au §3 de _design/MEGA-MENU-ETAT.md.

   AUCUN JETON NEUF. Espacements, durées et couleurs sortent tous de
   tokens.css. Contrastes calculés sur --ciel, le fond du panneau : --champ
   7,08, --label 6,49, --texte 13,24, tous au-dessus des 4,5 exigés. --gradue
   n'y est PAS employé : il y tombe à 3,74, et c'est la raison pour laquelle le
   prix est en --label et non en --gradue.
   ========================================================================= */

/* Le triangle par défaut disparaît des trois façons qu'il faut : display
   autre que list-item suffit à Blink, ::-webkit-details-marker à WebKit,
   ::marker au reste. */
.mega { position: static; }
.mega__decl { list-style: none; }
.mega__decl::-webkit-details-marker { display: none; }
.mega__decl::marker { content: ""; }

.mega__decl {
  display: flex; align-items: center; gap: var(--e-2);
  cursor: pointer; color: var(--champ);
  font-size: 1rem; font-weight: var(--g-corps-moyen);
  padding-block: var(--e-3);
  border-bottom: 1px solid var(--filet);
  transition: color var(--t-micro) ease;
}
.mega__decl:focus-visible {
  outline: var(--focus-l) solid var(--focus-couleur); outline-offset: var(--focus-o);
}
@media (hover: hover) { .mega__decl:hover { color: var(--texte); } }
.mega__glyphe { width: 1.375rem; height: 1.375rem; flex: none; }

.mega__panneau { padding-block: var(--e-3) var(--e-4); }
.mega__grille { display: grid; gap: var(--e-5); padding-inline: 0; }
.mega__grp { display: grid; align-content: start; gap: var(--e-2); }

/* L'intertitre de colonne a la forme de celui du pied : c'est le même office
   sur le même site, et deux dessins pour une même fonction est une dette. */
.mega__titre {
  font-family: var(--f-data); font-size: var(--d-mono); font-weight: var(--g-mono);
  text-transform: uppercase; letter-spacing: var(--l-brow);
  color: var(--label); text-decoration: none;
  display: inline-flex; align-items: center; min-height: 1.5rem;
  transition: color var(--t-micro) ease;
}
@media (hover: hover) { a.mega__titre:hover { color: var(--texte); } }
.mega__titre:focus-visible {
  outline: var(--focus-l) solid var(--focus-couleur); outline-offset: var(--focus-o);
}
/* Le deuxième intertitre d'une colonne (le forum sous les outils) reprend de
   l'air : sans lui les deux listes se lisent comme une seule. */
.mega__grp > .mega__titre ~ .mega__titre { margin-top: var(--e-3); }

.mega ul { list-style: none; padding: 0; margin: 0; }
.mega__sous {
  display: inline-flex; align-items: center; min-height: 1.5rem;
  font-size: var(--d-petit); font-weight: var(--g-corps-fort); color: var(--label);
  text-decoration: none; transition: color var(--t-micro) ease;
}
@media (hover: hover) { a.mega__sous:hover { color: var(--texte); } }
.mega__sous:focus-visible {
  outline: var(--focus-l) solid var(--focus-couleur); outline-offset: var(--focus-o);
}
/* Un sous-groupe et le suivant : l'air du pied entre deux colonnes, appliqué
   ici entre deux piles. */
.mega__pile > li + li, .mega__colonnes > li + li { margin-top: var(--e-2); }

/* LA CIBLE FAIT 2,25rem AU SERRÉ (36 px), ET C'EST UN ARBITRAGE ÉCRIT. La
   2.5.8 demande 24 px ; les contrôles principaux du site en font 44. Un menu
   de 81 liens à 44 px mesurerait 3 564 px de déroulé sur un téléphone. 36 px
   tient la moitié du chemin, reste à 50 % au-dessus du plancher de la norme,
   et garde le panneau parcourable. Au large la cible revient à la mesure du
   pied, 1,5rem plus deux fois --e-1 de retrait. */
/* LE SÉLECTEUR PORTE « li > a » ET CE N'EST PAS DU ZÈLE. base.css:312 pose
   « li > a:only-child { display: inline-flex } » pour garantir 24 px de cible
   aux liens isolés d'une liste ; sa spécificité (0,1,2) bat une simple classe,
   et le lien du menu se rétrécissait à son texte : le prix se collait au nom
   au lieu d'aller au bord, et « ≈ 200 € en pack Essentiel » se repliait dans
   une boîte de 161 px alors que la colonne en fait 272. Le sélecteur égale
   cette spécificité ; composants.css étant chargée après base.css, il gagne. */
li > a.mega__lien {
  display: flex; align-items: baseline; justify-content: space-between;
  flex-wrap: wrap; gap: var(--e-1);
  font-size: var(--d-petit); text-decoration: none; color: var(--champ);
  min-height: 2.25rem; padding-block: var(--e-1);
  transition: color var(--t-micro) ease;
}
@media (hover: hover) { .mega__lien:hover { color: var(--texte); } }
.mega__lien:focus-visible {
  outline: var(--focus-l) solid var(--focus-couleur); outline-offset: var(--focus-o);
}
/* --label et non --gradue : sur --ciel, --gradue vaut 3,74 pour 4,5 exigés. */
.mega__prix { color: var(--label); font-size: var(--d-mono); }

/* --- Le large : le déclencheur rejoint l'amas d'icônes -------------------- */
@media (min-width: 75rem) {
  /* 36 px de glyphe, exactement la cible de la loupe et du buste. */
  .mega__decl {
    display: grid; place-items: center;
    width: 2.25rem; height: 2.25rem;
    padding-block: 0; border-bottom: 0; gap: 0;
  }
  /* Le mot reste le nom accessible du déclencheur, invisible à l'oeil : au
     large la barre n'a pas la place d'un septième libellé, c'est la mesure du
     §5 de _design/RECHERCHE-ETAT.md et elle n'a pas changé. Les propriétés
     sont celles de .u-sr, écrites ici parce qu'une classe ne se pose pas sous
     condition de largeur. */
  .mega__mot {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap;
  }
  /* Hors du flux de la barre. 100svh et non 100vh : sur un mobile à barre
     d'adresse rétractable, 100vh vaut la fenêtre dépliée (tokens.css:249). */
  .mega__panneau {
    position: absolute; top: 100%; left: 0; right: 0;
    background: var(--ciel); border-bottom: 1px solid var(--filet);
    max-height: calc(100svh - var(--h-nav)); overflow-y: auto;
    overscroll-behavior: contain;
    padding-block: var(--e-5) var(--e-6);
  }
  /* La grille se cale sur la barre : même --contenu, même --marge, si bien
     que la première colonne s'aligne sur le sceau. */
  .mega__grille {
    grid-template-columns: repeat(5, minmax(0, 1fr));
    column-gap: var(--e-4); row-gap: var(--e-5);
    max-width: var(--contenu); margin-inline: auto; padding-inline: var(--marge);
  }
  /* CINQ PISTES, ET LE CATALOGUE EN PREND TROIS. Ce n'est pas un choix de
     goût : c'est la SEULE des douze combinaisons mesurées qui fasse tenir le
     panneau entier dans une fenêtre de 800 px de haut. Le catalogue porte 41
     objets et 11 désignations là où les deux autres groupes en portent 17 et
     8 : sa hauteur commande tout.
     LA MATRICE, RELEVÉE (.recette/megamenu/sorties/essai-grille.txt), en
     hauteur de panneau à 1440 x 900 puis à 1280 x 800, où 812 et 712 px sont
     disponibles sous la barre :

       pistes  catalogue  sous-col  familles      1440    1280   replis
            4          2         2  insécables     806     805        1
            4          2         2  sécables       806     805        1
            4          2         3  insécables   1 121   1 114       21
            4          2         3  sécables       737     733       21
            5          3         2  insécables     806     805        1
            5          3         2  sécables       806     805        1
            5          3         3  insécables     953     949       10
            5          3         3  sécables       647     645       10   <-
            6          4         2  insécables     806     805        5
            6          4         2  sécables       806     805        5
            6          4         3  insécables     809     808        7
            6          4         3  sécables       745     742        7

     DEUX CHOSES SE LISENT LÀ-DEDANS. La première : à deux sous-colonnes, la
     hauteur ne bouge pas d'une piste à l'autre (806 px partout), parce que ce
     qui la fixe n'est pas la largeur mais le partage en deux d'un contenu de
     1 606 px. La seconde : break-inside: avoid sur la famille « Nébuleuses »,
     27 objets d'un seul tenant, lui fait imposer sa hauteur à la colonne dès
     qu'on passe à trois sous-colonnes. Les familles sont donc SÉCABLES, et
     l'intertitre porte break-after: avoid pour ne jamais rester seul en pied
     de colonne : contrôlé, 0 orphelin dans les douze combinaisons.
     CE QUE ÇA COÛTE, ET C'EST DIT : les sous-colonnes tombent de 272 à 213 px
     et 10 des 81 libellés passent sur deux lignes. C'est le prix d'un menu
     qu'on voit en entier plutôt qu'un menu qu'on fait défiler. */
  .mega__grp--large { grid-column: span 3; }
  .mega__colonnes { columns: 3; column-gap: var(--e-4); }
  .mega__colonnes > li { margin-bottom: var(--e-3); }
  .mega__colonnes > li + li { margin-top: 0; }
  .mega__colonnes .mega__sous { break-after: avoid; }
  /* LA CIBLE REDESCEND À 1,5rem PILE, sans retrait, et c'est ce qui décide de
     la hauteur du panneau. Avec --e-1 de retrait haut et bas, la rangée faisait
     36 px et le panneau 1 217 px pour 812 disponibles à 1440 x 900 : un méga
     menu qui défile sur un écran de bureau. Sans retrait, la rangée vaut
     l'interligne du corps, 24 px, soit la cible de la 2.5.8 au pixel près et la
     mesure même des liens du pied. */
  /* MÊME SÉLECTEUR QU'AU BLOC DE BASE, et pour la même raison : une classe
     seule (0,1,0) ne bat pas « li > a:only-child » de base.css:312, et le
     retrait de --e-1 restait posé. Rangée mesurée à 40 px au lieu de 24, et
     panneau à 913 px au lieu de 647. */
  li > a.mega__lien { min-height: 1.5rem; padding-block: 0; }
  /* Les numéros de catalogue sont courts : deux par ligne plutôt qu'une
     colonne de onze lignes de quatre signes. */
  .mega__numeros { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--e-2); }
}

/* LA GOUTTIÈRE ENTRE .nav__liens ET .nav__outils TOMBE À --e-1, ET C'EST LA
   MESURE QUI PAIE LE MÉGA MENU. Le déclencheur est le dernier enfant de
   .nav__liens : il coûte son glyphe (36 px) plus la gouttière de la rangée.
   En reprenant 16 px sur la gouttière qui sépare les deux groupes, le total
   retombe à 44 px, exactement ce qu'a coûté la loupe, et les trois glyphes
   forment un seul amas à droite au lieu de trois îlots.
   Le pire cas mesurable, le portugais, demandait 1 099 px pour 1 160
   disponibles au plateau : il en demande 1 143 après, et il reste 17 px.
   Le relevé est au §3 de _design/MEGA-MENU-ETAT.md. */
@media (min-width: 80rem) {
  .nav__outils { margin-inline-start: calc(var(--e-1) - var(--e-4)); }
}
