/* ===========================================================================
   Vieux Plans — feuille de style
   ---------------------------------------------------------------------------
   Surface : EXPLORE. On parcourt un catalogue d'objets visuels. Les plans sont
   l'interface : ils arrivent en premier, en grand, et le texte les sert.
   Pas de hero centré — c'est la composition d'une page « Decide », pas d'un
   catalogue.

   Mobile-first : tout est écrit pour 390 px, les media queries élargissent.
   =========================================================================== */

@font-face{font-family:'Fraunces';font-style:normal;font-weight:400 700;
  font-display:swap;src:url('../vendor/fonts/fraunces.woff2') format('woff2')}
@font-face{font-family:'Inter';font-style:normal;font-weight:400 600;
  font-display:swap;src:url('../vendor/fonts/inter.woff2') format('woff2')}
/* Archivo sert UNIQUEMENT au logotype : capitales interlettrées. C'est la
   seule citation du « LILLE. INSVLA. » de 1581 — le rythme est ancien, le
   dessin des lettres ne l'est pas. Toute la tension de la marque est là. */
@font-face{font-family:'Archivo';font-style:normal;font-weight:500 600;
  font-display:swap;src:url('../vendor/fonts/archivo.woff2') format('woff2')}

*,*::before,*::after{box-sizing:border-box}

:root{
  /* Palette tirée des plans eux-mêmes : encre sépia, papier vergé, rouge de
     surimpression cartographique, vert d'eau des fossés. Aucune couleur
     inventée hors du sujet. */
  --encre:#171310;
  --encre-douce:#4c443c;
  --estompe:#8a7f72;
  --papier:#faf7f1;
  --papier-creux:#f1ebe0;
  --trait:#e0d7c7;
  --rouge:#9b2c1c;        /* rouge de surimpression des tramways */
  --vert:#5a6b5d;         /* vert d'eau des fossés */
  --or:#b08949;

  --serif:'Fraunces',"Iowan Old Style",Palatino,Georgia,serif;
  --sans:'Inter',-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;

  --marge:20px;
  --max:1240px;
  --r:2px;
}

@media (min-width:768px){:root{--marge:40px}}

html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *{animation-duration:.01ms!important;transition-duration:.01ms!important}
}

body{
  margin:0;background:var(--papier);color:var(--encre);
  font-family:var(--sans);font-size:16px;line-height:1.6;
  -webkit-font-smoothing:antialiased;
  font-feature-settings:"kern" 1;
}

img,svg{display:block;max-width:100%}
a{color:inherit}
h1,h2,h3{font-family:var(--serif);font-weight:600;line-height:1.1;
  letter-spacing:-.015em;margin:0;text-wrap:balance}
p{margin:0;text-wrap:pretty}

.wrap{max-width:var(--max);margin:0 auto;padding:0 var(--marge)}
.lire{max-width:62ch}

/* Cible tactile minimale de 44 px — obligatoire sur mobile */
a,button{min-height:44px}
a:focus-visible,button:focus-visible{
  outline:2px solid var(--rouge);outline-offset:3px;border-radius:var(--r)}

/* --------------------------------------------------------------- en-tête -- */
.annonce{background:var(--encre);color:#f3ece0;font-size:13px;
  letter-spacing:.01em;text-align:center;padding:9px var(--marge)}
