.sh,.sh *{box-sizing:border-box}
.sh p{margin:0}
/* LA GRILLE DE PRIX A UNE SEULE UNITE, ET CE N'EST PAS L'EM LOCAL.
   Elle etait ecrite deux fois dans deux corps differents: la case en `3.4em` de
   la CASE, l'intitule en `6.8em` d'un `.cols` a `.5em`. Tant que personne ne
   touchait au corps des prix les deux tombaient sur 3,4 corps et l'accord
   passait pour acquis. Or 32 habillages composent leurs prix a leur taille
   (m06 `.82em`, g03 `.92em`, m106 `.95em`, m111 `.94em`), et un `min-width` en
   em suit ce corps-la: la case de m06 mesurait 2,79 corps sous un intitule de
   3,40, et aucun reglage d'habillage ne pouvait les reconcilier puisque le
   defaut etait dans l'unite, pas dans la valeur. Meme famille que la gouttiere
   qui se lit dans l'em du voisin.
   Les deux grilles se declarent donc ici, une fois, dans l'unite de la FEUILLE
   -- le corps vaut `var(--fs) * var(--fsk) * var(--u)` -- et plus rien ne les
   desaccorde. Un habillage garde le droit de choisir la taille de ses chiffres;
   il n'a plus celui de deplacer la colonne. */
.sh{--u:2.35px;--w:210;--h:297;--pad:15;--cols:1;--fs:3.4;--gap:9;--lead:.34;--gsp:1.1;
  --corps:calc(var(--fs) * var(--fsk,1) * var(--u));
  --pcol:calc(3.4 * var(--corps));--rgut:calc(.6 * var(--corps));--pgut:calc(1 * var(--corps));
  width:calc(var(--w) * var(--u));height:calc(var(--h) * var(--u));
  padding:calc(var(--pad) * var(--u));font-size:calc(var(--fs) * var(--fsk,1) * var(--u));
  display:flex;flex-direction:column;position:relative;overflow:hidden;
  box-shadow:16px 22px 44px -20px rgba(36,26,22,.5),0 2px 8px rgba(36,26,22,.14)}
.f-a3-portrait{--w:297;--h:420;--pad:18;--cols:2;--fs:3.60;--gap:12;--lead:.34;--gsp:1.10}
.f-a3-paysage{--w:420;--h:297;--pad:18;--cols:3;--fs:3.60;--gap:12;--lead:.34;--gsp:1.10}
.f-a4-portrait{--w:210;--h:297;--pad:15;--cols:1;--fs:3.40;--gap:9;--lead:.34;--gsp:1.10}
.f-a4-paysage{--w:297;--h:210;--pad:14;--cols:2;--fs:3.40;--gap:11;--lead:.34;--gsp:1.10}
.f-a5-portrait{--w:148;--h:210;--pad:11;--cols:1;--fs:3.15;--gap:0;--lead:.34;--gsp:1.00}
.f-a5-paysage{--w:210;--h:148;--pad:11;--cols:2;--fs:3.15;--gap:9;--lead:.34;--gsp:1.00}
.f-a6-portrait{--w:105;--h:148;--pad:8;--cols:1;--fs:2.95;--gap:0;--lead:.32;--gsp:.90}
.f-a6-paysage{--w:148;--h:105;--pad:8;--cols:2;--fs:2.95;--gap:7;--lead:.32;--gsp:.90}
.f-carre{--w:210;--h:210;--pad:13;--cols:2;--fs:3.15;--gap:8;--lead:.34;--gsp:1.00}
.f-dl{--w:99;--h:210;--pad:9;--cols:1;--fs:3.15;--gap:0;--lead:.34;--gsp:1.00}
.f-livret-a4{--w:210;--h:297;--pad:15;--cols:1;--fs:3.40;--gap:9;--lead:.34;--gsp:1.10}
.r-serre{--fsk:.92}
.r-normal{--fsk:1}
.r-large{--fsk:1.22}
.sh .hd{flex:none}
.sh .hd .lg{display:flex;align-items:center;justify-content:center}
.sh .hd .lg img{display:block;max-width:100%;max-height:5.4em;width:auto;height:auto}
.sh .bd{flex:1;display:flex;gap:calc(var(--gap) * var(--u));min-height:0}
.sh .col{flex:1 1 0;min-width:0;display:flex;flex-direction:column;justify-content:safe center}
.sh .bd-1{justify-content:center}
.sh .bd-1>.col{flex:0 1 calc((100% - (var(--cols) - 1) * var(--gap) * var(--u)) / var(--cols))}
.sh .grp{display:flex;flex-direction:column;justify-content:flex-start;
  gap:calc(var(--lead) * 1em);flex:0 0 auto}
.sh .gp{flex:1 1 0;min-height:calc(var(--gsp) * 1em);max-height:calc(var(--gsp) * 3.2em)}
.sh .gp-t{min-height:0}
/* L'ALIGNEMENT VERTICAL NE DEPEND PLUS DU NOMBRE DE COLONNES.
   Il en dependait: `.col:not(:only-child)` calait en haut les pages a plusieurs
   colonnes, pendant qu'une page a une seule colonne se centrait. Or le nombre
   de colonnes EFFECTIVES varie d'une page a l'autre de la MEME carte -- il suit
   le contenu, pas le modele. Resultat signale le 2026-08-01 sur g02, m08 et
   m16: page 1 calee en haut, pages 2 et 3 centrees, sur la meme carte, sans que
   rien ne l'explique au lecteur.
   L'exception est retiree: le mou part d'abord dans les ressorts `.gp` (la
   regle de la maison, le blanc va aux ruptures de section), et ce qui reste se
   partage au-dessus et en dessous. L'alignement est donc une propriete du
   MODELE (`j-haut`, `j-centre`, ou la repartition par defaut), jamais du hasard
   du contenu. */
