/* Fiche produit — mise en page inspirée d'Exaprint.
   Servie sur les 68 fiches depuis le 17/09/2026 ; elle s'appelait `essai.css`
   du temps où ce n'était qu'une maquette.
   ⚠️ Le préfixe des classes est resté `ex-` (pour « essai »). Le renommer
   toucherait deux gabarits, un script en ligne et cette feuille : le risque
   d'en oublier un dépasse le bénéfice. Ce n'est qu'un préfixe. */

/* Sans le bandeau de titre, la marge haute de `.section` (jusqu'à 5 rem)
   laissait un grand vide : la page doit démarrer tout de suite. */
.ex-section { padding-top: 1.1rem; }
.ex-fil { margin: 0 0 1rem; font-size: .85rem; }

.ex-avertissement { background: #FFF8E1; border: 1px solid #F0C24B; border-radius: 8px;
  padding: .7rem 1rem; font-size: .9rem; margin: 0 0 1.6rem; }

/* ---- haut de page : photo + présentation ---- */
.ex-haut { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
  gap: 2rem; align-items: start; margin-bottom: 2.2rem; }
.ex-photo { background: var(--c-gray-50, #fafafa); border: 1px solid var(--c-gray-200, #e6e6e6);
  border-radius: 12px; overflow: hidden; }
.ex-photo img { width: 100%; height: auto; display: block; }
.ex-titre { margin: 0 0 .6rem; font-size: 2rem; line-height: 1.15; }
/* Ce n'est plus une promesse commerciale mais le résumé du produit : il se lit
   comme un chapeau, pas comme une pastille. */
.ex-inclus { margin: 0 0 1.4rem; color: var(--c-gray-700, #555); font-size: 1rem;
  line-height: 1.45; }

.ex-onglets { display: flex; gap: 1.6rem; border-bottom: 1px solid var(--c-gray-200, #e6e6e6);
  margin-bottom: 1.1rem; }
.ex-onglet { background: none; border: 0; padding: .6rem 0; font: inherit; font-weight: 600;
  color: var(--c-gray-600, #666); cursor: pointer; border-bottom: 3px solid transparent;
  margin-bottom: -1px; }
.ex-onglet.is-actif { color: var(--c-magenta, #e5007d); border-bottom-color: var(--c-magenta, #e5007d); }
.ex-volet p, .ex-volet li { line-height: 1.65; }
.ex-usages { margin: .9rem 0 0; padding-left: 1.1rem; list-style: disc; }

/* ---- les trois colonnes ---- */
.ex-config { display: grid; grid-template-columns: 1.25fr .7fr 1.25fr; gap: 1.4rem;
  align-items: start; }
.ex-colonne { border: 1px solid var(--c-gray-200, #e6e6e6); border-radius: 12px; padding: 1.1rem 1.2rem; }
.ex-etape { display: flex; align-items: center; gap: .55rem; margin: 0 0 1rem;
  font-size: 1.08rem; line-height: 1.2; }
.ex-etape span { flex: none; width: 1.7rem; height: 1.7rem; border-radius: 50%;
  background: var(--c-black, #1a1a1a); color: #fff; display: grid; place-items: center;
  font-size: .9rem; font-weight: 700; }

/* ⚠️ La colonne de valeur doit pouvoir s'étendre : avec un `auto`, le menu
   déroulant était rogné et « Sans plastification » s'affichait « Sans plastificati ». */
.ex-ligne { display: grid; grid-template-columns: 1.5rem auto minmax(0, 1fr); align-items: center;
  gap: .6rem; padding: .6rem .7rem; border: 1px solid var(--c-gray-200, #e6e6e6);
  border-radius: 9px; margin-bottom: .55rem; }
.ex-num { width: 1.5rem; height: 1.5rem; border-radius: 50%; background: var(--c-gray-100, #f0f0f0);
  display: grid; place-items: center; font-size: .78rem; font-weight: 700; color: #555; }
.ex-ligne label { font-weight: 600; font-size: .92rem; white-space: nowrap; }
.ex-choix { justify-self: end; text-align: right; }
.ex-choix select { width: 100%; max-width: 100%; font-weight: 600; color: var(--c-magenta, #e5007d);
  border: 0; background: none; text-align: right; font-size: .92rem; cursor: pointer; }
.ex-choix input:not(.ex-dim input) { width: 4.6rem; text-align: right; font-weight: 600;
  color: var(--c-magenta, #e5007d); border: 1px solid var(--c-gray-300, #ccc);
  border-radius: 6px; padding: .25rem .4rem; }

.ex-fichier-txt { margin: 0 0 .9rem; font-size: .9rem; line-height: 1.55; }
.ex-bloc { width: 100%; }
.ex-note { margin: .9rem 0 0; font-size: .8rem; color: var(--c-gray-600, #666); line-height: 1.5; }

/* ---- la grille quantité × délai ---- */
.ex-scroll { overflow-x: auto; overflow-y: visible; padding-top: 2.1rem; }
/* ⚠️ `overflow-x: auto` force `overflow-y` à `auto` par défaut (jamais
   `visible`), qui rognait le badge « Top choix » positionné au-dessus de
   l'en-tête — `overflow-y: visible` + `padding-top` corrigent ça. */
.ex-grille { width: 100%; border-collapse: separate; border-spacing: .35rem; }
.ex-grille th, .ex-grille td { padding: 0; }
.ex-vitesse { border-radius: 8px; padding: .5rem .6rem; font-size: .82rem; line-height: 1.35;
  vertical-align: top; }
.ex-vitesse-0 { background: #D8F5E3; }          /* le plus lent, le moins cher */
.ex-vitesse-1 { background: #FFE3EC; }          /* le plus rapide */
.ex-vitesse-2 { background: #FFD9A0; }          /* urgence */
/* ⭐⭐⭐⭐ 13/10/2026, demandé par Julien : badge « Top choix » sur la colonne
   Rapide (envoi_exp), repris de celui de Realisaprint au-dessus de leur
   colonne Express. Porté depuis doemo-print.fr. */
.ex-vitesse-recommandee { position: relative; overflow: visible; padding-top: 2rem; }
.ex-vitesse-badge { position: absolute; top: -1.75rem; left: 50%; transform: translateX(-50%);
  display: inline-flex; align-items: center; gap: .3rem;
  background: linear-gradient(180deg, #c6a15a, #a9823f); color: #fff; font-weight: 800;
  font-size: .72rem; letter-spacing: .03em; text-transform: uppercase; white-space: nowrap;
  padding: .32rem .75rem; border-radius: 999px; box-shadow: 0 2px 5px rgba(0,0,0,.3);
  border: 2px solid #fff; }
.ex-vitesse-badge::before { content: '★'; font-size: .8rem; }
@media (max-width: 480px) {
  .ex-vitesse-badge { font-size: .62rem; padding: .25rem .5rem; gap: .2rem; }
  .ex-vitesse-badge::before { font-size: .68rem; }
}
/* ⭐⭐⭐⭐ 13/10/2026 — « Urgence » en rouge, comme chez Realisaprint. */
.ex-vitesse-2 .ex-vitesse-nom { color: #D7342A; }
.ex-vitesse-nom { display: block; font-weight: 700; font-size: .92rem; margin-bottom: .25rem; }
.ex-vitesse-date { display: block; color: #444; font-weight: 400; }
.ex-grille tbody th { font-weight: 700; text-align: center; padding: .55rem;
  border: 1px solid var(--c-gray-200, #e6e6e6); border-radius: 8px; }
.ex-prix { width: 100%; padding: .6rem .5rem; font: inherit; font-weight: 600; font-size: .95rem;
  background: #fff; border: 1px solid var(--c-gray-200, #e6e6e6); border-radius: 8px;
  cursor: pointer; transition: border-color .15s, background .15s; }
.ex-prix:hover { border-color: var(--c-magenta, #e5007d); background: #fff6fa; }

@media (max-width: 1100px) {
  .ex-config { grid-template-columns: 1fr 1fr; }
  .ex-colonne-prix { grid-column: 1 / -1; }
}
@media (max-width: 760px) {
  .ex-haut, .ex-config { grid-template-columns: 1fr; }
  .ex-colonne-prix { grid-column: auto; }
}

/* ---- colonne de droite : la quantité, puis le fichier dessous ---- */
.ex-config { grid-template-columns: 1.15fr 1.6fr; }
.ex-droite { display: flex; flex-direction: column; gap: 1.4rem; min-width: 0; }
/* ⚠️⚠️ 26/09/2026, signalé par Julien : ce 2ᵉ jeu de colonnes n'en portait que
   deux, sans piste pour le 3ᵉ enfant de `.ex-ligne` (le champ lui-même) — un
   `<input>` sans piste dédiée retombe sur sa taille par défaut du navigateur,
   minuscule. C'est ce qui rendait « Répartition des tailles » quasi
   inutilisable. Même 3 colonnes que la règle de base : celle-ci ne fait plus
   que ce que son nom promet, un plus grand espace pour le libellé. */
.ex-ligne-large { grid-template-columns: 1.5rem auto minmax(0, 1fr); }
/* 26/09/2026 : le libellé garde son `white-space: nowrap` sur `.ex-ligne`, ce
   qui force sa colonne « auto » à la largeur du texte entier ; sur mobile ça
   n'en laisse presque plus pour le champ (l'input restait écrasé à ~16px
   malgré la piste minmax ci-dessus). On empile le champ sur sa propre ligne
   en dessous, pleine largeur, dès que l'écran est étroit. */
@media (max-width: 480px) {
  .ex-ligne-large { grid-template-columns: 1.5rem 1fr; }
  .ex-ligne-large .ex-champ { grid-column: 1 / -1; margin-top: .35rem; }
}
.ex-formats { grid-column: 1 / -1; display: flex; flex-wrap: wrap; gap: .4rem; margin-top: .5rem; }
.ex-format { font: inherit; font-size: .85rem; font-weight: 600; padding: .35rem .7rem;
  border: 1px solid var(--c-gray-300, #ccc); border-radius: 999px; background: #fff;
  cursor: pointer; white-space: nowrap; transition: background .15s, border-color .15s, color .15s; }
.ex-format:hover { border-color: var(--c-magenta, #e5007d); }
.ex-format.is-actif { background: var(--c-magenta, #e5007d); border-color: var(--c-magenta, #e5007d);
  color: #fff; }
/* La ligne de quantité libre : une saisie là où les autres ont un chiffre. */
.ex-ligne-perso th { padding: 0; }
#ex-qte-perso { width: 100%; padding: .5rem; text-align: center; font: inherit; font-weight: 700;
  border: 1px dashed var(--c-magenta, #e5007d); border-radius: 8px; color: var(--c-magenta, #e5007d); }
.ex-prix[disabled] { color: var(--c-gray-400, #aaa); cursor: default; background: #fbfbfb; }
.ex-prix[disabled]:hover { border-color: var(--c-gray-200, #e6e6e6); background: #fbfbfb; }

@media (max-width: 1100px) {
  .ex-config { grid-template-columns: 1fr; }
  .ex-colonne-prix { grid-column: auto; }
}

/* Les dimensions sur mesure passent sous leur libellé, comme les formats
   courants : à l'étroit, le « cm » tombait tout seul à la ligne suivante. */
/* Les deux cadres de dimension, centrés sous leur libellé. */
.ex-dims { grid-column: 1 / -1; justify-self: stretch; margin-top: .7rem;
  display: flex; align-items: flex-start; justify-content: center; gap: .7rem; }
/* ⭐ 24/09/2026 — bascule « sur mesure » d'étiquettes-rouleau : une case à
   cocher NICHÉE dans `.ex-choix` (pas d'office grid item, donc `.ex-dims`
   ci-dessus ne s'y applique que pour son alignement, pas son placement). */
.ex-mesure-bascule { display: inline-flex; align-items: center; gap: .45rem;
  font-weight: 600; font-size: .92rem; cursor: pointer; }
.ex-mesure-bascule input { width: auto; margin: 0; }
.ex-dim { display: flex; flex-direction: column; align-items: center; gap: .3rem; }
.ex-dim input { width: 6.4rem; height: 2.7rem; padding: 0 .5rem; text-align: center;
  font: inherit; font-size: 1.05rem; font-weight: 700; color: var(--c-magenta, #e5007d);
  background: #fff; border: 1.5px solid var(--c-gray-300, #ccc); border-radius: 10px;
  transition: border-color .15s, box-shadow .15s; }
.ex-dim input:hover { border-color: #9aa0a6; }
.ex-dim input:focus { outline: none; border-color: var(--c-magenta, #e5007d);
  box-shadow: 0 0 0 3px rgba(229, 0, 125, .14); }
/* La flèche des champs numériques mange la place et déséquilibre le centrage. */
.ex-dim input::-webkit-outer-spin-button,
.ex-dim input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.ex-dim input[type=number] { -moz-appearance: textfield; appearance: textfield; }
.ex-dim-nom { font-size: .72rem; font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; color: var(--c-gray-600, #666); }
/* ⚠️ Le « × » se centre sur le CHAMP, pas sur la colonne champ + légende. Une
   marge négative « au jugé » ne tombe jamais juste : elle dépend des métriques
   de la police. On donne donc au champ une hauteur explicite (2,7 rem) et on
   centre le « × » dans cette même hauteur — c'est exact par construction. */
.ex-dim-x { align-self: flex-start; display: flex; align-items: center; height: 2.7rem;
  font-size: 1.05rem; font-weight: 600; color: var(--c-gray-400, #aaa); }
/* ⚠️ Un `<select>` ne sait pas mettre de points de suspension : c'est le corps
   qu'il faut réduire, sinon « Contrôle de base — offert » se coupe net. */
.ex-choix select { font-size: .87rem; }
/* L'unité, en gris : elle précise sans alourdir le libellé. */
.ex-unite { font-weight: 500; color: var(--c-gray-600, #666); }

/* =====================================================================
   Passage en service sur les 68 fiches — 17/09/2026
   Ce que la maquette n'avait pas à porter et que la fiche en service doit.
   ===================================================================== */

/* ⚠️ Le prix TTC N'EST PAS décoratif : la boutique vend aussi à des
   particuliers, pour qui l'affichage toutes taxes comprises est obligatoire.
   Il tient sous le prix HT, dans le même bouton. */
.ex-prix { line-height: 1.25; }
.ex-prix-ht  { display: block; }
.ex-prix-ttc { display: block; font-weight: 500; font-size: .78rem;
  color: var(--c-gray-600, #666); }
.ex-prix[disabled] .ex-prix-ttc { color: var(--c-gray-400, #aaa); }

/* Une configuration refusée par le moteur de prix se dit, elle ne se devine
   pas dans une grille restée sur d'anciens chiffres. */
.ex-erreur { margin: .8rem 0 0; padding: .6rem .8rem; border-radius: 8px;
  background: #FDECEF; border: 1px solid #F3B7C2; color: #9B1B36;
  font-size: .9rem; font-weight: 600; }

/* Bornes du support, et aide d'un groupe d'options. */
.ex-aide { margin: .5rem 0 0; font-size: .82rem; color: var(--c-gray-600, #666); }
/* Le champ de la répartition des tailles : occupe la piste que lui donne
   désormais `.ex-ligne-large`, au lieu de sa taille par défaut. */
.ex-champ { display: block; }
.ex-champ input[type="text"] { width: 100%; padding: .45rem .6rem; font-size: .9rem;
  border: 1px solid var(--c-gray-300, #ccc); border-radius: 6px; }
.ex-aide-choix { display: block; margin-top: .3rem; font-size: .78rem;
  line-height: 1.35; color: var(--c-gray-600, #666); }
.ex-fixe { font-size: .9rem; color: var(--c-gray-700, #555); }

/* ⭐⭐ 26/09/2026 : la sélection couleur / taille / quantité des fiches
   textile (ex-ligne-ct). ⚠️⚠️ 26/09/2026, signalé par Julien : un tableau à
   colonnes ("Couleur | Taille | Quantité" côte à côte) débordait — cette
   colonne de configuration ne fait qu'environ 230px de large, bien trop
   étroit pour 3 select + bouton en ligne. Chaque sélection est donc une
   petite carte avec ses champs EMPILÉS (jamais côte à côte, à n'importe
   quelle largeur) : robuste sans media query. */
.ex-ct-lignes { display: flex; flex-direction: column; gap: .5rem; }
.ex-ct-ligne { position: relative; background: var(--c-gray-100, #f4f4f4);
  border-radius: 8px; padding: .6rem .6rem .5rem; display: flex; flex-direction: column; gap: .4rem; }
.ex-ct-champ { display: block; font-size: .74rem; font-weight: 600;
  color: var(--c-gray-600, #666); }
.ex-ct-couleur, .ex-ct-taille, .ex-ct-qte { display: block; width: 100%; margin-top: .2rem;
  padding: .45rem .6rem; font-size: .88rem; font-weight: 400; color: inherit;
  border: 1px solid var(--c-gray-300, #ccc); border-radius: 6px; background: #fff;
  box-sizing: border-box; }
.ex-ct-qte { text-align: left; }
.ex-ct-suppr { position: absolute; top: .4rem; right: .4rem; width: 1.8rem; height: 1.8rem;
  border: none; background: transparent; color: var(--c-gray-500, #888); font-size: 1.2rem;
  line-height: 1; cursor: pointer; border-radius: 6px; }
.ex-ct-suppr:hover { background: var(--c-gray-200, #e8e8e8); color: var(--c-magenta, #e5007d); }
/* ⚠️⚠️ 26/09/2026 : un <button> ne rétrécit ni ne renvoie à la ligne son
   texte — sans largeur imposée il déborde de sa colonne (minmax(0, 1fr)
   n'empêche que la piste de grille de grandir, pas ses enfants de dépasser).
   Signalé par Julien : le bouton traversait la ligne verticale de séparation
   avec la colonne suivante. */
#ex-ct-ajouter { display: block; width: 100%; box-sizing: border-box;
  margin-top: .2rem; text-align: center; white-space: normal; }
.ex-ligne-ct, .ex-ligne-ct .ex-champ, .ex-ct-lignes, .ex-ct-ligne { min-width: 0; max-width: 100%; box-sizing: border-box; }

/* La vignette du choix courant, sous la liste déroulante. Les pièces achetées
   sont détourées sur fond transparent : un cadre clair les pose sans les
   enfermer, et la légende n'est pas nécessaire — le libellé est juste au-dessus.

   ⚠️⚠️ `[hidden]` EST NEUTRALISÉ PAR UN `display`. Les vignettes non choisies
   portent l'attribut `hidden` ; sans la règle ci-dessous, le `display:block`
   les rendrait TOUTES visibles d'un coup. Ce piège a déjà mordu deux fois
   ailleurs, il est désamorcé d'emblée. */
.ex-vignettes { display: block; margin-top: .45rem; }
.ex-vignettes img { display: block; width: 120px; height: 120px; object-fit: contain;
  padding: 6px; border: 1px solid var(--c-gray-200, #E4E7EB); border-radius: 10px;
  background: #FFF; }
.ex-vignettes img[hidden] { display: none !important; }

/* ⭐⭐ GRILLE DE VIGNETTES CLIQUABLES (façon Realisaprint) — 22/09/2026.
   Le `<select>` reste dans le DOM pour porter la valeur et l'évènement
   `change` (configurateur.js les écoute), mais il est caché VISUELLEMENT,
   pas avec `display:none` : un `display:none` sort l'élément du flux
   d'accessibilité dans certains lecteurs d'écran et peut geler sa valeur
   dans quelques moteurs mobiles. `position:absolute` + `clip` le retire de
   l'écran sans le retirer du DOM ni de l'arbre d'accessibilité. */
.ex-select-cache { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.ex-ligne-grille { align-items: start; }
.ex-ligne-grille .ex-choix { justify-self: stretch; text-align: left; }
.ex-grille-vignettes { display: grid; grid-template-columns: repeat(auto-fill, minmax(6.4rem, 1fr));
  gap: .5rem; }
.ex-vignette-choix { display: flex; flex-direction: column; align-items: center; gap: .3rem;
  padding: .55rem .4rem .5rem; border: 1.5px solid var(--c-gray-300, #ccc); border-radius: 10px;
  background: #fff; cursor: pointer; font: inherit; text-align: center;
  transition: border-color .15s, background .15s, box-shadow .15s; }
.ex-vignette-choix:hover { border-color: var(--c-magenta, #e5007d); }
.ex-vignette-choix.is-actif { border-color: var(--c-magenta, #e5007d); background: #fff6fa;
  box-shadow: 0 0 0 2px rgba(229, 0, 125, .14); }
.ex-vignette-icone { width: 2.6rem; height: 2.6rem; color: var(--c-gray-600, #666); }
.ex-vignette-choix.is-actif .ex-vignette-icone { color: var(--c-magenta, #e5007d); }
.ex-vignette-icone svg { width: 100%; height: 100%; }
.ex-vignette-libelle { font-size: .74rem; font-weight: 600; line-height: 1.25; color: var(--c-gray-700, #444); }
.ex-vignette-choix.is-actif .ex-vignette-libelle { color: var(--c-magenta, #e5007d); }
.ex-vignette-supplement { font-size: .68rem; font-weight: 500; color: var(--c-gray-600, #666); }

/* L'encart des produits composables, entre la présentation et le configurateur.
   ⚠️ Sa mise en page d'origine (`boutique.css`) réservait 34 % de la largeur à
   la miniature. Elle vivait alors dans la colonne de description, étroite ; en
   pleine largeur de page cela donnait un visuel de 384 px et un encart de
   335 px de haut — aussi encombrant que toute la présentation du produit.
   Ici c'est un BANDEAU : miniature calibrée, texte au milieu, bouton à droite. */
.ex-composer { margin: 0 0 1.6rem; padding: 1rem 1.3rem;
  grid-template-columns: 160px minmax(0, 1fr) auto; gap: 1.3rem; align-items: center; }
/* ⚠️ 160 px est un COMPROMIS mesuré, pas un chiffre rond. En dessous de ~140 px
   la miniature du calendrier n'est plus qu'une trame grise ; au-dessus de
   ~175 px un format carré (pictogramme, numéro de chambre) devient plus haut
   que la colonne de texte et c'est lui qui dicte la hauteur du bandeau.
   ⚠️ La vignette est dimensionnée en `cqw` : sa largeur commande TOUT ce
   qu'elle contient. La rétrécir ne recadre pas, elle réduit. */
.ex-composer .bq-composer-visuel { width: 160px; }
.ex-composer .bq-composer-tag { font-size: .62rem; padding: .15rem .5rem; margin-bottom: .35rem; }
.ex-composer h2 { margin: 0 0 .3rem; font-size: 1.1rem; }
.ex-composer p { margin: 0; font-size: .89rem; line-height: 1.5; }
.ex-composer .btn { margin: 0; white-space: nowrap; }
.ex-composer .bq-composer-note { margin: .35rem 0 0 !important;
  font-size: .78rem; line-height: 1.4; }
/* Le crayon suit la miniature : à 160 px, son diamètre d'origine la mangeait. */
.ex-composer .bq-composer-curseur { width: 28px; height: 28px; font-size: .85rem;
  right: -9px; bottom: -9px; }

@media (max-width: 860px) {
  /* Le bouton repasse sous le texte avant que la colonne du milieu ne s'étrangle. */
  .ex-composer { grid-template-columns: 110px minmax(0, 1fr); }
  .ex-composer .bq-composer-visuel { width: 110px; grid-row: 1 / span 2; }
  .ex-composer .btn { grid-column: 2; justify-self: start; }
}
@media (max-width: 560px) {
  .ex-composer { grid-template-columns: 1fr; gap: 1rem; }
  .ex-composer .bq-composer-visuel { width: 150px; margin-inline: auto; grid-row: auto; }
  /* ⚠️⚠️ REMETTRE `grid-column` à 1. Les deux paliers s'appliquent ensemble sous
     560 px : sans cette ligne, le `grid-column: 2` du palier 860 px survit, crée
     une deuxième colonne à la largeur naturelle du bouton (281 px) et fait
     déborder tout l'encart hors de son cadre. Mesuré : 1 613 éléments au-delà
     du bord droit, sur une colonne qui n'en fait que 300. */
  .ex-composer .btn { grid-column: 1; justify-self: stretch; text-align: center; }
}

/* ---------- loupe : agrandir une photo ou un aperçu ----------
   Servie par `assets/loupe.js`, sur la fiche produit comme sur la page de
   composition. Les styles vivent ici parce que les deux pages chargent déjà
   cette feuille. */
.loupe-zone { position: relative; cursor: zoom-in; }
.loupe-bouton { position: absolute; right: .6rem; bottom: .6rem; z-index: 2;
  display: inline-flex; align-items: center; justify-content: center;
  width: 2.2rem; height: 2.2rem; padding: 0; cursor: zoom-in;
  color: #1a1a1a; background: rgba(255, 255, 255, .92);
  border: 1px solid var(--c-gray-300, #ccc); border-radius: 50%;
  box-shadow: 0 2px 8px rgba(0, 0, 0, .18);
  transition: background .15s, color .15s, border-color .15s; }
.loupe-bouton:hover, .loupe-bouton:focus-visible {
  color: #fff; background: var(--c-magenta, #e5007d); border-color: var(--c-magenta, #e5007d); }

.loupe { width: min(96vw, 1500px); max-width: 96vw; max-height: 94vh; padding: 0;
  border: none; border-radius: 14px; background: #fff;
  box-shadow: 0 24px 70px rgba(0, 0, 0, .35); overflow: hidden; }
.loupe::backdrop { background: rgba(12, 12, 14, .72); }
.loupe-barre { display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; padding: .7rem 1rem; border-bottom: 1px solid var(--c-gray-200, #e6e6e6); }
.loupe-titre { margin: 0; font-weight: 700; font-size: .95rem; }
.loupe-fermer { width: 2rem; height: 2rem; padding: 0; font: inherit; font-size: 1rem;
  line-height: 1; cursor: pointer; color: #1a1a1a; background: #fff;
  border: 1px solid var(--c-gray-300, #ccc); border-radius: 50%; }
.loupe-fermer:hover, .loupe-fermer:focus-visible {
  color: #fff; background: #1a1a1a; border-color: #1a1a1a; }
/* ⚠️ Le corps doit pouvoir défiler : un aperçu en portrait dépasse la hauteur
   de l'écran une fois élargi. */
.loupe-corps { padding: 1.1rem; overflow: auto; max-height: calc(94vh - 3.6rem); }
.loupe-corps > img { display: block; width: auto; height: auto; margin: 0 auto; }
/* L'aperçu composé, DÉPLACÉ ici : il est dimensionné en `cqw`, donc lui donner
   toute la largeur suffit à l'agrandir. Sa rotation d'encart n'a plus lieu
   d'être — on regarde le support, pas une vignette posée sur un bureau. */
.loupe-corps > * { max-width: 100%; margin: 0 auto; transform: none !important; }

@media (max-width: 560px) {
  .loupe { width: 100vw; max-width: 100vw; max-height: 100vh; border-radius: 0; }
  .loupe-corps { max-height: calc(100vh - 3.6rem); padding: .6rem; }
}

/* ---------- Studio : la page des outils ----------
   Chaque carte porte une VIGNETTE qui montre ce que l'outil fait. Du SVG, pas
   une photo : ça pèse quelques centaines d'octets, ça reste net à toute taille,
   et surtout ça dit quelque chose. */
.st-section { padding-top: 1.4rem; }

.st-tete { max-width: 46rem; margin: .4rem auto 2.4rem; text-align: center; }
.st-tete h1 { margin: 0 0 .9rem; font-size: clamp(2rem, 4.6vw, 3.1rem); line-height: 1.08; }
.st-tete h1 span { color: var(--c-magenta, #e5007d); }
.st-chapo { margin: 0 auto; max-width: 38rem; font-size: 1.08rem; line-height: 1.6;
  color: var(--c-gray-700, #555); }
.st-pastilles { display: flex; flex-wrap: wrap; justify-content: center; gap: .5rem;
  margin: 1.2rem 0 0; }
.st-pastille { padding: .3rem .8rem; border-radius: 99px; font-size: .78rem; font-weight: 700;
  letter-spacing: .02em; }
.st-p-gratuit { color: #0a7d3f; background: #e4f6ec; }
.st-p-compte  { color: #0a5c86; background: #e3f2fa; }
.st-p-garde   { color: #9b1b63; background: #fdeaf4; }

/* ---- l'outil mis en avant ---- */
.st-vedette { display: grid; grid-template-columns: 1.1fr .9fr; gap: 1.6rem; align-items: center;
  margin-bottom: 2.4rem; padding: 2rem 2.2rem; border-radius: 20px;
  color: #fff; text-decoration: none;
  background: linear-gradient(120deg, #0089bd 0%, #7b3fa8 52%, #e5007d 100%);
  box-shadow: 0 14px 38px rgba(123, 63, 168, .22);
  transition: transform .18s, box-shadow .18s; }
.st-vedette:hover, .st-vedette:focus-visible { text-decoration: none; transform: translateY(-3px);
  box-shadow: 0 18px 46px rgba(123, 63, 168, .3); }
.st-vedette-etiquette { display: inline-block; margin-bottom: .7rem; padding: .25rem .7rem;
  border-radius: 99px; font-size: .72rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .06em; color: #fff; background: rgba(255, 255, 255, .22); }
.st-vedette h2 { margin: 0 0 .5rem; color: #fff; font-size: clamp(1.4rem, 2.6vw, 1.95rem);
  line-height: 1.18; }
.st-vedette p { margin: 0 0 1.1rem; font-size: .98rem; line-height: 1.58;
  color: rgba(255, 255, 255, .92); }
.st-vedette-btn { display: inline-block; padding: .62rem 1.2rem; border-radius: 10px;
  font-weight: 700; color: #1a1a1a; background: #fff; }
.st-vedette-img { display: flex; justify-content: center; }
/* ⚠️ La vignette du vérificateur est dessinée sur fond clair : posée sur le
   dégradé, elle a besoin de son propre fond pour rester lisible. */
.st-vedette-img svg { width: 100%; max-width: 20rem; border-radius: 14px; background: #f7f7fa;
  box-shadow: 0 10px 26px rgba(0, 0, 0, .18); }

/* ---- la grille ---- */
.st-grille { display: grid; gap: 1.4rem; margin-bottom: 2.8rem;
  grid-template-columns: repeat(auto-fill, minmax(17rem, 1fr)); }
/* Trois par rangée, deux rangées : la disposition demandée. */
.st-grille-3 { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 980px) { .st-grille-3 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 620px) { .st-grille-3 { grid-template-columns: 1fr; } }
@media (max-width: 760px) { .st-vedette { grid-template-columns: 1fr; padding: 1.6rem; } }

/* ---------- les cartes d'outil, au style des cartes de partage ----------

   ⭐ MÊME IDENTITÉ QUE LES IMAGES OPEN GRAPH (`bin-og.php`) : fond noir, lueur
   diagonale dans la couleur de l'outil, filet cyan/magenta/jaune en tête, titre
   en Barlow Condensed. Une carte partagée sur LinkedIn et la carte de la page
   se ressemblent — c'est la même maison, et le visiteur qui arrive par le
   partage retrouve ce qu'il a vu.

   ⚠️ `--acc` est posé EN LIGNE par la vue, une couleur par outil. Le dégradé
   la consomme via `color-mix` : pas de second réglage à tenir à jour.
   ⚠️ `overflow: hidden` : la vignette va bord à bord, elle doit être rognée
   par les coins arrondis. */
.st-carte { --acc: var(--c-cyan, #00AEEF);
  position: relative; display: flex; flex-direction: column; overflow: hidden;
  text-decoration: none; border-radius: 16px; border: 1px solid #2b2b33;
  color: #fff;
  /* ⚠️ La lueur doit se VOIR : à 26 % sur 62 % de course elle passait pour du
     noir uni, et les six cartes se ressemblaient toutes. Mesuré à l'écran,
     pas supposé. */
  background:
    radial-gradient(135% 110% at 100% 0%, color-mix(in srgb, var(--acc) 38%, transparent) 0%, transparent 70%),
    #1A1A1A;
  box-shadow: 0 2px 10px rgba(0, 0, 0, .18);
  transition: border-color .18s, box-shadow .18s, transform .18s; }

/* Le filet de la maison, en tête de carte — exactement comme sur les cartes
   de partage. Trois tiers égaux, en pseudo-élément pour ne rien ajouter au
   balisage. */
.st-carte::before { content: ""; position: absolute; inset: 0 0 auto; height: 5px;
  background: linear-gradient(90deg,
    var(--c-cyan, #00AEEF) 0 33.33%, var(--c-magenta, #EC008C) 33.33% 66.66%,
    var(--c-yellow, #F5C300) 66.66% 100%); z-index: 2; }

a.st-carte:hover, a.st-carte:focus-visible {
  border-color: var(--acc); transform: translateY(-3px); text-decoration: none;
  box-shadow: 0 16px 38px rgba(0, 0, 0, .35); }

/* ⚠️ Les vignettes sont dessinées pour un fond CLAIR (page blanche, damier,
   traits gris). On leur garde donc leur propre fond clair plutôt que de les
   repeindre : les redessiner en clair sur noir, c'est six SVG à refaire et
   autant d'occasions de casser ce qu'ils montrent. */
.st-vignette { display: block; margin: 5px .9rem 0; border-radius: 10px;
  background: #f7f7fa; overflow: hidden; }
.st-v { display: block; width: 100%; height: auto; }

.st-corps { display: flex; flex-direction: column; gap: .5rem; flex: 1;
  padding: 1.1rem 1.35rem 1.35rem; }
.st-titre { margin: 0; color: #fff; line-height: 1.1;
  font-family: var(--font-head, inherit); font-size: 1.5rem;
  letter-spacing: .01em; text-transform: none; }
/* ⚠️ #d4d4dd et non #c8c8d2 : mesuré, le gris plus sombre tombait à 4,05:1
   sur la zone la plus teintée de la carte JAUNE — sous le seuil AA de 4,5.
   Le jaune est l'accent qui éclaircit le plus le fond, c'est donc lui qui
   fixe la couleur du texte pour les six. */
.st-texte { margin: 0; flex: 1; font-size: .92rem; line-height: 1.55;
  color: #d4d4dd; }
/* ⚠️⚠️ L'ACCENT PUR NE PASSE PAS EN TEXTE. Mesuré : le magenta #EC008C sur le
   fond sombre donne 3,9:1, sous le seuil AA de 4,5. On l'éclaircit de 25 % de
   blanc pour le TEXTE seulement — la lueur de fond, elle, garde la couleur
   pleine. Une même couleur ne peut pas servir d'aplat et de petit texte. */
.st-action { margin-top: .2rem; font-weight: 700; font-size: .92rem;
  color: color-mix(in srgb, var(--acc) 75%, #fff); }
.st-etat { align-self: flex-start; margin-top: .2rem; padding: .2rem .6rem; border-radius: 99px;
  font-size: .72rem; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
  color: #d4d4dd; background: rgba(255, 255, 255, .1); }

/* ⚠️ `cursor: default` ET aucun survol : une carte éteinte ne doit pas se
   comporter comme un lien, sinon on clique et il ne se passe rien. */
.st-bientot { cursor: default; background: #141418; border-color: #232329; }
.st-bientot::before { filter: grayscale(1); opacity: .5; }
.st-bientot .st-vignette { opacity: .4; filter: grayscale(1); }
.st-bientot .st-titre { color: #9a9aa6; }
.st-bientot .st-texte { color: #7c7c88; }

/* ---- les questions, sur fond chaud pour clore la page ---- */
.st-aide { background: #fdf7ef; }
.st-aide h2 { margin: 0 0 1.4rem; }
.st-compte { margin-top: 1.4rem; }

/* Le damier derrière un détourage : sans lui, on ne distingue pas un fond
   transparent d'un fond blanc — et le client croit que rien n'a été fait. */
.st-damier { margin: 1rem 0; }
.st-damier img { max-width: 100%; height: auto; border-radius: 10px;
  border: 1px solid var(--c-gray-200, #e6e6e6);
  background-color: #fff;
  background-image: linear-gradient(45deg, #e0e0e0 25%, transparent 25%),
                    linear-gradient(-45deg, #e0e0e0 25%, transparent 25%),
                    linear-gradient(45deg, transparent 75%, #e0e0e0 75%),
                    linear-gradient(-45deg, transparent 75%, #e0e0e0 75%);
  background-size: 18px 18px;
  background-position: 0 0, 0 9px, 9px -9px, -9px 0; }

/* ---------- l'attente d'une génération ----------
   ⚠️ La jauge est une ESTIMATION : elle plafonne à 92 % et ne prétend jamais
   avoir fini. Une barre qui atteint 100 % avant la réponse pousse à recharger,
   et sur un outil payant recharger coûte une seconde image. */
.st-attente { margin-top: 1rem; }
.st-barre { height: 8px; border-radius: 99px; overflow: hidden;
  background: var(--c-gray-200, #e6e6e6); }
.st-barre span { display: block; width: 0; height: 100%; border-radius: 99px;
  background: linear-gradient(90deg, var(--c-cyan, #0089bd), var(--c-magenta, #e5007d));
  transition: width .2s linear; }
.st-attente-txt { margin: .6rem 0 0; font-size: .92rem; font-weight: 600; }
#ia-compte { color: var(--c-magenta, #e5007d); }
.st-attente-note { display: block; margin-top: .15rem; font-weight: 400;
  font-size: .85rem; color: var(--c-gray-600, #666); }

/* ---------- le choix du style de logo ----------
   ⚠️ Le bouton radio reste dans le DOM (clavier, lecteurs d'écran) mais sort de
   l'écran : `display:none` le retirerait de la navigation au clavier. */
.st-styles-bloc { border: 0; padding: 0; margin: 0 0 1.4rem; }
.st-styles-bloc legend { padding: 0; margin-bottom: .7rem; font-weight: 700; font-size: 1rem; }
.st-styles { display: grid; gap: .8rem;
  grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr)); }
.st-style { display: flex; flex-direction: column; align-items: center; gap: .5rem;
  padding: .8rem .6rem; cursor: pointer; border-radius: 14px; background: #fff;
  border: 2px solid var(--c-gray-200, #e6e6e6);
  transition: border-color .15s, box-shadow .15s, transform .15s; }
.st-style:hover { border-color: var(--c-gray-400, #aaa); transform: translateY(-2px); }
.st-style input { position: absolute; width: 1px; height: 1px; opacity: 0;
  clip-path: inset(50%); }
.st-style:has(input:checked) { border-color: var(--c-magenta, #e5007d); background: #fdf7fb;
  box-shadow: 0 6px 18px rgba(229, 0, 125, .14); }
.st-style:has(input:focus-visible) { outline: 2px solid var(--c-magenta, #e5007d);
  outline-offset: 2px; }
.st-style-vue { display: block; width: 100%; border-radius: 10px; background: #f6f6f9; }
.st-style-vue svg { display: block; width: 100%; height: auto; }
.st-style-nom { font-size: .88rem; font-weight: 600; color: var(--c-gray-700, #555); }
.st-style:has(input:checked) .st-style-nom { color: var(--c-magenta, #e5007d); }

/* Le retour vers le Studio, identique sur les six outils. */
.st-retour { margin: 0 0 1.4rem; }
.st-retour .btn { font-weight: 600; }

/* ---------- le calculateur de lisibilité ----------
   ⚠️ Le tableau plus bas dans la page est rendu par le SERVEUR : c'est lui
   qu'un moteur lit, et lui qui reste si le script ne se charge pas. Ce bloc-ci
   n'est que le confort du calcul en direct. */
.li-calc { display: grid; gap: 1.2rem; margin: 1.6rem 0 2.4rem; padding: 1.4rem 1.5rem;
  border-radius: 16px; color: #fff;
  background: radial-gradient(120% 120% at 100% 0%, rgba(0,174,239,.30) 0%, transparent 68%), #1A1A1A; }
.li-champ label { display: block; margin-bottom: .45rem; font-weight: 700; color: #fff; }
.li-saisie { display: inline-flex; align-items: baseline; gap: .5rem; }
.li-saisie input { width: 7.5rem; padding: .55rem .7rem; font-size: 1.35rem; font-weight: 700;
  color: #fff; background: rgba(255,255,255,.08); border: 1px solid rgba(255,255,255,.22);
  border-radius: 10px; }
.li-saisie input:focus { outline: 2px solid var(--c-cyan, #00AEEF); outline-offset: 2px; }
.li-unite { color: #d4d4dd; }
.li-sortie { display: grid; gap: .8rem; grid-template-columns: repeat(3, 1fr); }
@media (max-width: 720px) { .li-sortie { grid-template-columns: 1fr; } }
.li-res { padding: .9rem 1rem; border-radius: 12px; background: rgba(255,255,255,.07);
  border: 1px solid rgba(255,255,255,.12); }
.li-res-nom { display: block; font-size: .8rem; text-transform: uppercase; letter-spacing: .05em;
  color: #d4d4dd; }
/* ⚠️ `tabular-nums` : sans ça le chiffre saute d'un pixel à chaque frappe et
   les trois colonnes dansent pendant qu'on tape. */
.li-res-val { display: block; margin: .15rem 0 .3rem; font-size: 1.9rem; line-height: 1.05;
  font-family: var(--font-head, inherit); color: var(--c-cyan, #00AEEF);
  font-variant-numeric: tabular-nums; }
.li-res-quoi { display: block; font-size: .85rem; line-height: 1.45; color: #d4d4dd; }
.li-formule { margin: .8rem 0 1.4rem; padding: .9rem 1.1rem; border-radius: 10px;
  background: var(--c-gray-100, #f4f4f6); font-size: 1.05rem; }
.li-table td { font-variant-numeric: tabular-nums; }
.li-reserves { margin: .6rem 0 1.6rem; padding-left: 1.2rem; line-height: 1.65; }
.li-reserves li { margin-bottom: .5rem; }

/* ---------- l'aperçu du fond perdu, avec sa ligne de coupe ----------
   ⭐ La ligne est DESSINÉE PAR LA PAGE, pas gravée dans le fichier : le client
   voit où ça coupe, et le fichier qu'il télécharge reste propre. Un trait noir
   incrusté dans une image en pixels finirait imprimé. */
.fp-apercu { position: relative; display: block; margin: 1rem 0 .4rem; line-height: 0; }
.fp-apercu img { display: block; max-width: 100%; height: auto; border-radius: 10px;
  border: 1px solid var(--c-gray-200, #e6e6e6); }
/* ⚠️ Deux traits superposés, blanc dessous et noir pointillé dessus : sur un
   visuel clair un pointillé noir seul disparaît, sur un visuel sombre c'est le
   blanc qui s'efface. Ensemble ils tiennent sur n'importe quelle image. */
.fp-coupe { position: absolute; pointer-events: none;
  outline: 2px solid rgba(255, 255, 255, .85); outline-offset: 0;
  border: 2px dashed #111; box-sizing: border-box; }
.fp-legende { display: flex; align-items: baseline; gap: .5rem; }
.fp-puce { flex: none; width: 26px; height: 0; margin-top: .55rem;
  border-top: 2px dashed #111; box-shadow: 0 1px 0 rgba(255,255,255,.9); }

/* Les trois atouts sous les onglets de la fiche produit (26/09/2026). */
.ex-atouts { list-style: none; margin: 1.6rem 0 0; padding: 1.2rem 0 0;
  border-top: 1px solid var(--c-gray-200, #e6e6e6);
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; }
.ex-atout { display: flex; align-items: center; gap: .7rem; }
.ex-atout-icone { flex: none; color: var(--c-cyan); }
.ex-atout span { font-size: .87rem; line-height: 1.3; font-weight: 600; color: var(--c-text, #1a1a1a); }
@media (max-width: 640px) {
  .ex-atouts { grid-template-columns: 1fr; }
}

/* ⭐⭐ 03/10/2026 : le bouton « ⓘ » et la modale d'explication du groupe
   « Couleur d'impression » (plexiglas). <dialog> natif. */
.ex-info-bouton { display: inline-flex; align-items: center; justify-content: center;
  width: 1.2rem; height: 1.2rem; margin-left: .3rem; padding: 0; border: none; border-radius: 50%;
  background: var(--c-gray-200, #e6e6e6); color: var(--c-gray-700, #555); font-size: .78rem;
  line-height: 1; cursor: pointer; vertical-align: middle; }
.ex-info-bouton:hover { background: var(--c-cyan, #00AEEF); color: #fff; }
dialog.ex-modale { border: none; border-radius: 10px; padding: 0; max-width: 900px; width: calc(100% - 2rem);
  box-shadow: 0 10px 40px rgba(0,0,0,.25); }
dialog.ex-modale::backdrop { background: rgba(0,0,0,.5); }
.ex-modale-corps { position: relative; padding: 1.5rem; max-height: 80vh; overflow: auto; }
.ex-modale-fermer { position: absolute; top: .6rem; right: .6rem; width: 2rem; height: 2rem;
  border: none; border-radius: 6px; background: var(--c-gray-100, #f4f4f4); color: var(--c-gray-700, #555);
  font-size: 1.3rem; line-height: 1; cursor: pointer; }
.ex-modale-fermer:hover { background: var(--c-gray-200, #e6e6e6); }
.ex-modale-tableau { width: 100%; border-collapse: collapse; font-size: .85rem; }
.ex-modale-tableau th { text-align: left; background: var(--c-cyan, #00AEEF); color: #fff;
  padding: .6rem .8rem; font-size: .78rem; text-transform: uppercase; letter-spacing: .02em; }
.ex-modale-tableau td { padding: .7rem .8rem; border-bottom: 1px solid var(--c-gray-200, #e6e6e6);
  vertical-align: top; line-height: 1.4; }
.ex-modale-tableau tr:last-child td { border-bottom: none; }
@media (max-width: 640px) {
  .ex-modale-tableau, .ex-modale-tableau thead, .ex-modale-tableau tbody,
  .ex-modale-tableau th, .ex-modale-tableau td, .ex-modale-tableau tr { display: block; }
  .ex-modale-tableau thead { display: none; }
  .ex-modale-tableau tr { margin-bottom: 1rem; border: 1px solid var(--c-gray-200, #e6e6e6); border-radius: 8px; padding: .5rem; }
  .ex-modale-tableau td { border-bottom: none; }
}