.annonce b{color:#e3bd7c;font-weight:600}

.entete{position:sticky;top:0;z-index:60;background:rgba(250,247,241,.94);
  backdrop-filter:blur(8px);border-bottom:1px solid var(--trait)}
.entete .wrap{display:flex;align-items:center;justify-content:space-between;
  min-height:58px;gap:16px}
/* ---------------------------------------------------------------- marque --
   « La Case » : le carroyage d'index du plan de 1892, par lequel un lecteur
   retrouve sa rue. La case carmin n'est pas un ornement, c'est VOTRE case.
   Deux graisses seulement, rapport 2:1 — filet gras 2u (bord de carte),
   filet maigre 1u (carroyage). Les crochets de marge débordent en bas et à
   gauche uniquement : c'est la disposition relevée sur le scan. Les retirer
   ferait retomber la marque dans l'icône générique. */
.logo{font-family:'Archivo',system-ui,sans-serif;font-size:15px;font-weight:600;
  text-decoration:none;letter-spacing:.17em;text-transform:uppercase;
  display:flex;align-items:center;gap:11px;color:var(--encre);line-height:1}
.logo .marque{width:30px;height:30px;flex:0 0 30px;color:currentColor}
.logo .marque .case{fill:var(--rouge)}
.logo em{font-style:normal;color:inherit}
/* Le mot n'est masqué qu'en dernier recours : un logotype sans son nom n'est
   plus une marque. À 360 px — largeur de la plupart des téléphones Android —
   l'ensemble tient largement, la navigation n'ayant qu'un seul lien visible.
   Le seuil est donc descendu à 310 px, ce qui ne concerne plus que les très
   vieux appareils. */
@media (max-width:310px){.logo .mot{display:none}}
.nav{display:flex;gap:4px;align-items:center}
.nav a{font-size:14px;text-decoration:none;color:var(--encre-douce);
  padding:10px 11px;display:flex;align-items:center;border-radius:var(--r)}
.nav a:hover{color:var(--rouge)}
@media (max-width:560px){.nav a.cache-mob{display:none}}

/* ------------------------------------------------------------- ouverture --
   PLANCHE D'INDEX, validée le 13 octobre 2026.
   Le texte ne se superpose plus au plan : il occupe sa propre colonne sur un
   voile de papier. Le contraste est donc STRUCTUREL, et le plan garde toute
   sa lisibilité — l'inverse de la version précédente, qui assombrissait le
   produit pour faire passer son titre alors que l'image EST ce qu'on vend.
   L'appareil cartographique (marge de repérage chiffrée et lettrée, carroyage,
   cartouche d'échelle) reprend le geste de la marque « LA CASE » : il désigne,
   il n'orne pas. */
.ouverture{position:relative;background:var(--papier)}
.ouverture .plaque{position:relative;display:grid;
  grid-template-columns:26px minmax(0,1fr);grid-template-rows:auto 22px}
.ouverture .marge-g{grid-column:1;grid-row:1;
  border-right:1px solid var(--encre);display:flex;flex-direction:column;
  justify-content:space-around;align-items:center;padding:10px 0}
.ouverture .marge-b{grid-column:2;grid-row:2;
  border-top:1px solid var(--encre);display:flex;
  justify-content:space-around;align-items:center}
.ouverture .coin{grid-column:1;grid-row:2;
  border-top:1px solid var(--encre);border-right:1px solid var(--encre)}
.ouverture .rep{font-size:10px;font-weight:500;letter-spacing:.08em;
  color:var(--encre-douce)}
.ouverture .champ{grid-column:2;grid-row:1;position:relative;
  overflow:hidden;background:var(--papier-creux);display:grid}

/* ⚠ Ordre des règles : la règle de base `display:none` doit précéder la media
   query, sinon elle la neutralise (même spécificité, source order gagne) et
   les deux tiers de la bande restent vides sur grand écran. */
.ouverture .fond{position:absolute;inset:0;display:grid;
  grid-template-columns:1fr}
/* Sur petit écran une seule image tient, et ce n'est pas forcément la première
   de la bande : .sur-mobile désigne celle qu'on veut y voir — le plan des
   tramways, celui qui a le plus plu à la braderie. */
.ouverture .fond img{display:none}
.ouverture .fond img.sur-mobile{display:block}
/* Le plan est en PAYSAGE, la fenêtre mobile en PORTRAIT : object-fit:cover
   montre donc toute la hauteur du document, marges blanches comprises, et le
   haut de la bande se retrouve vide. Mesuré : écart-type 19 sur la bande du
   haut contre 57 au milieu. Un recadrage ne suffit pas, il faut un zoom visé
   sur le cœur de la ville.
   MAIS le zoom coûte de la résolution. Mesure du besoin réel : cadre 764 px
   × zoom × densité d'écran 3. À ×2,1 il faudrait 4 815 px de source pour
   1 200 disponibles — d'où les pixels visibles. ×1,45 ramène le besoin à
   3 324 px, servis par le fichier 2000 px en densité 2 et acceptable en
   densité 3, et laisse reconnaître la ville dans son ensemble.
   CADRAGE sur la CITADELLE de Vauban, le repère que tout Lillois reconnaît.
   Elle a été localisée par découpage du plan en grille de 6 × 4 puis examen
   des cases : son étoile à cinq branches et ses douves occupent la colonne 3,
   rangée 2, soit 40 % en largeur et 35 % en hauteur du document.
   Le translateY est indispensable et ne se déduit pas : le cadre mobile étant
   en portrait et le plan en paysage, object-fit:cover montre TOUTE la hauteur
   du document, si bien qu'un object-position vertical n'a aucun effet. Sans
   ce décalage, la citadelle tombait pile sous le titre. */
.ouverture .fond img{width:100%;height:100%;object-fit:cover;
  object-position:40% 50%;transform:scale(1.45) translateY(-13%);
  transform-origin:40% 35%}

/* Dégradé de papier là où le texte se pose, et nulle part ailleurs.
   Sur mobile le texte occupe toute la largeur : le voile doit donc être
   VERTICAL et laisser le haut du plan franchement lisible, sinon le document
   n'est plus qu'une trame pâle. Mesure de l'écart-type par bande sur une
   première version montant à .72 partout : moyenne 225/255 sur toute la
   hauteur, autrement dit du papier et non une carte. */
.ouverture .champ::after{content:"";position:absolute;inset:0;z-index:1;
  pointer-events:none;
  /* Le voile devient franc juste SOUS la citadelle : au-dessus il laisse le
     plan intact, en dessous il porte le texte. Une version plus progressive
     laissait le sur-titre carmin sur la carte, à la limite du lisible. */
  background:linear-gradient(180deg,rgba(248,243,233,0) 0%,
    rgba(248,243,233,.04) 18%,rgba(248,243,233,.62) 25%,
    rgba(248,243,233,.94) 31%,rgba(248,243,233,.97) 100%)}
.ouverture .carroyage{position:absolute;inset:0;pointer-events:none;
  background-image:linear-gradient(to right,rgba(23,19,16,.10) 1px,transparent 1px),
                   linear-gradient(to bottom,rgba(23,19,16,.10) 1px,transparent 1px);
  background-size:12.5% 25%}

/* Le texte est un enfant de grille et non un bloc absolu : c'est lui qui
   impose la hauteur de la bande, donc plus de titre coupé.
   align-self:end sur mobile — le texte se cale en bas et laisse au plan la
   moitié haute de la bande. Le plan doit se voir en arrivant : c'est le
   produit, et c'est ce qui donne envie de descendre. */
.ouverture .dedans{position:relative;z-index:3;align-self:end;
  display:flex;flex-direction:column;justify-content:flex-end;
  padding:30px var(--marge) 30px;
  /* réserve de hauteur pour la carte au-dessus du texte */
  margin-top:min(44vw,210px)}
.ouverture .surligne{font-size:10px;font-weight:600;letter-spacing:.24em;
  text-transform:uppercase;color:var(--rouge);margin-bottom:13px}
.ouverture .surligne i{font-style:normal;color:var(--estompe)}
.ouverture h1{font-family:var(--serif);font-size:clamp(28px,7.4vw,34px);
  line-height:1.06;letter-spacing:-.02em;color:var(--encre);
  text-wrap:balance}
.ouverture .filet{width:52px;height:2px;background:var(--encre);
  margin:15px 0 14px}
.ouverture .appui{font-size:14.5px;line-height:1.52;color:#3a322b;
  max-width:36ch}
.ouverture .index{list-style:none;padding:0;margin:18px 0 0;
  display:grid;gap:3px}
.ouverture .index li{display:grid;
  grid-template-columns:44px minmax(0,1fr);gap:4px 10px;align-items:baseline;
  font-size:12px;color:#3a322b;padding-bottom:4px;
  border-bottom:1px dotted rgba(23,19,16,.26)}
.ouverture .index .num{font-weight:600;color:var(--encre);
  font-variant-numeric:tabular-nums}
.ouverture .index .quoi{font-weight:600;color:var(--encre)}
/* Le sous-titre réel du plan, et non une cote de carroyage inventée : une
   version intermédiaire affichait « A 1 », « C 2 », qui avaient l'air d'une
   information vérifiable sans en être une. */
.ouverture .index .prec{grid-column:2;color:var(--encre-douce);font-size:11.5px}
.ouverture .actions{display:flex;align-items:center;gap:15px;
  flex-wrap:wrap;margin-top:4px}
.ouverture .second{font-size:12.5px;color:#4c443c;text-decoration:none;
  border-bottom:1px solid rgba(23,19,16,.3);padding-bottom:1px}
.ouverture .second:hover{color:var(--rouge);border-color:var(--rouge)}
.ouverture .cartouche-ech{position:absolute;right:14px;bottom:12px;z-index:3;
  text-align:right;background:rgba(250,247,241,.9);padding:6px 9px;
  border:1px solid rgba(23,19,16,.42)}
.ouverture .cartouche-ech .t{font-family:var(--serif);font-size:11px;
  color:var(--encre);display:block;line-height:1.2}
.ouverture .cartouche-ech .s{font-size:9.5px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--encre-douce);display:block}