.sh.j-haut .col{justify-content:flex-start}
.sh.j-centre .col{justify-content:safe center}
.sh.j-centre .gp{flex:1 1 0;min-height:calc(var(--gsp) * 2.4em);max-height:calc(var(--gsp) * 4.2em)}
.sh.j-centre .gp-t{display:none}
.sh .it{flex:none}
.sh .ft{flex:none}
.sh .ft p{margin:0}
.sh .ft .hr{font-style:italic;font-weight:400;line-height:1.4;opacity:.72;font-size:max(calc(2.2 * var(--u)),.74em)}
.sh .ln{display:flex;align-items:baseline;line-height:1.32}
.sh .ln .t{flex:0 1 auto;padding-left:var(--puce,0)}
.sh .ln .t::before{margin-left:calc(-1 * var(--puce,0))}
.sh .ln .l{flex:1 1 auto;min-width:1em;margin:0 .5em;border-bottom:1px dotted currentColor;
  opacity:.45;transform:translateY(-.26em)}
.sh .ln .p{flex:none;font-variant-numeric:tabular-nums;font-weight:600}
.sh .dsc,.sh .nt,.sh .ac{opacity:.72;line-height:1.35;font-size:max(calc(2.5 * var(--u)),.8em)}
.sh .dsc,.sh .nt{padding-right:2.2em}
.sh .nt-bas{margin-top:.25em}
.sh .ac{font-style:normal;margin-left:.42em}
/* LE NOM ACCROCHE NE PREND PAS LA PLACE DU FILET, IL PREND CE QU'IL LUI FAUT.
   La regle valait `flex:1 1 auto`, posee en croyant qu'un nom suivi de sa
   garniture remplissait toujours la ligne: le filet n'aurait alors plus rien a
   parcourir. C'est faux des que l'accroche est courte. Le nom et le filet ayant
   le meme `flex-grow`, ils se partageaient le blanc a parts egales, et le filet
   demarrait au MILIEU du vide au lieu de partir du texte -- 107 px de trou en
   mediane sur les 62 lignes accrochees de la vitrine, soit pres du quart de la
   colonne. Vu sur m41: « Cidre brut fermier 75 cl a partager » et « Chouchen
   hydromel breton ».
   Le nom reprend donc le meme reglage que la ligne ordinaire, et seul
   `min-width:0` reste: lui n'est pas decoratif, il autorise le nom a passer
   sous sa largeur de plus long mot au lieu de sortir de la feuille (piege
   P54). */
.sh .ln-ac .t{flex:0 1 auto;min-width:0}
.sh .row{display:flex;align-items:baseline;gap:var(--rgut);line-height:1.3}
.sh .row .nm{flex:1 1 auto;min-width:0}
.sh .row .lc{display:block;font-size:.74em;font-style:italic;opacity:.75;margin-top:.05em}
/* LA CASE DE PRIX EST UN PLANCHER, PAS UNE LARGEUR FIXE.
   Elle valait `width:3.4em; flex:none`, taillee pour « 12,50 ». C'est juste
   tant qu'un prix est un nombre -- et il ne l'est pas: le contrat dit qu'il est
   une CHAINE, et le releve des vraies cartes a sorti « selon arrivage »,
   « offert », « au poids ». Une chaine plus large que 3,4em ne rentrait pas et
   ne se repliait pas non plus (`.pu` est en `nowrap`): elle sortait de la case,
   de la colonne, puis du papier. Vu sur la planche de tirage, deux cartes sur
   vingt, dont un carre a deux colonnes de prix ou le texte passait par-dessus
   la colonne voisine.
   `min-width` garde la grille INTACTE la ou elle sert -- deux prix de meme
   largeur restent alignes au pixel, puisqu'un nombre est toujours plus etroit
   que le plancher -- et laisse la case grandir dans le seul cas ou elle etait
   fausse. Le nom, lui, est deja elastique (`.nm{flex:1 1 auto;min-width:0}`):
   c'est lui qui cede la place, et c'est le bon ordre, un nom se replie, un prix
   ne se coupe pas. */
.sh .row .pv,.sh .row .pb{flex:0 0 auto;min-width:var(--pcol);text-align:right;font-weight:600;
  font-variant-numeric:tabular-nums}
/* UN PRIX A PLUSIEURS VALEURS NE SE RETRACTE PAS SOUS SON CONTENU. Il etait
   `flex:0 1 auto` avec un plafond de 11em: en colonne etroite il se faisait
   comprimer jusqu'a sa largeur minimale et « 3 / 3,50 » sortait de la boite,
   `.pu` etant en nowrap. C'est le nom qui doit ceder, il est elastique. */
.sh .row .pb.pm,.sh .row .pb.pn-u{width:auto;max-width:none;flex:0 0 auto}
/* DEUX PRIX COTE A COTE DEMANDENT PLUS D'AIR QUE LE RESTE DE LA RANGEE.
   La gouttiere valait `.6em`, celle du nom au prix, parce que c'est le gap de
   `.row`. Sous des chiffres, ce n'est pas la meme distance: 0,60 em entre
   « 8,00 » et « 42,00 » se lit comme un seul nombre des que l'habillage compose
   ses prix en gras et un peu grand -- verdict du owner sur g03, « illisible »,
   et sur m06, « pas loin d'etre difficile a lire ». Sur m111, dont les prix
   sont fins et petits, la meme gouttiere passe. Ce n'est donc pas l'habillage
   qui a tort, c'est la gouttiere qui etait reglee sur le mauvais voisin: un
   blanc entre deux CHIFFRES separe deux valeurs, un blanc entre un nom et un
   prix ferme une ligne, et les deux ne valent pas pareil.
   1 em, et seulement en grille: le `margin-left` porte la premiere gouttiere
   (celle que `.row` donnait), le `gap` porte les suivantes. La rangee ordinaire
   ne bouge pas, et le nom, elastique, cede les 0,4 em. `.cols` porte le meme
   1 em, sinon l'entete cesse de coiffer ses colonnes. */