/* Grand écran : les trois plans reviennent côte à côte, le texte prend sa
   colonne à gauche et le dégradé devient latéral. */
@media (min-width:900px){
  .ouverture .plaque{grid-template-columns:30px minmax(0,1fr)}
  .ouverture .fond{grid-template-columns:repeat(3,1fr);gap:2px}
  /* Pas de zoom sur grand écran : les trois plans tiennent dans leur tiers,
     c'est leur allure d'ensemble qu'on veut montrer. */
  .ouverture .fond img{display:block;transform:none;object-position:50% 50%}
  .ouverture .fond img:nth-child(2){object-position:50% 48%}
  .ouverture .fond img:nth-child(3){object-position:54% 50%}
  /* Le voile s'arrête juste après la colonne de texte, qui fait environ 420 px
     de large — soit ~30 % d'un écran de 1440. Une première version le faisait
     courir jusqu'à 84 %, ce qui lavait deux des trois plans : on ne voyait
     plus que celui de droite, à rebours de l'intention. */
  .ouverture .champ::after{
    background:linear-gradient(97deg,rgba(248,243,233,.99) 0%,
      rgba(248,243,233,.97) 24%,rgba(248,243,233,.86) 33%,
      rgba(248,243,233,.40) 43%,rgba(248,243,233,0) 54%)}
  .ouverture .dedans{padding:56px 26px 56px 30px;max-width:min(52ch,54%);
    /* retour au centrage vertical et pas de réserve : sur grand écran le texte
       est À CÔTÉ du plan, pas au-dessous de lui. */
    align-self:center;justify-content:center;margin-top:0}
  .ouverture h1{font-size:clamp(34px,3.6vw,48px)}
  .ouverture .appui{font-size:15.5px;max-width:38ch}
}
@media (min-width:1280px){
  .ouverture .dedans{padding:72px 26px 72px 42px}
}

.cta{display:inline-flex;align-items:center;justify-content:center;gap:9px;
  background:var(--rouge);color:#fff;text-decoration:none;font-weight:600;
  font-size:16px;padding:15px 26px;border-radius:var(--r);border:0;
  margin-top:26px;cursor:pointer;font-family:var(--sans);
  transition:background .15s,transform .15s}
.cta:hover{background:#7f2316;transform:translateY(-1px)}
.cta.pleine{width:100%}
.cta.claire{background:transparent;border:1px solid var(--trait);
  color:var(--encre)}
.cta.claire:hover{background:var(--papier-creux);transform:none}

/* ------------------------------------------------------------- catalogue -- */
/* L'en-tête est collant : sans cette marge, un lien d'ancre amène la section
   sous l'en-tête et son titre est masqué. */
[id]{scroll-margin-top:72px}

.section{padding:52px 0}
@media (min-width:768px){.section{padding:78px 0}}
.titre-section{font-size:clamp(25px,5.2vw,37px)}
.intro-section{color:var(--encre-douce);margin-top:11px;font-size:16.5px}

.catalogue{display:grid;gap:30px;margin-top:34px;grid-template-columns:1fr}
@media (min-width:640px){.catalogue{grid-template-columns:repeat(2,1fr);gap:26px}}
@media (min-width:1000px){.catalogue{grid-template-columns:repeat(3,1fr);gap:32px}}

/* La première carte occupe toute la largeur : une hiérarchie, pas une grille
   d'éléments de poids égal (tell n°3 du diagnostic de slop). */
@media (min-width:640px){.catalogue .carte:first-child{grid-column:1/-1}}
@media (min-width:1000px){.catalogue .carte:first-child{grid-column:1/3}}

.carte{text-decoration:none;color:inherit;display:block;
  transition:transform .2s ease}
.carte:hover{transform:translateY(-3px)}
.carte .cadre{position:relative;overflow:hidden;background:var(--papier-creux);
  border:1px solid var(--trait);border-radius:var(--r);aspect-ratio:4/3}
.catalogue .carte:first-child .cadre{aspect-ratio:16/9}
.carte .cadre img{width:100%;height:100%;object-fit:cover;
  transition:transform .55s cubic-bezier(.2,.7,.3,1)}
.carte:hover .cadre img{transform:scale(1.035)}
.carte .annee{position:absolute;top:0;left:0;background:var(--papier);
  color:var(--rouge);font-size:12px;font-weight:600;letter-spacing:.09em;
  padding:6px 11px}
.carte .loupe{position:absolute;right:10px;bottom:10px;background:rgba(23,19,16,.78);
  color:#fff;font-size:11.5px;letter-spacing:.04em;padding:6px 10px;
  border-radius:999px;display:flex;align-items:center;gap:5px}
.carte h3{font-size:20px;margin-top:14px}
.catalogue .carte:first-child h3{font-size:25px}
.carte p{color:var(--encre-douce);font-size:15px;margin-top:5px}

/* --------------------------------------------------------- fiche produit -- */
.produit{display:grid;grid-template-columns:1fr;gap:0}
@media (min-width:980px){
  /* La colonne d'achat n'a besoin que de sa largeur de lecture : tout le
     reste va a la visionneuse, qui est le produit. */
  .produit{grid-template-columns:minmax(0,1fr) minmax(330px,382px);
    gap:48px;padding-top:36px;align-items:start}
}
/* Sur grand ecran, la fiche gagne de la place : un texte se lit en 1240 px,
   un plan se regarde aussi large que l'ecran le permet.
   On elargit le CONTENEUR, on ne fait pas deborder son enfant. Donner
   width:100vw a un enfant d'un .wrap deja centre le poussait vers la droite
   (margin:auto vaut 0 des que l'enfant est plus large que son parent), ce qui
   coupait la colonne d'achat entre 1500 et 1920 px. Le texte sous la
   visionneuse garde sa mesure de lecture par ses propres max-width. */
@media (min-width:1500px){:root{--max:1560px}}

/* Sur mobile le zoom est collé en haut de l'écran, pleine largeur : c'est
   l'expérience principale, pas une vignette. */
.zone-zoom{position:relative;background:var(--papier-creux);
  margin:0 calc(var(--marge)*-1)}
@media (min-width:980px){
  .zone-zoom{margin:0;position:sticky;top:76px;border-radius:var(--r);
    overflow:hidden;border:1px solid var(--trait)}
}
/* Le cadre epouse le document : --ratio est pose en ligne par le generateur,
   depuis les dimensions reelles lues dans le .dzi. Un cadre au mauvais rapport
   laisse des bandes vides sur les cotes, tres visibles sur grand ecran. */
/* L'aspect-ratio donne au cadre une hauteur AVANT que le script ne tourne :
   OpenSeadragon s'initialise sur la taille de son conteneur, et dans une boite
   de hauteur nulle il ne dessinerait rien. */
#visionneuse{width:100%;aspect-ratio:var(--ratio,7/5);
  background:var(--papier-creux)}

/* ----------------------------------------- plein écran sur le plan (mobile)
   Tant qu'il reste une page derrière le plan, le pincement peut fuir vers le
   navigateur et grossir le site entier. En plein écran il n'y a plus de page
   derrière : l'ambiguïté disparaît, et le reste du site garde son zoom pour
   qui a besoin d'agrandir le texte.
   Calque fixe en CSS et non Fullscreen API seule : iOS ne l'accorde qu'aux
   vidéos. On demande le vrai plein écran en plus, quand il existe. */
/* Le fond du plein écran n'est pas noir mais la couleur MESURÉE du papier du
   plan affiché (--papier-plan, posée en ligne par le générateur depuis
   tools/couleur_papier.py). Le format d'un plan n'est jamais celui d'un
   téléphone : il reste des bandes, et un fond noir derrière un papier crème
   fait une bordure dure. En prolongeant le papier, la bande devient une marge.
   Chaque plan a sa teinte : de #d8c3a6 pour les canonniers, nettement ambrés,
   à #e9e4cd pour les promenades, presque ivoire. */