.sh .row .pb.pg{display:flex;gap:var(--pgut);width:auto;max-width:none;flex:none}
/* LA GOUTTIERE DE GRILLE SE POSE SUR LE VOISINAGE, PAS SUR LA CLASSE.
   Elle etait sur `.pb.pg`, et `.pg` n'est ecrite qu'a partir de TROIS colonnes:
   `mp_render_rangee()` retire la premiere valeur pour la colonne de gauche
   avant de compter, donc un couple verre/bouteille -- le cas courant, celui de
   toutes les cartes des vins -- tombait dans le `else` avec une seule valeur
   restante et n'etait pas marque grille. La gouttiere valait alors celle de
   `.row`, 0,6, sous un entete espace de 1: 0,40 de decalage, mesure identique
   sur les quatre modeles, et invisible a la relecture du CSS puisque la regle
   avait l'air juste.
   La condition qui compte n'est pas le nombre de colonnes, c'est qu'il y ait un
   VOISIN A GAUCHE: `.pv` n'est emis que lorsqu'une colonne de gauche est
   servie. Deux cases de prix cote a cote prennent donc la gouttiere de grille,
   qu'elles soient deux ou quatre, et une rangee a prix unique garde la sienne. */
.sh .row .pv+.pb{margin-left:calc(var(--pgut) - var(--rgut))}
/* LA CORRECTION OPTIQUE DE LA COLONNE DE GAUCHE, et c'est bien une correction,
   pas un alignement. Les deux bords droits coincident au pixel depuis
   aujourd'hui, et le owner voit pourtant les chiffres « tres legerement
   decales vers la droite » par rapport a leur intitule. Il a raison, et la
   mesure ne peut pas l'attraper: un chiffre porte moins d'approche a droite
   qu'une lettre bas-de-casse, et un intitule en capitales espacees en porte
   encore plus (`letter-spacing` ajoute son cran APRES la derniere lettre).
   L'oeil compare des masses, l'instrument compare des boites.
   Le decalage vaut donc l'ordre de grandeur d'une approche, pas une valeur en
   pixels: 1 a 2 px a 3,4 px/mm, ecrits en unite de feuille pour que la
   correction tienne a la vignette comme au PDF 300 dpi -- en px fixes elle
   dispararaitrait a l'impression et creverait les yeux sur une vignette.
   Elle ne touche que la colonne de gauche: la derniere case est calee sur le
   bord du corps, ou aucun intitule ne la suit et ou la deplacer se verrait. */
.sh .row .pv{transform:translateX(calc(-.12 * var(--corps)))}
.sh .row .pb.pg .pu{min-width:var(--pcol);flex:0 0 auto}
.sh .row .pb.pg .pu+.pu::before{content:none}
.sh .pu{white-space:nowrap}
/* UN PRIX QUI PORTE SON LIBELLE N'EST PAS UNE CASE DE GRILLE.
   La famille `table` aligne les prix en cases de 3.4em, et c'est ce qui fait
   que deux colonnes de prix se lisent l'une sous l'autre. Un libelle propre a
   la ligne (« le verre », « la bouteille ») ne tient pas dans 3.4em: il sortait
   de la case, puis de la feuille, jusqu'a 12 mm en DL. La case redevient donc
   elastique des qu'elle porte un libelle, et le groupe se replie plutot que de
   sortir. La grille reste intacte partout ailleurs, c'est-a-dire au cas ou les
   colonnes sont nommees UNE fois en tete par `colonnes_prix`. */
.sh .row .pv:has(i){width:auto;flex:0 1 auto;min-width:0}
.sh .row .pv>i{font-style:normal;font-weight:400;font-size:.78em;opacity:.7;margin-right:.28em}
.sh .row .pb:has(.pu>i){width:auto;max-width:none;flex:0 1 auto;min-width:0;
  display:flex;flex-wrap:wrap;justify-content:flex-end;gap:0 .5em}
.sh .row .pb:has(.pu>i) .pu{width:auto;flex:0 1 auto}
/* DEUX VALEURS DE PRIX SE REPLIENT, ELLES NE SORTENT PAS DE LA COLONNE.
   `.p` etait en `flex:none`, donc large comme son contenu quoi qu'il arrive:
   « le verre 8 / la bouteille 38 » poussait le nom puis sortait de la colonne
   et se posait sur le texte de la colonne voisine. Le rendre elastique ne
   suffit PAS: entre `</span><span class="pu">` il n'y a aucune espace, donc
   aucune occasion de coupure, et un `white-space` ne s'invente pas une. Les
   valeurs deviennent donc des ELEMENTS FLEX, qui se replient sans rien devoir
   au texte. La barre de separation tombe dans ce cas: deux libelles la rendent
   inutile, et une ligne qui commencerait par « / » se lit mal. */
.sh .ln .p:has(.pu+.pu){flex:0 1 auto;min-width:0;text-align:right;
  display:flex;flex-wrap:wrap;justify-content:flex-end;gap:0 .6em}
.sh .ln .p:has(.pu+.pu) .pu+.pu::before,
.sh .row .pb:has(.pu>i) .pu+.pu::before{content:none}
.sh .pu+.pu::before{content:"/";margin:0 .28em 0 .34em;font-weight:400;opacity:.5}
.sh .pu i{font-style:normal;font-weight:400;font-size:.78em;opacity:.7;margin-right:.28em}
.sh .fp{margin:.35em 0 1.05em;font-weight:600;font-size:1.18em;
  font-variant-numeric:tabular-nums;line-height:1.2}
.sh .fp .pn{display:block;margin-top:.12em;font-size:.56em;font-weight:400;
  line-height:1.35;opacity:.74;letter-spacing:.01em}
.sh .fp .pu:first-of-type::before,.sh .fp .pu:last-of-type::after{content:"";
  display:inline-block;width:2.2em;height:calc(.4 * var(--u));background:currentColor;
  opacity:.45;vertical-align:.2em;margin:0 .6em}
.sh .hd .fp{margin:.45em 0 0;font-size:1.34em}
.sh.j-centre .fp,.sh .hd .fp{text-align:center}
.sh.j-centre .txt,.sh.j-centre h4{text-align:center}
/* UN TITRE CENTRE AU-DESSUS D'UNE LIGNE DE TEXTE SE LIT COMME UN DEFAUT.
   Regle du owner, 2026-08-04: « c'est joli centre quand il n'y a rien en
   dessous; plus coherent au fer a gauche quand il y a une ligne de texte
   immediatement en dessous. » La condition se voit dans le balisage, donc le
   moteur la lit lui-meme: aucun reglage a poser, ni par nous ni par le client.
   La regle vise le h4 et pas son groupe: `text-align` herite, mais une regle
   DIRECTE sur h4 gagne toujours sur l'heritage. */