.zone-zoom.plein{position:fixed;inset:0;z-index:300;margin:0;
  background:var(--papier-plan,var(--papier-creux));
  display:flex;align-items:center;
  /* Courbe volontairement douce. Avec cubic-bezier(.16,.84,.26,1), essayee
     d'abord, 60 % du fondu se jouait dans les 70 premieres millisecondes :
     mesure a l'image pres, l'ouverture paraissait brutale malgre ses 440 ms.
     Une courbe trop chargee au depart se lit comme un saut, pas comme un
     mouvement. */
  animation:ouvre-plan .48s cubic-bezier(.25,.46,.45,.94) both;
  /* La composition est confiee au processeur graphique : sans cela le
     navigateur recalcule la mise en page a chaque image, et l'animation
     hache — d'autant qu'OpenSeadragon dessine ses tuiles en meme temps. */
  will-change:transform,opacity}
.zone-zoom.plein #visionneuse{height:100%;width:100%;aspect-ratio:auto;
  background:var(--papier-plan,var(--papier-creux))}
/* Hors plein écran aussi : le cadre épouse la teinte du document plutôt que
   le gris générique de la charte. */
#visionneuse{background:var(--papier-plan,var(--papier-creux))}
/* Un fondu seul laissait apparaitre un plan a moitie dessine, et le cadre
   sautait de 279 a 844 px sans transition : d'ou la sensation de coupure.
   La legere montee d'echelle donne au mouvement une direction — on entre DANS
   le plan — et elle ne coute rien, une transform n'entrainant aucun recalcul
   de mise en page. 440 ms : en dessous le geste paraissait brusque. */
@keyframes ouvre-plan{
  from{opacity:0;transform:scale(.93)}
  to{opacity:1;transform:scale(1)}
}
/* Sortie symetrique : une disparition seche apres une ouverture soignee se
   remarque autant qu'une ouverture ratee. Plus courte que l'entree — on sort
   plus vite qu'on entre, c'est ce qu'on attend d'une fermeture. */
.zone-zoom.plein.sort{animation:ferme-plan .3s cubic-bezier(.4,0,.7,.2) both}
@keyframes ferme-plan{
  from{opacity:1;transform:scale(1)}
  to{opacity:0;transform:scale(.95)}
}
@media (prefers-reduced-motion:reduce){
  .zone-zoom.plein,.zone-zoom.plein.sort{animation:none}
}
/* Le défilement de la page est gelé pendant le plein écran : sans cela elle
   continue de bouger derrière le calque, et on la retrouve ailleurs en
   sortant. La position est mémorisée et restaurée par le script. */
body.plan-ouvert{overflow:hidden}

/* Encoche et barre de gestes : sans les marges de sécurité, le bouton de
   sortie se retrouve sous l'encoche sur un iPhone récent. */
/* Boutons sombres : le fond du plein écran est désormais la couleur du papier,
   claire sur les cinq plans. Un bouton crème sur un papier crème disparaît.
   La classe .fond-sombre, posée par le générateur quand la luminance mesurée
   du papier descend sous 0,4, rétablit l'inverse — un plan au trait blanc sur
   fond foncé l'exigerait. */
.fermer{position:absolute;z-index:320;
  top:calc(12px + env(safe-area-inset-top));
  right:calc(12px + env(safe-area-inset-right));
  background:rgba(23,19,16,.88);color:#f2e9da;border:0;
  font:inherit;font-size:13.5px;font-weight:600;padding:10px 18px;
  border-radius:999px;cursor:pointer;min-height:44px;
  box-shadow:0 2px 14px rgba(0,0,0,.28)}
.fermer:hover{background:var(--encre)}
.zone-zoom.fond-sombre .fermer,
.zone-zoom.fond-sombre .revoir{background:rgba(242,233,218,.94);
  color:var(--encre)}
.zone-zoom.fond-sombre .fermer:hover,
.zone-zoom.fond-sombre .revoir:hover{background:#fff}
.fermer[hidden]{display:none}
.zone-zoom.plein .revoir{bottom:calc(14px + env(safe-area-inset-bottom))}
.zone-zoom.plein .indice-zoom{display:none}
/* Les plans sont tous en paysage : un cadre carré laisserait deux bandes
   vides. 4/3 colle au format réel des documents.
   Sur grand écran on raisonne en hauteur d'écran et non en ratio : une
   visionneuse de 495 px de haut sur un écran de 1080 est une vignette, et
   le zoom est l'argument de vente de la boutique. */
/* Sur grand ecran on borne par la HAUTEUR d'ecran, mais en calculant la
   largeur correspondante : on garde ainsi le rapport exact du document au lieu
   de rogner la hauteur et de recreer des bandes. */
@media (min-width:980px){
  #visionneuse{width:min(100%,calc(var(--ratio,1.4) * 74vh));
    margin-inline:auto}
}
/* En bas a droite, et non en haut : agrandie, la visionneuse fait passer son
   sommet sous l'en-tete collant, qui captait le clic. Et le bas droit est plus
   accessible au pouce sur un telephone.
   z-index eleve : le canvas d'OpenSeadragon se place au-dessus sinon. */