.sh.j-centre .grp:has(>h4+.nt)>h4,.sh.j-centre .grp:has(>h4+.txt)>h4,
.sh.j-centre .enc:has(>h4+.nt)>h4,.sh.j-centre .enc:has(>h4+.txt)>h4{text-align:left}
.sh .grp:has(>.fp)>h4,.sh .grp:has(>.fp)>.fp,.sh .grp:has(>.fp)>.txt{text-align:center}
.sh .cols{display:flex;gap:var(--pgut);justify-content:flex-end;
  font-size:.5em;letter-spacing:.06em;text-transform:uppercase;opacity:.62;margin-top:.4em}
/* UN INTITULE DE COLONNE NE SE REPLIE PAS, ET IL N'ELARGIT PAS SA COLONNE.
   Deux pannes successives sur la meme regle, et la seconde est nee de la parade
   contre la premiere. `width:6.8em` ferme cassait « la bouteille » en deux
   lignes; passee en PLANCHER, la largeur cesse d'etre cassee mais l'intitule
   GRANDIT sa case des qu'il est plus large que la colonne de prix, et il pousse
   tout l'entete vers la gauche. Mesure du 2026-08-05: 0,55 em de decalage sur
   m106 (« la bouteille »), 0,61 em sur m06, 0,00 em sur m111 dont les intitules
   sont courts. C'est le seul endroit ou l'oeil peut verifier une grille, et il
   la voyait fausse.
   La largeur revient donc FERMEE, a 6.8em de son propre corps, soit exactement
   les 3.4em de la case de prix qu'elle coiffe: le bord droit d'un intitule est
   le bord droit de sa colonne, par construction et non par chance. Ce qui
   empechait de le faire n'existe plus: `white-space:nowrap` est sur la meme
   regle, donc un intitule trop long ne se replie pas, il DEBORDE vers la
   gauche, dans la gouttiere et dans le blanc d'une case voisine que le prix,
   ferre a droite, laisse toujours libre. */
.sh .cols span{width:var(--pcol);text-align:right;flex:none;white-space:nowrap}
.sh .cols.cm span{width:auto;max-width:22em;flex:0 1 auto}
.sh .chr{display:flex;align-items:baseline;gap:.7em;line-height:1.3}
.sh .chr .rp{flex:none;width:3.4em;text-align:right;font-variant-numeric:tabular-nums;opacity:.8;font-size:max(calc(2.2 * var(--u)),.82em)}
.sh .chr .tx{flex:1 1 auto;min-width:0}
.sh .chr .tx>i{display:block;font-size:.8em;opacity:.72;line-height:1.35}
.sh .chr .p{flex:none;font-variant-numeric:tabular-nums;font-weight:600}
.sh .dbl{display:flex;align-items:baseline;gap:.8em;line-height:1.25}
.sh .dbl .tx{flex:1 1 auto;min-width:0}
.sh .dbl .tx .rp{display:block;letter-spacing:.22em;text-transform:uppercase;
  opacity:.66;margin-top:.15em;font-size:max(calc(2.2 * var(--u)),.6em)}
.sh .dbl .tx>i{display:block;font-style:normal;font-size:.8em;opacity:.72;line-height:1.35;
  margin-top:.12em}