/* Deux pistes essayees ici et ecartees, pour qu'on ne les retente pas :
   — position:fixed sur le bouton : sur mobile il s'ancre au viewport de MISE
     EN PAGE, distinct de l'ecran visible, et le bouton partait hors champ ;
   — overflow:hidden sur le corps pour verrouiller le defilement : deforme la
     geometrie et reste notoirement capricieux sur iOS.
   Le bouton reste donc ancre dans la visionneuse, qui ne depasse jamais 74 %
   de la hauteur visible : les deux se deplacent ensemble et restent lisibles.
   Le geste de zoom ne propage pas son elan a la page. */
/* touch-action:none sur la visionneuse ET sa descendance : OpenSeadragon y
   insère ses propres éléments, et la propriété ne s'hérite pas. Sans la
   descendance, le geste commence sur un enfant et échappe à la règle.
   Deux pistes écartées, pour qu'on ne les retente pas : position:fixed sur le
   bouton seul (il s'ancre au viewport de MISE EN PAGE, pas à l'écran visible)
   et user-scalable=no (ignoré par Safari, et il confisque le zoom du texte). */
.zone-zoom{overscroll-behavior:contain}
/* UNIQUEMENT en plein ecran. Hors plein ecran, touch-action:none empecherait
   de faire defiler la page en glissant sur le plan : le doigt se pose souvent
   dessus, et la page paraitrait bloquee. La vignette doit se comporter comme
   une image ordinaire. */
.zone-zoom.plein #visionneuse,
.zone-zoom.plein #visionneuse *{touch-action:none}
/* !important assume ici : OpenSeadragon pose touch-action:none en style EN
   LIGNE sur ses propres elements, et un style en ligne bat toute regle de
   feuille. Sans cette surcharge, glisser le doigt sur la vignette ne fait pas
   defiler la page — et le doigt s'y pose tout le temps.
   pan-y et non auto : le defilement vertical passe, le pincement et le
   deplacement horizontal restent neutralises. */
.zone-zoom:not(.plein) #visionneuse,
.zone-zoom:not(.plein) #visionneuse *{touch-action:pan-y !important}
.revoir{position:absolute;bottom:12px;right:12px;z-index:20;
  background:rgba(23,19,16,.86);color:#f2e9da;border:0;
  font:inherit;font-size:13.5px;padding:10px 16px;border-radius:999px;
  cursor:pointer;backdrop-filter:blur(2px);min-height:44px}
.revoir:hover{background:var(--encre)}
.revoir[hidden]{display:none}

/* Bouton d'entrée dans le plein écran. Il remplace le pincement, qui était
   invisible — il fallait le deviner — et entrait en concurrence avec le zoom
   du navigateur. Un bouton dit ce qu'il fait.
   Mêmes mesures que la pastille des vignettes d'accueil (.carte .loupe) :
   11,5 px, 6px 10px, en bas à droite. Le même geste doit avoir partout la
   même apparence, sinon on apprend deux fois la même chose. Seule la zone
   tactile est élargie, par du padding invisible, pour atteindre les 44 px
   recommandés sans grossir la pastille. */
.zoomer{position:absolute;right:10px;bottom:10px;z-index:20;
  background:rgba(23,19,16,.78);color:#fff;border:0;
  font:inherit;font-size:11.5px;letter-spacing:.04em;padding:6px 10px;
  border-radius:999px;display:flex;align-items:center;gap:5px;
  cursor:pointer}
/* La règle générale a,button{min-height:44px} assure les cibles tactiles,
   mais ici elle rendrait la pastille 14 px plus haute que celle de l'accueil.
   On la neutralise pour l'apparence et on rend la zone tactile par un
   pseudo-élément transparent : 62 px de haut atteignables, 30 px visibles. */
.zoomer{min-height:0}
.zoomer::after{content:"";position:absolute;inset:-16px -7px}
.zoomer:hover{background:var(--encre)}
.zoomer[hidden]{display:none}
.zone-zoom.plein .zoomer{display:none}

/* L'indice textuel ne sert plus que sur grand écran, où l'on zoome à la
   molette sans quitter la page : le bouton y serait redondant. */
.indice-zoom{display:none}
@media (min-width:901px){
  .zoomer{display:none}
  .indice-zoom{display:block;position:absolute;left:50%;bottom:14px;
    transform:translateX(-50%);background:rgba(23,19,16,.8);color:#f2e9da;
    font-size:12.5px;padding:7px 14px;border-radius:999px;
    pointer-events:none;white-space:nowrap;transition:opacity .4s}
}

/* --------------------------------------------------------- pages légales --
   Un blanc non comblé doit SE VOIR. Une mention légale fausse engage plus
   qu'une mention absente : on surligne plutôt que d'inventer. */
/* Bouton d'achat desactive : il doit se LIRE comme indisponible, pas comme
   un bouton normal sur lequel on cliquera en vain. */
.cta[disabled]{background:var(--papier-creux);color:var(--estompe);
  border:1px solid var(--trait);cursor:not-allowed;box-shadow:none}
.cta[disabled]:hover{transform:none}
/* Les lots : empiles par defaut, alignes en ligne seulement quand il y a la
   place. Un tableau a cinq colonnes se disloque sous 500 px. */
ul.lots{list-style:none;padding:0;margin:14px 0 0;
  border-top:1px solid var(--trait)}
/* Grille et non flexbox qui s'enroule. Avec un flex-wrap, une ligne sans
   economie a afficher — le lot d'un seul plan — ne se repliait pas comme les
   autres : son prix s'arretait 142 px avant celui des lignes voisines. En
   grille, la derniere colonne finit toujours au bord du conteneur, donc les
   bords droits coincident par construction, quel que soit le contenu. */
.lot{display:grid;grid-template-columns:1fr auto;gap:4px 14px;
  align-items:baseline;padding:14px 0;border-bottom:1px solid var(--trait)}
.lot-nom{font-weight:600}
/* align-items:flex-end — sans quoi le prix se cale a GAUCHE d'une colonne
   dont la largeur suit son texte le plus long. "+ 4,90 € de port" etant plus
   large que "port offert", le 19 € reculait de pres de 50 px et rompait
   l'alignement avec les 29, 39 et 59. Une colonne de prix se lit sur son bord
   droit : c'est la que l'oeil compare. */
.lot-prix{flex:0 0 auto;font-size:19px;font-weight:600;
  display:flex;flex-direction:column;align-items:flex-end;
  line-height:1.25;text-align:right}
.lot-prix small{font-size:12.5px;font-weight:400;color:var(--estompe)}
/* flex-end plutot que space-between : sans economie a afficher — c'est le cas
   du lot d'un seul plan — space-between laissait l'action seule a GAUCHE,
   alors qu'elle est a droite sur toutes les autres lignes. L'economie est
   repoussee a gauche par sa propre marge, ce qui donne le meme resultat quand
   les deux sont presents, et la bonne place quand l'action est seule. */
.lot-fin{grid-column:1/-1;display:flex;justify-content:flex-end;
  align-items:baseline;gap:12px}
.lot-fin .gain{margin-right:auto}
/* Troisieme colonne de largeur FIXE : si elle variait selon la presence d'une
   economie, le bord droit de la colonne des prix bougerait d'une ligne a
   l'autre. */
@media (min-width:560px){
  .lot{grid-template-columns:1fr auto 16ch}
  .lot-fin{grid-column:auto}
}
/* .gain est redefini plus bas en vert ; la regle rouge qui se trouvait ici
   etait morte depuis, et faisait croire a une economie affichee en rouge. */
.lien-lot{color:var(--rouge);font-weight:600;white-space:nowrap}

/* ------------------------------------------------------- guide déballage --
   Les dessins sont en SVG : nets à toute taille, de l'ordre du kilo-octet, et
   le texte à côté reste indexable — un GIF animé serait lourd et invisible au
   référencement. */
ol.etapes{list-style:none;padding:0;margin:34px 0 0;counter-reset:etape}
.etape{display:grid;grid-template-columns:1fr;gap:16px;
  padding:26px 0;border-top:1px solid var(--trait);align-items:center}
@media (min-width:720px){
  .etape{grid-template-columns:200px 1fr;gap:38px;padding:30px 0}
}
.etape-dessin{background:var(--papier-creux);border:1px solid var(--trait);
  border-radius:var(--r);padding:14px;color:var(--encre)}
.etape-dessin svg{display:block;width:100%;height:auto}
.etape-texte h3{font-size:19px;display:flex;align-items:baseline;gap:11px}
.etape-num{flex:0 0 auto;width:26px;height:26px;border-radius:50%;
  background:var(--rouge);color:#fff;font-size:13px;font-weight:600;
  display:inline-flex;align-items:center;justify-content:center;
  font-family:Inter,sans-serif}
.etape-texte p{margin-top:9px;color:var(--encre-douce);line-height:1.68;
  max-width:62ch}
ul.soin{padding-left:20px;margin-top:12px}
ul.soin li{margin-bottom:9px;line-height:1.65;color:var(--encre-douce);
  max-width:66ch}

.ech-note{display:block;margin-top:5px;font-size:12.5px;line-height:1.45;
  color:var(--encre-douce)}

mark.a-completer{background:#fdf0cd;color:#6b4a06;border-bottom:2px solid #d9a441;
  padding:1px 5px;border-radius:2px;font-size:.93em;font-weight:500}
.lire .chapeau{font-size:17px;color:var(--encre-douce);margin-bottom:26px}
.lire h2{font-size:21px;margin:34px 0 10px}
.lire p,.lire li{line-height:1.68}
.lire ul{padding-left:20px;margin-top:8px}
.lire li{margin-bottom:4px}
.lire .note{background:var(--papier-creux);border-left:2px solid var(--rouge);
  padding:12px 16px;margin-top:14px;font-size:14.5px;color:var(--encre-douce)}
.lire details{margin-top:14px;border:1px solid var(--trait);
  border-radius:var(--r);padding:12px 16px}
.lire details summary{cursor:pointer;font-weight:600}
.lire table.fiche-tech{margin-top:12px;font-size:14.5px}

.colonne-achat{padding-top:26px}

/* ------------------------------------------------- texte sous la fiche --
   L'histoire reprend une vraie largeur de lecture au lieu d'etre comprimee
   dans la colonne d'achat, et les caracteristiques tiennent en appoint. */
.apres-zoom{display:grid;grid-template-columns:1fr;gap:34px;
  margin-top:52px;padding-top:40px;border-top:1px solid var(--trait)}