.sh .dbl .p{flex:none;font-variant-numeric:tabular-nums;font-weight:600}
.sh .note{flex:none;line-height:1.4;margin-top:.7em;font-size:max(calc(2.2 * var(--u)),.62em)}
.sh .rv{font-size:.62em;vertical-align:super;line-height:0;margin-left:.12em;opacity:.8}
.sh .vs{font-size:.62em;vertical-align:super;line-height:0;margin-left:.12em;color:var(--acc,#9A7B34)}
.sh .ou{font-style:italic;opacity:.6;font-size:.86em;margin-right:.24em}
.sh .vsb{display:flex;flex-wrap:wrap;gap:0 1.1em;margin:.1em 0 .5em;font-size:.76em;opacity:.86}
.sh .vsb .vsx b{color:var(--acc,#9A7B34);margin-right:.2em}
.sh .vsb .vsx em{font-style:normal;font-weight:600}
.sh .ct{font-size:.72em;opacity:.72;margin-left:.42em;font-variant-numeric:tabular-nums;white-space:nowrap}
.sh .pun{font-size:.72em;font-weight:400;opacity:.72;margin-left:.34em;white-space:nowrap}
.sh .row .pb.pg .pun{width:auto;flex:none}
.sh .vr{display:block;font-size:.76em;font-style:italic;opacity:.7;line-height:1.35;margin-top:.06em}
.sh .dsc .vr{display:inline;font-size:1em;margin-top:0}
.sh .txt{flex:none;font-size:.92em;line-height:1.5;opacity:.8}
.sh .grp.cad{border:1px solid currentColor;padding:.55em .7em;margin:.2em 0}
.sh .grp.cad>h4{margin-top:0}
.sh.cv .bd{align-items:center}
.sh.cv .cvb{flex:1 1 auto;align-self:center;text-align:center;
  font-size:.82em;line-height:1.9;opacity:.86}
.sh.cv .cvb p{margin:0}
.sh .it.t-moment>*{position:relative}
.sh .cls{flex:none;display:flex;flex-wrap:wrap;gap:.1em .85em;
  line-height:1.5;opacity:.78;margin:.16em 0 0;font-size:max(calc(2.2 * var(--u)),.62em)}
.sh .ck{display:inline-flex;align-items:baseline;gap:.34em}
.sh .ck i{font:500 .82em/1 'IBM Plex Mono',monospace;font-style:normal;letter-spacing:.06em;font-size:max(calc(2.3 * var(--u)),.82em)}
.sh .bd+.cls,.sh .note+.cls{margin-top:1em}
.sh .cls+.lgd,.sh .cls+.mnt{margin-top:.4em}
.sh .lgd,.sh .mnt{flex:none;line-height:1.4;opacity:.72;margin:.16em 0 0;font-size:max(calc(2.2 * var(--u)),.62em)}
.sh .lgd b{font-weight:600;margin-right:.4em;opacity:.92}
.sh .bd+.lgd,.sh .bd+.mnt,.sh .note+.lgd,.sh .note+.mnt{margin-top:1em}
/* LA GOUTTIERE SOUS LA BOITE SE MESURE SUR LA FEUILLE, PAS SUR LE PETIT TEXTE.
   Elle valait `margin-top:1.1em` posee sur le VOISIN -- la note, la cle, la
   mention. Or ces blocs sont du petit texte par construction (.62em dans le
   moteur, mediane .58em dans les habillages), et un em s'y lit a leur corps a
   eux: les 1,1em annonces ne valaient que 0,71em de feuille en mediane sur les
   25 encarts de la vitrine, moins que le retrait interieur de la boite. Le
   filet du cadre se retrouvait donc plus pres du texte du dessous que de son
   propre contenu, et la boite se lisait collee.
   La gouttiere passe donc sur la BOITE, ou 1em vaut le corps de la feuille, et
   le voisin garde sa propre marge: chacun declare ce qui le regarde, la ou le
   moteur ECRASAIT celle du voisin pour y loger une valeur qui n'etait pas la
   sienne. Elle se prend sur `--gsp`, le ressort de rupture du format, comme la
   gouttiere sous le bloc affiche et pour la meme raison: se detacher du pied
   est une rupture, elle doit suivre la meme echelle quand le format change --
   1,1em sur A4, 1,0 sur le carre et le DL, 0,9 sur A6.
   `:has` la reserve au cas signale, la boite posee EN BAS avec du texte
   dessous; la boite en haut garde la sienne (`.enc+.bd`) et celle qui precede
   directement le pied garde le filet du pied pour la separer. */
.sh .enc:has(+.note,+.lgd,+.mnt,+.cls,+.dcl){margin-bottom:calc(var(--gsp) * 1em)}
.sh .lgd+.mnt{margin-top:.4em}
/* LE CADRE DU BLOC DETACHE, PAR DEFAUT ET DANS LE MOTEUR.
   Le moteur POSAIT l'encart sans jamais le dessiner: sa marge, sa place dans le
   flux, rien d'autre. Les habillages, eux, le dessinent tous de la meme facon
   -- fond de l'encre a 7 %, filet de .4 mm, titre en mono espace -- si bien que
   c'est un device de maison et non une idee par modele.
   Dix modeles ne l'avaient jamais recu: passes de la pile de barres a l'encart
   haut le 2026-07-31, ils ont perdu le dessin de la pile sans gagner celui de
   l'encart, et leur bloc detache sortait NU, exactement comme une section
   ordinaire. C'est le « la page 1 ne ressemble a rien » de g02, et les
   « il faudrait de l'espace apres la premiere section » de m21 et m24.
   Le defaut est donc rendu par le moteur, en `currentColor`: chaque modele
   l'encre de sa propre couleur sans rien ecrire. Les habillages qui declarent
   deja `.enc` gagnent, a specificite egale, parce qu'ils sont charges apres. */
/* LE TEXTE DE L'ENCART TOMBE SUR LA COLONNE, PAS 1,1EM A DROITE.
   La boite portait un retrait interieur de 1,1em et rien en face: son texte
   demarrait donc un cran a droite de celui des plats, sur TOUS les modeles a
   encart. Le owner l'a signale trois fois -- m21, m90, puis « comme
   d'habitude » -- et les deux premieres avaient ete traitees modele par modele.
   C'est une regle du moteur: la boite sort de la colonne d'exactement ce
   qu'elle reprend en dedans, donc elle respire hors de la liste et son texte
   reste sur l'axe. Un habillage qui declare sa propre marge gagne, il est
   charge apres. */
.sh .enc{flex:none;margin-top:.9em;
  background:color-mix(in srgb,currentColor 7%,transparent);
  border:calc(.4 * var(--u)) solid currentColor;padding:.7em 1.1em .8em;
  margin-inline:-1.1em}
.sh .enc>h4{letter-spacing:.24em;text-transform:uppercase;margin:0 0 .45em;
  font-size:max(calc(2.5 * var(--u)),.54em)}
/* L'ENCART EN HAUT A BESOIN D'UNE GOUTTIERE EN DESSOUS, ET IL N'EN AVAIT
   AUCUNE. Place avant le corps (`encart: haut`), il collait a la premiere
   colonne: la boite se lisait comme le debut de la liste au lieu d'un bloc a
   part. Signale sur m79 et m81, et ca concerne les dix-huit modeles a encart
   haut. La gouttiere est la meme que celle du dessus: un bloc detache se
   detache des deux cotes. */
.sh .enc+.bd{margin-top:.9em}
/* ET LE BLOC AFFICHE A LE MEME BESOIN, POUR LA MEME RAISON. La gouttiere sous
   l'encart avait ete posee ici en 2026-08-01; le bandeau d'affiche, lui, etait
   reste a la charge de chaque habillage, et sur huit modeles QUATRE n'en
   posaient aucune (g04, m12, m26, m63): la premiere section demarrait au
   contact du bloc. Les deux qui en posaient une la faisaient plus PETITE que
   la rupture entre deux sections -- 0,9em contre 1,1em au minimum et 3,5em au
   ressort plein -- donc la plus grande rupture de la feuille etait la plus
   serree, exactement le defaut deja mesure sous les en-tetes.
   La valeur se prend sur `--gsp`, le ressort de rupture du format, et non sur
   un em en dur: c'est la meme rupture, elle doit suivre la meme echelle quand
   le format change. Les habillages qui declarent deja une marge l'ajoutent, et
   c'est voulu: ils l'ont dessinee plus large expres. */
.sh .hero+.bd{margin-top:calc(var(--gsp) * 1em)}
/* LA PAGE QUI PORTE LE BLOC DETACHE SE CENTRE, ELLE AUSSI.
   `.enc` est epingle sous l'en-tete et `.bd` est glouton (`flex:1`): tout le
   mou tombait donc SOUS le bloc, et la page se lisait comme calee en haut
   pendant que les suivantes se centraient. Signale le 2026-08-01 sur m03, m12,
   m16, m20 et m110 -- cinq fois la meme phrase.
   Le selecteur ne vise que l'encart EN HAUT (`.enc` suivi du corps): sur un
   encart en bas, le corps doit garder sa croissance, sinon ce sont les
   ressorts de rupture qui meurent. Sur cette page-la ils n'ont rien a faire,
   la liste y est courte par construction. */
.sh:has(>.enc+.bd)>.enc,.sh:has(>.hero+.bd)>.hero{margin-top:auto}
.sh:has(>.enc+.bd)>.bd,.sh:has(>.hero+.bd)>.bd{flex:0 1 auto;margin-bottom:auto}
.sh .pile{display:flex;flex-direction:column;flex:1 1 auto;min-width:0;min-height:0}
.sh .bd>.pile:only-child{flex:1 1 auto}
.sh .bd:has(>.pile:only-child){flex:0 1 auto}
.sh .aside{flex:1 1 auto;min-height:0}
.sh .et{display:flex;align-items:center;gap:.6em;min-width:0}
.sh .et .tx{flex:1 1 auto;min-width:0}
.sh .et i{flex:none;font-style:normal}
.sh .cel{display:grid;grid-template-columns:auto 1fr auto;gap:.15em .6em;align-items:baseline}
.sh .cel .rp{grid-column:1;grid-row:1 / span 2;font-variant-numeric:tabular-nums;font-weight:600}
.sh .cel b{grid-column:2;grid-row:1;font-weight:600;line-height:1.25}
.sh .cel em{grid-column:3;font-style:normal;font-variant-numeric:tabular-nums;font-weight:600}
.sh .cel i{grid-column:2 / -1;grid-row:2;font-style:normal;font-size:.78em;opacity:.72;line-height:1.3}
.sh .cel .vr{grid-column:2 / -1}
.sh .cel.s-r{grid-template-columns:1fr auto}
.sh .cel.s-r b{grid-column:1}
.sh .cel.s-r em{grid-column:2}
.sh .cel.s-r i,.sh .cel.s-r .vr{grid-column:1 / -1}
.sh .cont-v{visibility:hidden}
.sh .cont{flex:none;font:500 .62em/1.4 'IBM Plex Mono',monospace;letter-spacing:.14em;
  text-transform:uppercase;text-align:right;margin-top:.8em;opacity:.8;font-size:max(calc(2.2 * var(--u)),.62em)}
.sh .tag{position:absolute;top:0;left:0;font:500 8px/1 'IBM Plex Mono',monospace;
  letter-spacing:.14em;text-transform:uppercase;padding:5px 8px;z-index:2}
.sh .nb{white-space:nowrap}
.sh .tgs{display:inline-flex;gap:.34em;margin-left:.42em;vertical-align:.05em}
.sh .tgs i{font:500 .46em/1 'IBM Plex Mono',monospace;font-style:normal;
  letter-spacing:.06em;opacity:.8;font-size:max(calc(2.3 * var(--u)),.46em)}
.sh .ft .evin{margin-top:.35em}
.sh .ft .wmk{margin-top:.5em;font:500 .5em/1.4 'IBM Plex Mono',monospace;letter-spacing:.18em;
  text-transform:uppercase;opacity:.5}
.sh .vide{margin:auto;text-align:center;font-style:italic;opacity:.55}
.sh.dos .cvb.dosb{display:flex;flex-direction:column;align-items:center;gap:.7em}
.sh.dos .dos-q{margin:0;line-height:0}
.sh.dos .dos-q svg{width:14em;height:14em;display:block}
.sh.dos .dos-u{margin:0;font-size:.72em;letter-spacing:.06em}
.sh.dos .dos-a{margin:.4em 0 0;font-weight:600}
.sh.dos .dos-n{margin:.6em 0 0;font-style:italic;opacity:.8}
.sh .orn{margin:0 0 .35em;line-height:0;text-align:center}
.sh .orn svg{width:auto;height:calc(26 * var(--u));max-width:100%;display:inline-block;
  color:currentColor;opacity:.9}
.sh.j-centre .orn,.sh .orn{text-align:center}
.sh .grp.pan{background:currentColor;padding:.7em .85em;margin:.25em 0;position:relative}
.sh .grp.pan>*{position:relative;color:var(--pan-txt,#FAF6E8)}
.sh .grp.pan .ln .l{opacity:.4}
.sh .grp.pan .dsc,.sh .grp.pan .nt{opacity:.78}
.sh .grp h5,.sh .enc h5{margin:.5em 0 .2em;font-size:.78em;font-weight:600;letter-spacing:.1em;
  text-transform:uppercase;opacity:.72;flex:none}
.sh .grp h5:first-child,.sh .enc h5:first-child{margin-top:0}
/* UN TITRE APPARTIENT A CE QU'IL ANNONCE, ET IL EN ETAIT SEPARE.
   Regle du owner, 2026-08-05, devant m111 puis m106: « il y a plus d'espace
   apres un titre de section qu'avant; ca devrait etre l'inverse », et sur le
   groupe: « ROUGES est un peu trop proche de Chablis premier cru, GAMAY est
   plus loin ». Mesure d'encre a encre: 0,84 em avant / 0,92 apres sur m111,
   0,93 / 1,02 sur m106, 0,93 / 1,20 sur m06. Le titre flottait, donc il se
   lisait comme la fin de la section precedente au lieu du debut de la suivante.
   La cause n'est pas dans les marges du titre, qui vont deja dans le bon sens
   (`.5em` dessus, `.2em` dessous): c'est le REMBOURRAGE de la rangee qui suit.
   Il est invisible dans la feuille de style du titre, il vaut ce que
   l'habillage veut (`.3em` sur m111), et il s'ajoute integralement au blanc
   d'en dessous. Une marge ne peut pas se defendre contre un padding qu'elle ne
   voit pas: on le retire donc a la rangee qui ouvre, la ou il fait le degat.
   La rangee garde son rembourrage bas, donc son filet reste a la meme distance
   de son texte que ses soeurs. */
.sh .grp>h4+.it>.row,.sh .grp>h5+.it>.row,.sh .enc>h4+.it>.row{padding-top:0}
/* UNE SOUS-SECTION QUI SUIT DES ENTREES OUVRE UN GROUPE, ELLE NE CONTINUE PAS
   LE PRECEDENT. « Il manque toujours de l'espace entre BLANCS, ROUGES et
   BULLES », owner, 2026-08-05, apres la reparation du sens du blanc: le titre
   n'etait plus mal place, il etait trop peu detache, donc les trois familles se
   lisaient comme une seule liste.
   La marge se pose ICI et pas sur `.grp h5`, pour une raison de cascade et non
   de gout: `.m111 .grp h5` a la meme specificite que `.sh .grp h5` et passe
   apres, donc une valeur ecrite la-bas serait perdue chez tous les habillages
   qui reglent leurs sous-titres. `.it+h5` en ajoute une et gagne partout.
   Le selecteur dit aussi exactement quel cas il vise: un h5 qui suit des
   ENTREES. Le premier d'un groupe n'a rien a detacher, il colle deja a son
   titre de section, et il garde donc sa marge d'origine. En unite de feuille,
   comme la grille de prix: sinon la separation vaudrait ce que vaut le corps du
   sous-titre, qui n'a rien a voir avec elle. */
.sh .grp>.it+h5,.sh .enc>.it+h5{margin-top:calc(.85 * var(--corps))}
.sh .grp h4 .ste{font-weight:400;font-size:.82em;opacity:.7;letter-spacing:0;text-transform:none}
.sh .tgs-av{margin:0 .42em 0 0}
.sh .fnd{position:absolute;inset:0;display:grid;place-items:center;pointer-events:none;z-index:0;opacity:.055}
.sh .fnd svg{width:auto;height:62%;color:currentColor}
.sh>*{position:relative;z-index:1}
.sh .cote{display:flex;gap:calc(var(--gap) * var(--u) * .6);align-items:flex-start;flex:0 0 auto}
.sh .cote>.grp{flex:1 1 0;min-width:0}
.sh.acc .hd .dt,.sh.acc .grp>h4,.sh.acc .enc>h4,.sh.acc .row .pv,
.sh.acc .chr .rp,.sh.acc .cel .rp,.sh.acc .cls .ck i{color:var(--acc)}
.sh.acc .tag{background:var(--acc);color:var(--acc-t)}
.sh.acc .grp>h4{border-bottom-color:color-mix(in srgb,var(--acc) 34%,transparent)}
.sh.acc .grp.pan{background:var(--acc);color:var(--acc-t)}
.sh .pdt{font-weight:600}
.sh .acd{display:block;font-size:.78em;font-style:italic;opacity:.66;line-height:1.35;margin-top:.04em}
.sh .dsc-acd{font-style:italic;opacity:.62}
.sh .dsc-acd .acd{display:inline;font-size:1em;opacity:1;margin-top:0}
.sh .alr{display:block;font-size:.72em;opacity:.82;line-height:1.3;
  letter-spacing:.012em;margin-top:.1em}
.sh .dsc.alr,.sh .row .lc.alr,.sh .chr .tx .alr,.sh .dbl .tx .alr,
.sh .cel .alr{font-style:normal}
.sh .dsc.alr{padding-right:2.2em}
.sh .alr.org{display:inline;font-size:1em;margin-top:0}
.sh .alr.org::before{content:'\00B7';margin:0 .4em;opacity:.6}
.sh .dcm{font-size:.6em;vertical-align:super;line-height:0;margin-left:.1em;opacity:.85}
.sh .dcl{flex:none;line-height:1.4;opacity:.78;margin:.16em 0 0;font-size:max(calc(2.2 * var(--u)),.62em)}
.sh .dcl b{font-weight:600;margin-right:.4em;opacity:.95}
.sh .lgd+.dcl,.sh .cls+.dcl,.sh .bd+.dcl,.sh .note+.dcl{margin-top:.4em}
/* L'ADRESSE SE DECOLLE DU CODE. `.22em` valait 0,75 mm sous le carre du QR:
   l'adresse touchait les modules et se lisait comme une bavure du code. Elle
   est en dessous de tous les modeles, donc c'est le moteur qui la porte. */
.sh .qrl{flex:none;display:flex;flex-direction:column;align-items:center;gap:.55em;
  margin:.9em 0 0;text-align:center}
/* LE CHIFFRE PERDU DE L'AFFICHE PREND UN SUFFIXE, ET LUI SEUL.
   Le prix d'une LIGNE n'en a pas besoin: il termine une ligne de conduite apres
   un nom, aligne en colonne avec ses voisins, et rien ne peut le lire
   autrement. Le prix de l'affiche, lui, est un nombre seul au milieu d'un bloc:
   il a perdu ce contexte, et « 6 » s'y lit comme un numero.
   Le suffixe est POSE PAR LE CSS et n'entre jamais dans la donnee: le
   restaurateur tape « 6 », le contrat stocke « 6 », et si on retire cette regle
   demain rien n'est a reecrire. `:empty` garde le cas d'une affiche sans prix,
   qui rendrait sinon un « .- » orphelin.
   LE SUFFIXE EST INLINE, ET IL L'EST POUR DEUX RAISONS PAYEES AU RENDU. Il
   etait absolu, cale a `left:100%` du `<i>`. Or `left:100%` suit la BOITE, pas
   le chiffre: des qu'un habillage passe le prix en `display:block` -- m26 et
   m69 le font, pour le poser sur sa propre ligne -- la boite prend toute la
   largeur de la feuille, et le « .- » part se coller au bord du papier a dix
   centimetres du « 6 » qu'il qualifie. C'est exactement le prix orphelin deja
   corrige en fin de ligne. Second effet, sur les cinq autres: une boite absolue
   ne compte pas dans la mise en page, donc le retrait interieur du cadre ne la
   protege pas et le suffixe venait toucher le filet de droite. Inline, il reste
   colle a son chiffre et il est pousse par le retrait comme n'importe quel
   texte. Le decalage optique qu'il ajoute a un chiffre centre vaut 0,4 % de la
   largeur d'une A4: hors de portee de l'oeil, contrairement aux deux defauts
   qu'il remplace.
   IL SE SOULEVE PAR `position:relative`, JAMAIS PAR `vertical-align`. Releve
   par le owner deux heures apres la premiere version: le prix du bandeau ne
   tombait plus a la meme hauteur que les prix de la liste. Cause exacte:
   `vertical-align` deplace la boite dans la ligne, donc la ligne grandit pour
   la contenir, donc la ligne de base du CHIFFRE descend. Un decalage relatif ne
   participe pas a la mise en page: le suffixe monte, la ligne ne bouge pas, et
   le prix reste sur l'axe de ses voisins. C'est la meme famille de piege que la
   boite absolue d'avant -- une position qui ment sur la place qu'elle prend --
   prise par l'autre bout. */
/* ET IL NE COMPTE PAS DANS LA LARGEUR, SINON C'EST LUI QU'ON CENTRE.
   Le bandeau centre son prix, et le suffixe etait dans le flux: la boite
   centree valait donc « 2,40.- » et le CHIFFRE tombait 4 px a gauche de l'axe
   du disque -- mesure sur m10, boite centree au pixel, chiffre a 276,9 pour un
   axe a 281,0. Un suffixe de monnaie se lit comme un appel de note: il pend
   apres le nombre, il ne le pousse pas. Le pseudo-element garde donc sa place
   dans la ligne (`position:relative`, pour la ligne de base, voir juste
   au-dessus) mais plus sa largeur, et son decalage passe de `margin-left` a
   `left`, qui ne compte pas non plus. */
.sh .hero i::after{content:".-";position:relative;top:-.42em;left:.08em;
  display:inline-block;width:0;
  font-size:.6em;opacity:.55;letter-spacing:.02em}
.sh .hero i:empty::after{content:none}
.sh .qrl svg{display:block;width:5.4em;height:5.4em}
.sh .qrl span{font-size:.58em;letter-spacing:.04em;opacity:.78;line-height:1.2}
.sh .cel .alr{grid-column:2 / -1;grid-row:auto}
.sh .cel.s-r .alr{grid-column:1 / -1}
.sh .bd-lrg{flex-wrap:wrap;align-content:flex-start}
.sh .grp.lrg{flex:1 0 100%;width:100%}
.sh .grp.lrg>h4{text-align:center}
.sh .lrg-c{display:flex;gap:calc(var(--gap) * var(--u));align-items:flex-start}
.sh .lrg-c>.col{flex:1 1 0;min-width:0;justify-content:flex-start}
.sh.fil{--corps:clamp(16.5px,4.3vw,19px);--u:calc(var(--corps) / var(--fs));--fsk:1;
  --pad:calc(var(--fs) * 1.5);box-sizing:border-box;width:100%;max-width:none;
  height:auto;min-height:0;padding:2.4em calc(var(--pad) * var(--u));
  overflow:visible;box-shadow:none}
.sh.fil .bd,.sh.fil .col,.sh.fil .lrg-c,.sh.fil .cote,.sh.fil .pile,
.sh.fil .aside{display:block;min-height:0}
.sh.fil .hd{flex-wrap:wrap}
.sh.fil .col{border-left:0;border-right:0}
.sh.fil .gp{flex:none;height:calc(var(--gsp) * 1.8em);min-height:0;max-height:none}
.sh.fil .gp-t{display:none}
.sh.fil .grp.lrg{width:auto}
.sh.fil .et .tx>span,.sh.fil .hero .tx>span{display:block;margin-top:.1em}
.sh.fil .et>.tx,.sh.fil .hero>.tx{font-size:1em}
.sh.fil .pile .et{width:auto;height:auto;min-height:0}
.sh.fil .cls,.sh.fil .lgd,.sh.fil .mnt,.sh.fil .dcl,.sh.fil .note,.sh.fil .cont,
.sh.fil .cols,.sh.fil .hd .pd-c,.sh.fil .ft .ad,.sh.fil .ft .hr,.sh.fil .ft .tt,
.sh.fil .hero .kd,.sh.fil .et .tx>span,.sh.fil .hero .tx>span{font-size:calc(var(--corps) * .80);font-size:max(calc(2.2 * var(--u)),calc(var(--corps) * .80))}
.sh.fil .tgs i,.sh.fil .ck i{font-size:calc(var(--corps) * .74);font-size:max(calc(2.3 * var(--u)),calc(var(--corps) * .74))}
.sh.fil .dsc,.sh.fil .nt,.sh.fil .ac{opacity:.84;font-size:max(calc(2.5 * var(--u)),.87em)}
.sh.fil .ln .p,.sh.fil .pu,.sh.fil .pv,.sh.fil .mnt b{font-variant-numeric:lining-nums tabular-nums}
.sh .it .ep{display:none}
.sh.fil .it.t-epuise{opacity:.6;text-decoration:line-through}
.sh.fil .it.t-epuise .ep{display:inline-block;text-decoration:none;margin-left:.5em;
  font:500 .62em/1 'IBM Plex Mono',monospace;font-style:normal;letter-spacing:.09em;
  text-transform:uppercase;opacity:.92;vertical-align:0}
.sh .hd .pd-c{font-size:.62em;letter-spacing:.14em;text-transform:uppercase;opacity:.66;margin:.24em 0 0}
.sh .cvp{font-size:1.35em;letter-spacing:.06em;text-transform:uppercase;opacity:.92;margin:0 0 .3em}
.sh .cvn{font-style:italic;opacity:.78;margin:0 0 1.1em}
.sh .chp{flex:none;font-style:italic;font-size:.86em;line-height:1.4;opacity:.78;
  margin:0 0 .7em;text-align:center}