@media (min-width:980px){
  .apres-zoom{grid-template-columns:minmax(0,1fr) minmax(300px,360px);
    gap:64px;align-items:start}
}
.apres-zoom .recit .bloc+.bloc{margin-top:34px}
.apres-zoom .recit p{max-width:68ch}
.fil{font-size:12.5px;color:var(--estompe);letter-spacing:.02em}
.fil a{color:var(--estompe)}
.produit h1{font-size:clamp(27px,6.4vw,41px);margin-top:12px}
.produit .annee-grande{color:var(--rouge);font-weight:600;font-size:13px;
  letter-spacing:.11em}
.produit .resume{color:var(--encre-douce);font-size:17px;margin-top:12px}

.achat{border-top:1px solid var(--trait);border-bottom:1px solid var(--trait);
  padding:20px 0;margin:26px 0}
.prix{display:flex;align-items:baseline;gap:10px}
.prix .montant{font-family:var(--serif);font-size:34px;font-weight:600}
.prix .mention{font-size:14px;color:var(--estompe)}
.rassurance{display:grid;gap:7px;margin-top:15px;font-size:14px;
  color:var(--encre-douce)}
.rassurance div{display:flex;gap:9px;align-items:flex-start}
.rassurance svg{flex:none;margin-top:3px;color:var(--vert)}

.bloc{margin-top:38px}
.bloc h2{font-size:22px;margin-bottom:13px}
.bloc p+p{margin-top:13px}
.bloc p{color:var(--encre-douce);font-size:16px}

.detail{border-top:1px solid var(--trait);padding:18px 0}
.detail:last-child{border-bottom:1px solid var(--trait)}
.detail .num{font-family:var(--serif);font-size:13px;color:var(--rouge);
  font-weight:600}
.detail h3{font-family:var(--sans);font-size:16px;font-weight:600;margin-top:3px}
.detail .ou{font-size:13.5px;color:var(--or);margin-top:3px}
.detail p{font-size:15.5px;color:var(--encre-douce);margin-top:8px}

.fiche-tech{width:100%;border-collapse:collapse;font-size:15px}
.fiche-tech th,.fiche-tech td{text-align:left;padding:11px 0;
  border-bottom:1px solid var(--trait);vertical-align:top}
.fiche-tech th{color:var(--estompe);font-weight:400;width:45%}

.apparte{background:var(--papier-creux);padding:17px 19px;font-size:14.5px;
  color:var(--encre-douce);border-radius:var(--r);margin-top:18px}
.apparte strong{color:var(--encre)}

/* -------------------------------------------------------------- tarifs --- */
.deux-cols{display:grid;gap:38px;grid-template-columns:1fr;margin-top:30px;
  align-items:start}
@media (min-width:860px){.deux-cols{grid-template-columns:1fr 1.1fr;gap:56px}}
/* Sans ceci, la table s'étire pour égaler la hauteur de la colonne voisine et
   ses lignes se retrouvent séparées par de grands vides. */
.deux-cols>*{align-self:start}
.deux-cols .fiche-tech{height:auto}

.tarifs{display:grid;gap:0;margin-top:26px;border-top:1px solid var(--trait)}
.tarif{display:flex;justify-content:space-between;align-items:baseline;gap:16px;
  padding:15px 0;border-bottom:1px solid var(--trait)}
.tarif .quoi{font-size:16px}
.tarif .quoi small{display:block;color:var(--estompe);font-size:13.5px;
  margin-top:2px}
.tarif .combien{font-family:var(--serif);font-size:21px;font-weight:600;
  white-space:nowrap;font-variant-numeric:tabular-nums}
.tarif.phare{position:relative}
.tarif.phare::before{content:"";position:absolute;inset:-1px -16px;
  background:rgba(155,44,28,.055);border-left:2px solid var(--rouge);
  pointer-events:none}
.tarif.phare>*{position:relative}
.gain{color:var(--vert);font-size:13.5px;font-weight:600}

/* ----------------------------------------------------------------- FAQ --- */
details{border-bottom:1px solid var(--trait)}
summary{cursor:pointer;padding:17px 0;font-weight:600;font-size:16.5px;
  list-style:none;display:flex;justify-content:space-between;gap:16px;
  align-items:center;min-height:44px}
summary::-webkit-details-marker{display:none}
summary::after{content:"+";font-size:21px;color:var(--rouge);flex:none;
  font-family:var(--serif)}
details[open] summary::after{content:"–"}
details p{padding-bottom:17px;color:var(--encre-douce);font-size:15.5px}

/* -------------------------------------------------------------- pied ----- */
.pied{background:var(--encre);color:#cfc5b6;margin-top:72px;
  padding:46px 0 38px;font-size:14.5px}
.pied a{color:#cfc5b6;text-decoration:none}
.pied a:hover{color:#fff;text-decoration:underline}
.pied .cols{display:grid;gap:30px;grid-template-columns:1fr}
@media (min-width:700px){.pied .cols{grid-template-columns:2fr 1fr 1fr}}
.pied h4{font-family:var(--sans);font-size:13px;letter-spacing:.09em;
  text-transform:uppercase;color:#8d8275;margin:0 0 11px;font-weight:600}
.pied ul{list-style:none;padding:0;margin:0;display:grid;gap:8px}
.pied .mentions{border-top:1px solid #2e2821;margin-top:34px;padding-top:20px;
  font-size:12.5px;color:#8d8275}

.alerte{background:#fdf3d6;border:1px solid #d9bd79;color:#5e4a15;
  padding:14px 17px;border-radius:var(--r);font-size:14.5px;margin:22px 0}
