/* ============================================================================
   gpuserver.io — feuille de style unique.

   [!] La CSP du site est `style-src 'self'` : AUCUN style en ligne ne
       s'applique, ni <style>, ni attribut style="". Tout vit ici.
   [!] Les `clamp()` gardent des espaces autour des opérateurs : `calc()` à
       l'intérieur d'un clamp sans espaces est ignoré en silence.
   ========================================================================== */

/* --- 1. Réglages ---------------------------------------------------------- */
:root {
  --bg:          #ffffff;
  --bg-soft:     #f7f9fc;
  --bg-sunk:     #eef2f8;
  --line:        #e3e9f1;
  --line-strong: #cfd9e6;

  --ink:         #0e1726;
  --ink-2:       #4a5a70;
  --ink-3:       #6f7f95;

  --acc:         #1f4fe0;
  --acc-dark:    #163cb0;
  --acc-soft:    #eef3ff;
  --acc-line:    #cddaff;

  --ok:          #0e8f5f;
  --ok-soft:     #e8f7f0;
  --warn:        #9a5b00;
  --warn-soft:   #fff5e5;

  --r-sm: 8px;
  --r:    12px;
  --r-lg: 18px;

  --shadow-1: 0 1px 2px rgba(14, 23, 38, .05);
  --shadow-2: 0 4px 16px rgba(14, 23, 38, .07);
  --shadow-3: 0 18px 44px rgba(14, 23, 38, .11);

  /* [!] Élargi de 1200 à 1380 px le 2026-08-24 : le catalogue à facettes a
     une colonne de filtres EN PLUS des sept colonnes de résultats, et 1200 px
     obligeait chaque nom de GPU à s'élider. */
  --wrap: 1380px;
  --gut:  clamp(1rem, 4vw, 2rem);
  --hdr-h: 66px;

  /* --- Mesures de texte -----------------------------------------------------
     [!] Vingt-deux `max-width` choisies au cas par cas, de 44rem a 96ch, sans
     systeme : le chapeau d'une section d'accueil occupait 576 px dans un
     conteneur de 1380, soit 42 % de la largeur. Un bloc de texte perdu au
     milieu d'un vide n'est pas de la respiration, c'est un defaut de mise en
     page. Quatre mesures, et elles seules, decident desormais.

     [!] `ch` vaut la largeur du ZERO, pas celle d'un caractere moyen : l'ecart
     depasse 15 % sur une police proportionnelle. Les mesures sont donc en rem,
     sauf pour les titres ou la variation de graisse rend le rem trompeur.

     [!] La longueur de ligne confortable (65-85 signes) vaut pour la lecture
     SUIVIE. Un chapeau de une a trois lignes n'est pas de la lecture suivie :
     c'est de l'affichage, et il peut aller nettement plus large sans fatiguer.
     D'ou deux mesures distinctes plutot qu'une seule moyenne qui trahirait les
     deux usages. */
  --m-lead:  56rem;   /* chapeaux de section : titre + 1 a 3 lignes */
  --m-read:  47rem;   /* prose longue : juridique, guides, documentation.
                         [!] 50rem donnait 112 signes par ligne : au-dela de la
                         limite de lecture suivie (65-85), et sur des conditions
                         generales cela se paie en abandons. Le chapeau peut
                         aller large, le corps non. */
  --m-note:  44rem;   /* notes, legendes, textes secondaires */
  --m-hero:  50rem;   /* hero : borne par le degrade qui rend le fond lisible */
  --m-h:     30ch;    /* titres d'affichage */

  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
}

/* --- 2. Base -------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
/* L'ancre ne doit pas passer sous l'en-tête collant. */
:target { scroll-margin-top: calc(var(--hdr-h) + 16px); }
[id] { scroll-margin-top: calc(var(--hdr-h) + 16px); }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .001ms !important; transition-duration: .001ms !important; }
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  /* Une page ne défile jamais horizontalement : ce qui déborde défile chez lui. */
  overflow-x: hidden;
}

h1, h2, h3, h4 { margin: 0; line-height: 1.18; letter-spacing: -.02em; font-weight: 700; }
p  { margin: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }
img, svg { max-width: 100%; height: auto; display: block; }
a { color: var(--acc); text-decoration: none; }
a:hover { color: var(--acc-dark); }

:focus-visible {
  outline: 2px solid var(--acc);
  outline-offset: 3px;
  border-radius: 4px;
}

.sr {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}
.skip {
  position: absolute; left: 12px; top: -60px; z-index: 200;
  background: var(--acc); color: #fff; padding: 10px 16px;
  border-radius: var(--r-sm); font-weight: 600; transition: top .15s;
}
.skip:focus { top: 12px; color: #fff; }

.wrap { width: 100%; max-width: var(--wrap); margin-inline: auto; padding-inline: var(--gut); }

/* --- 3. Typographie de section -------------------------------------------- */
.sec { padding-block: clamp(3.5rem, 7vw, 6rem); }
.sec--soft { background: var(--bg-soft); border-block: 1px solid var(--line); }
.sec--sunk { background: var(--bg-sunk); border-block: 1px solid var(--line); }

.sec__head { max-width: var(--m-lead); margin-bottom: clamp(2rem, 4vw, 3rem); }
.sec__head--center { margin-inline: auto; text-align: center; }
/* Un chapeau réduit à son titre n'a pas besoin de l'espace d'un chapeau plein. */
.sec__head--tight { margin-bottom: clamp(1.25rem, 2.5vw, 1.75rem); }

.eyebrow {
  display: inline-block; margin-bottom: .75rem;
  font-size: .78rem; font-weight: 700; letter-spacing: .09em; text-transform: uppercase;
  color: var(--acc);
}
.sec__h { font-size: clamp(1.7rem, 3.4vw, 2.45rem); }
.sec__sub { margin-top: .9rem; font-size: clamp(1rem, 1.6vw, 1.125rem); color: var(--ink-2); }

/* --- 4. Boutons ----------------------------------------------------------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  padding: .78rem 1.25rem; border-radius: var(--r-sm);
  font-size: .95rem; font-weight: 600; line-height: 1.2;
  border: 1px solid transparent; cursor: pointer; white-space: nowrap;
  transition: background-color .15s, border-color .15s, color .15s, box-shadow .15s, transform .08s;
}
.btn:active { transform: translateY(1px); }
/* [!] `.btn` pose `display: inline-flex`, qui l'emporte sur `[hidden]` de la
   feuille du navigateur (spécificité égale, la feuille auteur gagne). Sans
   cette garde, un bouton marqué `hidden` reste VISIBLE : « Send the request »
   s'affichait dès la première étape de l'assistant. La garde était posée sur
   `.wnav`, mais les boutons du récapitulatif n'y sont pas. */
.btn[hidden] { display: none !important; }
.btn--primary { background: var(--acc); color: #fff; box-shadow: var(--shadow-1); }
.btn--primary:hover { background: var(--acc-dark); color: #fff; }
.btn--ghost { background: #fff; color: var(--ink); border-color: var(--line-strong); }
.btn--ghost:hover { background: var(--bg-soft); color: var(--ink); border-color: var(--ink-3); }
.btn--quiet { background: transparent; color: var(--ink-2); padding-inline: .6rem; }
.btn--quiet:hover { color: var(--acc); }
.btn--lg { padding: .95rem 1.6rem; font-size: 1rem; }
.btn--block { width: 100%; }

/* --- 5. Pastilles --------------------------------------------------------- */
.pill {
  display: inline-flex; align-items: center; gap: .4rem;
  padding: .28rem .6rem; border-radius: 999px;
  font-size: .76rem; font-weight: 600; line-height: 1.4;
  border: 1px solid var(--line); background: #fff; color: var(--ink-2);
}
.pill--ok   { background: var(--ok-soft);  color: var(--ok);   border-color: #c9ecdd; }
.pill--low  { background: var(--warn-soft);color: var(--warn); border-color: #f4dfb8; }
.pill--out  { background: var(--bg-sunk);  color: var(--ink-3);border-color: var(--line-strong); }
.pill--acc  { background: var(--acc-soft); color: var(--acc-dark); border-color: var(--acc-line); }

.dot { width: 8px; height: 8px; border-radius: 50%; background: var(--ink-3); flex: none; }
.dot--live { background: var(--ok); box-shadow: 0 0 0 3px var(--ok-soft); }

/* --- 9. Bande de preuve --------------------------------------------------- */
/* [!] QUATRE ENGAGEMENTS, QUATRE CELLULES ÉGALES, ET CHACUNE EST UN LIEN VERS
   LA PAGE QUI LE PROUVE (docs de livraison, SLA, page sans KYC, catalogue).
   La version d'avant tenait sur une ligne de texte qui s'arrêtait au tiers de
   la largeur : sur bureau elle se lisait comme un sous-titre, sur téléphone
   elle devenait quatre lignes de liste sans puces, aux libellés décalés.
   Ici : grille de 4 à partir de 900 px, 2 × 2 en dessous, filets entre les
   cellules. Même vocabulaire que .sla-row en bas de page (chiffre + phrase),
   mais sans cadre ni fond : c'est une BANDE sous le hero, pas une section.
   [!] Le DOM est PLAT (glyphe, chiffre, libellé côte à côte dans le lien) :
   ce sont deux grilles qui font les deux mises en page, sans `display:
   contents` et sans balisage différent par largeur. */
.proof { border-bottom: 1px solid var(--line); background: #fff; }
.proof__row {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  list-style: none; margin: 0; padding: 0;
}
.proof__item { position: relative; min-width: 0; }

.proof__a {
  display: grid;
  grid-template-columns: 30px minmax(0, 1fr);
  column-gap: .6rem; row-gap: .3rem;
  align-items: center;
  /* Les rangées se serrent en HAUT : les cellules d'une même rangée ont la
     même hauteur (grille extérieure), et sans ceci un libellé d'une ligne
     flottait au milieu du vide, loin de son chiffre, à côté d'un libellé
     français de trois lignes. */
  align-content: start;
  padding: .95rem .75rem .95rem 0;
  color: inherit; text-decoration: none;
  height: 100%;
  border-radius: var(--r-sm);
}
.proof__a:focus-visible { outline: 2px solid var(--acc); outline-offset: -2px; }

.proof__ic {
  grid-column: 1; grid-row: 1;
  display: grid; place-items: center;
  width: 30px; height: 30px; border-radius: 9px;
  background: var(--acc-soft); color: var(--acc);
  transition: background-color .15s ease, color .15s ease;
}
.proof__ic .ico { width: 17px; height: 17px; }
.proof__v {
  grid-column: 2; grid-row: 1;
  font-size: 1.18rem; font-weight: 700; letter-spacing: -.03em; line-height: 1.1;
  white-space: nowrap; font-variant-numeric: tabular-nums;
  transition: color .15s ease;
}
/* Sous 900 px le libellé prend TOUTE la largeur de la cellule, sous la ligne
   « glyphe + chiffre » : à 164 px de large, une colonne de texte à droite d'un
   glyphe n'aurait laissé que 110 px, soit cinq lignes en français. */
.proof__l {
  grid-column: 1 / -1; grid-row: 2;
  font-size: .84rem; line-height: 1.35; color: var(--ink-2);
  text-wrap: pretty;
}

/* Filets : entre les deux colonnes, et entre les deux rangées. */
.proof__item:nth-child(even) .proof__a { padding-left: .9rem; }
.proof__item:nth-child(even)::before {
  content: ""; position: absolute; left: 0; top: .9rem; bottom: .9rem; width: 1px;
  background: var(--line);
}
.proof__item:nth-child(n+3) { border-top: 1px solid var(--line); }

@media (hover: hover) {
  .proof__a:hover .proof__ic { background: var(--acc); color: #fff; }
  .proof__a:hover .proof__v  { color: var(--acc); }
}

@media (min-width: 900px) {
  .proof__row { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .proof__item:nth-child(n+3) { border-top: 0; }
  .proof__item:nth-child(even) .proof__a { padding-left: 0; }
  .proof__item:nth-child(even)::before { display: none; }

  /* Bureau : le glyphe sur deux rangées à gauche, chiffre puis libellé à
     droite — la lecture « 40 px de glyphe, un chiffre, une phrase » des
     bandes de statistiques, en 76 px de haut. */
  .proof__a {
    grid-template-columns: 40px minmax(0, 1fr);
    column-gap: .85rem; row-gap: .1rem;
    align-content: center;
    padding: 1.05rem 1rem 1.05rem 0;
  }
  .proof__ic { grid-row: 1 / 3; width: 40px; height: 40px; border-radius: 12px; }
  .proof__ic .ico { width: 20px; height: 20px; }
  .proof__v { font-size: 1.3rem; align-self: end; }
  .proof__l { grid-column: 2; grid-row: 2; align-self: start; }

  .proof__item + .proof__item .proof__a { padding-left: 1.4rem; }
  .proof__item + .proof__item::before {
    content: ""; position: absolute; left: 0; top: 1rem; bottom: 1rem; width: 1px;
    background: var(--line); display: block;
  }
}

/* --- 12. Tableaux --------------------------------------------------------- */
/* [!] Un tableau large défile DANS SON CONTENEUR, jamais dans la page. */
.tbl-wrap {
  overflow-x: auto; -webkit-overflow-scrolling: touch;
  border: 1px solid var(--line); border-radius: var(--r-lg); background: #fff;
  box-shadow: var(--shadow-1);
}
.tbl { width: 100%; border-collapse: collapse; min-width: 780px; font-size: .9rem; }
.tbl th, .tbl td { padding: .95rem 1.1rem; text-align: left; border-bottom: 1px solid var(--line); vertical-align: middle; }
.tbl thead th {
  background: var(--bg-soft); font-size: .76rem; font-weight: 700;
  letter-spacing: .07em; text-transform: uppercase; color: var(--ink-3); white-space: nowrap;
}
.tbl tbody tr:last-child td { border-bottom: 0; }
.tbl tbody tr:hover { background: var(--bg-soft); }
.tbl .num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.tbl__name { font-weight: 700; }
.tbl__meta { display: block; margin-top: .15rem; font-size: .8rem; font-weight: 400; color: var(--ink-3); }
.tbl__price { font-size: 1.05rem; font-weight: 700; letter-spacing: -.02em; }
.tbl__price span { font-size: .8rem; font-weight: 600; color: var(--ink-3); }
.tbl-hint { margin-top: .7rem; font-size: .82rem; color: var(--ink-3); }

/* --- 14. Étapes ----------------------------------------------------------- */
.steps { display: grid; gap: 1.25rem; counter-reset: step; }
@media (min-width: 700px)  { .steps { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1040px) { .steps { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.step { position: relative; background: #fff; border: 1px solid var(--line); border-radius: var(--r-lg); padding: 1.4rem; min-width: 0; }
.step__n { font-family: var(--mono); font-size: .82rem; font-weight: 700; color: var(--acc); letter-spacing: .1em; }
.step__t { margin-top: .5rem; font-size: 1.05rem; }
.step__d { margin-top: .45rem; font-size: .9rem; color: var(--ink-2); }

/* --- 15. Pourquoi le mensuel + exemple chiffré ---------------------------- */
.why { display: grid; gap: clamp(2rem, 4vw, 3rem); align-items: start; }
@media (min-width: 960px) { .why { grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr); } }
.why__list { display: grid; gap: 1.5rem; min-width: 0; }
.why__item { display: flex; gap: .85rem; min-width: 0; }
.why__ico { flex: none; width: 34px; height: 34px; border-radius: 9px; background: var(--acc-soft); color: var(--acc); display: grid; place-items: center; }
.why__t { font-size: 1rem; font-weight: 700; }
.why__d { margin-top: .3rem; font-size: .9rem; color: var(--ink-2); }

.calc { background: #fff; border: 1px solid var(--line); border-radius: var(--r-lg); box-shadow: var(--shadow-2); overflow: hidden; min-width: 0; }
.calc__h { padding: 1.1rem 1.4rem; border-bottom: 1px solid var(--line); background: var(--bg-soft); }
.calc__t { font-size: 1rem; }
.calc__s { margin-top: .2rem; font-size: .85rem; color: var(--ink-3); }
.calc__rows { padding: .4rem 1.4rem 1.4rem; }
.calc__row { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; padding-block: .85rem; border-bottom: 1px solid var(--line); min-width: 0; }
.calc__row:last-child { border-bottom: 0; }
.calc__lbl { font-size: .92rem; color: var(--ink-2); min-width: 0; }
.calc__lbl b { display: block; color: var(--ink); font-weight: 600; }
.calc__val { font-size: 1.15rem; font-weight: 700; letter-spacing: -.02em; white-space: nowrap; font-variant-numeric: tabular-nums; }
.calc__row--win .calc__val { color: var(--ok); }
.calc__foot { padding: 1rem 1.4rem; background: var(--acc-soft); border-top: 1px solid var(--acc-line); font-size: .87rem; color: var(--acc-dark); }

/* --- 16. Centres de données ---------------------------------------------- */
.locs { display: grid; gap: 1rem; }
@media (min-width: 640px)  { .locs { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1000px) { .locs { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.loc { background: #fff; border: 1px solid var(--line); border-radius: var(--r); padding: 1.25rem; min-width: 0; }
.loc__top { display: flex; align-items: center; justify-content: space-between; gap: .75rem; }
.loc__code { font-family: var(--mono); font-size: .78rem; font-weight: 700; letter-spacing: .1em; color: var(--acc); }
.loc__city { margin-top: .35rem; font-size: 1.1rem; font-weight: 700; }
.loc__country { font-size: .88rem; color: var(--ink-3); }
.loc__meta { display: grid; gap: .3rem; margin-top: .9rem; padding-top: .9rem; border-top: 1px solid var(--line); font-size: .85rem; color: var(--ink-2); }
.loc__meta div { display: flex; justify-content: space-between; gap: .75rem; min-width: 0; }
.loc__meta span:last-child { font-weight: 600; text-align: right; }

/* --- 17. SLA -------------------------------------------------------------- */
.sla { display: grid; gap: 1rem; }
@media (min-width: 700px)  { .sla { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1040px) { .sla { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.sla__card { background: #fff; border: 1px solid var(--line); border-radius: var(--r); padding: 1.4rem; min-width: 0; }
.sla__v { font-size: 1.5rem; font-weight: 700; letter-spacing: -.03em; color: var(--acc); }
.sla__t { margin-top: .35rem; font-weight: 700; }
.sla__d { margin-top: .35rem; font-size: .9rem; color: var(--ink-2); }

/* --- 18. FAQ -------------------------------------------------------------- */
/* <details> natif : l'accordéon fonctionne sans une ligne de JavaScript. */
.faq { display: grid; gap: .75rem; max-width: 62rem; margin-inline: auto; }
.qa { background: #fff; border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; }
.qa[open] { border-color: var(--line-strong); box-shadow: var(--shadow-1); }
.qa__q {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: 1.1rem 1.3rem; cursor: pointer; list-style: none;
  font-weight: 600; font-size: 1rem;
}
.qa__q::-webkit-details-marker { display: none; }
.qa__q:hover { color: var(--acc); }
.qa__sign { flex: none; width: 20px; height: 20px; position: relative; color: var(--ink-3); }
.qa__sign::before, .qa__sign::after {
  content: ""; position: absolute; left: 50%; top: 50%; background: currentColor;
  transform: translate(-50%, -50%); transition: transform .18s, opacity .18s;
}
.qa__sign::before { width: 12px; height: 2px; }
.qa__sign::after  { width: 2px; height: 12px; }
.qa[open] .qa__sign::after { transform: translate(-50%, -50%) rotate(90deg); opacity: 0; }
.qa__a { padding: 0 1.3rem 1.25rem; font-size: .93rem; color: var(--ink-2); max-width: var(--m-read); }

/* --- 19. Appel final ------------------------------------------------------ */
.cta { background: var(--ink); color: #fff; }
.cta__in { padding-block: clamp(3rem, 6vw, 4.5rem); text-align: center; }
.cta__h { font-size: clamp(1.7rem, 3.4vw, 2.4rem); color: #fff; }
.cta__p { margin: .9rem auto 0; max-width: var(--m-note); color: #c3cddc; font-size: 1.05rem; }
.cta__acts { display: flex; flex-wrap: wrap; justify-content: center; gap: .75rem; margin-top: 1.9rem; }
.cta .btn--ghost { background: transparent; color: #fff; border-color: rgba(255,255,255,.32); }
.cta .btn--ghost:hover { background: rgba(255,255,255,.09); color: #fff; border-color: rgba(255,255,255,.55); }
.cta__fine { margin-top: 1.2rem; font-size: .85rem; color: #8b9ab0; }

/* --- 21. Page 404 --------------------------------------------------------- */
.err { padding-block: clamp(4rem, 10vw, 7rem); text-align: center; }
.err__code { font-family: var(--mono); font-size: .85rem; font-weight: 700; letter-spacing: .14em; color: var(--acc); }
.err__h { margin-top: .6rem; font-size: clamp(1.8rem, 4vw, 2.6rem); }
.err__p { margin: 1rem auto 0; max-width: var(--m-note); color: var(--ink-2); }
.err__acts { display: flex; flex-wrap: wrap; justify-content: center; gap: .7rem; margin-top: 2rem; }

/* --- 23. Impression ------------------------------------------------------- */
@media print {
  .notice, .hdr, .nav, .burger, .cta, .hero__bg, .hero__veil { display: none !important; }
  body { color: #000; }
  .tbl-wrap { overflow: visible; box-shadow: none; }
}

/* ==========================================================================
   6. BARRE UTILITAIRE + EN-TÊTE + MÉGA-MENUS
   ========================================================================== */
.topbar { background: var(--ink); color: #cfd8e6; font-size: .82rem; }
.topbar__in { display: flex; align-items: center; gap: 1.25rem; min-height: 38px; flex-wrap: wrap; }
.topbar__item { display: flex; align-items: center; gap: .5rem; }
.topbar__right { display: flex; align-items: center; gap: 1.25rem; margin-left: auto; }
.topbar__link { color: #eaf0f8; font-weight: 500; }
.topbar__link:hover { color: #fff; text-decoration: underline; }
@media (max-width: 767px) {
  .topbar__sep, .topbar__right .topbar__link:first-child { display: none; }
  .topbar__in { justify-content: space-between; gap: .75rem; }
}

.hdr {
  position: sticky; top: 0; z-index: 90;
  background: rgba(255, 255, 255, .92);
  backdrop-filter: saturate(180%) blur(12px);
  border-bottom: 1px solid var(--line);
}
.hdr.is-stuck { box-shadow: var(--shadow-2); }
.hdr__in { display: flex; align-items: center; gap: 1rem; min-height: var(--hdr-h); }

/* --- La marque -------------------------------------------------------------
   [!] Le verrou est UN SEUL <svg> : le signe et les lettres y sont des courbes,
       tirees de la meme geometrie. Une version precedente collait un signe
       dessine a la main contre des lettres rendues par la police SYSTEME --
       deux dessins etrangers l'un a l'autre. C'est ce heurt qui se lisait comme
       un defaut, et aucun reglage de taille ne pouvait le rattraper.
   [!] LA HAUTEUR A AUGMENTE ET LA LARGEUR A BAISSE. Le mot tient desormais sur
       DEUX lignes : le verrou fait 2,8 fois sa hauteur au lieu de 8,2. A 38 px
       de haut il occupe 106 px de large, contre 197 px quand il en faisait 24 :
       la marque est une fois et demie plus grande et prend deux fois moins de
       barre. C'est la raison d'etre du passage a deux lignes.
   [!] La hauteur est donnee, la largeur suit (`width: auto`) : la figer en
       pixels deformerait le verrou au premier changement de dessin.
       `preserveAspectRatio` est dans le SVG, pas ici. */
.brand { display: inline-flex; align-items: center; flex: none; text-decoration: none; }
.brand__lock { height: 38px; width: auto; display: block; }
.brand:hover .brand__lock { opacity: .84; }
/* Le pied de page porte le meme verrou, un cran plus bas. */
.ft .brand__lock { height: 32px; }
/* Sous 380 px la barre est etroite : on descend d'un cran, sans jamais passer
   sous 30 px -- « SERVER » y est en chasse fixe a 44 unites de capitale sur
   182, donc 7,2 px a 30. En dessous, ce n'est plus un mot, c'est une trame. */
@media (max-width: 379px) { .brand__lock { height: 30px; } }

.nav { display: flex; align-items: center; gap: 1rem; margin-left: auto; }
.nav__list { display: flex; align-items: center; gap: .25rem; }
.nav__item { position: static; }

.nav__link, .nav__btn {
  display: inline-flex; align-items: center; gap: .35rem;
  padding: .55rem .7rem; border-radius: var(--r-sm);
  font-family: inherit; font-size: .93rem; font-weight: 500; line-height: 1.2;
  color: var(--ink-2); background: transparent; border: 0; cursor: pointer;
  white-space: nowrap; transition: background-color .14s, color .14s;
}
.nav__link:hover, .nav__btn:hover { color: var(--ink); background: var(--bg-soft); }
.nav__btn[aria-expanded="true"] { color: var(--acc); background: var(--acc-soft); }
.chev { transition: transform .16s; }
.nav__btn[aria-expanded="true"] .chev { transform: rotate(180deg); }

/* Le panneau occupe toute la largeur sous l'en-tête. Il est ancré sur .hdr
   (position: sticky crée le contexte), pas sur l'entrée de menu. */
.mega {
  position: absolute; left: 0; right: 0; top: 100%;
  background: #fff; border-bottom: 1px solid var(--line);
  box-shadow: var(--shadow-3);
}
.mega[hidden] { display: none !important; }
.mega__in { display: grid; gap: clamp(1.5rem, 3vw, 2.5rem); padding-block: clamp(1.5rem, 3vw, 2.25rem); }
@media (min-width: 1080px) {
  .mega__in--4   { grid-template-columns: repeat(3, minmax(0, 1fr)) minmax(0, .9fr); }
  .mega__in--3   { grid-template-columns: repeat(2, minmax(0, 1fr)) minmax(0, .9fr); }
  .mega__in--loc { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (min-width: 700px) and (max-width: 1079px) {
  .mega__in { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.mega__col { min-width: 0; }
.mega__h { font-size: .74rem; font-weight: 700; letter-spacing: .09em; text-transform: uppercase; color: var(--ink-3); margin-bottom: .85rem; }
.mega__list { display: grid; gap: .15rem; }
.mega__list a, .mega__loc {
  display: grid; gap: .1rem; padding: .5rem .6rem; margin-inline: -.6rem;
  border-radius: var(--r-sm); color: var(--ink); transition: background-color .14s;
}
.mega__list a:hover, .mega__loc:hover { background: var(--bg-soft); color: var(--ink); }
.mega__name { font-size: .92rem; font-weight: 600; }
.mega__meta { font-size: .8rem; color: var(--ink-3); }
.mega__loc-top { display: flex; align-items: center; justify-content: space-between; gap: .5rem; margin-bottom: .2rem; }
.mega__code { font-family: var(--mono); font-size: .74rem; font-weight: 700; letter-spacing: .1em; color: var(--acc); }
.mega__col--promo { background: var(--bg-soft); border: 1px solid var(--line); border-radius: var(--r); padding: 1.15rem; }
.mega__promo-txt { font-size: .87rem; color: var(--ink-2); margin-block: 0 1rem; }
.mega__facts { display: grid; gap: .35rem; margin-top: 1rem; font-size: .8rem; color: var(--ink-3); }
.mega__facts li { display: flex; gap: .4rem; }
.mega__facts li::before { content: "—"; color: var(--line-strong); }

/* Recherche de l'en-tête : UN seul élément, réutilisé dans le tiroir mobile. */
.hsearch {
  display: none; align-items: center; gap: .45rem; flex: none;
  width: 210px; padding: .42rem .7rem;
  background: var(--bg-soft); border: 1px solid var(--line); border-radius: 999px;
  color: var(--ink-3); transition: border-color .14s, background-color .14s;
}
.hsearch:focus-within { border-color: var(--acc); background: #fff; }
@media (min-width: 1240px) { .hsearch { display: flex; } }
.hsearch__ico { flex: none; }
.hsearch__in {
  width: 100%; min-width: 0; border: 0; background: transparent; outline: none;
  font-family: inherit; font-size: .87rem; color: var(--ink);
}
.hsearch__in::-webkit-search-cancel-button { -webkit-appearance: none; }

.nav__cta { display: flex; align-items: center; gap: .5rem; flex: none; }
.burger { display: none; }
.nav-scrim { position: fixed; inset: 0; z-index: 80; background: rgba(14, 23, 38, .38); border: 0; }
.nav-scrim[hidden] { display: none !important; }

/* ==========================================================================
   7. HERO
   ========================================================================== */
.hero { position: relative; isolation: isolate; overflow: hidden; border-bottom: 1px solid var(--line); }
.hero__bg {
  position: absolute; inset: 0; z-index: -2;
  background-size: cover; background-position: 70% 45%;
  /* [!] DEUX declarations, dans cet ordre. La premiere est le JPEG nu : un
     moteur qui ne comprend pas `image-set()` la garde et affiche l'image. La
     seconde le remplace partout ailleurs et laisse le navigateur choisir le
     format qu'il sait decoder. Une seule declaration `image-set()` afficherait
     un hero VIDE sur les moteurs anciens, sans la moindre erreur. */
  background-image: url("/assets/img/hero-1000.jpg");
  background-image: image-set(
    url("/assets/img/hero-1000.avif") type("image/avif"),
    url("/assets/img/hero-1000.webp") type("image/webp"),
    url("/assets/img/hero-1000.jpg")  type("image/jpeg"));
}
@media (min-width: 701px) {
  .hero__bg {
    background-image: url("/assets/img/hero.jpg");
    background-image: image-set(
      url("/assets/img/hero.avif") type("image/avif"),
      url("/assets/img/hero.webp") type("image/webp"),
      url("/assets/img/hero.jpg")  type("image/jpeg"));
  }
}
.hero__veil {
  position: absolute; inset: 0; z-index: -1;
  background:
    linear-gradient(100deg, rgba(255,255,255,.96) 0%, rgba(255,255,255,.90) 42%, rgba(255,255,255,.50) 68%, rgba(255,255,255,.16) 100%),
    linear-gradient(to bottom, rgba(255,255,255,.42), rgba(255,255,255,0) 32%, rgba(255,255,255,.72) 100%);
}
/* Sous 960 px le texte occupe toute la largeur : le voile redevient opaque,
   sinon un titre se retrouve posé sur une rangée de baies. */
@media (max-width: 959px) {
  .hero__veil { background: linear-gradient(to bottom, rgba(255,255,255,.95) 0%, rgba(255,255,255,.90) 55%, rgba(255,255,255,.82) 100%); }
}

.hero__in { padding-block: clamp(2.5rem, 5vw, 3.75rem); }
.hero__grid { display: grid; gap: clamp(1.75rem, 4vw, 3rem); align-items: center; }
@media (min-width: 980px) { .hero__grid { grid-template-columns: minmax(0, 1.35fr) minmax(0, .65fr); } }
.hero__col { min-width: 0; }

/* Le titre prend la largeur : 26ch tient « Dedicated GPU servers, billed by
   the month. » sur deux lignes pleines au lieu de trois lignes courtes. */
.hero__h { font-size: clamp(2.05rem, 4.7vw, 3.3rem); letter-spacing: -.033em; max-width: var(--m-h); }
.hero__h em { font-style: normal; color: var(--acc); }
.hero__p { margin-top: 1.05rem; max-width: var(--m-hero); font-size: clamp(1rem, 1.5vw, 1.14rem); color: var(--ink-2); }
.hero__acts { display: flex; flex-wrap: wrap; gap: .7rem; margin-top: 1.6rem; }
.hero__bullets { display: grid; gap: .5rem; margin-top: 1.7rem; }
@media (min-width: 560px) { .hero__bullets { grid-template-columns: 1fr 1fr; } }
.hero__bullet { display: flex; align-items: flex-start; gap: .5rem; font-size: .9rem; color: var(--ink-2); min-width: 0; }
.hero__bullet svg { flex: none; margin-top: .18rem; color: var(--ok); }

/* --- Sélecteur « à quoi ça va servir » ----------------------------------- */
.picker {
  background: #fff; border: 1px solid var(--line); border-radius: var(--r-lg);
  box-shadow: var(--shadow-3); padding: 1.25rem; min-width: 0;
}
.picker__h { font-size: 1rem; font-weight: 700; }
.picker__chips { display: flex; flex-wrap: wrap; gap: .35rem; margin-top: .85rem; }
.picker__chip {
  appearance: none; cursor: pointer; font-family: inherit;
  padding: .32rem .65rem; border-radius: 999px; white-space: nowrap;
  font-size: .8rem; font-weight: 600; line-height: 1.5;
  background: var(--bg-soft); border: 1px solid var(--line); color: var(--ink-2);
  transition: background-color .14s, border-color .14s, color .14s;
}
.picker__chip:hover { border-color: var(--line-strong); color: var(--ink); }
.picker__chip[aria-pressed="true"] { background: var(--acc); border-color: var(--acc); color: #fff; }
.picker__out { margin-top: 1.1rem; padding-top: 1.1rem; border-top: 1px solid var(--line); }
.picker__lbl { font-size: .72rem; font-weight: 700; letter-spacing: .09em; text-transform: uppercase; color: var(--ink-3); }
.picker__name { margin-top: .3rem; font-size: 1.22rem; font-weight: 700; letter-spacing: -.02em; }
.picker__meta { margin-top: .2rem; font-size: .84rem; color: var(--ink-2); }
.picker__price { display: flex; align-items: baseline; gap: .3rem; margin-top: .75rem; }
.picker__price b { font-size: 1.95rem; font-weight: 700; letter-spacing: -.03em; }
.picker__price span { color: var(--ink-3); font-weight: 600; font-size: .92rem; }
.picker__note { margin-top: .15rem; font-size: .8rem; color: var(--ink-3); }
.picker .btn { margin-top: 1rem; }

/* ==========================================================================
   8. CATALOGUE : barre d'outils + tableau dense
   ========================================================================== */
.cat { min-width: 0; }
.cat__bar {
  position: sticky; top: var(--hdr-h); z-index: 40;
  background: var(--bg-soft); padding-block: .85rem;
  border-bottom: 1px solid var(--line); margin-bottom: 1rem;
}
.cat__row { display: flex; flex-wrap: wrap; align-items: center; gap: .6rem; }
.cat__row + .cat__row { margin-top: .6rem; }
.cat__row--chips { gap: .75rem 1.25rem; }

.cat__field { display: flex; align-items: center; gap: .5rem; min-width: 0; }
.cat__field--search {
  flex: 1 1 260px; padding: .5rem .8rem; color: var(--ink-3);
  background: #fff; border: 1px solid var(--line); border-radius: var(--r-sm);
  transition: border-color .14s, box-shadow .14s;
}
.cat__field--search:focus-within { border-color: var(--acc); box-shadow: 0 0 0 3px var(--acc-soft); }
.cat__input { width: 100%; min-width: 0; border: 0; outline: none; background: transparent; font-family: inherit; font-size: .92rem; color: var(--ink); }
.cat__input::-webkit-search-cancel-button { -webkit-appearance: none; }
.cat__select {
  appearance: none; font-family: inherit; font-size: .9rem; color: var(--ink); cursor: pointer;
  padding: .58rem 2rem .58rem .8rem; border: 1px solid var(--line); border-radius: var(--r-sm); background: #fff;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='11' height='7' fill='none'%3E%3Cpath d='M1 1.5 5.5 5.5 10 1.5' stroke='%236f7f95' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right .7rem center;
}
.cat__select:focus-visible { border-color: var(--acc); }

.chips { display: flex; flex-wrap: wrap; gap: .3rem; min-width: 0; }
.chips--right { margin-left: auto; }
.chip {
  appearance: none; cursor: pointer; font-family: inherit;
  padding: .4rem .75rem; border-radius: 999px; white-space: nowrap;
  font-size: .84rem; font-weight: 600; line-height: 1.4;
  background: #fff; border: 1px solid var(--line); color: var(--ink-2);
  transition: background-color .14s, border-color .14s, color .14s;
}
.chip:hover { border-color: var(--line-strong); color: var(--ink); }
.chip[aria-pressed="true"] { background: var(--ink); border-color: var(--ink); color: #fff; }
.chip--term[aria-pressed="true"] { background: var(--acc); border-color: var(--acc); }

.cat__count { margin-top: .7rem; font-size: .84rem; color: var(--ink-3); }
.cat__count [data-cat-count] { font-weight: 700; color: var(--ink); }
.cat__empty { margin-top: 1rem; padding: 1.25rem; background: #fff; border: 1px dashed var(--line-strong); border-radius: var(--r); color: var(--ink-2); }
.cat__empty[hidden] { display: none !important; }
.linkish { appearance: none; border: 0; background: none; padding: 0; font: inherit; color: var(--acc); cursor: pointer; text-decoration: underline; }

.tbl--cat { min-width: 940px; }
.tbl--cat td { vertical-align: top; }
.crow[hidden] { display: none !important; }
.crow__name { display: block; font-weight: 700; font-size: .95rem; }
.crow__strong { display: block; font-weight: 600; }
.crow__meta { display: block; margin-top: .18rem; font-size: .8rem; font-weight: 400; color: var(--ink-3); }
.crow__sites { font-size: .87rem; }
.crow__price { font-size: 1.1rem; font-weight: 700; letter-spacing: -.02em; }
.btn--sm { padding: .48rem .85rem; font-size: .85rem; }
/* Une pastille ne doit jamais se casser en trois lignes dans une cellule. */
.pill { white-space: nowrap; }

/* ==========================================================================
   9. MOBILE : tiroir de navigation, méga-menus en accordéon
   ========================================================================== */
@media (max-width: 1079px) {
  .burger {
    display: inline-flex; align-items: center; justify-content: center;
    margin-left: auto; width: 42px; height: 42px; padding: 0; flex: none;
    background: #fff; border: 1px solid var(--line); border-radius: var(--r-sm); cursor: pointer;
  }
  .burger__box { display: grid; gap: 4px; width: 18px; }
  .burger__box i { display: block; height: 2px; background: var(--ink); border-radius: 2px; transition: transform .18s, opacity .18s; }
  .burger[aria-expanded="true"] .burger__box i:nth-child(1) { transform: translateY(6px) rotate(45deg); }
  .burger[aria-expanded="true"] .burger__box i:nth-child(2) { opacity: 0; }
  .burger[aria-expanded="true"] .burger__box i:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

  /* [!] LE BOUTON DOIT PASSER AU-DESSUS DU TIROIR QU'IL OUVRE.
         `.nav` porte `z-index: 85` ; le burger, lui, restait en flux normal
         DANS le meme contexte d'empilement -- donc peint dessous. Une fois le
         tiroir ouvert, la croix de fermeture se retrouvait cachee derriere le
         panneau blanc : il ne restait, pour refermer, que la bande de 31 px
         laissee a gauche.

         Ce defaut etait invisible tant que le tiroir se repliait dans la barre
         (voir le correctif `backdrop-filter` plus bas) : on ne voyait pas non
         plus le tiroir. Reparer l'un a revele l'autre.

         Que le design ATTENDE la croix a cet endroit se lit dans la feuille
         elle-meme : `.nav__list` porte `margin-top: 3.25rem`, exactement la
         place d'un bouton de 42 px en haut du panneau. */
  .burger { position: relative; z-index: 86; }

  /* [!] `backdrop-filter` FAIT DE L'EN-TETE LE BLOC CONTENEUR DE TOUT
         DESCENDANT `position: fixed`. C'est une regle de CSS, pas un bogue de
         navigateur : `filter`, `transform`, `perspective`, `will-change` et
         `backdrop-filter` creent tous un contexte de positionnement.

         Consequence, sur telephone uniquement : le tiroir `.nav`, qui vit DANS
         `.hdr`, ne se positionnait pas contre la fenetre mais contre la BARRE.
         Son `inset: 0 0 0 auto` se resolvait donc sur 390 x 67 px : le menu
         s'ouvrait bel et bien -- classe `is-open` posee, voile affiche, corps
         verrouille -- mais dans un rectangle de 359 x 66 px cache derriere la
         barre. Aucune erreur JavaScript, aucun 404, rien dans les journaux :
         un menu qui repond a tout sauf a l'oeil.

         Mesure : bin/probe.sh a rendu `.nav` = [31, 38, 359, 66] au lieu de
         [31, 0, 359, 844]. C'est ce chiffre-la qui a designe le coupable ; la
         capture d'ecran, elle, ne montrait qu'une page grisee.

         Le meme piege est deja documente pour les fenetres modales dans
         inc/footer.php, qui les pose en fille DIRECTE de <body> pour cette
         raison. Le tiroir, lui, etait reste dans l'en-tete.

         L'en-tete est deja opaque a 92 % : le flou ne se voyait presque pas sur
         un ecran de telephone, et il coutait le menu. */
  .hdr { backdrop-filter: none; background: #fff; }

  .nav {
    position: fixed; z-index: 85; inset: 0 0 0 auto; width: min(400px, 92vw);
    flex-direction: column; align-items: stretch; gap: 0; margin: 0;
    background: #fff; border-left: 1px solid var(--line);
    padding: 1.25rem var(--gut) 2.5rem;
    transform: translateX(100%); transition: transform .22s ease;
    overflow-y: auto; overscroll-behavior: contain;
  }
  .nav.is-open { transform: translateX(0); }
  .nav__list { flex-direction: column; align-items: stretch; gap: 0; margin-top: 3.25rem; }
  .nav__item { border-bottom: 1px solid var(--line); }
  .nav__link, .nav__btn { width: 100%; justify-content: space-between; padding: .95rem 0; font-size: 1rem; font-weight: 600; color: var(--ink); border-radius: 0; }
  .nav__link:hover, .nav__btn:hover { background: transparent; }
  .nav__btn[aria-expanded="true"] { background: transparent; }

  /* Le panneau devient un dépliant dans le flux, plus une couche flottante. */
  .mega { position: static; box-shadow: none; border-bottom: 0; background: transparent; }
  .mega__in { padding: 0 0 1.1rem; gap: 1.25rem; grid-template-columns: 1fr; max-width: none; padding-inline: 0; }
  .mega__col--promo { padding: 1rem; }
  .mega__facts { display: none; }

  .hsearch { display: flex; width: 100%; margin-top: 1.25rem; }
  .nav__cta { flex-direction: column; align-items: stretch; gap: .55rem; margin-top: 1rem; }
  .nav__cta .btn { width: 100%; }
  body.nav-open { overflow: hidden; }

  /* En mobile la barre du catalogue ne colle pas : elle mangerait l'écran. */
  .cat__bar { position: static; }
}

@media (max-width: 559px) {
  .hero__h { max-width: none; }
  .picker { padding: 1.1rem; }
  .chips--right { margin-left: 0; }
}

/* ==========================================================================
   10. IMPRESSION
   ========================================================================== */
@media print {
  .topbar, .hdr, .nav, .burger, .cta, .hero__bg, .hero__veil, .cat__bar, .picker { display: none !important; }
  body { color: #000; }
  .tbl-wrap { overflow: visible; box-shadow: none; }
  .tbl--cat { min-width: 0; }
}

/* ==========================================================================
   11. (RETIRÉ) LE CATALOGUE EN FICHES SOUS 820 px
   ==========================================================================

   [!] CETTE SECTION ÉTAIT DU CODE MORT QUI CASSAIT LE SITE.

   Elle repliait en fiches un tableau `.tbl--cat` — un composant qui N'EXISTE
   PLUS : le catalogue a été réécrit en `<ul class="orows">` (voir §12f). Aucun
   gabarit, aucun script ne produit plus une seule classe `.tbl--cat` ni
   `.crow__*`. Vingt-cinq règles sans cible.

   Sauf UNE, qui n'était pas préfixée et s'appliquait donc à TOUS les
   tableaux du site :

       @media (max-width: 819px) { .tbl-wrap { overflow: visible; … } }

   `.tbl-wrap` porte par défaut `overflow-x: auto` — c'est ce qui rend un
   tableau large parcourable au doigt. Cette ligne le lui retirait sur tout
   téléphone. Résultat mesuré sur /gpu/h100-sxm5 à 390 px :

       conteneur 358 px · tableau 780 px (min-width) · overflow-x: visible

   Le tableau dépassait de 422 px, un ancêtre le rognait, et la colonne du
   PRIX — celle qui décide — devenait à la fois invisible et INATTEIGNABLE :
   rien ne défilait. Trente et un tableaux dans quinze fichiers, dont les
   douze pages produit.

   Rien ne le signalait : pas d'erreur, pas de défilement horizontal de la
   page (le rognage l'absorbait), et le contrôle « tableau sans conteneur à
   défilement » de bin/mobile-audit.js le trouvait justement DANS un
   `.tbl-wrap`. Seule une capture d'écran à 390 px l'a montré, et seule la
   mesure du DOM a nommé la cause.

   Leçon : un refactor qui remplace un composant doit emporter sa feuille de
   style. Une règle orpheline ne fait pas rien — elle fait ce qu'elle dit, sur
   ce qui reste.
   ========================================================================== */

/* ==========================================================================
   12. CRYPTO & SANS KYC : badges du hero, prix barré, section paiement
   ========================================================================== */
.badges { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: 1.25rem; }
.badge {
  display: inline-flex; align-items: center; gap: .45rem;
  padding: .42rem .75rem; border-radius: 999px;
  font-size: .85rem; font-weight: 600; line-height: 1.3;
  background: #fff; border: 1px solid var(--line); color: var(--ink-2);
}
.badge svg { flex: none; color: var(--acc); }
.badge--key { background: var(--acc-soft); border-color: var(--acc-line); color: var(--acc-dark); }

/* Le prix de référence, barré, sous le nôtre. Sans les DEUX nombres,
   « -30 % » n'est qu'une affirmation. */

/* Le message de positionnement, en tête de chaque page. */
.topbar__cta { color: #fff; font-weight: 600; margin-left: .5rem; white-space: nowrap; }
.topbar__cta:hover { color: #fff; text-decoration: underline; }
.topbar__cta .arr { display: inline-block; margin-left: .25rem; transition: transform .15s; }
.topbar__cta:hover .arr { transform: translateX(3px); }

/* ==========================================================================
   13. FORMATS COMPACTS — comparatif, centres, engagement
   [!] Trois sections pleines ont été remplacées par ces trois bandes : la page
       demandait plus de lecture qu'un visiteur pressé n'en accorde.
   ========================================================================== */
.vs { margin-top: 1.25rem; background: #fff; border: 1px solid var(--line); border-radius: var(--r-lg); padding: 1.35rem; }
.vs__lbl { font-size: .92rem; font-weight: 700; }
.vs__lbl span { font-weight: 400; color: var(--ink-3); }
.vs__row { display: grid; gap: 1px; margin-top: 1rem; background: var(--line); border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; }
@media (min-width: 700px) { .vs__row { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.vs__item { background: #fff; padding: .95rem 1.1rem; min-width: 0; }
.vs__item--win { background: var(--ok-soft); }
.vs__v { display: block; font-size: 1.45rem; font-weight: 700; letter-spacing: -.03em; font-variant-numeric: tabular-nums; }
.vs__item--win .vs__v { color: var(--ok); }
.vs__k { display: block; margin-top: .1rem; font-size: .84rem; color: var(--ink-3); }
.vs__note { margin-top: .9rem; font-size: .85rem; color: var(--ink-3); }

.dcs { display: grid; gap: 1px; background: var(--line); border: 1px solid var(--line); border-radius: var(--r-lg); overflow: hidden; }
@media (min-width: 560px)  { .dcs { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 900px)  { .dcs { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 1180px) { .dcs { grid-template-columns: repeat(6, minmax(0, 1fr)); } }
.dc { background: #fff; padding: 1.1rem; display: grid; gap: .12rem; min-width: 0; }
.dc__code { font-family: var(--mono); font-size: .74rem; font-weight: 700; letter-spacing: .1em; color: var(--acc); }
.dc__city { font-size: 1.02rem; font-weight: 700; letter-spacing: -.01em; }
.dc__meta { font-size: .81rem; color: var(--ink-2); }
.dc__meta--dim { color: var(--ink-3); }

.sla-row { display: grid; gap: 1px; margin-top: 1.25rem; background: var(--line); border: 1px solid var(--line); border-radius: var(--r-lg); overflow: hidden; }
@media (min-width: 640px)  { .sla-row { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1060px) { .sla-row { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.sla-cell { background: #fff; padding: 1.2rem; min-width: 0; }
.sla-cell b { display: block; font-size: 1.35rem; letter-spacing: -.03em; color: var(--acc); }
.sla-cell span { display: block; margin-top: .3rem; font-size: .86rem; color: var(--ink-2); }

/* ==========================================================================
   14. « CE QUE VOUS AVEZ » — un panneau, six tuiles d'une ligne
   [!] Refonte du 2026-08-24 : six titres suivis d'un paragraphe, ça ne se lit
       pas. Une tuile = une icône, trois mots, une ligne.
   ========================================================================== */
/* [!] Refonte du 2026-08-25. L'ancienne version posait une image de 300 px de
   haut EN TETE de la carte, les six tuiles serrees dessous : le sujet de la
   section passait apres une photo qui n'apprend rien. Et `.kit__ico` occupait
   `grid-row: 1 / 3`, ce qui laissait titre et phrase se caler chacun a sa
   guise -- l'alignement d'une tuile a l'autre dependait de la longueur du
   texte. Grille plate, icone au-dessus, et la ligne de specification poussee
   en bas par `margin-top: auto` : les six specifications tombent sur la meme
   ligne de base quoi qu'il arrive au-dessus. */
.kit {
  display: grid; gap: 1px; background: var(--line);
  border: 1px solid var(--line); border-radius: var(--r-lg);
  overflow: hidden; box-shadow: var(--shadow-1);
}
@media (min-width: 640px)  { .kit { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1040px) { .kit { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.kit__i {
  display: flex; flex-direction: column; min-width: 0;
  background: #fff; padding: clamp(1.35rem, 2.2vw, 1.8rem);
}
/* [!] L'icone etait posee AU-DESSUS du titre, sur sa propre ligne : une ligne
   entiere depensee pour un carre de 40 px, et l'icone detachee de ce qu'elle
   designe. Elle vit sur la ligne du titre.
   [!] Ce n'est PAS un retour au `grid-row: 1 / 3` d'avant : la l'icone
   s'etendait sur deux rangees et laissait titre et phrase se caler chacun a sa
   guise. Ici l'en-tete est une rangee flex a lui seul, la phrase occupe toute
   la largeur en dessous, et l'alignement des six tuiles reste garanti par la
   ligne de specification. */
.kit__hd { display: flex; align-items: center; gap: .75rem; min-width: 0; }
.kit__ico {
  width: 36px; height: 36px; border-radius: 10px; flex: none;
  background: var(--acc-soft); color: var(--acc);
  display: grid; place-items: center;
}
.kit__t { font-size: 1.02rem; min-width: 0; }
.kit__d { margin-top: .7rem; font-size: .9rem; color: var(--ink-2); }
.kit__s {
  margin-top: auto; padding-top: 1.05rem;
  font-family: var(--mono); font-size: .77rem; color: var(--ink-3);
}
/* La reglure appartient a la ligne de specification, pas a la cellule : sans
   cela elle flotterait au milieu du vide quand la phrase est courte. */
.kit__s::before {
  content: ""; display: block; height: 1px;
  background: var(--line); margin-bottom: .8rem;
}

.kit__foot {
  display: flex; align-items: flex-start; gap: .6rem;
  margin-top: 1.15rem; max-width: var(--m-lead);
  font-size: .87rem; color: var(--ink-3);
}
.kit__foot svg { color: var(--acc); flex: none; margin-top: .18rem; }

/* Sur une page de carte, la specification vit dans une `.card` et non dans une
   `.kit__i` : elle y garde son filet et sa chasse fixe, sans la marge auto qui
   n'a de sens que dans une grille a hauteurs egales. */
.card > .kit__s { margin-top: auto; }

/* ==========================================================================
   15. PAIEMENT — trois bandes qui se lisent sans lire
   ========================================================================== */
.band { background: #fff; border: 1px solid var(--line); border-radius: var(--r-lg); padding: 1.4rem; }
.band + .band { margin-top: 1rem; }
.band__h { display: flex; align-items: center; gap: .5rem; font-size: .78rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-3); }
.band__h .ico { color: var(--acc); flex: none; }
.band__note { margin-top: 1.1rem; padding-top: 1rem; border-top: 1px solid var(--line); font-size: .85rem; color: var(--ink-3); }

/* Ce qu'on ne demande jamais : des pastilles barrées, pas des phrases. */
.nopes { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: 1.1rem; }
.nope {
  display: inline-flex; align-items: center; gap: .45rem;
  padding: .42rem .8rem .42rem .65rem; border-radius: 999px;
  background: var(--bg-sunk); border: 1px solid var(--line-strong);
  font-size: .88rem; font-weight: 500; color: var(--ink-3); text-decoration: line-through;
  text-decoration-color: var(--line-strong);
}
.nope::before {
  content: ""; flex: none; width: 15px; height: 15px; border-radius: 50%;
  background-color: #fff;
  background-image: linear-gradient(45deg, transparent 43%, var(--ink-3) 43%, var(--ink-3) 57%, transparent 57%),
                    linear-gradient(-45deg, transparent 43%, var(--ink-3) 43%, var(--ink-3) 57%, transparent 57%);
  background-size: 8px 8px; background-position: center; background-repeat: no-repeat;
}

/* Le parcours : quatre étapes en ligne, reliées par un filet. */
.flow { display: grid; gap: 1px; margin-top: 1.1rem; background: var(--line); border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; }
@media (min-width: 700px)  { .flow { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1060px) { .flow { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.flow__step { background: #fff; padding: 1.1rem 1.2rem; display: grid; gap: .2rem; min-width: 0; }
.flow__n { font-family: var(--mono); font-size: .74rem; font-weight: 700; letter-spacing: .12em; color: var(--acc); }
.flow__t { font-size: .97rem; font-weight: 700; letter-spacing: -.01em; }
.flow__d { font-size: .85rem; color: var(--ink-2); }

/* Les monnaies : une rangée de pastilles, pas une liste de huit lignes. */
.cchips { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: 1.1rem; }
.cchip {
  display: inline-flex; align-items: baseline; gap: .45rem;
  padding: .48rem .8rem; border-radius: var(--r-sm);
  background: var(--bg-soft); border: 1px solid var(--line); min-width: 0;
}
.cchip b { font-size: .89rem; font-weight: 700; }
.cchip span { font-size: .76rem; color: var(--ink-3); }

/* ==========================================================================
   16. FORMULAIRE DE COMMANDE (/contact)
   ========================================================================== */
.form { max-width: 46rem; }
.form__grid { display: grid; gap: 1.1rem; }
@media (min-width: 680px) { .form__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.field { display: grid; gap: .35rem; margin: 0; min-width: 0; align-content: start; }
.field--wide { grid-column: 1 / -1; }
/* [!] `.field` pose `display: grid` : sans cette garde, un champ marqué
   `hidden` reste visible. Une garde d'attribut existait pour le champ d'image
   personnalisée, mais elle ne couvrait que celui-là. */
.field[hidden] { display: none !important; }
.field__l { font-size: .88rem; font-weight: 600; }
.field__opt { margin-left: .35rem; font-weight: 400; font-size: .8rem; color: var(--ink-3); }
.field__c {
  width: 100%; min-width: 0; font-family: inherit; font-size: .95rem; color: var(--ink);
  padding: .72rem .85rem; background: #fff;
  border: 1px solid var(--line-strong); border-radius: var(--r-sm);
  transition: border-color .14s, box-shadow .14s;
}
.field__c:focus { outline: none; border-color: var(--acc); box-shadow: 0 0 0 3px var(--acc-soft); }
select.field__c {
  appearance: none; cursor: pointer; padding-right: 2.2rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='11' height='7' fill='none'%3E%3Cpath d='M1 1.5 5.5 5.5 10 1.5' stroke='%236f7f95' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right .8rem center;
}
textarea.field__c { resize: vertical; min-height: 6rem; }
.field__hint { font-size: .81rem; color: var(--ink-3); line-height: 1.4; }
/* Une aide masquée ne doit pas laisser sa gouttière derrière elle. */
.field__hint[hidden], .field__err[hidden] { display: none !important; }
.form__foot { display: grid; gap: .8rem; margin-top: 1.75rem; padding-top: 1.5rem; border-top: 1px solid var(--line); justify-items: start; }
.form__note { font-size: .85rem; color: var(--ink-3); max-width: var(--m-note); }

/* [!] Piège à robots : jamais `display:none`, que certains détectent. Sorti du
   flux et rendu inatteignable au clavier comme au lecteur d'écran. */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.alert { max-width: 46rem; margin-bottom: 1.5rem; padding: 1.1rem 1.25rem; background: var(--warn-soft); border: 1px solid #f4dfb8; border-radius: var(--r); color: var(--warn); }
.alert__h { font-weight: 700; font-size: .92rem; }
.alert ul { margin-top: .5rem; display: grid; gap: .3rem; }
.alert li { font-size: .89rem; }
.alert li::before { content: "— "; }

.done { max-width: 44rem; text-align: center; margin-inline: auto; padding-block: clamp(1rem, 4vw, 3rem); }
.done__ico { display: inline-grid; place-items: center; width: 54px; height: 54px; border-radius: 50%; background: var(--ok-soft); color: var(--ok); }
.done__h { margin-top: 1.1rem; font-size: clamp(1.6rem, 3.2vw, 2.2rem); }
.done__p { margin-top: .8rem; color: var(--ink-2); }
.done__ref {
  margin: 1.25rem auto 0; display: inline-block; padding: .8rem 1.5rem;
  font-family: var(--mono); font-size: 1.5rem; font-weight: 700; letter-spacing: .14em;
  background: var(--bg-sunk); border: 1px dashed var(--line-strong); border-radius: var(--r);
}
.done__note { margin: 1.25rem auto 1.75rem; max-width: var(--m-note); font-size: .9rem; color: var(--ink-3); }

/* ==========================================================================
   17. CONFIGURATEUR (/configure)
   ========================================================================== */
.cfg { padding-block: clamp(2rem, 4vw, 3rem); }
.cfg__head { max-width: var(--m-lead); margin-bottom: clamp(1.5rem, 3vw, 2.25rem); }
.cfg__h { font-size: clamp(1.7rem, 3.4vw, 2.3rem); }
.cfg__p { margin-top: .7rem; color: var(--ink-2); }

.cfg__grid { display: grid; gap: clamp(1.25rem, 2.5vw, 2rem); align-items: start; }
@media (min-width: 1040px) { .cfg__grid { grid-template-columns: minmax(0, 1fr) 340px; } }
.cfg__main { display: grid; gap: 1rem; min-width: 0; }

.step { min-width: 0; margin: 0; padding: 1.4rem; border: 1px solid var(--line); border-radius: var(--r-lg); background: #fff; }
.step__lg { display: flex; align-items: center; gap: .6rem; padding: 0; font-size: 1.05rem; font-weight: 700; letter-spacing: -.01em; }
.step__n { flex: none; display: grid; place-items: center; width: 26px; height: 26px; border-radius: 50%; background: var(--acc); color: #fff; font-size: .82rem; }
.step__opt { font-size: .72rem; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--ink-3); background: var(--bg-sunk); border: 1px solid var(--line); border-radius: 4px; padding: .1rem .35rem; }
.step__hint { margin-top: .75rem; font-size: .87rem; color: var(--ink-3); }
.chips--pad { margin-top: 1rem; }

/* --- Choix de la machine -------------------------------------------------- */

/* --- Vérification de tenue ------------------------------------------------ */
.fit__ctl { display: grid; gap: .8rem; margin-top: 1rem; }
@media (min-width: 700px) { .fit__ctl { grid-template-columns: 2fr 1.3fr 1fr; } }
.fit { margin-top: 1rem; padding: 1.1rem 1.2rem; border: 1px solid var(--line); border-radius: var(--r); background: var(--bg-soft); }
.fit__verdict { font-weight: 700; font-size: 1rem; }
.fit__verdict--fits    { color: var(--ok); }
.fit__verdict--sharded { color: var(--acc-dark); }
.fit__verdict--no      { color: #b42318; }
.fit__nums { display: flex; flex-wrap: wrap; gap: 1.25rem 2rem; margin-top: .85rem; }
.fit__nums li { display: grid; }
.fit__nums li[hidden] { display: none !important; }
.fit__nums b { font-size: 1.25rem; font-weight: 700; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.fit__nums span { font-size: .8rem; color: var(--ink-3); }
.fit__note { margin-top: .9rem; padding-top: .8rem; border-top: 1px solid var(--line); font-size: .8rem; color: var(--ink-3); }

/* --- Options en cartes radio ---------------------------------------------- */
.opts { display: grid; gap: .5rem; margin-top: 1rem; }
@media (min-width: 620px) { .opts { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 900px) { .opts--img { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.opts--term { margin-top: .9rem; }
@media (min-width: 620px) { .opts--term { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.opt { position: relative; display: block; min-width: 0; cursor: pointer; }
.opt input { position: absolute; opacity: 0; width: 0; height: 0; }
.opt__b { display: grid; gap: .12rem; height: 100%; padding: .7rem .85rem; border: 1px solid var(--line); border-radius: var(--r-sm); background: #fff; transition: border-color .14s, background-color .14s; }
.opt:hover .opt__b { border-color: var(--line-strong); }
.opt input:checked + .opt__b { border-color: var(--acc); background: var(--acc-soft); box-shadow: 0 0 0 1px var(--acc); }
.opt input:focus-visible + .opt__b { outline: 2px solid var(--acc); outline-offset: 2px; }
.opt__t { font-size: .9rem; font-weight: 600; }
.opt__d { font-size: .79rem; color: var(--ink-3); }
/* [!] Une option indisponible reste VISIBLE et grisée : la cacher laisse le
   visiteur croire qu'elle n'existe pas, au lieu de comprendre pourquoi. */
.opt.is-off { cursor: not-allowed; }
.opt.is-off .opt__b { opacity: .45; background: var(--bg-sunk); }

/* --- Options quantifiables ------------------------------------------------ */
.addons { display: grid; gap: .5rem; margin-top: 1rem; }
.addon { display: flex; align-items: center; gap: 1rem; padding: .7rem .9rem; border: 1px solid var(--line); border-radius: var(--r-sm); background: #fff; min-width: 0; }
.addon[hidden] { display: none !important; }
.addon__b { display: grid; gap: .1rem; flex: 1 1 auto; min-width: 0; }
.addon__t { font-size: .9rem; font-weight: 600; }
.addon__d { font-size: .79rem; color: var(--ink-3); }
.addon__p { font-weight: 700; white-space: nowrap; font-size: .92rem; }
.addon__p small { font-weight: 600; color: var(--ink-3); font-size: .74rem; }
.stepper { display: inline-flex; align-items: center; flex: none; border: 1px solid var(--line-strong); border-radius: var(--r-sm); overflow: hidden; }
.stepper__b { appearance: none; border: 0; background: #fff; cursor: pointer; width: 30px; height: 32px; font-size: 1rem; font-family: inherit; color: var(--ink-2); }
.stepper__b:hover { background: var(--bg-soft); color: var(--ink); }
.stepper__in { width: 40px; height: 32px; border: 0; border-inline: 1px solid var(--line); text-align: center; font-family: inherit; font-size: .9rem; -moz-appearance: textfield; }
.stepper__in::-webkit-outer-spin-button, .stepper__in::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.stepper__in:focus { outline: none; background: var(--acc-soft); }

.field--half { max-width: 26rem; margin-top: 1.1rem; }
.field__hint--warn { color: var(--warn); font-weight: 600; }

/* --- Récapitulatif collant ------------------------------------------------ */
.cfg__side { min-width: 0; }
@media (min-width: 1040px) { .cfg__side { position: sticky; top: calc(var(--hdr-h) + 1rem); } }
.sum { border: 1px solid var(--line); border-radius: var(--r-lg); background: #fff; box-shadow: var(--shadow-2); padding: 1.35rem; }
.sum__h { font-size: .74rem; font-weight: 700; letter-spacing: .09em; text-transform: uppercase; color: var(--ink-3); }
.sum__machine { margin-top: .5rem; font-size: 1.1rem; font-weight: 700; letter-spacing: -.02em; }
.sum__spec { font-size: .82rem; color: var(--ink-3); }
.sum__lines { display: grid; gap: .45rem; margin-top: 1.1rem; padding-top: 1.1rem; border-top: 1px solid var(--line); }
.sum__lines li { display: flex; align-items: baseline; justify-content: space-between; gap: .75rem; font-size: .85rem; color: var(--ink-2); min-width: 0; }
.sum__lines b { font-weight: 600; color: var(--ink); white-space: nowrap; }
.sum__row { display: flex; align-items: baseline; justify-content: space-between; gap: .75rem; margin-top: 1.1rem; padding-top: 1.1rem; border-top: 1px solid var(--line); }
.sum__row span { font-size: .88rem; color: var(--ink-2); }
.sum__row b { font-size: 1.5rem; font-weight: 700; letter-spacing: -.03em; }
.sum__row--dim { margin-top: .4rem; padding-top: 0; border-top: 0; }
.sum__row--dim b { font-size: 1rem; color: var(--ink-2); }
.sum__saved { margin-top: .6rem; padding: .5rem .7rem; border-radius: var(--r-sm); background: var(--ok-soft); color: var(--ok); font-size: .84rem; font-weight: 600; }
.sum__saved[hidden] { display: none !important; }
.sum .btn { margin-top: 1.1rem; }
.sum__note { margin-top: .8rem; font-size: .79rem; color: var(--ink-3); }
[data-custom-wrap][hidden] { display: none !important; }

/* ==========================================================================
   18. L'ASSISTANT — une décision par écran
   [!] Les étapes ne sont masquées que lorsque `.is-wizard` est posée par le
       JavaScript. Sans lui, tout reste visible et le formulaire s'envoie.
   ========================================================================== */
.wbar { display: flex; flex-wrap: wrap; gap: .35rem; margin-bottom: 1.25rem; counter-reset: w; }
.wbar__i { flex: 1 1 auto; min-width: 0; }
.wbar__b {
  display: flex; align-items: center; gap: .55rem; width: 100%;
  padding: .6rem .8rem; border: 1px solid var(--line); border-radius: var(--r-sm);
  background: #fff; font-family: inherit; font-size: .85rem; color: var(--ink-3);
  cursor: pointer; text-align: left; transition: border-color .14s, color .14s, background-color .14s;
}
.wbar__b:disabled { cursor: default; opacity: .55; }
.wbar__b:not(:disabled):hover { border-color: var(--line-strong); color: var(--ink); }
.wbar__n {
  flex: none; display: grid; place-items: center; width: 22px; height: 22px;
  border-radius: 50%; background: var(--bg-sunk); color: var(--ink-3);
  font-size: .76rem; font-weight: 700;
}
.wbar__l { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wbar__i.is-now .wbar__b { border-color: var(--acc); background: var(--acc-soft); color: var(--acc-dark); font-weight: 600; }
.wbar__i.is-now .wbar__n { background: var(--acc); color: #fff; }
.wbar__i.is-done .wbar__b { color: var(--ink); }
.wbar__i.is-done .wbar__n { background: var(--ok-soft); color: var(--ok); }
@media (max-width: 720px) {
  .wbar__l { display: none; }
  .wbar__i { flex: 0 0 auto; }
  .wbar__b { padding: .5rem; }
}

.wiz__body { display: grid; gap: clamp(1.25rem, 2.5vw, 2rem); align-items: start; }
@media (min-width: 1040px) { .wiz__body { grid-template-columns: minmax(0, 1fr) 330px; } }
.wiz__main { min-width: 0; }

.wstep {
  min-width: 0; padding: clamp(1.25rem, 2.5vw, 1.75rem);
  border: 1px solid var(--line); border-radius: var(--r-lg); background: #fff;
}
.wiz.is-wizard .wstep[hidden] { display: none !important; }
/* Sans JavaScript, les étapes se suivent : il leur faut un intervalle. */
.wiz:not(.is-wizard) .wstep + .wstep { margin-top: 1rem; }
.wiz:not(.is-wizard) .wstep[hidden] { display: block !important; }
.wstep__h { font-size: clamp(1.15rem, 2.2vw, 1.4rem); }
/* [!] Pleine largeur : borné à 62ch, le texte d'une étape se cassait sur trois
   ou quatre lignes dans une colonne large, et chaque ligne gagnée est du
   défilement épargné dans un tunnel de commande. */
.wstep__p { margin-top: .5rem; font-size: .9rem; color: var(--ink-2); max-width: none; }
.step__hint { max-width: none; }
.wstep__sub { margin-top: 1.5rem; font-size: .78rem; font-weight: 700; letter-spacing: .09em; text-transform: uppercase; color: var(--ink-3); }
.wstep .chips { margin-top: 1.1rem; }

.wnav { display: flex; align-items: center; gap: .6rem; margin-top: 1.1rem; }
.wnav [hidden] { display: none !important; }
.wnav [data-next], .wnav [data-send] { margin-left: auto; }
.wiz:not(.is-wizard) .wnav [data-back], .wiz:not(.is-wizard) .wnav [data-next] { display: none !important; }
.wiz:not(.is-wizard) .wnav [data-send] { display: inline-flex !important; }

/* Le contrôle de tenue, replié par défaut : utile, jamais imposé. */
/* [!] `margin-top` seul : le bloc se retrouvait collé à l'étape suivante, qui
   n'a pas de marge haute dans l'assistant. Marge BASSE, comme le bandeau. */
.fitbox { margin: 0 0 1rem; border: 1px solid var(--line); border-radius: var(--r); background: var(--bg-soft); }
.fitbox__s {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: .8rem 1rem; cursor: pointer; list-style: none; font-size: .92rem; font-weight: 600;
}
.fitbox__s::-webkit-details-marker { display: none; }
.fitbox__s > span:first-child { display: inline-flex; align-items: center; gap: .45rem; }
.fitbox__opt { margin-left: .5rem; font-size: .66rem; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--ink-3); background: #fff; border: 1px solid var(--line); border-radius: 4px; padding: .12rem .38rem; }
.fitbox__s svg { color: var(--acc); }
.fitbox__hint { font-size: .82rem; font-weight: 500; color: var(--ink-3); text-align: right; }
.fitbox__hint--fits    { color: var(--ok); }
.fitbox__hint--sharded { color: var(--acc-dark); }
.fitbox__hint--no      { color: #b42318; }
.fitbox__b { padding: 0 1rem 1rem; }
.fitbox[open] .fitbox__hint { display: none; }
.fitbox .fit { background: #fff; }

.field__err { font-size: .82rem; font-weight: 600; color: #b42318; }
.field__err[hidden] { display: none !important; }

/* La pile logicielle est facultative : le dire, et offrir la sortie. */
.wstep__opt { margin-left: .4rem; font-size: .68rem; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--ink-3); background: var(--bg-sunk); border: 1px solid var(--line); border-radius: 4px; padding: .15rem .4rem; vertical-align: middle; }
.imgclear { margin-top: .8rem; font-size: .86rem; }
.imgclear[hidden] { display: none !important; }

/* Ce que la machine fait tourner, annoncé sur sa carte. */
.pick__runs { display: flex; align-items: center; gap: .35rem; margin-top: .3rem; font-size: .8rem; color: var(--ink-2); }
.pick__runs svg { flex: none; color: var(--acc); }
.pick__runs b { font-weight: 600; color: var(--ink); }
.fit__act { margin-top: .9rem; font-size: .85rem; }


/* ==========================================================================
   19. CONFIGURATEUR — lecture visuelle
   [!] Les largeurs passent par des CLASSES : la CSP interdit `style=`, une
       largeur en ligne serait ignorée en silence et la barre resterait à zéro.
   ========================================================================== */
.w-0 { width: 0%; }
.w-5 { width: 5%; }
.w-10 { width: 10%; }
.w-15 { width: 15%; }
.w-20 { width: 20%; }
.w-25 { width: 25%; }
.w-30 { width: 30%; }
.w-35 { width: 35%; }
.w-40 { width: 40%; }
.w-45 { width: 45%; }
.w-50 { width: 50%; }
.w-55 { width: 55%; }
.w-60 { width: 60%; }
.w-65 { width: 65%; }
.w-70 { width: 70%; }
.w-75 { width: 75%; }
.w-80 { width: 80%; }
.w-85 { width: 85%; }
.w-90 { width: 90%; }
.w-95 { width: 95%; }
.w-100 { width: 100%; }

/* --- La jauge de tenue ---------------------------------------------------- */
.fit__verdict { display: flex; align-items: center; gap: .5rem; }
.fit__dot { flex: none; width: 9px; height: 9px; border-radius: 50%; background: currentColor; }
.gauge { margin-top: .85rem; }
.gauge__t { height: 10px; border-radius: 5px; background: var(--bg-sunk); overflow: hidden; border: 1px solid var(--line); }
.gauge__f { height: 100%; border-radius: 5px 0 0 5px; transition: width .22s; }
.gauge__f--fits    { background: var(--ok); }
.gauge__f--sharded { background: var(--acc); }
.gauge__f--no      { background: #e4553f; }
.gauge__lbl { display: flex; justify-content: space-between; gap: 1rem; margin-top: .4rem; font-size: .8rem; color: var(--ink-3); }
.gauge__lbl b { font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }
.fit__nums { margin-top: .9rem; }
.fit__nums li { display: flex; align-items: center; gap: .5rem; }
.fit__ico { display: grid; place-items: center; width: 28px; height: 28px; border-radius: 8px; background: var(--acc-soft); color: var(--acc); flex: none; }
.fit__nums b { font-size: 1.05rem; }
.fit__nums span:last-child { font-size: .8rem; }

/* --- Icônes dans les options --------------------------------------------- */
.opt__b--ico { display: flex; align-items: flex-start; gap: .6rem; }
.opt__i { flex: none; display: grid; place-items: center; width: 30px; height: 30px; border-radius: 8px; background: var(--bg-sunk); color: var(--ink-3); transition: background-color .14s, color .14s; }
.opt input:checked + .opt__b .opt__i { background: var(--acc); color: #fff; }
.opt__x { display: grid; gap: .1rem; min-width: 0; }
.addon__i { flex: none; display: grid; place-items: center; width: 32px; height: 32px; border-radius: 8px; background: var(--bg-sunk); color: var(--ink-3); }
.addon:has(.stepper__in:not([value="0"])) .addon__i { background: var(--acc-soft); color: var(--acc); }

/* ==========================================================================
   20. CHOIX DE MACHINE — rangées denses
   [!] Onze cartes remplissaient deux écrans pour un seul choix. Une rangée par
       machine : même contenu, un quart de la hauteur, et onze lignes alignées
       se comparent bien mieux que onze cartes côte à côte.
   ========================================================================== */
.mhead {
  display: none; gap: .75rem; padding: 0 .9rem .45rem;
  font-size: .68rem; font-weight: 700; letter-spacing: .07em;
  text-transform: uppercase; color: var(--ink-3);
}
@media (min-width: 980px) {
  .mhead { display: grid; grid-template-columns: 26px minmax(0, 2.1fr) 5.6rem 5.6rem minmax(0, 1.5fr) 7.4rem; }
  .mhead span:first-child { grid-column: 1 / 3; }
}
.mrows { display: grid; gap: .3rem; margin-top: .55rem; }
.mrow { min-width: 0; }
.mrow[hidden] { display: none !important; }
.mrow__in { position: absolute; opacity: 0; width: 0; height: 0; }
.mrow__l {
  display: grid; gap: .15rem .75rem; align-items: center;
  grid-template-columns: 26px minmax(0, 1fr); padding: .7rem .9rem; cursor: pointer;
  border: 1px solid var(--line); border-radius: var(--r-sm); background: #fff;
  transition: border-color .13s, background-color .13s, box-shadow .13s;
}
.mrow__l:hover { border-color: var(--line-strong); background: var(--bg-soft); }
.mrow__in:checked + .mrow__l { border-color: var(--acc); background: var(--acc-soft); box-shadow: 0 0 0 1px var(--acc); }
.mrow__in:focus-visible + .mrow__l { outline: 2px solid var(--acc); outline-offset: 2px; }

.mrow__ico { display: grid; place-items: center; width: 26px; height: 26px; }
.mrow__id { min-width: 0; }
.mrow__gpu { display: block; font-weight: 700; font-size: .92rem; letter-spacing: -.01em; }
.mrow__sub { display: block; font-size: .75rem; color: var(--ink-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.mrow__num { grid-column: 2; display: grid; gap: .18rem; min-width: 0; }
.mrow__n { font-size: .82rem; font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; }
.mrow__n small { font-weight: 500; color: var(--ink-3); font-size: .72rem; }
.mrow__bar { height: 4px; border-radius: 2px; background: var(--bg-sunk); overflow: hidden; }
.mrow__fill { display: block; height: 100%; background: var(--acc); border-radius: 2px; }
.mrow__fill--b { background: #7c9cf5; }

.mrow__runs { grid-column: 2; font-size: .78rem; color: var(--ink-2); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mrow__runs small { display: block; font-size: .7rem; color: var(--ink-3); }
.mrow__end { grid-column: 2; display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.mrow__price { font-weight: 700; font-size: .95rem; white-space: nowrap; }
.mrow__price small { font-weight: 600; color: var(--ink-3); font-size: .72rem; }

@media (min-width: 980px) {
  .mrow__l { grid-template-columns: 26px minmax(0, 2.1fr) 5.6rem 5.6rem minmax(0, 1.5fr) 7.4rem; gap: .75rem; }
  .mrow__num, .mrow__runs, .mrow__end { grid-column: auto; }
  .mrow__end { justify-content: flex-end; }
}

/* Une icône de marque garde ses couleurs : pas de teinte imposée. */
.bico { display: block; }
.opt__i--brand { background: #fff; border: 1px solid var(--line); }
.opt input:checked + .opt__b .opt__i--brand { background: #fff; border-color: var(--acc); }
.opts--os { margin-top: .7rem; }
@media (min-width: 780px) { .opts--os { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

/* ==========================================================================
   21. CATALOGUE À FACETTES — conçu pour la quantité
   ========================================================================== */
.browse { display: grid; gap: 1.25rem; align-items: start; }
@media (min-width: 1000px) { .browse { grid-template-columns: 252px minmax(0, 1fr); gap: 1.75rem; } }

.browse__toggle {
  display: inline-flex; align-items: center; gap: .5rem; align-self: start;
  padding: .6rem 1rem; border: 1px solid var(--line-strong); border-radius: var(--r-sm);
  background: #fff; font-family: inherit; font-size: .9rem; font-weight: 600; cursor: pointer;
}
.browse__toggle svg { color: var(--acc); }
.browse__count { display: grid; place-items: center; min-width: 20px; height: 20px; padding-inline: .3rem; border-radius: 999px; background: var(--acc); color: #fff; font-size: .72rem; }
.browse__count[hidden] { display: none !important; }
@media (min-width: 1000px) { .browse__toggle { display: none; } }

.facets { min-width: 0; }
@media (max-width: 999px) {
  .facets { display: none; }
  .browse.is-facets-open .facets { display: block; }
}
@media (min-width: 1000px) { .facets { position: sticky; top: calc(var(--hdr-h) + 1rem); max-height: calc(100vh - var(--hdr-h) - 2rem); overflow-y: auto; } }
.facets__top { display: flex; align-items: baseline; justify-content: space-between; gap: .75rem; padding-bottom: .6rem; border-bottom: 1px solid var(--line); }
.facets__h { font-size: .74rem; font-weight: 700; letter-spacing: .09em; text-transform: uppercase; color: var(--ink-3); }
.facets__top .linkish[hidden] { display: none !important; }

.fswitch { display: flex; align-items: center; gap: .6rem; padding: .75rem 0; font-size: .88rem; font-weight: 600; cursor: pointer; border-bottom: 1px solid var(--line); }
.fswitch input { position: absolute; opacity: 0; width: 0; height: 0; }
.fswitch__b { flex: none; width: 34px; height: 20px; border-radius: 999px; background: var(--line-strong); position: relative; transition: background-color .15s; }
.fswitch__k { position: absolute; top: 2px; left: 2px; width: 16px; height: 16px; border-radius: 50%; background: #fff; transition: transform .15s; }
.fswitch input:checked + .fswitch__b { background: var(--ok); }
.fswitch input:checked + .fswitch__b .fswitch__k { transform: translateX(14px); }
.fswitch input:focus-visible + .fswitch__b { outline: 2px solid var(--acc); outline-offset: 2px; }

.fgroup { border-bottom: 1px solid var(--line); }
.fgroup__s { display: flex; align-items: center; justify-content: space-between; gap: .5rem; padding: .75rem 0; cursor: pointer; list-style: none; font-size: .86rem; font-weight: 600; }
.fgroup__s::-webkit-details-marker { display: none; }
.fgroup__s::after { content: "+"; color: var(--ink-3); font-weight: 400; }
.fgroup[open] .fgroup__s::after { content: "−"; }
.fgroup__n { margin-left: auto; margin-right: .5rem; font-size: .72rem; font-weight: 600; color: var(--ink-3); background: var(--bg-sunk); border-radius: 999px; padding: .05rem .4rem; }
.fgroup__l { display: grid; gap: .1rem; padding-bottom: .7rem; }

.fopt { display: block; cursor: pointer; }
.fopt input { position: absolute; opacity: 0; width: 0; height: 0; }
.fopt__b { display: flex; align-items: center; gap: .5rem; padding: .32rem .45rem; border-radius: var(--r-sm); font-size: .83rem; color: var(--ink-2); transition: background-color .12s; }
.fopt__b::before {
  content: ""; flex: none; width: 15px; height: 15px; border-radius: 4px;
  border: 1.5px solid var(--line-strong); background: #fff; transition: background-color .12s, border-color .12s;
}
.fopt:hover .fopt__b { background: var(--bg-sunk); }
.fopt input:checked + .fopt__b { color: var(--ink); font-weight: 600; }
.fopt input:checked + .fopt__b::before {
  background: var(--acc) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='8' fill='none'%3E%3Cpath d='M1 4l2.6 2.6L9 1.2' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center no-repeat;
  border-color: var(--acc);
}
.fopt input:focus-visible + .fopt__b { outline: 2px solid var(--acc); outline-offset: 1px; }
.fopt__t { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fopt__n { margin-left: auto; font-size: .74rem; color: var(--ink-3); font-variant-numeric: tabular-nums; }
/* [!] Une valeur qui ne rendrait rien reste VISIBLE mais éteinte : la retirer
   ferait sauter la liste à chaque clic et perdre le repère visuel. */
.fopt.is-zero { opacity: .38; }

.results { min-width: 0; }
.results__bar { display: flex; flex-wrap: wrap; align-items: center; gap: .6rem; }
.results__search { display: flex; align-items: center; gap: .5rem; flex: 1 1 220px; padding: .5rem .8rem; background: #fff; border: 1px solid var(--line); border-radius: var(--r-sm); color: var(--ink-3); }
.results__search:focus-within { border-color: var(--acc); box-shadow: 0 0 0 3px var(--acc-soft); }
.results__in { width: 100%; min-width: 0; border: 0; outline: none; background: transparent; font-family: inherit; font-size: .92rem; color: var(--ink); }
.results__in::-webkit-search-cancel-button { -webkit-appearance: none; }
.chips--term { margin-left: auto; }
.results__n { margin-top: .7rem; font-size: .84rem; color: var(--ink-3); }
.results__n b { color: var(--ink); }

.ohead { display: none; gap: .75rem; padding: .8rem .9rem .35rem; font-size: .68rem; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--ink-3); }
@media (min-width: 1120px) {
  .ohead { display: grid; grid-template-columns: 24px minmax(0, 2.4fr) 5.2rem 5.8rem 7.4rem 6.8rem 6.4rem 5.6rem; }
  .ohead span:first-child { grid-column: 1 / 3; }
}
.orows { display: grid; gap: .3rem; }
.orow {
  display: grid; gap: .35rem .75rem; align-items: center;
  grid-template-columns: 26px minmax(0, 1fr); padding: .8rem .9rem;
  background: #fff; border: 1px solid var(--line); border-radius: var(--r-sm);
  transition: border-color .12s, box-shadow .12s;
}
.orow:hover { border-color: var(--line-strong); box-shadow: var(--shadow-1); }
.orow[hidden] { display: none !important; }
.orow__ico { display: grid; place-items: center; width: 26px; height: 26px; }
.orow__id { min-width: 0; }
.orow__gpu { display: block; font-weight: 700; font-size: .93rem; letter-spacing: -.01em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.orow__sub { display: block; font-size: .75rem; color: var(--ink-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.orow__c { grid-column: 2; display: grid; gap: .1rem; min-width: 0; }
.orow__c b { font-size: .82rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.orow__c small { font-size: .71rem; color: var(--ink-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.orow__c b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.orow__bar { height: 4px; border-radius: 2px; background: var(--bg-sunk); overflow: hidden; }
.orow__fill { display: block; height: 100%; background: var(--acc); border-radius: 2px; }
.orow__c--price b { font-size: 1rem; }
.orow__go { grid-column: 2; }
.orow__go .btn { width: 100%; }
@media (min-width: 1120px) {
  .orow { grid-template-columns: 24px minmax(0, 2.4fr) 5.2rem 5.8rem 7.4rem 6.8rem 6.4rem 5.6rem; gap: .7rem; }
  .orow__c, .orow__go { grid-column: auto; }
  .orow__go .btn { width: auto; }
}

/* ==========================================================================
   22. LA MACHINE CHOISIE — bandeau, plus une étape
   [!] Elle arrive du catalogue : la redemander était un écran entier pour une
       décision déjà prise. Elle reste changeable, par un lien.
   ========================================================================== */
.chosen {
  display: flex; align-items: center; flex-wrap: wrap; gap: .5rem 1rem;
  padding: 1rem 1.2rem; margin-bottom: 1rem;
  background: #fff; border: 1px solid var(--acc); border-radius: var(--r-lg);
  box-shadow: 0 0 0 1px var(--acc-soft);
}
.chosen__ico { flex: none; display: grid; place-items: center; width: 38px; height: 38px; border-radius: 10px; background: var(--acc-soft); }
.chosen__id { flex: 1 1 260px; min-width: 0; }
.chosen__gpu { font-size: 1.08rem; font-weight: 700; letter-spacing: -.02em; }
.chosen__sub { font-size: .8rem; color: var(--ink-3); overflow: hidden; text-overflow: ellipsis; }
.chosen__price { font-size: 1.15rem; font-weight: 700; white-space: nowrap; }
.chosen__price small { font-size: .78rem; font-weight: 600; color: var(--ink-3); }
.chosen__change { font-size: .85rem; font-weight: 600; white-space: nowrap; }

/* Le panneau de tenue avant tout choix : une invitation, pas un verdict. */
.fit__ask { font-size: .88rem; color: var(--ink-2); padding: .9rem 1rem; background: #fff; border: 1px dashed var(--line-strong); border-radius: var(--r); }
.fit__ask[hidden] { display: none !important; }
.fit[hidden] { display: none !important; }

/* ==========================================================================
   23. LE CHOIX DE LA MONNAIE, dans le récapitulatif
   ========================================================================== */
.paywith { margin-top: 1.1rem; padding-top: 1.1rem; border-top: 1px solid var(--line); }
.paywith[hidden] { display: none !important; }
.paywith__h { font-size: .74rem; font-weight: 700; letter-spacing: .09em; text-transform: uppercase; color: var(--ink-3); margin-bottom: .6rem; }
.paywith__g { display: grid; grid-template-columns: 1fr 1fr; gap: .35rem; }
.pcoin { display: block; cursor: pointer; min-width: 0; }
.pcoin input { position: absolute; opacity: 0; width: 0; height: 0; }
.pcoin__b {
  display: flex; align-items: center; gap: .4rem; min-width: 0;
  padding: .45rem .55rem; border: 1px solid var(--line); border-radius: var(--r-sm);
  background: #fff; transition: border-color .12s, background-color .12s;
}
.pcoin__b img { flex: none; }
.pcoin:hover .pcoin__b { border-color: var(--line-strong); }
.pcoin input:checked + .pcoin__b { border-color: var(--acc); background: var(--acc-soft); box-shadow: 0 0 0 1px var(--acc); }
.pcoin input:focus-visible + .pcoin__b { outline: 2px solid var(--acc); outline-offset: 2px; }
.pcoin__n { font-size: .8rem; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pcoin__net { margin-left: auto; font-size: .68rem; font-weight: 600; color: var(--ink-3); white-space: nowrap; }

/* ==========================================================================
   24. ÉCRAN DE PAIEMENT
   ========================================================================== */
.payw { display: grid; gap: 1.5rem; align-items: start; }
@media (min-width: 820px) { .payw { grid-template-columns: minmax(0, 1fr) 260px; } }
.payw__main { min-width: 0; background: #fff; border: 1px solid var(--line); border-radius: var(--r-lg); padding: 1.4rem; }
.payw__qr { text-align: center; background: #fff; border: 1px solid var(--line); border-radius: var(--r-lg); padding: 1.2rem; }
.payw__qr img { margin: 0 auto; border-radius: var(--r-sm); }
.payrow { display: grid; gap: .2rem; padding: .85rem 0; border-bottom: 1px solid var(--line); margin: 0; }
.payrow:last-child { border-bottom: 0; padding-bottom: 0; }
.payrow dt { font-size: .74rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-3); }
.payrow dd { margin: 0; display: flex; align-items: center; flex-wrap: wrap; gap: .5rem; }
.payamt { font-size: 1.5rem; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.payaddr { font-family: var(--mono); font-size: .84rem; word-break: break-all; background: var(--bg-sunk); border: 1px solid var(--line); border-radius: var(--r-sm); padding: .4rem .6rem; }
.payhint { flex: 1 0 100%; font-size: .8rem; color: var(--ink-3); }
.paystate { display: flex; align-items: center; gap: .5rem; padding: .8rem 1rem; border-radius: var(--r-sm); font-size: .9rem; font-weight: 600; margin-bottom: 1rem; }
.paystate--seen  { background: var(--ok-soft);   color: var(--ok); }
.paystate--short { background: var(--warn-soft); color: var(--warn); }
.paynote { margin-top: 1.2rem; font-size: .85rem; color: var(--ink-3); }
.paynote code { font-family: var(--mono); font-size: .8rem; }
.paydone { text-align: center; padding: 2rem 1rem; background: #fff; border: 1px solid var(--line); border-radius: var(--r-lg); }
.paydone__t { margin-top: .9rem; font-size: 1.3rem; font-weight: 700; }
.paydone__d { margin-top: .5rem; color: var(--ink-2); }

/* ==========================================================================
   25. LE FORMULAIRE DE COMPTE — grille serrée
   [!] Trois blocs empilés en pleine largeur faisaient défiler deux écrans pour
       huit champs. Une grille de 12 colonnes : les champs courts partagent une
       ligne, et l'accès facultatif est replié.
   ========================================================================== */
.acct { display: grid; grid-template-columns: repeat(12, 1fr); gap: .85rem; margin-top: 1.1rem; }
/* [!] `align-content: start` est OBLIGATOIRE ici. Un conteneur grid a
   `align-content: normal`, qui vaut ÉTIRER : quand le champ voisin de la même
   rangée est plus haut — parce qu'il porte une aide sous lui — l'espace en trop
   est réparti entre les lignes du champ court, et son intitulé comme son champ
   descendent de quelques pixels. Résultat : deux champs côte à côte dont les
   bordures ne s'alignent pas, sans qu'aucune règle ne semble en cause. */
.fld { display: grid; gap: .3rem; margin: 0; min-width: 0; grid-column: span 12; align-content: start; }
@media (min-width: 700px) {
  .fld--3 { grid-column: span 3; }
  .fld--4 { grid-column: span 4; }
  .fld--5 { grid-column: span 5; }
  .fld--6 { grid-column: span 6; }
  .fld--8 { grid-column: span 8; }
  .fld--12 { grid-column: span 12; }
}
.fld[hidden] { display: none !important; }

/* Le champ de mot de passe, avec son œil et sa jauge. */
.pw { position: relative; display: block; }
.pw .field__c { padding-right: 2.6rem; }
.pw__eye {
  position: absolute; right: .4rem; top: 50%; transform: translateY(-50%);
  display: grid; place-items: center; width: 30px; height: 30px;
  border: 0; background: transparent; color: var(--ink-3); cursor: pointer; border-radius: 6px;
}
.pw__eye:hover { color: var(--acc); background: var(--bg-sunk); }
.pw__eye[aria-pressed="true"] { color: var(--acc); }
.pw__bar { display: block; height: 3px; border-radius: 2px; background: var(--bg-sunk); overflow: hidden; }
.pw__fill { display: block; height: 100%; border-radius: 2px; background: var(--line-strong); transition: width .18s, background-color .18s; }
.pw__fill--weak { background: #e4553f; }
.pw__fill--ok   { background: var(--warn); }
.pw__fill--good { background: var(--ok); }


/* ==========================================================================
   26. LE FORMULAIRE, EN GROUPES LISIBLES
   [!] Une pile de champs identiques ne se lit pas : trois groupes titrés, une
       ligne de séparation, et des intitulés qui tiennent sur une ligne.
   ========================================================================== */
.fgrp { padding-top: 1.25rem; margin-top: 1.25rem; border-top: 1px solid var(--line); }
.fgrp:first-of-type { padding-top: 1rem; }
.fgrp__h {
  display: flex; align-items: center; gap: .45rem;
  font-size: .74rem; font-weight: 700; letter-spacing: .09em; text-transform: uppercase; color: var(--ink-3);
}
.fgrp__h svg { color: var(--acc); flex: none; }
.fgrp .acct { margin-top: .85rem; }

.field__l { font-size: .82rem; font-weight: 600; color: var(--ink-2); }
.field__c--mono { font-family: var(--mono); font-size: .82rem; }

/* [!] Le champ et son bouton partagent une LIGNE, avec `align-items: stretch` :
   le bouton prend exactement la hauteur du champ, quelle que soit la police et
   quel que soit le rembourrage. Les aligner en compensant la hauteur d'un
   intitulé casse au premier changement de l'un ou de l'autre. */
.pwrow { display: flex; align-items: stretch; gap: .5rem; min-width: 0; }
.pwrow .pw { flex: 1 1 auto; min-width: 0; }
.pwrow .pw .field__c { height: 100%; }
.pwrow__gen { flex: 0 0 auto; white-space: nowrap; }
@media (min-width: 700px) { .fld--7 { grid-column: span 7; } .fld--5 { grid-column: span 5; } }

/* ==========================================================================
   27. LE PANNEAU DU CATALOGUE — pensé pour 41 produits
   [!] Les 12 cartes tiennent sur DEUX colonnes serrées : une liste d'une seule
       colonne obligeait à parcourir douze lignes pour trouver la sienne.
   ========================================================================== */
@media (min-width: 1080px) {
  .mega__in--gpu { grid-template-columns: minmax(0, 1.9fr) minmax(0, 1fr) minmax(0, 1.15fr); }
}
.mega__col--wide { min-width: 0; }
.mega__cards { display: grid; gap: .1rem; }
@media (min-width: 560px) { .mega__cards { grid-template-columns: 1fr 1fr; gap: .1rem .75rem; } }
.mega__cards a {
  display: flex; align-items: baseline; justify-content: space-between; gap: .6rem;
  padding: .42rem .55rem; margin-inline: -.55rem; border-radius: var(--r-sm);
  color: var(--ink); transition: background-color .13s;
}
.mega__cards a:hover { background: var(--acc-soft); color: var(--ink); }
.mega__gpu { font-size: .87rem; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mega__cards .mega__meta { white-space: nowrap; font-size: .76rem; }
.mega__cards .mega__meta small { color: var(--ink-3); }

.mega__foot { border-top: 1px solid var(--line); background: var(--bg-soft); }
.mega__foot-in { display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap; padding-block: .8rem; }
.mega__all { display: inline-flex; align-items: center; gap: .45rem; font-size: .9rem; font-weight: 600; }
.mega__all .arr { transition: transform .15s; }
.mega__all:hover .arr { transform: translateX(3px); }
.mega__note { font-size: .82rem; color: var(--ink-3); }


/* ==========================================================================
   29. PIED DE PAGE
   [!] Refait sans <details> : les Chrome récents rendent le contenu d'un
       <details> fermé par un mécanisme interne que `display: block !important`
       ne surcharge plus. Les cinq colonnes de liens étaient INVISIBLES sur PC.
       Une grille qui passe de 5 à 2 colonnes fait le même travail et ne dépend
       d'aucun comportement de moteur.
   [!] Aucune classe ne s'appelle `.pay` ici : ce nom sert déjà à la mise en
       page de l'écran de paiement, et la règle la plus tardive écrasait les
       pastilles du pied de page — elles s'étiraient en larges cartes.
   ========================================================================== */
.ft { background: var(--bg-soft); border-top: 1px solid var(--line); padding-block: clamp(2.5rem, 5vw, 3.5rem) 1.75rem; }

.ft__top { display: grid; gap: clamp(2rem, 4vw, 3rem); }
@media (min-width: 1000px) { .ft__top { grid-template-columns: minmax(0, 300px) minmax(0, 1fr); } }
.ft__brand { min-width: 0; }
.ft__pitch { margin-top: .9rem; font-size: .87rem; line-height: 1.6; color: var(--ink-2); max-width: 46ch; }
.ft__live { display: flex; align-items: center; gap: .5rem; margin-top: 1rem; font-size: .85rem; font-weight: 600; color: var(--ok); }

.ft__nav { display: grid; gap: 1.75rem 1.5rem; min-width: 0; grid-template-columns: 1fr 1fr; }
@media (min-width: 640px)  { .ft__nav { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 1000px) { .ft__nav { grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 1.5rem 1.25rem; } }
.ft__col { min-width: 0; }
.ft__h { font-size: .72rem; font-weight: 700; letter-spacing: .09em; text-transform: uppercase; color: var(--ink-3); }
.ft__l { display: grid; gap: .5rem; margin-top: .8rem; }
.ft__l a {
  display: inline-flex; align-items: center; gap: .35rem; flex-wrap: wrap;
  font-size: .87rem; line-height: 1.4; color: var(--ink-2);
}
.ft__l a:hover { color: var(--acc); }

.ft__pay { margin-top: clamp(2rem, 4vw, 2.75rem); padding-top: 1.5rem; border-top: 1px solid var(--line); }
.ft__coins { display: flex; flex-wrap: wrap; gap: .4rem; margin-top: .8rem; }
.fcoin {
  display: inline-flex; align-items: center; gap: .4rem; flex: 0 0 auto;
  padding: .35rem .65rem; background: #fff;
  border: 1px solid var(--line); border-radius: 999px;
  font-size: .81rem; font-weight: 600; color: var(--ink-2); white-space: nowrap;
}
.fcoin img { flex: none; display: block; }

.ft__legal { margin-top: 1.75rem; padding-top: 1.25rem; border-top: 1px solid var(--line); display: grid; gap: .5rem; }
.ft__legal p { font-size: .82rem; line-height: 1.6; color: var(--ink-3); }
.ft__fine { max-width: 96ch; }

/* [!] `.tag` vivait dans le bloc du pied de page supprimé lors de sa refonte :
   les mentions « soon » se rendaient en texte gris nu, indiscernables du
   libellé du lien. Une classe partagée ne doit pas vivre dans le bloc d'UNE
   section. */
.tag {
  display: inline-block; font-size: .62rem; font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase;
  padding: .1rem .34rem; border-radius: 4px; line-height: 1.5;
}
.tag--soon { background: var(--bg-sunk); color: var(--ink-3); border: 1px solid var(--line); }

/* ==========================================================================
   24. PAGES ÉDITORIALES — socle commun

   [!] Toutes les pages hors accueil/configurateur partagent CE bloc. Elles ne
       déclarent aucune classe qui leur soit propre : une page qui a besoin
       d'un composant inédit l'ajoute ici, nommé pour l'usage et non pour la
       page, sinon la quatorzième page ne ressemble plus à la première.
   ========================================================================== */

/* --- 24.1 Fil d'Ariane ---------------------------------------------------- */
.crumb { margin-bottom: 1.15rem; }
.crumb__l { display: flex; flex-wrap: wrap; align-items: center; gap: .3rem .55rem; font-size: .82rem; }
.crumb__l li { display: flex; align-items: center; gap: .55rem; color: var(--ink-3); min-width: 0; }
.crumb__l li + li::before { content: "/"; color: var(--line-strong); }
.crumb__l a { color: var(--ink-2); }
.crumb__l a:hover { color: var(--acc); }
.crumb__l [aria-current] { color: var(--ink); font-weight: 600; }

/* --- 24.2 Bandeau de titre ------------------------------------------------ */
.phero { background: var(--bg-soft); border-bottom: 1px solid var(--line); }
.phero__in { padding-block: clamp(2.25rem, 5vw, 3.75rem); }
.phero__h { max-width: var(--m-h); font-size: clamp(2rem, 4.6vw, 3.05rem); }
.phero__p { margin-top: 1.05rem; max-width: var(--m-lead); font-size: clamp(1rem, 1.5vw, 1.14rem); color: var(--ink-2); }

.phero__facts {
  display: grid; gap: 1px; margin-top: clamp(1.75rem, 3.5vw, 2.5rem);
  background: var(--line); border: 1px solid var(--line);
  border-radius: var(--r-lg); overflow: hidden;
}
@media (min-width: 620px)  { .phero__facts { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 980px)  { .phero__facts { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.phero__fact { background: #fff; padding: 1.05rem 1.2rem; min-width: 0; }
.phero__v { display: block; font-size: 1.32rem; font-weight: 700; letter-spacing: -.03em; font-variant-numeric: tabular-nums; }
.phero__l { display: block; margin-top: .2rem; font-size: .85rem; color: var(--ink-2); }

/* La variante sombre : réservée aux pages où le sujet EST la confiance. */
.phero--dark { background: var(--ink); border-bottom-color: rgba(255,255,255,.12); }
.phero--dark .phero__h { color: #fff; }
.phero--dark .phero__p { color: #c3cddc; }
.phero--dark .eyebrow { color: #7fa4ff; }
.phero--dark .crumb__l li { color: #8b9ab0; }
.phero--dark .crumb__l a { color: #c3cddc; }
.phero--dark .crumb__l a:hover { color: #fff; }
.phero--dark .crumb__l li + li::before { color: #55637a; }
.phero--dark .crumb__l [aria-current] { color: #fff; }
.phero--dark .phero__facts { background: rgba(255,255,255,.13); border-color: rgba(255,255,255,.13); }
.phero--dark .phero__fact { background: #16202f; }
.phero--dark .phero__v { color: #fff; }
.phero--dark .phero__l { color: #8b9ab0; }

/* --- 24.3 Article à deux colonnes ---------------------------------------- */
.doc { display: grid; gap: clamp(2rem, 4vw, 3.25rem); align-items: start; }
@media (min-width: 1000px) { .doc { grid-template-columns: 244px minmax(0, 1fr); } }
.doc__side { min-width: 0; }
.doc__main { min-width: 0; }

@media (min-width: 1000px) {
  .doc__side { position: sticky; top: calc(var(--hdr-h) + 20px); }
}
.toc { border-left: 2px solid var(--line); padding-left: 1.1rem; }
.toc__h {
  font-size: .74rem; font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; color: var(--ink-3); margin-bottom: .7rem;
}
.toc__l { display: grid; gap: .1rem; counter-reset: toc; }
.toc__l a {
  display: block; padding: .34rem 0; font-size: .89rem; color: var(--ink-2);
  border-left: 2px solid transparent; margin-left: -1.1rem; padding-left: 1.1rem;
}
.toc__l a:hover { color: var(--acc); border-left-color: var(--acc-line); }
.toc__l a.is-now { color: var(--acc); font-weight: 600; border-left-color: var(--acc); }
/* Sur mobile la table des matières se replie : dix ancres avant le premier mot
   du texte, c'est un écran entier de sommaire. */
@media (max-width: 999px) {
  .toc { border-left: 0; padding-left: 0; border: 1px solid var(--line); border-radius: var(--r); padding: 1rem 1.1rem; background: var(--bg-soft); }
  .toc__l { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .1rem .9rem; }
  .toc__l a { margin-left: 0; padding-left: 0; border-left: 0; }
  .toc__l a:hover, .toc__l a.is-now { border-left: 0; }
}

/* --- 24.4 Prose ----------------------------------------------------------- */
/* [!] La prose contractuelle est le seul endroit du site où l'on écrit du texte
   long sans classe sur chaque nœud. Les marges vivent donc sur les enfants
   DIRECTS de `.prose`, jamais plus profond, pour qu'un composant inséré dans
   un article garde ses propres espacements. */
.prose { max-width: var(--m-read); color: var(--ink-2); font-size: 1rem; }
.prose > h2 {
  margin-top: 2.9rem; padding-top: 1.9rem; border-top: 1px solid var(--line);
  font-size: clamp(1.3rem, 2.2vw, 1.62rem); color: var(--ink);
}
.prose > h2:first-child { margin-top: 0; padding-top: 0; border-top: 0; }
.prose > h3 { margin-top: 1.9rem; font-size: 1.06rem; color: var(--ink); }
.prose > p { margin-top: .95rem; }
.prose > p:first-child { margin-top: 0; }
/* [!] DEUX BALISAGES, UNE SEULE APPARENCE. Ces règles ne visaient que
       `.prose > ol` — une liste CONTENUE dans un bloc de prose. Or huit listes
       du site écrivent `<ol class="prose">` : la liste EST le bloc, donc
       `.prose > ol` ne l'atteint jamais. Résultat en production : les « Step by
       step » des guides, la procédure d'/abuse et /docs rendus SANS numéros et
       sans retrait — quatre étapes qui se lisent comme un paragraphe. Aucune
       erreur, aucun code HTTP anormal : la règle ne s'applique simplement pas.
   [!] `list-style: none` est posé sur tous les `ol` par la remise à zéro en
       tête de feuille : sans `::before`, il ne reste RIEN. C'est ce qui rend le
       défaut total plutôt que discret. */
.prose > ul, .prose > ol, ul.prose, ol.prose { margin-top: .95rem; display: grid; gap: .55rem; }
.prose > ul > li, ul.prose > li { position: relative; padding-left: 1.4rem; }
.prose > ul > li::before, ul.prose > li::before {
  content: ""; position: absolute; left: .3rem; top: .62em;
  width: 5px; height: 5px; border-radius: 50%; background: var(--acc);
}
.prose > ol, ol.prose { counter-reset: pro; }
.prose > ol > li, ol.prose > li { position: relative; padding-left: 2.1rem; counter-increment: pro; }
.prose > ol > li::before, ol.prose > li::before {
  content: counter(pro); position: absolute; left: 0; top: .1em;
  width: 1.5rem; height: 1.5rem; border-radius: 50%;
  background: var(--acc-soft); color: var(--acc-dark);
  font-size: .76rem; font-weight: 700; display: grid; place-items: center;
}
.prose strong { color: var(--ink); font-weight: 600; }
.prose a { text-decoration: underline; text-underline-offset: 2px; }
.prose code {
  font-family: var(--mono); font-size: .88em; padding: .12em .38em;
  background: var(--bg-sunk); border: 1px solid var(--line); border-radius: 5px; color: var(--ink);
}
.prose > .tbl-wrap, .prose > .callout, .prose > .kv, .prose > .code { margin-top: 1.5rem; }
.prose__meta {
  display: flex; flex-wrap: wrap; gap: .5rem .9rem; margin-bottom: 2rem;
  padding-bottom: 1.4rem; border-bottom: 1px solid var(--line);
  font-size: .84rem; color: var(--ink-3);
}
.prose__meta b { color: var(--ink-2); font-weight: 600; }

/* --- 24.5 Encadré --------------------------------------------------------- */
.callout {
  display: flex; gap: .95rem; padding: 1.15rem 1.3rem;
  border: 1px solid var(--line); border-left: 3px solid var(--acc);
  border-radius: var(--r); background: var(--bg-soft); color: var(--ink-2); font-size: .93rem;
}
.callout__i { flex: none; color: var(--acc); margin-top: .1rem; }
.callout__t { display: block; font-weight: 700; color: var(--ink); margin-bottom: .25rem; }
.callout--warn { border-left-color: var(--warn); background: var(--warn-soft); }
.callout--warn .callout__i { color: var(--warn); }
.callout--ok { border-left-color: var(--ok); background: var(--ok-soft); }
.callout--ok .callout__i { color: var(--ok); }

/* --- 24.6 Bloc de commandes ---------------------------------------------- */
.code {
  border: 1px solid var(--line); border-radius: var(--r); background: #0f1a2b;
  overflow: hidden; box-shadow: var(--shadow-1);
}
.code__h {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: .6rem .95rem; background: #16233a; border-bottom: 1px solid rgba(255,255,255,.09);
  font-family: var(--mono); font-size: .76rem; color: #93a6c4; letter-spacing: .03em;
}
.code__copy {
  border: 1px solid rgba(255,255,255,.2); background: transparent; color: #c3cddc;
  border-radius: 6px; padding: .2rem .55rem; font-size: .72rem; font-weight: 600;
  cursor: pointer; display: inline-flex; align-items: center; gap: .35rem;
}
.code__copy:hover { background: rgba(255,255,255,.1); color: #fff; }
.code pre {
  margin: 0; padding: 1rem 1.1rem; overflow-x: auto; -webkit-overflow-scrolling: touch;
  font-family: var(--mono); font-size: .84rem; line-height: 1.75; color: #dbe5f4;
}
.code pre b { color: #7fd3a2; font-weight: 400; }   /* invite */
.code pre i { color: #8195b4; font-style: normal; } /* commentaire */

/* --- 24.7 Paires clef / valeur ------------------------------------------- */
.kv {
  display: grid; gap: 1px; background: var(--line);
  border: 1px solid var(--line); border-radius: var(--r); overflow: hidden;
}
@media (min-width: 700px) { .kv { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.kv__i { background: #fff; padding: .95rem 1.15rem; min-width: 0; }
.kv__k { display: block; font-size: .78rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-3); }
.kv__v { display: block; margin-top: .3rem; font-size: .95rem; color: var(--ink); font-weight: 600; }
.kv__d { display: block; margin-top: .2rem; font-size: .85rem; color: var(--ink-2); font-weight: 400; }

/* --- 24.8 Grille de cartes ------------------------------------------------ */
.cards { display: grid; gap: 1rem; }
@media (min-width: 640px)  { .cards--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 700px)  { .cards--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1040px) { .cards--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 640px)  { .cards--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1040px) { .cards--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.card {
  display: flex; flex-direction: column; background: #fff; border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: 1.4rem; min-width: 0;
}
/* [!] L'ICONE PARTAGE LA LIGNE DU TITRE, elle ne la prend plus pour elle seule.
       Avant ce bloc, `.card` etant une colonne flex, la pastille de 36 px
       occupait une ligne entiere : 157 fois sur le site, mesurees par
       bin/icon-line.sh. Ce n'etait pas une faute de balisage -- chaque carte
       etait correcte -- mais la mise en page produisait partout le meme creux
       de 51 px entre une pastille et le mot qu'elle annonce.
   [!] LA CORRECTION EST DANS LE BALISAGE, PAS ICI. `.card` doit rester une
       colonne flex : deux cartes s'en servent pour coller leur pied en bas
       (`margin-top: auto`), ce qui ne survit pas au passage en grille. D'ou un
       en-tete `.card__hd` qui est, lui, une rangee. */
.card__hd { display: flex; align-items: center; gap: .8rem; margin-bottom: .8rem; min-width: 0; }
.card__i {
  width: 36px; height: 36px; border-radius: 10px; flex: none;
  background: var(--acc-soft); color: var(--acc); display: grid; place-items: center;
}
/* Carte de guide : le chapeau et le titre s'empilent A COTE de la pastille.
   Deux lignes de texte font 34 px, la pastille 36 : les deux blocs se repondent
   au lieu de se succeder. */
.card__hb { display: grid; gap: .1rem; min-width: 0; }
.card__hb .gcard__tag { margin: 0; }
.card__t { font-size: 1.02rem; min-width: 0; }
.card__d { margin-top: .45rem; font-size: .9rem; color: var(--ink-2); }
.card__l { margin-top: .95rem; display: grid; gap: .4rem; font-size: .87rem; color: var(--ink-2); }
.card__l li { position: relative; padding-left: 1.15rem; }
.card__l li::before { content: ""; position: absolute; left: .25rem; top: .6em; width: 4px; height: 4px; border-radius: 50%; background: var(--line-strong); }
.card__f { margin-top: auto; padding-top: 1.1rem; }
a.card { color: inherit; transition: border-color .15s, box-shadow .15s, transform .1s; }
a.card:hover { color: inherit; border-color: var(--acc-line); box-shadow: var(--shadow-2); transform: translateY(-2px); }

/* --- 24.9 Frise chronologique -------------------------------------------- */
.tl { display: grid; gap: 0; border-left: 2px solid var(--line); margin-left: .45rem; }
.tl__i { position: relative; padding: 0 0 1.75rem 1.75rem; }
.tl__i:last-child { padding-bottom: 0; }
.tl__i::before {
  content: ""; position: absolute; left: -7px; top: .42em;
  width: 12px; height: 12px; border-radius: 50%;
  background: #fff; border: 2px solid var(--acc-line);
}
.tl__i--now::before { background: var(--acc); border-color: var(--acc); }
.tl__d { font-family: var(--mono); font-size: .78rem; font-weight: 700; letter-spacing: .08em; color: var(--acc); }
.tl__t { margin-top: .25rem; font-size: 1rem; font-weight: 700; }
.tl__p { margin-top: .3rem; font-size: .9rem; color: var(--ink-2); max-width: var(--m-note); }

/* --- 24.10 Page d'état ---------------------------------------------------- */
.stban {
  display: flex; align-items: center; gap: 1rem; padding: 1.2rem 1.4rem;
  border: 1px solid #c9ecdd; background: var(--ok-soft); border-radius: var(--r-lg);
}
.stban__i { flex: none; width: 42px; height: 42px; border-radius: 50%; background: var(--ok); color: #fff; display: grid; place-items: center; }
.stban__t { font-size: 1.14rem; font-weight: 700; color: #0a6e49; }
.stban__p { font-size: .9rem; color: #12805a; margin-top: .15rem; }

.strow {
  display: grid; gap: .35rem 1rem; align-items: center;
  padding: .95rem 1.15rem; border-bottom: 1px solid var(--line); min-width: 0;
}
@media (min-width: 760px) { .strow { grid-template-columns: minmax(0, 1fr) 190px 108px; } }
.strow:last-child { border-bottom: 0; }
.strow__n { font-weight: 600; font-size: .95rem; min-width: 0; }
.strow__s { display: block; margin-top: .1rem; font-size: .82rem; color: var(--ink-3); font-weight: 400; }
.strow__v { font-size: .86rem; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.strow__b { justify-self: start; }
@media (min-width: 760px) { .strow__b { justify-self: end; } }
.stbox { background: #fff; border: 1px solid var(--line); border-radius: var(--r-lg); overflow: hidden; box-shadow: var(--shadow-1); }
.stbox__h {
  padding: .8rem 1.15rem; background: var(--bg-soft); border-bottom: 1px solid var(--line);
  font-size: .76rem; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--ink-3);
}
/* 90 jours : des barres, pas un tableau. Chaque barre porte son propre titre. */
.spark { display: flex; gap: 2px; align-items: flex-end; height: 34px; margin-top: .2rem; }
.spark__d { flex: 1 1 0; min-width: 2px; height: 100%; border-radius: 2px; background: var(--ok); opacity: .82; }
.spark__d--warn { background: var(--warn); }
.spark__d--down { background: #d94141; }
.spark__k { display: flex; justify-content: space-between; margin-top: .35rem; font-size: .75rem; color: var(--ink-3); }

/* --- 24.11 Rappel de fin -------------------------------------------------- */
.pcta { background: var(--ink); color: #fff; }
.pcta__in {
  display: grid; gap: 1.6rem; align-items: center;
  padding-block: clamp(2.5rem, 5vw, 3.75rem);
}
@media (min-width: 900px) { .pcta__in { grid-template-columns: minmax(0, 1fr) auto; gap: 2.5rem; } }
.pcta__h { font-size: clamp(1.45rem, 2.8vw, 2rem); color: #fff; }
.pcta__p { margin-top: .65rem; max-width: var(--m-note); color: #c3cddc; font-size: 1rem; }
.pcta__acts { display: flex; flex-wrap: wrap; gap: .7rem; }
.pcta .btn--ghost { background: transparent; color: #fff; border-color: rgba(255,255,255,.32); }
.pcta .btn--ghost:hover { background: rgba(255,255,255,.09); color: #fff; border-color: rgba(255,255,255,.55); }

/* --- 24.12 Pages voisines ------------------------------------------------- */
.pnext__h { font-size: 1.12rem; margin-bottom: 1.1rem; }
.pnext { display: grid; gap: 1px; background: var(--line); border: 1px solid var(--line); border-radius: var(--r-lg); overflow: hidden; }
@media (min-width: 760px) { .pnext { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.pnext__i { display: block; background: #fff; padding: 1.15rem 1.3rem; color: inherit; min-width: 0; }
.pnext__i:hover { background: var(--acc-soft); color: inherit; }
.pnext__t { display: flex; align-items: center; gap: .45rem; font-weight: 700; font-size: .98rem; color: var(--acc); }
.pnext__d { display: block; margin-top: .3rem; font-size: .87rem; color: var(--ink-2); }
.pnext__i:hover .arr { transform: translateX(3px); }
.arr { display: inline-block; transition: transform .15s; }

/* --- 24.13 Liste barrée (ce qu'on ne fait pas) --------------------------- */
.nots { display: grid; gap: .6rem; }
@media (min-width: 700px) { .nots { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.not { display: flex; gap: .65rem; align-items: flex-start; font-size: .92rem; color: var(--ink-2); }
.not__i { flex: none; width: 20px; height: 20px; border-radius: 50%; background: var(--bg-sunk); color: var(--ink-3); display: grid; place-items: center; font-size: .7rem; font-weight: 700; margin-top: .12rem; }
.not b { color: var(--ink); font-weight: 600; }

/* --- 24.14 Retouches -------------------------------------------------------
   L'unité d'un chiffre de bandeau ne doit pas peser autant que le chiffre :
   « 25 Gbit/s » entièrement en corps 1,32 rem se lit comme une phrase. */
.phero__v small { font-size: .6em; font-weight: 600; color: var(--ink-3); letter-spacing: 0; }
.phero--dark .phero__v small { color: #8b9ab0; }
.prose em, .sec__sub em, .not em { font-style: italic; }
/* Un tableau de prose n'a pas besoin de 780 px quand il n'a que trois colonnes. */
.tbl--slim { min-width: 480px; }

/* --- 24.15 Rythme vertical d'un article ------------------------------------
   [!] Les rubriques d'une page éditoriale sont des `.sec__h` posés à la suite,
       sans conteneur. Sans cette règle, l'espace avant un titre dépend de ce
       qui le précède : un titre après un tableau collait, un titre après un
       paragraphe respirait. Le rythme se décide ICI, une fois, pour les
       quatorze pages — et la ligne de séparation dit où une rubrique commence
       même quand le titre est court. */
.doc__main > .sec__h {
  margin-top: clamp(2.75rem, 5vw, 3.5rem);
  padding-top: clamp(1.75rem, 3vw, 2.25rem);
  border-top: 1px solid var(--line);
}
.doc__main > .sec__h:first-child { margin-top: 0; padding-top: 0; border-top: 0; }
.doc__main > .sec__sub { margin-top: .85rem; max-width: var(--m-lead); }
.doc__main > .tbl-wrap,
.doc__main > .cards, .doc__main > .kv, .doc__main > .locs, .doc__main > .nots,
.doc__main > .callout, .doc__main > .code, .doc__main > .steps, .doc__main > .tl,
.doc__main > .stbox, .doc__main > .stban, .doc__main > .faq, .doc__main > .sla { margin-top: 1.6rem; }
.doc__main > h3 { margin-top: 2rem; font-size: 1.08rem; }
.doc__main > h3 + .sec__sub { margin-top: .5rem; }

/* Un libellé court en regard d'une valeur longue : sur une carte étroite, la
   mise en regard casse le libellé en deux lignes. On empile. */
.loc__meta--stack div { display: block; }
.loc__meta--stack span:first-child { display: block; font-size: .78rem; text-transform: uppercase; letter-spacing: .06em; color: var(--ink-3); }
.loc__meta--stack span:last-child { display: block; text-align: left; margin-top: .1rem; }

/* --- 24.16 Page d'état : compléments -------------------------------------- */
/* [!] `flex-wrap` EST LA POUR L'HORODATAGE, PAS POUR LA PASTILLE. Sans le
       groupe `.stban__hd`, c'est le bloc de texte qui passait a la ligne sous
       390 px et laissait la pastille seule sur la sienne — invisible a 1440 px,
       et invisible aussi tant que la bannière est verte, puisque le texte est
       plus court. Mesuré par bin/icon-line.sh a trois largeurs. */
.stban { flex-wrap: wrap; }
.stban__hd { display: flex; align-items: center; gap: 1rem; min-width: 0; flex: 1 1 auto; }
.stban__when { margin-left: auto; text-align: right; font-size: .8rem; color: #12805a; line-height: 1.45; }
.stban__when time { font-family: var(--mono); font-weight: 600; }
/* La bannière change de couleur avec l'état — jamais l'inverse. */
.stban--warn { border-color: #f4dfb8; background: var(--warn-soft); }
.stban--warn .stban__i { background: var(--warn); }
.stban--warn .stban__t { color: #7a4700; }
.stban--warn .stban__p, .stban--warn .stban__when { color: var(--warn); }
.stban--down { border-color: #f2c9c9; background: #fdeded; }
.stban--down .stban__i { background: #d94141; }
.stban--down .stban__t { color: #8f2020; }
.stban--down .stban__p, .stban--down .stban__when { color: #b53232; }
.stban--none { border-color: var(--line-strong); background: var(--bg-sunk); }
.stban--none .stban__i { background: var(--ink-3); }
.stban--none .stban__t { color: var(--ink); }
.stban--none .stban__p, .stban--none .stban__when { color: var(--ink-2); }

.stsec { margin-top: clamp(2.75rem, 5vw, 3.75rem); font-size: clamp(1.3rem, 2.4vw, 1.7rem); }
.sec__sub + .stbox, .sec__sub + .sla, .sec__sub + .tl, .sec__sub + .stempty { margin-top: 1.5rem; }
.stban + .stsec { margin-top: clamp(2.25rem, 4vw, 3rem); }
.stbox + .callout { margin-top: 1.1rem; }

/* La frise des 90 jours occupe toute la largeur sous la ligne du composant. */
.strow__spark { grid-column: 1 / -1; margin-top: .6rem; }
.spark__d--none { background: var(--line-strong); opacity: 1; }

.stempty {
  text-align: center; padding: clamp(2.25rem, 5vw, 3.25rem) 1.5rem;
  border: 1px dashed var(--line-strong); border-radius: var(--r-lg); background: var(--bg-soft);
}
/* [!] Meme regle que les cartes : la pastille se met A COTE du message, pas
       au-dessus. Elle passe de 52 a 42 px pour tenir la ligne d'un titre de
       1,08 rem sans l'ecraser. */
.stempty__hd { display: flex; align-items: center; justify-content: center; gap: .7rem; }
.stempty__i { display: grid; place-items: center; flex: none; width: 42px; height: 42px; border-radius: 50%; background: #fff; border: 1px solid var(--line); color: var(--ok); }
.stempty__t { font-size: 1.08rem; font-weight: 700; text-align: left; }
.stempty__p { margin: .5rem auto 0; max-width: var(--m-note); font-size: .92rem; color: var(--ink-2); }

/* --- 24.17 Bande photographique ------------------------------------------- */
/* Pleine largeur, hauteur bornée : une photo 16/9 sur un écran 2560 px prend
   1440 px de haut et pousse tout le contenu sous la ligne de flottaison. */
.bandimg { margin: 0; position: relative; background: var(--bg-sunk); }
.bandimg img { width: 100%; height: clamp(220px, 34vw, 460px); object-fit: cover; object-position: center 45%; }
.bandimg__c {
  max-width: var(--wrap); margin-inline: auto;
  padding: .85rem var(--gut) 0;
  font-size: .85rem; color: var(--ink-3);
}
.bandimg { padding-bottom: 1.4rem; border-bottom: 1px solid var(--line); }

/* Une pile de cartes dans la colonne d'un bloc `.why` : une seule colonne. */
.why > .cards { gap: 1rem; }

/* --- 24.18 Guides --------------------------------------------------------- */
.ghero { background: var(--bg-soft); border-bottom: 1px solid var(--line); overflow: hidden; }
.ghero__in { display: grid; gap: clamp(1.75rem, 3vw, 2.75rem); align-items: center; padding-block: clamp(2.25rem, 5vw, 3.5rem); }
@media (min-width: 1000px) { .ghero__in { grid-template-columns: minmax(0, 1fr) minmax(0, .88fr); } }
.ghero__txt { min-width: 0; }
.ghero__img { min-width: 0; }
.ghero__img img { width: 100%; border-radius: var(--r-lg); border: 1px solid var(--line); box-shadow: var(--shadow-2); aspect-ratio: 16 / 10; object-fit: cover; }
.ghero__facts { display: grid; gap: .55rem; margin-top: 1.6rem; }
.ghero__facts li { display: flex; align-items: center; gap: .6rem; font-size: .92rem; color: var(--ink-2); }
.ghero__facts svg { color: var(--acc); flex: none; }

.gsec + .gsec { margin-top: clamp(2.5rem, 5vw, 3.5rem); }
.gsec__h { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; margin-bottom: 1.25rem; }
.gsec__h .sec__h { font-size: clamp(1.25rem, 2.2vw, 1.6rem); }
.gsec__n { font-size: .84rem; color: var(--ink-3); white-space: nowrap; }

.gcard__tag {
  display: block; margin-bottom: .4rem;
  font-size: .74rem; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--acc);
}
/* [!] NE PAS reutiliser `.linkish` ici : cette classe existe deja plus haut,
   pour les BOUTONS deguises en lien du configurateur, et elle porte un
   soulignement. Un composant qui reprend un nom deja pris herite de ses
   proprietes non redefinies -- ici, un soulignement en travers de chaque carte
   de guide, invisible a la relecture du code et evident a l'ecran. Meme piege
   que `.pay` contre `.payw` sur la page de paiement. */
.cardgo { font-weight: 600; font-size: .89rem; color: var(--acc); text-decoration: none; }
.card:hover .cardgo .arr { transform: translateX(3px); }
.btn--sm { padding: .45rem .8rem; font-size: .83rem; }

/* L'encadré d'ouverture d'un guide : la réponse avant la démonstration. */
.gsum {
  border: 1px solid var(--acc-line); background: var(--acc-soft);
  border-radius: var(--r-lg); padding: 1.3rem 1.45rem; margin-bottom: 2rem;
}
.gsum__h { font-size: .76rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--acc-dark); margin-bottom: .85rem; }
.gsum__l { display: grid; gap: .8rem; margin: 0; }
.gsum__l > div { display: grid; gap: .15rem; }
@media (min-width: 700px) { .gsum__l > div { grid-template-columns: 210px minmax(0, 1fr); gap: 1rem; align-items: baseline; } }
.gsum__l dt { font-size: .85rem; font-weight: 700; color: var(--acc-dark); }
.gsum__l dd { margin: 0; font-size: .93rem; color: var(--ink); }

/* --- 24.19 Page de contact ------------------------------------------------ */
.cbox { border: 1px solid var(--line); border-radius: var(--r-lg); background: #fff; padding: 1.15rem 1.25rem; }
.cbox + .cbox { margin-top: 1rem; }
.cbox--quiet { background: var(--bg-soft); }
.cbox__h { font-size: .74rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-3); margin-bottom: .8rem; }
.cbox__l { display: grid; gap: .15rem; }
.cbox__l a { display: flex; gap: .65rem; align-items: flex-start; padding: .6rem .5rem; border-radius: var(--r-sm); color: inherit; }
.cbox__l a:hover { background: var(--acc-soft); color: inherit; }
.cbox__l svg { color: var(--acc); flex: none; margin-top: .15rem; }
.cbox__l b { display: block; font-size: .89rem; font-weight: 600; }
.cbox__l span span { display: block; font-size: .82rem; color: var(--ink-2); margin-top: .1rem; }
.cnots { display: grid; gap: .5rem; font-size: .86rem; color: var(--ink-2); }
.cnots li { position: relative; padding-left: 1.15rem; }
.cnots li::before { content: "\00d7"; position: absolute; left: .1rem; top: -.05em; color: var(--ink-3); font-weight: 700; }

/* Le sujet, en cartes radio pleine largeur. */
.opts--topic { display: grid; gap: .6rem; }
@media (min-width: 640px)  { .opts--topic { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1240px) { .opts--topic { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

/* [!] `.field` porte un `display` de la feuille : sans cette garde, un champ
   marqué `hidden` par le serveur reste VISIBLE. Même piège que `.btn[hidden]`,
   et il rendrait tout contact.js inopérant sans la moindre erreur. */
.field[hidden] { display: none !important; }

/* [!] NE PAS reutiliser `.fgrp` : cette classe appartient au CONFIGURATEUR et
   porte un `border-top` de separation entre etapes. Reprise ici pour le groupe
   de sujets, elle dessinait un trait qui partait a droite de la legende --
   exactement le genre d'artefact qu'on impute au navigateur alors qu'on l'a
   ecrit soi-meme. Troisieme collision de nom sur ce site apres `.pay` et
   `.linkish` : un composant nouveau prend un nom nouveau. */
.tgrp { margin-bottom: 1.75rem; }
.tgrp__h {
  font-size: .74rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  color: var(--ink-3); margin-bottom: .85rem; padding: 0;
  /* [!] `float: left` est la vieille recette pour faire tenir une legende sur
     sa propre ligne. Elle SORT la legende du flux : la grille de cartes qui
     suivait s'est effondree en colonnes superposees et illisibles. `display:
     block` fait le meme travail sans toucher au flux. */
  display: block; width: 100%;
}

/* Le bouton d'un encadré passe à la ligne, il ne s'aligne pas sur le texte. */
.callout__act { display: block; margin-top: .95rem; }

/* --- 24.20 Corrections relevées à l'écran --------------------------------- */
/* Une carte dans un <li> de grille : le <li> s'étire, la carte NON. Deux cartes
   côte à côte finissaient de hauteurs différentes alors que la grille, elle,
   était parfaitement régulière. */
.cards > li { display: flex; min-width: 0; }
.cards > li > .card { width: 100%; }
/* `a { text-decoration: none }` ne couvre pas tous les moteurs pour un lien qui
   contient des blocs. On le pose sur la carte elle-même. */
a.card, a.card:hover { text-decoration: none; }

/* Un bandeau de titre est déjà un grand espace : la section qui le suit n'a pas
   besoin de reposer le sien en entier. */
.phero + .sec, .ghero + .sec, .bandimg + .sec { padding-top: clamp(2.25rem, 4.5vw, 3.25rem); }

/* Le compteur de rubriques passe sous le titre quand il n'y a pas la place. */
.gsec__h { flex-wrap: wrap; margin-bottom: 1.5rem; }

/* --- 24.21 La ligne « c'est la nôtre » d'un tableau de comparaison ---------
   [!] Cette ligne portait `is-now`, une classe qui appartient DÉJÀ au sommaire
       des articles. Deux composants sans rapport sur le même nom : le jour où
       l'un des deux change de couleur, l'autre change aussi, et personne ne
       fait le lien. Nom propre, portée propre. */
.tbl__ours { background: var(--acc-soft); }
.tbl__ours td:first-child { white-space: nowrap; }
.tbl__ours .pill { margin-left: .45rem; vertical-align: middle; }
.tbl tbody .tbl__ours:hover { background: var(--acc-soft); }

/* --- 24.22 Groupes de champs ---------------------------------------------
   [!] `<fieldset>` arrive avec une BORDURE, une marge latérale et un rembourrage
       de la feuille du navigateur. Sur la page de contact, cela dessinait un
       cadre gris autour des six cartes de sujet, avec la légende incrustée
       dedans — un artefact de 1997 au milieu d'un formulaire par ailleurs
       propre. `min-width: 0` en prime : un fieldset refuse par défaut de
       rétrécir sous la largeur de son contenu, ce qui casse toute grille
       posée à l'intérieur. */
fieldset { border: 0; margin: 0; padding: 0; min-width: 0; }
legend { padding: 0; }

/* Une colonne latérale qui porte des libellés sur deux lignes a besoin de plus
   que 244 px : sinon chaque entrée occupe quatre lignes et la liste se lit
   comme un paragraphe. */
@media (min-width: 1000px) { .doc--side-wide { grid-template-columns: 296px minmax(0, 1fr); } }

/* Une valeur de récapitulatif qui est une ICÔNE et non un prix : elle prend la
   couleur d'accent, comme toutes les autres icônes du site. Sélecteur sur
   l'enfant direct, pour que les prix (du texte) ne soient pas concernés. */
.calc__val > svg { color: var(--acc); }


/* --- 24.23 Le nom de carte est un lien vers sa page ------------------------
   [!] Passe de <span> a <a>, il heritait du bleu et du survol des liens au
       milieu d'une ligne de catalogue ou tout le reste est du texte. Il garde
       l'apparence d'un titre de ligne et ne se signale qu'au survol. */
a.orow__gpu { color: inherit; text-decoration: none; }
a.orow__gpu:hover { color: var(--acc); text-decoration: underline; text-underline-offset: 2px; }

/* Le lien « comparer toutes les cartes » sous la grille du mega-menu. */
.mega__more { margin-top: .85rem; padding-top: .75rem; border-top: 1px solid var(--line); }
.mega__more a { font-size: .86rem; font-weight: 600; }
.mega__more a:hover .arr { transform: translateX(3px); }

/* La grille de cartes GPU du carrefour respire un peu plus que les autres. */
.gpugrid { margin-top: clamp(1.75rem, 3vw, 2.5rem); }

/* --- 24.24 Le champ fautif se voit -----------------------------------------
   [!] Après un refus du serveur, le message était vrai et invisible : affiché
       en haut du formulaire pendant que le champ vivait trois écrans plus loin.
       Le champ porte maintenant sa propre marque, et le JavaScript ouvre
       l'étape qui le contient. */
.field__c.is-bad,
select.is-bad,
input.is-bad,
textarea.is-bad {
  border-color: #d94141;
  box-shadow: 0 0 0 3px rgba(217, 65, 65, .13);
}
.field__c.is-bad:focus,
select.is-bad:focus { outline-color: #d94141; }

/* --- 24.25 Planche de choix du logo (page interne /logos) ------------------ */
.lgo { border: 1px solid var(--line); border-radius: var(--r-lg); background: #fff; padding: clamp(1.25rem, 2.5vw, 1.9rem); margin-top: 1.25rem; }
.lgo--best { border-color: var(--acc-line); box-shadow: var(--shadow-2); }
.lgo__hd { margin-bottom: 1.25rem; }
.lgo__n { font-size: 1.15rem; display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; }
.lgo__d { margin-top: .4rem; font-size: .9rem; color: var(--ink-2); max-width: var(--m-lead); }
.lgo__lbl { font-size: .72rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-3); margin-bottom: .7rem; }
.lgo__show { display: grid; gap: 1px; background: var(--line); border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; }
@media (min-width: 900px) { .lgo__show { grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr); } }
.lgo__cell { background: var(--bg-soft); padding: 1.1rem 1.2rem; min-width: 0; }
.lgo__full { width: 100%; height: auto; }
.lgo__row { display: flex; align-items: flex-end; gap: 1.5rem; flex-wrap: wrap; }
.lgo__one { display: grid; justify-items: center; gap: .45rem; }
.lgo__one small { font-size: .7rem; color: var(--ink-3); font-family: var(--mono); }
.lgo__s48 { width: 48px; height: 48px; }
.lgo__s32 { width: 32px; height: 32px; }
/* Sur fond foncé : l'image a un fond blanc, on la met dans une pastille pour
   voir si la forme tient quand elle n'est plus posée sur du blanc pleine page. */
.lgo__one--dark { background: var(--ink); padding: .7rem .9rem; border-radius: var(--r-sm); }
.lgo__one--dark small { color: #8b9ab0; }
.lgo__one--dark img { border-radius: 4px; }

.lgo__hdr { margin-top: 1.25rem; }
.lgo__bar { display: flex; align-items: center; gap: 1.25rem; padding: .8rem 1.1rem; border: 1px solid var(--line); border-radius: var(--r); background: #fff; box-shadow: var(--shadow-1); }
.lgo__inbar { height: 30px; width: auto; }
.lgo__nav { font-size: .86rem; color: var(--ink-2); margin-left: auto; white-space: nowrap; }
.lgo__cta { background: var(--acc); color: #fff; font-size: .82rem; font-weight: 600; padding: .5rem .9rem; border-radius: var(--r-sm); white-space: nowrap; }
@media (max-width: 700px) { .lgo__nav { display: none; } }

.lgo__note { margin-top: 1.1rem; display: grid; gap: .5rem; }
.lgo__note .not__i { background: var(--acc-soft); color: var(--acc-dark); }

/* ==========================================================================
   25. LA FENÊTRE « SIGN IN »
   [!] C'est un <dialog> : le fond, le piège à focus et la touche Échap sont
       gérés par le navigateur. On ne redessine ici que la boîte.
   [!] `::backdrop` ne peut PAS hériter des variables de :root dans tous les
       moteurs — la valeur est donc écrite en dur, volontairement.
   ========================================================================== */
.sgn {
  border: 0; padding: 0; background: transparent;
  max-width: min(420px, calc(100vw - 2rem)); width: 100%;
  color: var(--ink);
}
.sgn::backdrop { background: rgba(14, 23, 38, .55); backdrop-filter: blur(2px); }

.sgn__box {
  position: relative; background: #fff; border: 1px solid var(--line);
  border-radius: var(--r-lg); box-shadow: var(--shadow-2);
  padding: 1.6rem 1.5rem 1.35rem;
}
.sgn__x {
  position: absolute; top: .7rem; right: .7rem;
  display: grid; place-items: center; width: 32px; height: 32px;
  border: 0; border-radius: 8px; background: transparent; color: var(--ink-3);
  cursor: pointer;
}
.sgn__x:hover { background: var(--bg-sunk); color: var(--ink); }

.sgn__head { display: flex; align-items: center; gap: .8rem; margin-bottom: 1.25rem; }
.sgn__head .brand__mark { flex: none; border-radius: 9px; }
.sgn__h { font-size: 1.22rem; font-weight: 700; letter-spacing: -.015em; }
.sgn__sub { font-size: .85rem; color: var(--ink-3); margin-top: .1rem; }

.sgn__err {
  margin-bottom: .9rem; padding: .6rem .75rem; border-radius: 8px;
  background: #fdf2f1; border: 1px solid #f4d5d2;
  color: #b42318; font-size: .86rem;
}

.sgn__lab {
  display: block; font-size: .8rem; font-weight: 600; color: var(--ink-2);
  margin-bottom: .3rem;
}
.sgn__lab + .sgn__in, .sgn__lab + .sgn__pw { margin-bottom: .85rem; }
.sgn__in {
  width: 100%; padding: .62rem .75rem; font: inherit; font-size: .95rem;
  color: var(--ink); background: #fff;
  border: 1px solid var(--line-strong); border-radius: 9px;
}
.sgn__in:focus-visible { outline: 2px solid var(--acc); outline-offset: 1px; border-color: var(--acc); }
.sgn__in::placeholder { color: #a9b6c6; }

/* [!] Le bouton « Show » est DANS le champ : posé à côté, il déplaçait la
       colonne et cassait l'alignement des deux libellés. */
.sgn__pw { position: relative; }
.sgn__pw .sgn__in { padding-right: 4.1rem; }
.sgn__eye {
  position: absolute; top: 50%; right: .45rem; transform: translateY(-50%);
  border: 0; background: transparent; cursor: pointer;
  font: inherit; font-size: .78rem; font-weight: 600; color: var(--acc-dark);
  padding: .3rem .4rem; border-radius: 6px;
}
.sgn__eye:hover { background: var(--acc-soft); }

.sgn__row {
  display: flex; align-items: center; justify-content: space-between;
  gap: .75rem; flex-wrap: wrap; margin: .1rem 0 1.1rem;
}
.sgn__keep { display: flex; align-items: center; gap: .45rem; font-size: .83rem; color: var(--ink-2); cursor: pointer; }
.sgn__keep input { accent-color: var(--acc); }
.sgn__link {
  border: 0; background: transparent; padding: 0; cursor: pointer;
  font: inherit; font-size: .83rem; font-weight: 600; color: var(--acc-dark);
  text-decoration: underline; text-underline-offset: 2px;
}
.sgn__go { width: 100%; justify-content: center; }
.sgn__go[disabled] { opacity: .65; cursor: progress; }

.sgn__note {
  margin-top: .85rem; font-size: .82rem; line-height: 1.55; color: var(--ink-3);
  padding: .7rem .8rem; background: var(--bg-sunk); border-radius: 8px;
}
.sgn__note strong { color: var(--ink-2); }

/* La règle métier : le compte naît pendant la commande. */
.sgn__new { margin-top: 1.3rem; padding-top: 1.1rem; border-top: 1px solid var(--line); }
.sgn__newh { font-size: .92rem; font-weight: 700; }
.sgn__newp { margin-top: .35rem; font-size: .85rem; line-height: 1.6; color: var(--ink-2); }
.sgn__newa { margin-top: .85rem; width: 100%; justify-content: center; }

/* Le déclencheur dans la barre. */
.nav__signin {
  border: 1px solid var(--line-strong); background: #fff; color: var(--ink);
  font: inherit; font-size: .9rem; font-weight: 600; cursor: pointer;
  padding: .5rem .85rem; border-radius: 9px; flex: none;
}
.nav__signin:hover { border-color: var(--ink-3); background: var(--bg-sunk); }

/* [!] SUR UN PETIT ÉCRAN LA FENÊTRE DÉPASSE LE BAS, et un <dialog> ne défile
       pas tout seul : le bouton « Sign in » se retrouvait sous le pli, sans
       aucun moyen de l'atteindre. Mesuré à 390×780. `dvh` et non `vh` : sur
       mobile, `vh` compte la barre d'adresse comme si elle était rétractée,
       donc promet une hauteur qui n'existe pas au chargement. */
@media (max-height: 720px), (max-width: 420px) {
  .sgn { max-height: calc(100dvh - 1.25rem); }
  .sgn__box { max-height: calc(100dvh - 1.25rem); overflow-y: auto; padding: 1.3rem 1.15rem 1.15rem; }
  .sgn__new { margin-top: 1.05rem; padding-top: .9rem; }
}

/* ==========================================================================
   26. LA FENÊTRE DE PAIEMENT (.pmx) ET CE QUI RESTE DERRIÈRE (.cfgdone)
   [!] C'est un <dialog> : le fond, la couche supérieure et le piège à focus
       sont au navigateur. On ne dessine ici que la boîte.
   [!] `::backdrop` n'hérite pas des variables de :root dans tous les moteurs —
       la couleur y est écrite en dur, volontairement.
   [!] Nom en `pmx` et non `pay` : `.pay`, `.payw` et `.paywith` existent déjà
       plus haut, sur la page de paiement et dans le récapitulatif.
   ========================================================================== */

/* [!] Un <dialog> modal n'empêche PAS la page derrière de défiler sous le
   doigt sur mobile. Sans cette ligne, l'arrière-plan glisse pendant qu'on
   essaie de faire défiler la fenêtre.
   [!] LA RÈGLE DE TÊTE EST `:has()`, PAS LA CLASSE, et c'est délibéré : un
   <dialog> peut être refermé par le navigateur sans émettre `close` — mesuré,
   et le blocage du défilement restait alors collé sur une page dont la fenêtre
   avait disparu. Une règle qui lit l'attribut `open` ne peut pas se désynchroniser.
   La classe reste en second, pour les moteurs sans `:has()`. */
html:has(dialog.pmx[open]) { overflow: hidden; }
html.pmx-on { overflow: hidden; }

.pmx {
  border: 0; padding: 0; background: transparent; color: var(--ink);
  width: 100%; max-width: min(760px, calc(100vw - 2rem));
  max-height: calc(100dvh - 2rem);
}
.pmx::backdrop { background: rgba(14, 23, 38, .62); backdrop-filter: blur(3px); }

.pmx__box {
  display: flex; flex-direction: column;
  max-height: calc(100dvh - 2rem);
  background: #fff; border: 1px solid var(--line);
  border-radius: var(--r-lg); box-shadow: var(--shadow-3);
  overflow: hidden;
}
.pmx__box:focus { outline: none; }
.pmx__box:focus-visible { outline: 2px solid var(--acc); outline-offset: -2px; }

/* --- L'en-tête, et la SEULE sortie --------------------------------------- */
.pmx__top {
  display: flex; align-items: center; gap: .8rem; flex: none;
  padding: 1rem 1.1rem; border-bottom: 1px solid var(--line);
  background: var(--bg-soft);
}
.pmx__coin {
  display: grid; place-items: center; flex: none;
  width: 38px; height: 38px; border-radius: 11px;
  background: #fff; border: 1px solid var(--line);
}
.pmx__coin img[hidden] { display: none; }
.pmx__ttl { min-width: 0; flex: 1 1 auto; }
.pmx__h { font-size: 1.08rem; font-weight: 700; letter-spacing: -.012em; }
.pmx__ref { margin-top: .12rem; font-size: .8rem; color: var(--ink-3); }
.pmx__ref b { font-family: var(--mono); font-size: .82rem; color: var(--ink-2); letter-spacing: .02em; }

/* [!] Toujours visible, jamais dans le flux du contenu : c'est la seule façon
   de sortir, elle ne doit pas partir en haut d'une zone qui défile. */
.pmx__x {
  flex: none; display: grid; place-items: center; width: 36px; height: 36px;
  border: 1px solid transparent; border-radius: 9px;
  background: transparent; color: var(--ink-3); cursor: pointer;
}
.pmx__x:hover { background: #fff; border-color: var(--line-strong); color: var(--ink); }
.pmx__x:focus-visible { outline: 2px solid var(--acc); outline-offset: 1px; }

/* --- Le corps, qui défile ------------------------------------------------- */
.pmx__body { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 1.15rem 1.1rem 1.35rem; }

/* --- Le rail des trois temps --------------------------------------------- */
.pmx__rail {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .5rem;
  margin: 0 0 1rem; padding: 0; list-style: none; counter-reset: none;
}
.pmx__r { display: flex; align-items: flex-start; gap: .5rem; min-width: 0; }
.pmx__r::before { content: none; }
.pmx__rn {
  flex: none; display: grid; place-items: center; width: 22px; height: 22px;
  border-radius: 50%; font-size: .72rem; font-weight: 700;
  background: var(--bg-sunk); color: var(--ink-3); border: 1px solid var(--line);
}
.pmx__rt { font-size: .78rem; line-height: 1.35; color: var(--ink-3); min-width: 0; }
.pmx__r.is-now .pmx__rn  { background: var(--acc); border-color: var(--acc); color: #fff; }
.pmx__r.is-now .pmx__rt  { color: var(--ink); font-weight: 600; }
.pmx__r.is-done .pmx__rn { background: var(--ok-soft); border-color: #bfe6d5; color: var(--ok); }
.pmx__r.is-done .pmx__rt { color: var(--ink-2); }

/* --- L'état, annoncé ------------------------------------------------------ */
.pmx__state { margin-bottom: 1.05rem; }
.pmx__msg {
  padding: .7rem .85rem; border-radius: var(--r-sm);
  font-size: .87rem; line-height: 1.55;
  background: var(--acc-soft); border: 1px solid var(--acc-line); color: var(--ink-2);
}
.pmx__msg[hidden] { display: none !important; }
.pmx__msg--off { background: var(--warn-soft); border-color: #f0dcb4; color: var(--warn); }
.pmx__msg--warn { background: #fff0f0; border-color: #f5c2c2; color: var(--c-warn, #dc3545); }
.pmx[data-state="confirming"] .pmx__msg[data-pmx-msg="confirming"] { background: var(--ok-soft); border-color: #bfe6d5; color: var(--ok); }
.pmx[data-state="underpaid"] .pmx__msg[data-pmx-msg="underpaid"] { background: var(--warn-soft); border-color: #f0dcb4; color: var(--warn); }
.pmx[data-state="error"] .pmx__msg[data-pmx-msg="error"] { background: #fdf2f1; border-color: #f4d5d2; color: #b42318; }

.pmx__short { display: grid; grid-template-columns: 1fr 1fr; gap: .6rem; margin: 0 0 1.05rem; }
.pmx__short[hidden] { display: none !important; }
.pmx__short > div { padding: .6rem .75rem; background: var(--bg-sunk); border-radius: var(--r-sm); min-width: 0; }
.pmx__short dt { font-size: .7rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-3); }
.pmx__short dd { margin: .15rem 0 0; font-family: var(--mono); font-size: .86rem; word-break: break-all; }

/* --- Combien, où, sur quel réseau ---------------------------------------- */
.pmx__grid { display: grid; gap: 1.1rem; align-items: start; }
@media (min-width: 620px) { .pmx__grid { grid-template-columns: minmax(0, 1fr) 208px; } }

.pmx__fields { display: grid; gap: .95rem; min-width: 0; }
.pmx__f {
  min-width: 0; padding: .85rem .9rem;
  border: 1px solid var(--line); border-radius: var(--r); background: #fff;
}
.pmx__fl { font-size: .71rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-3); }
.pmx__fv { display: flex; align-items: center; flex-wrap: wrap; gap: .5rem; margin-top: .35rem; min-width: 0; }
.pmx__fv--addr { align-items: stretch; }
.pmx__fh { margin-top: .5rem; font-size: .79rem; line-height: 1.55; color: var(--ink-3); }
.pmx__fh--warn {
  display: flex; align-items: flex-start; gap: .4rem;
  padding: .5rem .6rem; border-radius: var(--r-sm);
  background: var(--warn-soft); color: var(--warn); font-weight: 500;
}
.pmx__fh--warn svg { flex: none; margin-top: .12rem; }

.pmx__amt {
  font-family: var(--mono); font-size: clamp(1.25rem, 4.5vw, 1.6rem);
  letter-spacing: -.015em; font-variant-numeric: tabular-nums;
  word-break: break-all; min-width: 0;
}
.pmx__unit { font-size: .9rem; font-weight: 700; color: var(--ink-2); }
.pmx__net { font-size: 1.05rem; font-weight: 700; }
.pmx__addr {
  flex: 1 1 12rem; min-width: 0;
  font-family: var(--mono); font-size: .82rem; line-height: 1.5; word-break: break-all;
  background: var(--bg-sunk); border: 1px solid var(--line);
  border-radius: var(--r-sm); padding: .45rem .6rem;
}
.pmx__cp {
  flex: none; align-self: center;
  border: 1px solid var(--line-strong); background: #fff; color: var(--ink-2);
  font: inherit; font-size: .78rem; font-weight: 600; cursor: pointer;
  padding: .38rem .65rem; border-radius: 8px;
}
.pmx__cp:hover { border-color: var(--ink-3); color: var(--ink); }
.pmx__cp.is-done { background: var(--ok-soft); border-color: #bfe6d5; color: var(--ok); }
/* La zone de repli pour la copie, quand l'API du presse-papiers n'existe pas. */
.pmx__sink { position: fixed; top: 0; left: -9999px; width: 1px; height: 1px; opacity: 0; }

/* --- La colonne de droite : QR et rebours -------------------------------- */
.pmx__side { display: grid; gap: .8rem; min-width: 0; }
.pmx__qr { text-align: center; padding: .8rem; border: 1px solid var(--line); border-radius: var(--r); background: #fff; }
.pmx__qr img { display: block; margin: 0 auto; border-radius: var(--r-sm); max-width: 100%; height: auto; }
.pmx__qr img[hidden] { display: none; }
.pmx__qrl { margin-top: .5rem; font-size: .76rem; color: var(--ink-3); }
.pmx__qrnone { font-size: .8rem; color: var(--ink-3); }
.pmx__qrl[hidden], .pmx__qrnone[hidden] { display: none !important; }
.pmx__hold { padding: .7rem .8rem; border-radius: var(--r); background: var(--bg-sunk); text-align: center; }
.pmx__hold[hidden] { display: none !important; }
.pmx__holdl { font-size: .7rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-3); }
.pmx__holdv { font-family: var(--mono); font-size: 1.25rem; font-variant-numeric: tabular-nums; margin-top: .1rem; }
.pmx__holdh { margin-top: .35rem; font-size: .73rem; line-height: 1.5; color: var(--ink-3); }

/* --- Ce qu'on paie, replié ----------------------------------------------- */
.pmx__rec { margin-top: 1.05rem; border: 1px solid var(--line); border-radius: var(--r); background: var(--bg-soft); }
.pmx__recs { cursor: pointer; padding: .7rem .9rem; font-size: .85rem; font-weight: 600; list-style: none; }
.pmx__recs::-webkit-details-marker { display: none; }
.pmx__recs::after { content: "+"; float: right; color: var(--ink-3); font-weight: 400; }
.pmx__rec[open] .pmx__recs::after { content: "−"; }
.pmx__recd { margin: 0; padding: 0 .9rem .85rem; display: grid; gap: .4rem; }
.pmx__recd > div { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; font-size: .83rem; }
.pmx__recd dt { color: var(--ink-3); flex: none; }
.pmx__recd dd { margin: 0; text-align: right; color: var(--ink); min-width: 0; }
.pmx__recd-t { padding-top: .45rem; border-top: 1px solid var(--line); font-weight: 700; }

.pmx__coinnote {
  display: flex; align-items: flex-start; gap: .45rem;
  margin-top: 1rem; padding: .7rem .85rem; border-radius: var(--r-sm);
  background: var(--bg-sunk); font-size: .81rem; line-height: 1.6; color: var(--ink-2);
}
.pmx__coinnote svg { flex: none; margin-top: .15rem; color: var(--ink-3); }

/* --- Payé, fermé ---------------------------------------------------------- */
.pmx__done, .pmx__closed { text-align: center; padding: 1.5rem .5rem .5rem; }
.pmx__done[hidden], .pmx__closed[hidden], .pmx__live[hidden] { display: none !important; }
.pmx__doneico { display: inline-grid; place-items: center; width: 52px; height: 52px; border-radius: 50%; background: var(--ok-soft); color: var(--ok); }
.pmx__doneh { margin-top: .9rem; font-size: 1.25rem; font-weight: 700; }
.pmx__donep { margin-top: .5rem; font-size: .9rem; line-height: 1.6; color: var(--ink-2); max-width: 34rem; margin-inline: auto; }
.pmx__donen { margin-top: .8rem; font-size: .82rem; color: var(--ink-3); }
.pmx__closedh { font-size: 1.15rem; font-weight: 700; }
.pmx__closedp { margin-top: .5rem; font-size: .88rem; line-height: 1.6; color: var(--ink-2); max-width: 34rem; margin-inline: auto; }

/* Blocked state (kill switch) */
.pmx__blocked { padding: 1.25rem 1rem 1rem; }
.pmx__blocked[hidden] { display: none !important; }

/* Message box */
.pmx__blk-box { display: flex; align-items: flex-start; gap: .75rem; padding: 1rem; background: #fef2f2; border: 1px solid #fecaca; border-radius: 10px; margin-bottom: 1.25rem; }
.pmx__blk-icon { flex-shrink: 0; display: grid; place-items: center; width: 40px; height: 40px; border-radius: 50%; background: #fee2e2; color: #dc2626; }
.pmx__blk-msg { flex: 1; }
.pmx__blk-msg p { margin: 0; font-size: .9rem; line-height: 1.55; color: #1e293b; }
.pmx__blk-msg p + p { margin-top: .4rem; color: #475569; }
.pmx__blk-msg b { color: #1e293b; font-weight: 600; }

/* Formulaire */
.pmx__blk-form { margin-bottom: 1rem; }
.pmx__blk-field { margin-bottom: .85rem; }
.pmx__blk-label { display: block; font-size: .85rem; font-weight: 600; margin-bottom: .4rem; color: #1e293b; }
.pmx__blk-net { font-weight: 400; color: #64748b; }
.pmx__blk-input { display: block; width: 100%; padding: .7rem .85rem; font-size: .9rem; font-family: ui-monospace, SFMono-Regular, monospace; border: 2px solid #cbd5e1; border-radius: 8px; background: #fff; color: #1e293b; transition: border-color .15s, box-shadow .15s; }
.pmx__blk-input::placeholder { color: #94a3b8; }
.pmx__blk-input:focus { outline: none; border-color: #6366f1; box-shadow: 0 0 0 3px rgba(99,102,241,.15); }
.pmx__blk-err { font-size: .85rem; color: #fff; padding: .6rem .85rem; background: #dc3545; border-radius: 8px; margin-bottom: .85rem; }
.pmx__blk-err[hidden] { display: none; }
.pmx__blk-btn { display: flex; align-items: center; justify-content: center; gap: .6rem; width: 100%; padding: .85rem 1.5rem; font-size: 1rem; font-weight: 600; background: #6366f1; color: #fff; border: none; border-radius: 10px; cursor: pointer; transition: background .15s, transform .1s, box-shadow .15s; }
.pmx__blk-btn:hover { background: #4f46e5; box-shadow: 0 4px 12px rgba(99,102,241,.35); }
.pmx__blk-btn:active { transform: scale(.98); }
.pmx__blk-btn:disabled { opacity: .6; cursor: wait; }
.pmx__blk-btn svg { flex-shrink: 0; color: #fff; }

/* Détails supplémentaires */
.pmx__blk-details { font-size: .8rem; color: #64748b; border-top: 1px solid #e2e8f0; padding-top: .75rem; margin-top: .5rem; }
.pmx__blk-details summary { cursor: pointer; font-weight: 500; color: #475569; }
.pmx__blk-details summary:hover { color: #1e293b; }
.pmx__blk-details p { margin: .6rem 0 0; line-height: 1.6; }
.pmx__blk-details p:first-of-type { margin-top: .75rem; }

.pmx__foot { flex: none; padding: .85rem 1.1rem; border-top: 1px solid var(--line); background: var(--bg-soft); }
.pmx__keep { font-size: .78rem; line-height: 1.55; color: var(--ink-3); }
.pmx__url { color: var(--acc-dark); }
.pmx__url code { font-family: var(--mono); font-size: .76rem; word-break: break-all; }

/* [!] Sur un petit écran la fenêtre occupe tout : une boîte flottante de 90 %
   au milieu d'un fond sombre laisse deux bandes inutilisables de chaque côté
   au moment précis où l'on a besoin de place pour une adresse. */
@media (max-width: 560px) {
  .pmx { max-width: 100vw; max-height: 100dvh; width: 100vw; }
  .pmx__box { max-height: 100dvh; border-radius: 0; border: 0; }
  .pmx__body { padding: 1rem .9rem 1.2rem; }
  .pmx__rail { grid-template-columns: 1fr; gap: .4rem; }
  .pmx__short { grid-template-columns: 1fr; }
}

/* --- Ce qui reste sur /configure derrière la fenêtre ---------------------- */
.cfgres {
  display: flex; align-items: center; flex-wrap: wrap; gap: .75rem;
  margin-bottom: 1.4rem; padding: .8rem 1rem;
  background: var(--acc-soft); border: 1px solid var(--acc-line); border-radius: var(--r);
}
.cfgres[hidden], .cfgdone[hidden] { display: none !important; }
.cfgres__i { display: grid; place-items: center; width: 30px; height: 30px; border-radius: 9px; background: #fff; color: var(--acc); flex: none; }
.cfgres__t { flex: 1 1 14rem; min-width: 0; font-size: .88rem; color: var(--ink-2); }
.cfgres__t b { font-family: var(--mono); font-size: .86rem; color: var(--ink); }
.cfgres__x { border: 0; background: none; padding: .3rem .2rem; font: inherit; font-size: .8rem; color: var(--ink-3); cursor: pointer; text-decoration: underline; }

.cfgdone {
  max-width: 46rem; margin: 0 auto; padding: clamp(1.4rem, 4vw, 2.4rem) clamp(1.1rem, 3vw, 2rem);
  background: #fff; border: 1px solid var(--line); border-radius: var(--r-lg);
  box-shadow: var(--shadow-1); text-align: center;
}
.cfgdone__i { display: inline-grid; place-items: center; width: 50px; height: 50px; border-radius: 50%; background: var(--ok-soft); color: var(--ok); }
.cfgdone__h { margin-top: .9rem; font-size: clamp(1.3rem, 3vw, 1.7rem); letter-spacing: -.015em; }
.cfgdone__h b { font-family: var(--mono); font-size: .82em; letter-spacing: .01em; }
.cfgdone__p { margin-top: .7rem; font-size: .95rem; line-height: 1.65; color: var(--ink-2); max-width: var(--m-note); margin-inline: auto; }
.cfgdone__p b { color: var(--ink); font-family: var(--mono); font-size: .92em; word-break: break-all; }
.cfgdone__acts { display: flex; flex-wrap: wrap; gap: .6rem; justify-content: center; margin-top: 1.25rem; }
.cfgdone__alt { margin-top: 1.35rem; padding-top: 1.1rem; border-top: 1px solid var(--line); font-size: .86rem; color: var(--ink-3); }
.cfgdone__alt[hidden] { display: none !important; }
.cfgdone__sure { margin-top: 1rem; padding: 1rem; background: var(--warn-soft); border: 1px solid #f0dcb4; border-radius: var(--r); }
.cfgdone__sure[hidden] { display: none !important; }
.cfgdone__surep { font-size: .87rem; line-height: 1.6; color: var(--warn); max-width: var(--m-note); margin-inline: auto; }
.cfgdone__err { margin-top: .7rem; font-size: .85rem; font-weight: 600; color: #b42318; }
.cfgdone__err[hidden] { display: none !important; }

/* Le refus d'un envoi, à côté du bouton qui vient d'être cliqué. */
.sum__err {
  margin-bottom: .7rem; padding: .6rem .7rem; border-radius: var(--r-sm);
  background: #fdf2f1; border: 1px solid #f4d5d2; color: #b42318;
  font-size: .82rem; line-height: 1.5;
}
.sum__err[hidden] { display: none !important; }


/* ============================================================================
   SÉLECTEUR DE LANGUE FLOTTANT (.lsw)
   ============================================================================

   [!] LA CSP DU SITE EST `style-src 'self'` : pas de <style>, pas de style="".
       L'ouverture se joue donc entièrement sur des CLASSES (`is-open`) et sur
       l'attribut `hidden`, jamais sur `element.style`. Le script ne fait que
       basculer des classes.

   [!] `z-index: 60` — SOUS le voile de navigation (80) et sous le tiroir (85).
       Un sélecteur qui flotterait au-dessus de la fenêtre de connexion ou du
       tiroir de paiement resterait cliquable pendant qu'on saisit une adresse
       de remboursement : le pire moment pour recharger la page dans une autre
       langue.

   [!] `env(safe-area-inset-*)` — sur un iPhone, la barre d'accueil mange le bas
       de l'écran. Sans cette marge, le bouton se retrouve à moitié dessous et
       le pouce ouvre le multitâche au lieu du menu.
   ========================================================================== */

.lsw {
  position: fixed;
  z-index: 60;
  right:  calc(1.15rem + env(safe-area-inset-right, 0px));
  bottom: calc(1.15rem + env(safe-area-inset-bottom, 0px));
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: .6rem;
  font-size: .875rem;
}

/* --- Le bouton ------------------------------------------------------------ */

.lsw__btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  padding: .58rem .82rem .58rem .72rem;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: #fff;
  color: var(--ink);
  font: inherit;
  font-weight: 600;
  letter-spacing: .01em;
  cursor: pointer;
  box-shadow: var(--shadow-2);
  transition: transform .18s cubic-bezier(.2, .8, .3, 1),
              box-shadow .18s ease,
              border-color .18s ease;
}
.lsw__btn:hover  { transform: translateY(-1px); box-shadow: var(--shadow-3); border-color: var(--acc-line); }
.lsw__btn:active { transform: translateY(0); }
.lsw__btn:focus-visible { outline: 2px solid var(--acc); outline-offset: 3px; }

.lsw__globe { color: var(--ink-3); flex: none; transition: color .18s ease, transform .4s cubic-bezier(.2, .8, .3, 1); }
.lsw__btn:hover .lsw__globe { color: var(--acc); }
/* Le globe pivote quand le panneau s'ouvre : le bouton dit qu'il a agi. */
.lsw.is-open .lsw__globe { color: var(--acc); transform: rotate(180deg); }
.lsw.is-open .lsw__btn   { border-color: var(--acc-line); background: var(--acc-soft); }

.lsw__cur { font-variant-numeric: tabular-nums; }

/* La pastille de suggestion : présente, jamais bruyante. */
.lsw__dot {
  position: absolute;
  top: 6px; right: 8px;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--acc);
  box-shadow: 0 0 0 2px #fff;
}

/* --- Le panneau ----------------------------------------------------------- */

.lsw__panel {
  width: 232px;
  max-height: min(58vh, 420px);
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: .5rem;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: #fff;
  box-shadow: var(--shadow-3);

  /* [!] L'ORIGINE EST EN BAS À DROITE, sous le bouton : le panneau doit avoir
         l'air de SORTIR du bouton, pas d'apparaître à côté. C'est ce détail-là
         qui fait la différence entre « animé » et « juste en mouvement ». */
  transform-origin: 100% calc(100% + 8px);
  transform: scale(.94) translateY(6px);
  opacity: 0;
  transition: opacity .16s ease,
              transform .22s cubic-bezier(.16, 1, .3, 1),
              visibility .22s;

  /* [!] `visibility: hidden` ET NON `display: none`, POUR TROIS RAISONS :
         - `display: none` n'a aucun etat intermediaire : il n'y a rien a
           animer, la carte apparait d'un coup.
         - `visibility: hidden` sort quand meme les dix liens de l'ordre de
           tabulation : on ne tabule pas dans un menu ferme.
         - les liens restent DANS LE DOM, donc explorables. C'est ce qui fait de
           ce selecteur un vrai maillage interne entre les variantes de langue
           et pas seulement un confort visuel. */
  visibility: hidden;
  pointer-events: none;
}
.lsw.is-open .lsw__panel {
  transform: scale(1) translateY(0);
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
}

.lsw__h {
  margin: .15rem .55rem .45rem;
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.lsw__list { list-style: none; margin: 0; padding: 0; }

/* Les entrées arrivent en cascade — 22 ms d'écart, assez pour qu'on le sente,
   trop peu pour qu'on attende. Au-delà de la 10e, plus de retard : une liste
   longue ne doit pas se dérouler comme un générique. */
.lsw__li { opacity: 0; transform: translateY(4px); transition: opacity .18s ease, transform .18s ease; }
.lsw.is-open .lsw__li { opacity: 1; transform: none; }
.lsw.is-open .lsw__li:nth-child(1)  { transition-delay: .02s; }
.lsw.is-open .lsw__li:nth-child(2)  { transition-delay: .04s; }
.lsw.is-open .lsw__li:nth-child(3)  { transition-delay: .06s; }
.lsw.is-open .lsw__li:nth-child(4)  { transition-delay: .08s; }
.lsw.is-open .lsw__li:nth-child(5)  { transition-delay: .10s; }
.lsw.is-open .lsw__li:nth-child(6)  { transition-delay: .12s; }
.lsw.is-open .lsw__li:nth-child(7)  { transition-delay: .14s; }
.lsw.is-open .lsw__li:nth-child(8)  { transition-delay: .16s; }
.lsw.is-open .lsw__li:nth-child(9)  { transition-delay: .18s; }
.lsw.is-open .lsw__li:nth-child(n+10) { transition-delay: .2s; }

.lsw__opt {
  display: flex;
  align-items: center;
  gap: .6rem;
  padding: .5rem .55rem;
  border-radius: var(--r-sm);
  color: var(--ink-2);
  text-decoration: none;
  transition: background .12s ease, color .12s ease;
}
.lsw__opt:hover { background: var(--bg-soft); color: var(--ink); }
.lsw__opt:focus-visible { outline: 2px solid var(--acc); outline-offset: -2px; }
.lsw__opt.is-on { color: var(--ink); font-weight: 600; background: var(--acc-soft); }

.lsw__native { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lsw__iso {
  flex: none;
  font-size: .68rem; font-weight: 700; letter-spacing: .06em;
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}
.lsw__tick { flex: none; color: var(--acc); opacity: 0; }
.lsw__opt.is-on .lsw__tick { opacity: 1; }
.lsw__opt.is-on .lsw__iso  { color: var(--acc); }

/* --- La suggestion -------------------------------------------------------- */

.lsw__hint {
  display: flex;
  align-items: center;
  gap: .1rem;
  padding: .3rem .3rem .3rem .8rem;
  border: 1px solid var(--acc-line);
  border-radius: 999px;
  background: var(--acc-soft);
  box-shadow: var(--shadow-2);
  animation: lsw-in .3s cubic-bezier(.16, 1, .3, 1) both;
}
.lsw__hint-go {
  color: var(--acc-dark);
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
}
.lsw__hint-go:hover { text-decoration: underline; }
.lsw__hint-x {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px;
  margin-left: .35rem;
  border: 0; border-radius: 50%;
  background: transparent;
  color: var(--acc-dark);
  cursor: pointer;
  opacity: .6;
  transition: opacity .15s ease, background .15s ease;
}
.lsw__hint-x:hover { opacity: 1; background: rgba(31, 79, 224, .1); }
.lsw__hint-x:focus-visible { outline: 2px solid var(--acc); outline-offset: 1px; }

@keyframes lsw-in {
  from { opacity: 0; transform: translateX(10px) scale(.96); }
  to   { opacity: 1; transform: none; }
}

/* --- Écrans étroits ------------------------------------------------------- */

@media (max-width: 560px) {
  .lsw        { right: .85rem; bottom: calc(.85rem + env(safe-area-inset-bottom, 0px)); }
  .lsw__panel { width: min(258px, calc(100vw - 1.7rem)); }
  /* La suggestion garde le nom de la langue mais perd le superflu : sur 360 px
     une puce trop large recouvre le bouton qu'elle désigne. */
  .lsw__hint  { max-width: calc(100vw - 1.7rem); }
  .lsw__hint-go { overflow: hidden; text-overflow: ellipsis; }
}

/* --- Impression et mouvement réduit --------------------------------------- */

/* --- Deux défauts vus le 2026-09-02 à la sonde DOM ------------------------ */

/* [!] `display: flex` L'EMPORTE SUR `[hidden]` — même piège que `.btn[hidden]`
       en §4 : la suggestion VIDE s'affichait en permanence, une pilule bleue
       avec une croix et rien dedans, posée au-dessus du bouton, sur toutes les
       pages et à toutes les largeurs. `hidden` ne suffit jamais à un élément
       qui a une règle `display` : il lui faut sa garde. */
.lsw__hint[hidden] { display: none !important; }

/* [!] LE CONTENEUR NE DOIT PAS INTERCEPTER LES CLICS. Il est dimensionné par
       le panneau fermé (visibility: hidden, mais présent) : 232 × 218 px sur
       bureau, 258 × 232 px sur téléphone, en bas à droite — et un bloc
       positionné reçoit les clics même sans fond. `elementFromPoint` y
       rendait `div.lsw` : les boutons « Configure » du catalogue qui passaient
       dessous ne répondaient plus. Le conteneur laisse passer le pointeur ;
       seuls le bouton, la suggestion et le panneau OUVERT le reçoivent. */
.lsw { pointer-events: none; }
.lsw__btn, .lsw__hint { pointer-events: auto; }

/* [!] CIBLES TACTILES À 44 px, le plancher de l'audit mobile. La pilule de
       suggestion mesurait 22 px de haut et sa croix 22 × 22 : au pouce, un
       clic sur deux tombait sur le bouton du hero qui passe dessous. */
@media (max-width: 767px) {
  .lsw__hint { min-height: 44px; gap: .6rem; padding: .15rem .15rem .15rem .95rem; }
  .lsw__hint-go { display: inline-flex; align-items: center; min-height: 44px; }
  .lsw__hint-x { width: 44px; height: 44px; margin-left: 0; }
}

@media print { .lsw { display: none; } }

/* [!] `prefers-reduced-motion` N'EST PAS UNE PRÉFÉRENCE ESTHÉTIQUE : pour une
       personne sujette au mal des transports vestibulaire, une mise à l'échelle
       déclenche une nausée réelle. On garde le fondu, qui ne bouge rien, et on
       retire toute translation, rotation et mise à l'échelle. */
@media (prefers-reduced-motion: reduce) {
  .lsw__btn, .lsw__globe, .lsw__panel, .lsw__li, .lsw__opt {
    transition-duration: .01ms !important;
    transition-delay: 0s !important;
  }
  .lsw__panel { transform: none; }
  .lsw.is-open .lsw__panel { transform: none; }
  .lsw__li { transform: none; }
  .lsw.is-open .lsw__globe { transform: none; }
  .lsw__hint { animation: none; }
  .lsw__btn:hover { transform: none; }
}


/* ============================================================================
   DRAPEAUX DES CENTRES DE DONNÉES (.flag)
   ============================================================================
   [!] Les coins arrondis sont découpés ICI et non par un `<clipPath id="…">`
       dans le SVG : un identifiant en ligne est GLOBAL à la page, et les six
       drapeaux apparaissent deux fois sur certaines pages. Douze `id` en
       double, c'est du HTML invalide et un rendu qui dépend de l'ordre.
   ========================================================================== */

.flag { display: inline-block; vertical-align: -.18em; flex: none; }
.flag__g { clip-path: inset(0 round 2.2px); }

/* Devant un nom de pays : une respiration, jamais un décalage vertical. */
.dc__meta > .flag,
.tbl__meta > .flag,
.loc__country > .flag { margin-right: .4rem; }

/* Dans le configurateur, le drapeau REMPLACE la punaise : il occupe la même
   case de 30 px, mais sans le fond gris qui l'encadrait — un drapeau posé sur
   une pastille grise se lit comme un bouton désactivé. */
.opt__i--flag { background: transparent; width: auto; }
.opt:hover .opt__i--flag,
.opt input:checked + .opt__b .opt__i--flag { background: transparent; }


/* ============================================================================
   12. MOBILE — LES FONDATIONS TACTILES
   ============================================================================

   Cette section ne change RIEN sur un poste de travail : tout y est sous
   `(max-width: 1079px), (pointer: coarse)`. La seconde condition est là pour
   les tablettes et les portables tactiles, qui reçoivent la mise en page large
   mais se pilotent au doigt.

   [!] POURQUOI 44 px. Ce n'est pas un chiffre de confort, c'est la largeur
       moyenne d'une pulpe de pouce (Apple HIG, WCAG 2.5.8 niveau AAA). En
       dessous, le taux d'échec au premier appui grimpe vite — et sur le bouton
       qui lance un paiement, un échec sur trois se compte en commandes perdues.
       Aucun de ces défauts ne se voit sur un écran de bureau rétréci : la
       souris touche au pixel près.

   [!] POURQUOI 16 px SUR LES CHAMPS. C'est le seuil EXACT en dessous duquel
       Safari iOS agrandit la page au moment où le champ prend le focus — et ne
       la réduit jamais ensuite. Le visiteur tape une recherche, la page reste
       agrandie pour tout le reste de sa visite, et il navigue dans un site qui
       déborde de l'écran. Le défaut ne se reproduit sur AUCUN émulateur de
       bureau : il faut un vrai iPhone, ou connaître la règle.
   ========================================================================== */

@media (max-width: 1079px), (pointer: coarse) {

  /* --- Le socle du geste ---------------------------------------------------
     `touch-action: manipulation` supprime l'attente de 300 ms que certains
     navigateurs gardent pour distinguer un appui d'un double appui destiné au
     zoom. Sans elle, chaque bouton du site répond avec un tiers de seconde de
     retard — assez pour qu'on appuie une seconde fois. */
  a, button, input, select, textarea, summary, label.opt, [role="button"] {
    touch-action: manipulation;
  }

  /* Le cadre gris que WebKit peint sur l'élément touché est laid et arrive
     APRÈS le geste. On le remplace par une teinte de marque, discrète. */
  a, button, summary, label.opt, [role="button"] {
    -webkit-tap-highlight-color: rgba(31, 79, 224, .12);
  }

  /* --- Les champs de saisie ------------------------------------------------
     16 px, sans exception. Voir l'en-tête de section. */
  input, select, textarea {
    font-size: 16px;
  }
  /* [!] `font-size` seul ne suffit pas : les champs de ce site tirent leur
         hauteur du texte, et un champ de 20 px de haut reste impossible à
         viser même si sa police fait 16 px. */
  input:not([type="radio"]):not([type="checkbox"]):not([type="hidden"]),
  select, textarea {
    min-height: 44px;
  }

  /* --- Le plancher de 44 px sur ce qui se touche --------------------------- */
  .btn, .nav__signin, .burger, .code__copy, .chip, .picker__chip,
  .wbar__b, .lsw__btn, .lsw__opt, .cardgo, .orow__gpu {
    min-height: 44px;
  }
  .btn { display: inline-flex; align-items: center; justify-content: center; }

  /* `--sm` était le format « discret » du bureau : sur un téléphone, il n'y a
     pas de bouton discret, il y a des boutons qu'on rate. */
  .btn--sm { padding-block: .6rem; font-size: .9rem; }

  .burger { width: 44px; height: 44px; }

  /* La marque est un lien vers l'accueil, donc une cible. */
  .brand { min-height: 44px; }

  /* --- La recherche de l'en-tête -------------------------------------------
     Elle mesurait 20 px de haut pour 14 px de police : à la fois impossible à
     viser et déclencheuse du zoom iOS. */
  .hsearch { min-height: 44px; align-items: center; }
  .hsearch__in { min-height: 40px; }

  /* --- Le pied de page -----------------------------------------------------
     Vingt-huit liens de 19 px de haut, sur toutes les pages du site : c'était
     le premier gisement de cibles ratées. Ils passent en lignes de 44 px, en
     gardant les deux colonnes — une seule colonne donnerait un pied de page de
     1 200 px que personne ne fait défiler jusqu'au bout. */
  .ft__l { gap: 0; }
  .ft__l a {
    display: flex; align-items: center;
    min-height: 44px;
    padding-right: .5rem;
  }
  /* Les intitulés de colonne étaient à 11,5 px : lisibles à 40 cm sur un écran
     de bureau, devinés à 25 cm sur un téléphone. */
  .ft__h { font-size: .78rem; }

  /* --- Le plancher de lisibilité ------------------------------------------
     Rien sous 12 px. Ces sept classes portaient des étiquettes de 10,6 à
     11,8 px — des tailles conçues pour être discrètes sur un grand écran, et
     qui deviennent illisibles sur un petit. */
  .toc__h, .gcard__tag, .dc__code, .fitbox__opt, .sum__h,
  .picker__lbl, .code__copy, .tag, .lsw__h {
    font-size: .75rem;
  }

  /* --- Le sommaire d'article ----------------------------------------------- */
  .toc__l { gap: 0; }
  .toc__l a { display: flex; align-items: center; min-height: 44px; }

  /* --- La barre d'étapes du configurateur ---------------------------------- */
  .wbar__b { padding-block: .55rem; }

  /* --- Les listes qui défilent horizontalement -----------------------------
     `overscroll-behavior: contain` empêche le geste d'être transmis à la page
     une fois la fin du rail atteinte : sans lui, faire défiler un tableau de
     prix jusqu'au bout fait partir la PAGE de côté, et le visiteur croit avoir
     cassé quelque chose. */
  .tbl-wrap, .cat__scroll, [data-hscroll] {
    overscroll-behavior-x: contain;
    scroll-snap-type: x proximity;
  }

  /* --- Le retour au toucher ------------------------------------------------
     Sur un téléphone il n'y a pas de survol : sans état `:active`, rien ne
     confirme que l'appui a été pris, et le visiteur appuie deux fois. */
  .btn:active, .chip:active, .picker__chip:active,
  .nav__signin:active, .lsw__opt:active, label.opt:active {
    transform: scale(.985);
  }
  .btn, .chip, .picker__chip, .nav__signin, label.opt {
    transition: transform .1s ease, background-color .14s ease, border-color .14s ease;
  }
}

/* --- Mouvement réduit : le retour tactile devient une teinte, pas un
       mouvement. --------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .btn:active, .chip:active, .picker__chip:active,
  .nav__signin:active, .lsw__opt:active, label.opt:active { transform: none; }
}


/* ---------------------------------------------------------------------------
   12b. MOBILE — ce que la première passe n'a pas atteint
   ---------------------------------------------------------------------------
   [!] `input, select, textarea { font-size: 16px }` N'A RIEN CHANGÉ sur six
       champs, et la raison vaut d'être écrite : un sélecteur d'ÉLÉMENT perd
       contre un sélecteur de CLASSE, quelle que soit sa place dans la feuille.
       `.hsearch__in { font-size: .87rem }` gagnait donc en silence, et les
       champs restaient sous le seuil de zoom d'iOS. On nomme les classes.
   ------------------------------------------------------------------------ */

@media (max-width: 1079px), (pointer: coarse) {

  /* Les six champs qui résistaient, nommés un par un. */
  .hsearch__in, .field__c, .results__in, .cat__select, .sgn__in, .fld__in {
    font-size: 16px;
  }

  /* --- Le fil d'Ariane -----------------------------------------------------
     Ses liens faisaient 34 x 21 px sur 46 pages. Un fil d'Ariane EST une
     navigation : c'est souvent le seul chemin de retour vers la rubrique
     depuis une page profonde, et sur un téléphone c'est le geste le plus
     naturel. On l'aère au lieu de le laisser décoratif. */
  .crumb__l a, .crumb__l span[aria-current] {
    display: inline-flex; align-items: center; min-height: 40px;
  }
  .crumb__l { row-gap: 0; }

  /* --- Les deux dernières cibles courtes ---------------------------------- */
  .chosen__change { display: inline-flex; align-items: center; min-height: 44px; }
  .browse__toggle { min-height: 44px; }

  /* --- Les mentions en <small> --------------------------------------------
     Cent soixante-quatre occurrences sur la seule page du catalogue : la
     spécification de chaque machine (processeur, mémoire, disque) y est en
     <small> à 11,4 px. C'est précisément l'information qu'on vient lire pour
     choisir, et c'est la plus petite de la page. */
  small { font-size: .78rem; }

  /* --- L'espacement entre cibles ------------------------------------------
     WCAG 2.5.8 : deux cibles voisines doivent être séparées, faute de quoi la
     précision du doigt ne suffit plus. Quatre pixels entre deux boutons de
     comparaison, c'est un appui sur deux qui part sur le mauvais. */
  .cmp__acts, .card__acts, .gpu__acts, .picker__chips, .chips, .wbar__l {
    gap: .6rem;
  }
  .picker__chips, .chips { row-gap: .6rem; }
}


/* ---------------------------------------------------------------------------
   12c. MOBILE — les dernières résistances de spécificité
   ------------------------------------------------------------------------ */

@media (max-width: 1079px), (pointer: coarse) {

  /* Le fil d'Ariane : 40 px ne suffisait pas, le plancher est 44. */
  .crumb__l a, .crumb__l span[aria-current] { min-height: 44px; }

  /* --- La ligne de spécification du catalogue ------------------------------
     `.orow__c small` : 11,4 px, tronqué à l'ellipse, et répété 164 fois sur la
     page du catalogue. C'est LA ligne qu'on vient lire pour choisir une
     machine — processeur, mémoire, disque — et c'était le plus petit texte du
     site, coupé au milieu.

     [!] On lève la police ET on autorise le retour à la ligne. Garder
         `white-space: nowrap` avec une police plus grande ne ferait que couper
         plus tôt : on troquerait un texte illisible contre un texte absent.
         Deux lignes lisibles valent mieux qu'une ligne tronquée — sur un
         téléphone, la hauteur est la ressource abondante, pas la largeur. */
  .orow__c small {
    font-size: .78rem;
    white-space: normal;
    overflow: visible;
    line-height: 1.35;
  }
}


/* ---------------------------------------------------------------------------
   12d. MOBILE — /status et la barre d'étapes
   ------------------------------------------------------------------------ */

@media (max-width: 1079px), (pointer: coarse) {

  /* --- La courbe de disponibilité de /status -------------------------------
     Elle débordait de 39 px, et c'était de l'ARITHMÉTIQUE, pas un accident :
       90 barres × 2 px minimum + 89 espaces × 2 px = 358 px,
     pour 319 px de large disponibles à l'intérieur de la rangée. Comme les
     barres sont des éléments de grille, `min-width: auto` leur interdit de
     descendre sous leur contenu minimal : la piste de grille s'élargit, et
     toute la rangée sort de l'écran.

     [!] ON NE RETIRE PAS DE JOURS. Quatre-vingt-dix jours d'historique, c'est
         la promesse de la page ; en afficher soixante sur téléphone donnerait
         deux versions différentes de la même mesure. On rétrécit la barre et
         l'espace : 90 × 1 + 89 × 1 = 179 px, largement dans les 319. */
  .spark { gap: 1px; }
  .spark__d { min-width: 1px; }

  /* La rangée elle-même : une piste qui a le droit de rétrécir. Sans
     `minmax(0, 1fr)`, une piste `auto` prend la taille de son contenu et
     déborde silencieusement du conteneur. */
  .strow { grid-template-columns: minmax(0, 1fr); }
  .strow > * { min-width: 0; }

  /* --- La barre d'étapes du configurateur ----------------------------------
     Les trois étapes sont des boutons à 5,6 px l'un de l'autre. La règle
     précédente visait `.wbar__l`, qui n'existe pas : la liste est `ol.wbar`.
     C'est le genre d'erreur qu'un sélecteur muet ne signale jamais — d'où
     l'audit, qui l'a redit à l'identique au passage suivant. */
  .wbar { gap: .6rem; }
}


/* ---------------------------------------------------------------------------
   12e. MOBILE — le tableau de comparaison
   ------------------------------------------------------------------------ */
/* [!] LA PREMIÈRE VERSION DE CETTE RÈGLE VISAIT `.tbl--cmp`, QUI N'EXISTE PAS.
       Elle n'a donc rien fait, en silence -- et l'audit a redit les quatre
       mêmes paires au passage suivant, mot pour mot. C'est tout l'intérêt de
       remesurer après chaque correctif : un sélecteur qui ne désigne rien ne
       lève aucune erreur, ni dans le navigateur, ni dans l'outillage.
       La vraie cause était ailleurs : les deux boutons se suivaient dans UNE
       cellule, séparés par un simple espace de 4 px. Corrigé dans le balisage
       (`.cmp__pick`, compare.php), où l'écart est désormais déclaré. */
.cmp__pick { display: inline-flex; flex-wrap: wrap; gap: .625rem; }


/* ---------------------------------------------------------------------------
   12f. MOBILE — LA FICHE DU CATALOGUE
   ---------------------------------------------------------------------------
   C'est l'écran le plus important du site sur téléphone : la liste des
   machines. Il était rendu par la grille du tableau de bureau, repliée en deux
   colonnes — avec trois conséquences visibles sur la capture :

     1. UNE GOUTTIÈRE PERMANENTE DE 38 px. Le logo NVIDIA occupait sa propre
        colonne, et TOUT le contenu était poussé derrière lui : sur 390 px de
        large, la ligne de spécification commençait à 68 px. Un dixième de
        l'écran perdu sur chaque ligne, quarante et une fois.
     2. HUIT LIGNES PAR FICHE. Chaque spécification empilait sa valeur et sa
        précision l'une sous l'autre (« 128 GB » puis « Intel Xeon Silver
        4410Y »), alors qu'elles tiennent côte à côte.
     3. LE PRIX EN BAS. Sur une liste de quarante et une machines qu'on
        parcourt au pouce, le prix est le critère de tri ; il était sous les
        specs, hors du champ au moment où l'on compare.

   [!] AUCUNE DE CES RÈGLES NE TOUCHE LE BUREAU. La disposition en tableau
       reprend telle quelle à 1120 px, où elle est juste — le poste de travail
       du propriétaire ne bouge pas d'un pixel.
   ------------------------------------------------------------------------ */

@media (max-width: 1119px) {

  .orow {
    grid-template-columns: 26px minmax(0, 1fr) auto;
    column-gap: .6rem;
    row-gap: .5rem;
    align-items: center;
    padding: .95rem 1rem;
    border-radius: var(--r);
  }

  /* --- La ligne de tête : logo, nom, PRIX ---------------------------------- */
  .orow__ico { grid-column: 1; grid-row: 1; }
  .orow__id  { grid-column: 2; grid-row: 1; }

  /* Le prix remonte à côté du nom : c'est le couple qu'on compare. */
  .orow__c--price {
    grid-column: 3; grid-row: 1;
    justify-self: end;
    display: flex; flex-direction: column; align-items: flex-end; gap: 0;
    text-align: right;
  }
  .orow__c--price b { font-size: 1.15rem; letter-spacing: -.02em; }
  /* [!] .75rem ET NON .7rem : 11,2 px passe sous le plancher de lisibilité posé
         en §12a, et l'audit me l'a renvoyé en 90 occurrences sur 26 pages au
         passage suivant. Un plancher ne vaut que si l'on s'y tient soi-même --
         surtout dans la règle écrite juste après l'avoir posé. */
  .orow__c--price small { font-size: .75rem; }

  /* --- Les spécifications : pleine largeur, une ligne chacune -------------- */
  .orow__c:not(.orow__c--price) {
    grid-column: 1 / -1;
    display: flex; flex-wrap: wrap; align-items: baseline;
    column-gap: .5rem; row-gap: .1rem;
    padding-top: .1rem;
  }
  /* La valeur et sa précision côte à côte, séparées par une puce : deux lignes
     deviennent une, et la fiche passe de huit lignes à quatre. */
  .orow__c:not(.orow__c--price) small::before {
    content: "·";
    margin-right: .5rem;
    color: var(--line-strong);
  }

  /* La jauge de mémoire devient un petit indicateur EN LIGNE, à droite de la
     valeur, au lieu d'une barre pleine largeur qu'on ne rattachait à rien. */
  .orow__bar { flex: 1 1 48px; min-width: 48px; max-width: 120px; }

  /* --- L'action ------------------------------------------------------------ */
  .orow__go { grid-column: 1 / -1; margin-top: .15rem; }

  /* Un peu d'air entre les fiches : sur un écran tactile, la séparation se lit
     au premier coup d'oeil et évite de viser la mauvaise machine. */
  .orows { display: grid; gap: .6rem; }
}


/* ---------------------------------------------------------------------------
   12g. MOBILE — la fiche du catalogue, deuxième passe
   ------------------------------------------------------------------------ */

@media (max-width: 1119px) {

  /* [!] LE LOGO NVIDIA DISPARAÎT SUR TÉLÉPHONE, et ce n'est pas une économie
         de place arbitraire : sur une page où les QUARANTE ET UNE machines
         sont des NVIDIA, ce logo répété quarante et une fois ne porte AUCUNE
         information. Il coûtait 38 px sur 390 — un dixième de la largeur — et
         il décalait le titre de la fiche par rapport à ses propres
         spécifications, ce qui se voyait comme un défaut d'alignement.
         Sur grand écran il reste : il y sert d'ancre visuelle en tête de
         colonne, et la place ne manque pas. */
  .orow__ico { display: none; }

  .orow { grid-template-columns: minmax(0, 1fr) auto; }
  .orow__id       { grid-column: 1; grid-row: 1; }
  .orow__c--price { grid-column: 2; grid-row: 1; }
  .orow__c:not(.orow__c--price),
  .orow__go       { grid-column: 1 / -1; }

  /* La jauge de mémoire : plus courte et plus contrastée. Étalée sur 120 px
     dans un gris très clair, elle se lisait comme un filet de séparation, pas
     comme une mesure — et la portion remplie d'une carte de 24 Go sur une
     échelle qui monte à 180 en devenait invisible. */
  .orow__bar {
    flex: 0 0 72px; min-width: 72px; max-width: 72px;
    height: 5px; background: var(--line);
  }
}


/* ---------------------------------------------------------------------------
   12h. MOBILE — les contrôles du catalogue
   ---------------------------------------------------------------------------
   Sur la capture à 390 px, les quatre contrôles ne s'accordaient pas :
   « Filtres » et la recherche prenaient toute la largeur, le tri s'arrêtait à
   la moitié, et les trois durées d'engagement étaient CENTRÉES alors que tout
   le reste de la page est aligné à gauche. Trois alignements différents dans
   un bloc de quatre éléments : c'est ce qui donne l'impression d'une mise en
   page de bureau rétrécie plutôt que d'une interface pensée pour le pouce.
   ------------------------------------------------------------------------ */

@media (max-width: 819px) {

  /* Le tri s'aligne sur les deux contrôles au-dessus. */
  .cat__select { width: 100%; }

  /* [!] `margin-left: auto` POUSSAIT LES DURÉES À DROITE. C'est juste dans une
         barre horizontale de bureau, où le tri est à gauche et la durée à
         droite ; empilé, cela produit un bloc centré au milieu de contrôles
         alignés à gauche. */
  .chips--term { margin-left: 0; }

  /* Les trois durées deviennent un SÉLECTEUR SEGMENTÉ pleine largeur : c'est
     le motif que toute application mobile emploie pour un choix exclusif de
     deux à quatre options, et il double la surface de chaque cible. */
  .chips--term {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: .4rem;
    width: 100%;
  }
  .chips--term .chip {
    width: 100%;
    justify-content: center;
    text-align: center;
  }
}


/* ---------------------------------------------------------------------------
   12i. MOBILE — le bandeau de chiffres des pages produit
   ---------------------------------------------------------------------------
   Quatre chiffres empilés, 93 px chacun : 372 px de haut — presque un écran
   entier de téléphone — pour quatre nombres de trois caractères. Le passage à
   deux colonnes se faisait à 620 px, une largeur qu'aucun téléphone n'atteint
   en portrait.

   [!] LE SEUIL DE 620 px ÉTAIT LE DÉFAUT : il supposait qu'en dessous il n'y a
       pas la place pour deux colonnes. Il y en a — « 3 350 GB/s » tient
       largement dans 175 px. Ce qui manquait, c'est d'avoir regardé la page à
       390 px.
   ------------------------------------------------------------------------ */

@media (max-width: 619px) {
  .phero__facts { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  /* Un peu moins de rembourrage : deux colonnes serrent naturellement. */
  .phero__fact { padding: .9rem 1rem; }
  .phero__v { font-size: 1.18rem; }
  /* [!] L'UNITE DE L'ENFANT EST RELATIVE A CELLE DU PARENT. `.phero__v small`
         vaut `.6em` : en ramenant le parent de 1,32 a 1,18 rem, l'unite
         (« GB », « Gbit/s », « /mo ») est tombee de 12,7 a 11,3 px -- sous le
         plancher de lisibilite, sur vingt-cinq pages. Reduire une taille de
         police reduit AUSSI tout ce qui s'exprime en `em` en dessous, et c'est
         le genre d'effet de bord qu'aucune relecture ne rattrape : seul le
         comptage l'a vu, deux passages de suite. On repasse donc l'unite en
         `rem`, qui ne depend plus de son parent. */
  .phero__v small { font-size: .75rem; }
  .phero__l { font-size: .8rem; line-height: 1.35; }
}

/* Sur les écrans vraiment étroits, un libellé de trois mots ne tient plus à
   deux colonnes sans se couper : on repasse à une colonne sous 340 px. */
@media (max-width: 339px) {
  .phero__facts { grid-template-columns: minmax(0, 1fr); }
}


/* ---------------------------------------------------------------------------
   12j. MOBILE — LE CONFIGURATEUR
   ---------------------------------------------------------------------------
   C'est le chemin qui mène au paiement : c'est donc l'écran où un défaut coûte
   de l'argent, pas seulement de l'élégance.
   ------------------------------------------------------------------------ */

/* --- La barre d'étapes ------------------------------------------------------
   [!] SOUS 720 px, LES QUATRE LIBELLÉS ÉTAIENT MASQUÉS D'UN BLOC, et il ne
       restait que « 1 2 3 4 ». Le visiteur voyait bien qu'il y a quatre
       étapes, et pas du tout ce que l'étape en cours lui demande. Masquer
       quatre libellés parce que quatre ne tiennent pas, c'est jeter
       l'information plutôt que la hiérarchiser : UN libellé tient très bien.
   [!] L'étape en cours porte donc son nom et prend la place restante ; les
       trois autres restent des pastilles numérotées, qui suffisent à dire où
       l'on en est. Le libellé suit automatiquement l'avancement, la classe
       `is-now` étant déjà déplacée par le script. */
@media (max-width: 720px) {
  .wbar__i.is-now .wbar__l { display: block; }
  .wbar__i.is-now          { flex: 1 1 auto; }
  .wbar__i:not(.is-now)    { flex: 0 0 auto; }
  .wbar__i:not(.is-now) .wbar__b { padding-inline: .7rem; justify-content: center; }
}

/* --- Le dépliant « ce modèle tient-il ? » -----------------------------------
   [!] `justify-content: space-between` sur trois éléments dans 358 px : le
       titre se cassait en trois lignes dans une colonne de 60 px, la pastille
       « OPTIONAL » flottait au milieu, et l'indication tenait sur deux lignes
       alignées à droite. Une ligne de bureau pliée en accordéon.
       Sur téléphone, on empile : titre et pastille d'abord, indication en
       dessous, alignée à gauche comme tout le reste de la page. */
@media (max-width: 639px) {
  .fitbox__s {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: .35rem .6rem;
    padding: .85rem 1rem;
  }
  .fitbox__s > span:first-child { grid-column: 1; min-width: 0; }
  .fitbox__opt { grid-column: 2; margin-left: 0; justify-self: end; }
  .fitbox__hint {
    grid-column: 1 / -1;
    text-align: left;
    font-size: .8rem;
  }
}


/* ---------------------------------------------------------------------------
   12k. MOBILE — LE SOMMAIRE D'ARTICLE
   ------------------------------------------------------------------------ */

/* Sur grand écran, le bouton n'en est pas un : il rend exactement l'intitulé
   d'avant. `all: unset` remet une balise `<button>` à plat — sans lui, on
   hérite du fond gris, de la bordure et de la police du système. */
.toc__t {
  all: unset;
  display: flex; align-items: center; gap: .5rem;
  width: 100%; box-sizing: border-box;
  cursor: default;
}
.toc__n, .toc__chev { display: none; }

@media (max-width: 999px) {
  .toc__t {
    cursor: pointer;
    min-height: 44px;
    padding: .1rem 0;
  }
  .toc__n {
    display: inline-grid; place-items: center;
    min-width: 20px; height: 20px; padding: 0 .35rem;
    border-radius: 999px; background: var(--bg-sunk);
    /* Le plancher de 12 px vaut aussi pour un compteur : voir §12a. */
    font-size: .75rem; font-weight: 700; color: var(--ink-3);
    font-variant-numeric: tabular-nums;
  }
  .toc__chev {
    display: block; margin-left: auto; color: var(--ink-3);
    transition: transform .2s cubic-bezier(.2, .8, .3, 1);
  }
  .toc__t[aria-expanded="false"] .toc__chev { transform: rotate(-90deg); }

  /* [!] UNE SEULE COLONNE. Les deux colonnes économisaient de la hauteur au
         prix d'intitulés cassés en lignes inégales — « Where estimates go
         wrong » sur deux lignes à côté de « Weights » sur une : une grille
         bancale qu'on ne parcourt plus, on la déchiffre. Repliée par défaut,
         la hauteur n'est plus le problème. */
  .toc__l { grid-template-columns: minmax(0, 1fr); gap: 0; }

  /* Fermé : la liste disparaît vraiment (pas d'ordre de tabulation fantôme). */
  .toc:not(.is-open) .toc__l { display: none; }

  .toc__l a {
    min-height: 44px;
    border-top: 1px solid var(--line);
  }
  .toc__l li:first-child a { border-top: 0; }
}


/* ---------------------------------------------------------------------------
   12l. MOBILE — LES TABLEAUX LARGES
   ---------------------------------------------------------------------------
   Trente et un tableaux du site sont plus larges qu'un téléphone : ils
   défilent latéralement, et c'est le bon choix — les replier en fiches
   demanderait un `data-label` sur chaque cellule de quinze fichiers, et une
   fiche de sept lignes se compare moins bien que deux colonnes de chiffres.

   Mais un tableau qui défile doit DIRE qu'il défile, et garder son intitulé de
   ligne sous les yeux. Sans ces deux repères, on lit « 2 × Intel Xeon Gold »
   dans une colonne et « $6 061 » dans une autre sans plus savoir de quelle
   machine il s'agit.
   ------------------------------------------------------------------------ */

@media (max-width: 819px) {

  /* --- L'ombre de bord -----------------------------------------------------
     Deux dégradés blancs (attachés au CONTENU) masquent deux ombres (attachées
     au CADRE). Quand il reste du contenu à droite, le blanc a défilé et l'ombre
     apparaît ; arrivé au bout, le blanc la recouvre. Aucune ligne de script :
     c'est `background-attachment: local` qui fait tout le travail. */
  .tbl-wrap {
    background-image:
      linear-gradient(to right, #fff 38%, rgba(255, 255, 255, 0)),
      linear-gradient(to left,  #fff 38%, rgba(255, 255, 255, 0)),
      radial-gradient(farthest-side at 0 50%,   rgba(14, 23, 38, .13), rgba(14, 23, 38, 0)),
      radial-gradient(farthest-side at 100% 50%, rgba(14, 23, 38, .13), rgba(14, 23, 38, 0));
    background-position: 0 0, 100% 0, 0 0, 100% 0;
    background-repeat: no-repeat;
    background-size: 42px 100%, 42px 100%, 15px 100%, 15px 100%;
    background-attachment: local, local, scroll, scroll;
    background-color: #fff;
  }

  /* --- La colonne d'en-tête, collante --------------------------------------
     [!] `background` OPAQUE OBLIGATOIRE : une cellule collante sans fond
         laisse voir défiler les colonnes suivantes DERRIÈRE son texte. C'est
         l'erreur classique de ce motif, et elle est spectaculaire.
     [!] Un `z-index` supérieur à celui de l'en-tête de tableau, sinon la
         cellule d'angle passe dessous au croisement des deux. */
  /* [!] `:not(.tbl--cards …)` : UNE FICHE N'A PLUS DE COLONNES. Sur les
   *     tableaux repliés en fiches (§13c), la colonne collante n'a plus d'objet
   *     -- et son ombre de 1 px traçait un filet vertical au bord de chaque
   *     en-tête de fiche, visible sur la capture et inexplicable sans connaître
   *     cette règle-ci. Deux motifs de mise en page pour le même élément : il
   *     faut que le second désarme le premier, explicitement. */
  .tbl:not(.tbl--cards) th:first-child,
  .tbl:not(.tbl--cards) td:first-child {
    position: sticky; left: 0; z-index: 2;
    background: #fff;
    /* Un filet à droite marque la frontière entre ce qui reste et ce qui
       défile — sans lui, la colonne collante semble flotter. */
    box-shadow: 1px 0 0 var(--line);
  }
  .tbl:not(.tbl--cards) thead th:first-child { background: var(--bg-soft); z-index: 3; }

  /* La zone défilante prend un peu de marge à droite pour que la dernière
     colonne ne colle pas au bord une fois au bout de la course. */
  .tbl { padding-right: 0; }
}

/* ---------------------------------------------------------------------------
   12m. MOBILE — LE PIED DE PAGE REPLIABLE
   ------------------------------------------------------------------------ */

/* Sur grand écran, le bouton n'en est pas un : il rend l'intitulé d'avant. */
.ft__t {
  all: unset;
  display: flex; align-items: center; gap: .5rem;
  width: 100%; box-sizing: border-box;
  cursor: default;
}
.ft__chev { display: none; }

@media (max-width: 767px) {
  .ft__t {
    cursor: pointer;
    min-height: 48px;
    border-bottom: 1px solid var(--line);
  }
  .ft__chev {
    display: block; margin-left: auto; color: var(--ink-3);
    transition: transform .2s cubic-bezier(.2, .8, .3, 1);
  }
  .ft__t[aria-expanded="false"] .ft__chev { transform: rotate(-90deg); }

  /* [!] UNE COLONNE, PAS DEUX. Repliés, les cinq intitulés forment une liste
         de réglages — le motif que toute application emploie pour un pied de
         page. En deux colonnes, cinq accordéons de largeurs inégales qui
         s'ouvrent l'un à côté de l'autre décalent la page à chaque appui. */
  .ft__nav { grid-template-columns: minmax(0, 1fr); gap: 0; }
  .ft__col { min-width: 0; }

  .ft__col:not(.is-open) .ft__l { display: none; }
  .ft__l { margin-top: 0; padding-bottom: .5rem; }
  .ft__l a { padding-left: .2rem; }
}


/* ---------------------------------------------------------------------------
   12n. MOBILE — LES APPELS À L'ACTION
   ---------------------------------------------------------------------------
   [!] DEUX BOUTONS EMPILÉS DE LARGEURS DIFFÉRENTES. En ligne, `flex-wrap`
       donne à chacun la largeur de son texte, ce qui est juste : ils se suivent
       et la différence ne se voit pas. Repliés l'un sous l'autre, elle saute
       aux yeux — 233 px puis 246 px, deux bords droits qui ne s'alignent pas.
       C'est le détail qui fait qu'une page « fait site rétréci » plutôt
       qu'« application » : dans une application, une action principale occupe
       la largeur du pouce, c'est-à-dire l'écran.
   ------------------------------------------------------------------------ */

@media (max-width: 559px) {
  .hero__acts,
  .pcta__acts,
  .err__acts,
  .cfgdone__acts {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: .6rem;
  }
  .hero__acts .btn,
  .pcta__acts .btn,
  .err__acts .btn,
  .cfgdone__acts .btn {
    width: 100%;
  }
}


/* ---------------------------------------------------------------------------
   12o. MOBILE — LES CHOIX DU CONFIGURATEUR EN DÉROULANTS
   ---------------------------------------------------------------------------
   Le configurateur posait quatre listes de boutons radio : centre de données
   (7), pile logicielle (10), système (5), monnaie (8). Sur un téléphone, la
   seule étape 1 imposait 758 px de liste — et l'on ne voit à aucun moment son
   choix courant sans remonter.

   Chaque groupe devient un déroulant : une ligne qui montre CE QUI EST CHOISI,
   et la liste ne s'ouvre que sur demande. Les 758 px tombent à 112.

   [!] LE BALISAGE DES OPTIONS N'EST PAS TOUCHÉ. Ce sont les mêmes `<input
       type="radio">` dans le même formulaire : la soumission, la validation et
       le filtrage dynamique de `configure.js` (qui masque les images trop
       grosses pour la carte choisie) continuent de fonctionner sans rien
       savoir de ce déroulant.

   [!] SANS JAVASCRIPT, LES LISTES RESTENT VISIBLES. Le déclencheur est créé par
       le script ; en son absence, `.opts` n'a pas la classe `osel__list` et
       s'affiche comme avant. On ne met jamais un choix de commande derrière un
       script.

   [!] TOUT EST SOUS 760 px. Sur un poste de travail les listes restent
       ouvertes, en grille : la place ne manque pas, et comparer six centres
       d'un coup d'oeil y est plus rapide qu'ouvrir un menu.
   ------------------------------------------------------------------------ */

@media (max-width: 759px) {

  /* Le sous-titre de section que le déroulant répète mot pour mot (voir
     configure.js) : deux fois « Term » à douze pixels d'écart. */
  .osel__dup { display: none; }

  /* --- Le déclencheur : ce qui est choisi, en une ligne -------------------- */
  .osel__t {
    display: flex; align-items: center; gap: .7rem;
    width: 100%; box-sizing: border-box;
    min-height: 60px;
    margin: 0 0 .5rem;
    padding: .6rem .85rem;
    border: 1px solid var(--line-strong); border-radius: var(--r);
    background: #fff;
    font: inherit; color: var(--ink);
    text-align: left;
    cursor: pointer;
    box-shadow: var(--shadow-1);
    transition: border-color .14s ease, box-shadow .14s ease;
  }
  .osel__t:hover { border-color: var(--acc-line); }
  .osel__t:focus-visible { outline: 2px solid var(--acc); outline-offset: 2px; }
  .osel__t[aria-expanded="true"] {
    border-color: var(--acc);
    box-shadow: 0 0 0 3px var(--acc-soft);
  }

  /* La colonne de gauche : l'intitulé du champ, puis la valeur choisie. */
  .osel__c { flex: 1 1 auto; min-width: 0; display: grid; gap: .1rem; }
  .osel__k {
    /* [!] .75rem = 12 px, le plancher de §12a. J'y suis passé en dessous trois
           fois de suite dans ce chantier, chaque fois dans une règle écrite
           APRÈS avoir posé le plancher : une légende « discrète » se choisit à
           l'oeil sur un grand écran, et l'oeil se trompe. Seul le comptage l'a
           vu, les trois fois. */
    font-size: .75rem; font-weight: 700; letter-spacing: .06em;
    text-transform: uppercase; color: var(--ink-3);
  }
  /* [!] La valeur est un CLONE du contenu de l'option cochée — drapeau, logo,
         prix compris. Recopier seulement le texte perdrait le drapeau du pays
         et l'icône de la monnaie, c'est-à-dire ce qui rend le choix
         reconnaissable d'un coup d'oeil. */
  .osel__v { display: flex; align-items: center; gap: .55rem; min-width: 0; }
  .osel__v .opt__b,
  .osel__v .pcoin__b {
    display: flex; align-items: center; gap: .55rem;
    padding: 0; border: 0; background: none; box-shadow: none; min-height: 0;
    width: 100%; min-width: 0;
  }
  .osel__v .opt__i { width: auto; background: transparent; }
  .osel__v .opt__x { min-width: 0; }
  .osel__v .opt__t, .osel__v .pcoin__n { font-weight: 600; }
  /* La deuxième ligne de l'option (pays, description) tient sur une ligne. */
  .osel__v .opt__d {
    display: block; min-width: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .osel__v--empty { color: var(--ink-3); }

  .osel__chev {
    flex: none; color: var(--ink-3);
    transition: transform .2s cubic-bezier(.2, .8, .3, 1);
  }
  .osel__t[aria-expanded="true"] .osel__chev { transform: rotate(180deg); }

  /* --- La liste, dépliée --------------------------------------------------- */
  .osel__list {
    display: none;
    max-height: min(58vh, 460px);
    overflow-y: auto;
    overscroll-behavior: contain;
    margin-bottom: .75rem;
    padding: .35rem;
    border: 1px solid var(--line); border-radius: var(--r);
    background: var(--bg-soft);
  }
  .osel__list.is-open { display: grid; gap: .35rem; }

  /* Les options gardent leur apparence, en un peu plus compact. */
  .osel__list .opt__b,
  .osel__list .pcoin__b { min-height: 52px; }
}

/* [!] AU-DESSUS DE 760 px, LE DÉCLENCHEUR N'EXISTE PAS À L'ÉCRAN et la liste
       reprend sa mise en page normale — même si le script a posé les classes.
       C'est la requête de média qui décide, pas l'état JavaScript : une
       rotation de tablette ne peut donc pas laisser une liste fermée sur un
       écran large. */
@media (min-width: 760px) {
  .osel__t { display: none; }
  .osel__list { display: grid; }
}


/* ===========================================================================
   13. MOBILE — LA BARRE D'ONGLETS
   ===========================================================================

   Cinq raccourcis ancrés en bas de l'écran, l'action au centre et surélevée.

   [!] POURQUOI EN BAS. Ce n'est pas une mode : sur un téléphone de six pouces
       tenu à une main, le haut de l'écran est hors d'atteinte du pouce. Une
       navigation logée là oblige à faire glisser l'appareil dans la paume — le
       geste qui fait tomber les téléphones. Le bas est la seule zone atteignable
       sans changer de prise.

   [!] ELLE NE REMPLACE PAS LE MENU. Le tiroir garde toute la navigation ; la
       barre est une couche de raccourcis vers cinq destinations. C'est
       précisément parce qu'elle ne contient QUE cinq entrées qu'elle est utile.

   [!] LES Z-INDEX, dans l'ordre : barre 70 < voile du menu 80 < tiroir 85 <
       en-tête 90. Une barre qui flotterait au-dessus du voile resterait
       cliquable pendant qu'on lit le menu, et au-dessus de la fenêtre de
       paiement pendant qu'on copie une adresse — le pire moment pour changer
       de page.
   ========================================================================== */

/* [!] MASQUÉE PAR DÉFAUT, montrée sur téléphone — et surtout PAS L'INVERSE.
       Toutes les règles de la barre vivaient dans la requête mobile ; au-dessus
       de 767 px il n'en restait AUCUNE, et un `<nav>` reprend alors son
       `display: block` par défaut : la barre s'affichait en pied de page sur
       poste de travail, en liste à puces. Une règle qui n'existe que dans une
       requête de média ne « désactive » rien ailleurs. */
.tabbar { display: none; }

@media (max-width: 767px) {

  :root { --tabbar-h: 58px; }

  .tabbar {
    display: block;
    position: fixed;
    z-index: 70;
    left: 0; right: 0; bottom: 0;
    padding-bottom: env(safe-area-inset-bottom, 0px);
    background: rgba(255, 255, 255, .93);
    backdrop-filter: saturate(180%) blur(14px);
    border-top: 1px solid var(--line);
    box-shadow: 0 -1px 0 rgba(14, 23, 38, .03), 0 -8px 28px rgba(14, 23, 38, .06);
  }

  .tabbar__l {
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    align-items: end;
    list-style: none;
    margin: 0; padding: 0;
    height: var(--tabbar-h);
  }

  .tabbar__i { min-width: 0; }

  .tabbar__a {
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: .18rem;
    width: 100%; height: var(--tabbar-h);
    padding: 0 .15rem;
    border: 0; background: none;
    font: inherit;
    color: var(--ink-3);
    text-decoration: none;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: color .14s ease;
  }
  .tabbar__a:focus-visible { outline: 2px solid var(--acc); outline-offset: -3px; border-radius: 10px; }

  .tabbar__ic { display: grid; place-items: center; height: 22px; }
  .tabbar__t {
    /* [!] 12 px, LE PLANCHER, SANS EXCEPTION. J'avais mis 11 px en me disant
           qu'un libellé d'onglet « n'est pas de la prose » : l'audit a rendu 255
           occurrences (51 pages x 5 onglets) et il avait raison. Un plancher
           qui souffre une exception argumentée en souffre bientôt cinq. À 12 px
           semi-gras, « Configure » mesure 62 px dans une colonne de 78 : il
           tient. La contrainte se résout en choisissant des libellés courts,
           pas en réduisant la police. */
    font-size: 12px; font-weight: 600; letter-spacing: -.01em; line-height: 1;
    max-width: 100%;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }

  /* L'onglet courant. `aria-current` porte l'information pour les lecteurs
     d'écran ; la couleur ne la porte que pour les voyants. */
  .tabbar__i.is-on .tabbar__a { color: var(--acc); }
  .tabbar__i.is-on .tabbar__ic { transform: translateY(-1px); }

  .tabbar__a:active .tabbar__ic { transform: scale(.9); }
  .tabbar__ic { transition: transform .16s cubic-bezier(.2, .8, .3, 1); }

  /* --- Le bouton central, surélevé -----------------------------------------
     [!] IL DÉBORDE LA BARRE VERS LE HAUT, ce qui exige que la barre ne rogne
         pas (`overflow: visible`, valeur par défaut — ne pas y toucher) et que
         le disque ait un fond OPAQUE : posé sur un fond flouté translucide, on
         verrait le contenu de la page défiler à travers l'icône. */
  .tabbar__i--mid .tabbar__a {
    justify-content: flex-end;
    padding-bottom: .34rem;
    color: var(--ink-3);
  }
  .tabbar__i--mid .tabbar__ic {
    display: grid; place-items: center;
    width: 52px; height: 52px;
    margin-top: -22px;
    border-radius: 50%;
    background: var(--acc);
    color: #fff;
    box-shadow: 0 6px 18px rgba(31, 79, 224, .35), 0 0 0 4px #fff;
  }
  .tabbar__i--mid.is-on .tabbar__ic,
  .tabbar__i--mid .tabbar__a:active .tabbar__ic { background: var(--acc-dark); }
  .tabbar__i--mid.is-on .tabbar__a { color: var(--acc); }
  .tabbar__i--mid .tabbar__t { font-weight: 700; }

  /* --- Ce que la barre recouvre --------------------------------------------
     [!] LA MARGE VA AU PIED DE PAGE, PAS AU `<body>`. Le fond du pied de page
         est gris et celui du corps est blanc : une marge sur `<body>` aurait
         glissé une bande blanche SOUS le pied de page, visible à travers le
         flou de la barre. */
  .ft { padding-bottom: calc(var(--tabbar-h) + 1.25rem + env(safe-area-inset-bottom, 0px)); }

  /* [!] LE SÉLECTEUR DE LANGUE REMONTE AU-DESSUS DE LA BARRE, sans quoi il se
         poserait exactement dessus. Son `z-index` passe au-dessus de la barre
         (70) mais reste sous le voile du menu (80). */
  .lsw {
    bottom: calc(var(--tabbar-h) + .9rem + env(safe-area-inset-bottom, 0px));
    z-index: 75;
  }

  /* Le tiroir de navigation ouvert verrouille le corps : la barre suit, sinon
     elle flotte au-dessus d'une page figée. */
  body.nav-open .tabbar { pointer-events: none; }
}

@media print { .tabbar { display: none; } }

@media (prefers-reduced-motion: reduce) {
  .tabbar__ic { transition: none; }
  .tabbar__a:active .tabbar__ic { transform: none; }
}


/* ---------------------------------------------------------------------------
   13b. MOBILE — la navigation entre étapes du configurateur
   ---------------------------------------------------------------------------
   [!] `margin-left: auto` POUSSAIT « Continue » À DROITE, où il mesurait
       117 px sur 390. C'est juste sur un poste de travail — l'action avance
       vers la droite, dans le sens de la lecture — et c'est faux au pouce :
       l'action principale d'une étape doit occuper la largeur de l'écran, et
       le retour rester secondaire.
   ------------------------------------------------------------------------ */

@media (max-width: 559px) {
  .wnav {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: .55rem;
  }
  .wnav [data-next], .wnav [data-send] { margin-left: 0; }
  .wnav .btn { width: 100%; }
  /* L'action d'abord, le retour en dessous : sur un téléphone on descend, et
     ce qu'on trouve en bas de l'étape est ce qu'on veut faire ensuite. */
  .wnav [data-next], .wnav [data-send] { order: -1; }
}


/* ===========================================================================
   13c. MOBILE — LE COMPARATIF DES CARTES EN FICHES  (.tbl--cards)
   ===========================================================================

   `/gpu` compare douze cartes sur sept colonnes : 856 px de tableau dans un
   écran de 356. Il défilait — c'est déjà mieux que d'être rogné — mais la
   colonne « From », c'est-à-dire LE PRIX, était la septième : il fallait
   pousser le tableau jusqu'au bout, douze fois, pour comparer ce qu'on est
   venu comparer. Sur un téléphone, un tableau large n'est pas une grille, c'est
   une file d'attente.

   Chaque ligne devient donc une fiche : nom et prix sur la même ligne de tête,
   puis les cinq caractéristiques en paires « intitulé / valeur ».

   [!] `data-label` PORTE L'INTITULÉ DE COLONNE, posé dans gpu.php. L'en-tête
       du tableau disparaît en mode fiche : sans lui, « 3 350 GB/s » et
       « Hopper » se retrouveraient l'un sous l'autre sans rien dire de ce
       qu'ils mesurent.

   [!] NE PAS UTILISER `display: contents` SUR LES CELLULES. Les enfants
       remontent alors dans la grille de la LIGNE, et l'intitulé d'une cellule
       se retrouve apparié à la valeur de la suivante. Chaque cellule reste une
       boîte. (Le même avertissement figurait dans la section supprimée §11 :
       il valait la peine d'être gardé.)
   ========================================================================== */

@media (max-width: 819px) {

  .tbl-wrap:has(.tbl--cards) {
    overflow: visible;
    border: 0; background: transparent; box-shadow: none;
    /* Les repères de défilement du §12l n'ont plus d'objet ici. */
    background-image: none;
  }

  .tbl--cards { display: block; min-width: 0; }
  .tbl--cards thead { display: none; }
  .tbl--cards tbody { display: grid; gap: .6rem; }

  .tbl--cards tr {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: .1rem .8rem;
    padding: .95rem 1rem;
    background: #fff;
    border: 1px solid var(--line);
    border-radius: var(--r);
    box-shadow: var(--shadow-1);
  }
  .tbl--cards tbody tr:hover { background: #fff; }

  /* --- La ligne de tête : le nom, et le PRIX en face ------------------------ */
  .tbl--cards td.tbl__lead {
    grid-column: 1; grid-row: 1;
    display: block; padding: 0; border: 0;
  }
  .tbl--cards td.tbl__lead::before { display: none; }
  .tbl--cards td.tbl__lead .tbl__name { font-size: 1.05rem; }

  .tbl--cards td.tbl__cta {
    grid-column: 2; grid-row: 1;
    display: block; padding: 0; border: 0; text-align: right;
  }
  .tbl--cards td.tbl__cta::before { display: none; }
  .tbl--cards td.tbl__cta .tbl__price { font-size: 1.15rem; }

  /* --- Les cinq caractéristiques, en paires --------------------------------- */
  .tbl--cards td:not(.tbl__lead):not(.tbl__cta) {
    grid-column: 1 / -1;
    display: flex; flex-wrap: wrap; align-items: baseline;
    column-gap: .7rem; row-gap: .1rem;
    padding: .42rem 0 0;
    border: 0;
    text-align: left;
    font-size: .88rem;
  }
  /* Un filet au-dessus de la première : il sépare la tête des données sans
     ajouter un élément au balisage. */
  .tbl--cards td.tbl__lead + td { margin-top: .35rem; border-top: 1px solid var(--line); padding-top: .6rem; }

  .tbl--cards td:not(.tbl__lead):not(.tbl__cta)::before {
    content: attr(data-label);
    flex: 0 0 7.6rem;
    font-size: .72rem; font-weight: 700; letter-spacing: .05em;
    text-transform: uppercase; color: var(--ink-3);
  }

  /* `.num` aligne à droite pour la grille de bureau ; en fiche cela collerait
     la valeur contre le bord opposé à son intitulé. */
  .tbl--cards td.num { text-align: left; }
  .tbl--cards td .tbl__meta { display: inline; margin: 0; }
  .tbl--cards td .tbl__name { font-weight: 600; }
}

/* Sous 380 px, l'intitulé et la valeur ne tiennent plus côte à côte : la
   valeur passe dessous plutôt que de se couper en deux. */
@media (max-width: 379px) {
  .tbl--cards td:not(.tbl__lead):not(.tbl__cta)::before { flex-basis: 100%; }
}


/* ---------------------------------------------------------------------------
   13d. MOBILE — la cellule d'action d'une fiche de tableau
   ---------------------------------------------------------------------------
   Le tableau des tarifs par durée termine chaque ligne par un bouton
   « Configure ». En fiche, il ne peut pas rester une cellule étroite en bout
   de ligne : il devient la dernière rangée, pleine largeur — la place où l'on
   agit après avoir lu.
   ------------------------------------------------------------------------ */

@media (max-width: 819px) {
  .tbl--cards td.tbl__act {
    grid-column: 1 / -1;
    display: block;
    padding: .8rem 0 0;
    border: 0;
    text-align: left;
  }
  .tbl--cards td.tbl__act::before { display: none; }
  .tbl--cards td.tbl__act .btn { width: 100%; }

  /* Une cellule VIDE (l'en-tête sans intitulé de la colonne du bouton) ne doit
     pas laisser une rangée blanche dans la fiche. */
  .tbl--cards td:empty { display: none; }
}


/* ---------------------------------------------------------------------------
   13e. MOBILE — la ligne secondaire d'une cellule de fiche
   ---------------------------------------------------------------------------
   [!] `CPU AND MEMORY | 2 × Intel Xeon Gold 6438Y+` tenait sur une ligne, mais
       sa précision (« 64 c · 512 GB · 4 × 3.84 TB NVMe ») repartait à la MARGE
       GAUCHE, sous l'intitulé — elle se lisait alors comme une entrée à part
       plutôt que comme la suite de la valeur. Ce sont deux éléments flexibles
       distincts : le second passe à la ligne au début de la boîte.
       On l'indente de la largeur de la colonne d'intitulés, qui est réduite à
       6.4rem pour lui laisser de la place.
   ------------------------------------------------------------------------ */

@media (max-width: 819px) {
  .tbl--cards td:not(.tbl__lead):not(.tbl__cta):not(.tbl__act)::before {
    flex-basis: 6.4rem;
  }
  .tbl--cards td:not(.tbl__lead):not(.tbl__cta):not(.tbl__act) .tbl__meta {
    flex: 1 0 100%;
    padding-left: calc(6.4rem + .7rem);
    margin-top: .05rem;
  }
}

/* Sous 380 px, l'intitulé prend sa propre ligne : la valeur et sa précision
   s'alignent alors toutes deux à gauche, et l'indentation n'a plus lieu d'être. */
@media (max-width: 379px) {
  .tbl--cards td:not(.tbl__lead):not(.tbl__cta):not(.tbl__act) .tbl__meta {
    padding-left: 0;
  }
}


/* ===========================================================================
   30. PAGE D'ÉTAT v2 (.stx-*) — /status, /status/history, /status/incidents/*
   Refonte du 2026-09-03. Les anciens blocs §24.10 et §24.16 (.stban, .strow,
   .spark, .stempty) ne sont plus référencés par aucun gabarit.

   [!] TOUT EST MOBILE D'ABORD, et les cibles tactiles font 44 px sous 900 px :
       l'audit bin/mobile-audit.sh mesure chaque bouton, chaque lien en bloc,
       chaque <summary>. Un texte ne descend jamais sous 12 px.
   [!] AUCUNE COULEUR D'ÉTAT N'EST INVENTÉE ICI : vert = --ok, ambre = --warn,
       bleu = --acc ; l'orange et le rouge des pannes sont posés une fois en
       variables locales et réutilisés partout (barres, pastilles, cartes).
   ========================================================================== */
.stx {
  --st-ok:    var(--ok);
  --st-warn:  #d08a00;
  --st-bad:   #e0621f;
  --st-down:  #d94141;
  --st-maint: var(--acc);
  --st-unm:   var(--line-strong);
  padding-top: 0;
}
.pg-status .phero--dark { padding-bottom: 2.2rem; }
.pg-status .phero__h { max-width: 40ch; }

/* --- 30.1 Pastilles d'état (.stp) ------------------------------------------ */
.stp {
  display: inline-flex; align-items: center; gap: .42rem; white-space: nowrap;
  padding: .28rem .62rem; border-radius: 999px; font-size: .78rem; font-weight: 600; line-height: 1.4;
  border: 1px solid var(--line); background: #fff; color: var(--ink-2);
}
.stp__d { width: 8px; height: 8px; border-radius: 50%; background: currentColor; flex: none; }
.stp--ok    { background: var(--ok-soft); color: var(--ok); border-color: #c9ecdd; }
.stp--warn  { background: var(--warn-soft); color: #8a5300; border-color: #f4dfb8; }
.stp--bad   { background: #fff1e8; color: #a8420f; border-color: #f7cdb3; }
.stp--down  { background: #fdeded; color: #b53232; border-color: #f2c9c9; }
.stp--maint { background: var(--acc-soft); color: var(--acc-dark); border-color: var(--acc-line); }
.stp--none  { background: var(--bg-sunk); color: var(--ink-3); border-color: var(--line-strong); }
.stp--ok .stp__d { box-shadow: 0 0 0 3px rgba(14, 143, 95, .16); }

/* --- 30.2 Le bandeau vivant ------------------------------------------------ */
.stx-live {
  position: relative; z-index: 2;
  display: grid; gap: 1rem; padding: 1.25rem 1.3rem;
  margin-top: -1.6rem;
  background: #fff; border: 1px solid var(--line); border-left: 5px solid var(--st-ok);
  border-radius: var(--r-lg); box-shadow: var(--shadow-3);
}
@media (min-width: 860px) { .stx-live { grid-template-columns: minmax(0, 1fr) auto; align-items: center; padding: 1.4rem 1.6rem; margin-top: -2.2rem; } }
.stx-live__main { display: flex; align-items: center; gap: 1rem; min-width: 0; }
.stx-live__ico {
  flex: none; display: grid; place-items: center; width: 46px; height: 46px; border-radius: 50%;
  background: var(--st-ok); color: #fff;
}
.stx-live__ico .ico { width: 24px; height: 24px; }
.stx-live__t { font-size: 1.22rem; font-weight: 700; letter-spacing: -.015em; color: var(--ink); }
.stx-live__p { margin-top: .2rem; font-size: .9rem; color: var(--ink-2); max-width: var(--m-note); }
.stx-live__meta { display: grid; gap: .6rem; }
@media (min-width: 860px) { .stx-live__meta { justify-items: end; text-align: right; } }
.stx-live__chk { display: inline-flex; align-items: center; gap: .5rem; font-size: .84rem; color: var(--ink-2); }
.stx-live__chk time { font-family: var(--mono); font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; }
.stx-live__dot {
  width: 9px; height: 9px; border-radius: 50%; background: var(--st-ok); flex: none;
  box-shadow: 0 0 0 0 rgba(14, 143, 95, .45); animation: stx-pulse 2.2s ease-out infinite;
}
@keyframes stx-pulse { 0% { box-shadow: 0 0 0 0 rgba(14, 143, 95, .45); } 70% { box-shadow: 0 0 0 8px rgba(14, 143, 95, 0); } 100% { box-shadow: 0 0 0 0 rgba(14, 143, 95, 0); } }
.stx-live__acts { display: flex; flex-wrap: wrap; gap: .5rem; }
.stx-live--warn  { border-left-color: var(--st-warn); }  .stx-live--warn  .stx-live__ico { background: var(--st-warn); }
.stx-live--bad   { border-left-color: var(--st-bad); }   .stx-live--bad   .stx-live__ico { background: var(--st-bad); }
.stx-live--down  { border-left-color: var(--st-down); }  .stx-live--down  .stx-live__ico { background: var(--st-down); }
.stx-live--maint { border-left-color: var(--st-maint); } .stx-live--maint .stx-live__ico { background: var(--st-maint); }

/* Le petit bouton des barres d'action : même famille que .btn, plus court. */
.stx-btn { padding: .55rem .85rem; font-size: .86rem; gap: .4rem; }
.stx-btn .ico { width: 16px; height: 16px; }

/* --- 30.3 Ce qui est ouvert, ce qui approche -------------------------------- */
.stx-now { margin-top: 1.5rem; padding: 1.1rem 1.2rem 1.2rem; border: 1px solid #f4dfb8; background: #fffaf0; border-radius: var(--r-lg); }
.stx-now__h { display: flex; align-items: center; gap: .5rem; font-size: 1rem; font-weight: 700; color: #7a4700; margin-bottom: .8rem; }
.stx-now__h .ico { color: var(--st-warn); }
.stx-soon {
  display: flex; align-items: center; gap: .8rem; margin-top: 1.2rem; padding: .9rem 1.1rem; min-height: 44px;
  border: 1px solid var(--acc-line); background: var(--acc-soft); border-radius: var(--r); color: var(--ink); font-size: .9rem;
}
.stx-soon:hover { border-color: var(--acc); color: var(--ink); }
.stx-soon__i { flex: none; color: var(--acc); display: grid; place-items: center; }
.stx-soon__t { min-width: 0; flex: 1 1 auto; }
.stx-soon__t b { color: var(--acc-dark); }
.stx-soon .arr { color: var(--acc); flex: none; }

/* --- 30.4 Têtes de rubrique ------------------------------------------------- */
.stx-sech { margin-top: clamp(2.75rem, 5vw, 3.75rem); max-width: var(--m-lead); }
.stx-sech .sec__h { font-size: clamp(1.3rem, 2.4vw, 1.7rem); }
.stx-sech .sec__sub { margin-top: .5rem; }
.stx-sech + .stx-grp, .stx-sech + .stx-chart, .stx-sech + .stx-days, .stx-sech + .stx-list, .stx-sech + .stx-empty, .stx-sech + .stx-how, .stx-sech + .stx-arch { margin-top: 1.4rem; }

/* --- 30.5 Groupes et lignes de composants ----------------------------------- */
.stx-grp { background: #fff; border: 1px solid var(--line); border-radius: var(--r-lg); box-shadow: var(--shadow-1); overflow: hidden; }
.stx-grp + .stx-grp, .stx-grp + .stx-dcs { margin-top: 1rem; }
.stx-dcs { display: grid; gap: .8rem; margin-top: 1rem; }
.stx-grp__hd {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: .35rem .9rem; align-items: center;
  padding: .9rem 1.1rem; background: var(--bg-soft); border-bottom: 1px solid var(--line);
}
@media (min-width: 720px) { .stx-grp__hd { grid-template-columns: minmax(0, 1fr) auto auto; padding: .95rem 1.25rem; } }
.stx-grp__t { display: flex; flex-wrap: wrap; align-items: center; gap: .3rem .55rem; font-weight: 700; font-size: 1rem; min-width: 0; }
.stx-grp__t .ico { color: var(--acc); }
.stx-grp__t .flag { flex: none; }
.stx-grp__code { font-family: var(--mono); font-size: .78rem; font-weight: 600; color: var(--ink-3); letter-spacing: .04em; }
.stx-grp__s { flex-basis: 100%; font-size: .8rem; font-weight: 400; color: var(--ink-3); }
.stx-grp__u { font-family: var(--mono); font-size: .92rem; font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; white-space: nowrap; }
.stx-grp__u small, .stx-row__u small { font-size: .78rem; font-weight: 500; color: var(--ink-3); }
.stx-grp__b { justify-self: end; grid-row: 1; grid-column: 2; }
@media (min-width: 720px) { .stx-grp__b { grid-column: 3; } .stx-grp__u { grid-column: 2; grid-row: 1; } }
@media (max-width: 719px) { .stx-grp__u { grid-column: 1; grid-row: 2; } }

/* Le groupe repliable d'un centre de données : un <details>, ouvert à la main
   ou par l'état (ouvert d'office quand quelque chose n'y va pas). */
details.stx-grp > summary { list-style: none; cursor: pointer; position: relative; padding-right: 2.6rem; min-height: 44px; }
details.stx-grp > summary::-webkit-details-marker { display: none; }
details.stx-grp > summary:hover { background: var(--bg-sunk); }
details.stx-grp > summary:focus-visible { outline: 2px solid var(--acc); outline-offset: -2px; }
details.stx-grp[open] > summary { border-bottom: 1px solid var(--line); }
details.stx-grp:not([open]) > summary { border-bottom: 0; }
.stx-grp__chev { position: absolute; right: 1.1rem; top: 50%; transform: translateY(-50%); color: var(--ink-3); transition: transform .15s; }
details.stx-grp[open] .stx-grp__chev { transform: translateY(-50%) rotate(180deg); }
@media (min-width: 720px) { .stx-grp__chev { right: 1.25rem; } .stx-grp__b { margin-right: .9rem; } details.stx-grp > summary { padding-right: 2.8rem; } }

.stx-row { padding: .95rem 1.1rem 1rem; border-bottom: 1px solid var(--line); }
@media (min-width: 720px) { .stx-row { padding: 1rem 1.25rem 1.05rem; } }
.stx-row:last-child { border-bottom: 0; }
.stx-row__hd { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: .3rem .9rem; align-items: center; }
@media (min-width: 720px) { .stx-row__hd { grid-template-columns: minmax(0, 1fr) auto auto; } }
.stx-row__n { font-weight: 600; font-size: .95rem; min-width: 0; }
.stx-row__s { display: block; margin-top: .1rem; font-size: .8rem; color: var(--ink-3); font-weight: 400; }
.stx-row__u { font-family: var(--mono); font-size: .88rem; font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; white-space: nowrap; }
.stx-row__b { justify-self: end; grid-row: 1; grid-column: 2; }
@media (min-width: 720px) { .stx-row__b { grid-column: 3; } .stx-row__u { grid-column: 2; } }
@media (max-width: 719px) { .stx-row__u { grid-column: 1; grid-row: 2; } }

/* Les 90 barres : une par jour, du plus ancien au plus récent. */
.stx-bars { display: flex; gap: 2px; align-items: stretch; height: 30px; margin-top: .7rem; }
/* [!] `min-width: 0`, pas 2 px : quatre-vingt-dix barres a 2 px plus leurs
   interstices font 358 px, et l'ecran de 360 n'en offre que 326 a la rangee.
   Le debordement se voyait a l'audit (23 barres hors ecran), pas a l'oeil. */
.stx-bar { flex: 1 1 0; min-width: 0; border-radius: 2px; background: var(--st-ok); opacity: .9; display: block; }
.stx-bar:hover { outline: 2px solid var(--ink); outline-offset: 1px; opacity: 1; z-index: 1; position: relative; }
.stx-bar--warn  { background: var(--st-warn); }
.stx-bar--bad   { background: var(--st-bad); }
.stx-bar--down  { background: var(--st-down); }
.stx-bar--maint { background: var(--st-maint); }
.stx-bar--unm   { background: var(--st-unm); opacity: 1; }
.stx-bar--none  { background: var(--st-unm); opacity: 1; }
.stx-bars__k { display: flex; justify-content: space-between; gap: .8rem; margin-top: .4rem; font-size: .78rem; color: var(--ink-3); }
.stx-bars__k span:nth-child(2) { text-align: center; min-width: 0; }
@media (max-width: 560px) { .stx-bars__k span:nth-child(2) { display: none; } }

.stx-legend { display: flex; flex-wrap: wrap; gap: .5rem 1.2rem; margin-top: 1rem; font-size: .8rem; color: var(--ink-2); }
.stx-legend li { display: inline-flex; align-items: center; gap: .45rem; }
.stx-legend .stx-bar { flex: none; width: 14px; height: 12px; }

/* L'infobulle des barres, posée par le script. */
.stx-tip {
  position: absolute; z-index: 300; max-width: 300px; padding: .7rem .85rem;
  background: #fff; border: 1px solid var(--line-strong); border-radius: var(--r-sm); box-shadow: var(--shadow-2);
  font-size: .82rem; color: var(--ink-2); pointer-events: auto;
}
.stx-tip__d { font-weight: 700; color: var(--ink); }
.stx-tip__s { margin-top: .15rem; font-weight: 600; }
.stx-tip__s--ok { color: var(--ok); } .stx-tip__s--warn { color: #8a5300; } .stx-tip__s--bad { color: #a8420f; } .stx-tip__s--down { color: #b53232; } .stx-tip__s--maint { color: var(--acc-dark); }
.stx-tip__l { margin-top: .45rem; display: grid; gap: .25rem; border-top: 1px solid var(--line); padding-top: .45rem; }
.stx-tip__l a { display: block; color: var(--acc); }
.stx-tip__n { margin-top: .3rem; color: var(--ink-3); }

/* --- 30.6 Le graphique ------------------------------------------------------ */
.stx-chart { background: #fff; border: 1px solid var(--line); border-radius: var(--r-lg); box-shadow: var(--shadow-1); padding: 1rem 1.1rem 1.1rem; }
@media (min-width: 720px) { .stx-chart { padding: 1.1rem 1.4rem 1.3rem; } }
.stx-chart__hd { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: .7rem 1rem; margin-bottom: .8rem; }
.stx-lg { display: flex; flex-wrap: wrap; gap: .4rem; }
.stx-lg__b {
  display: inline-flex; align-items: center; gap: .45rem; padding: .35rem .65rem; min-height: 34px;
  border: 1px solid var(--line); border-radius: 999px; background: #fff; color: var(--ink-2);
  font: inherit; font-size: .8rem; cursor: pointer;
}
.stx-lg__b b { font-family: var(--mono); font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; }
.stx-lg__b.is-off { opacity: .45; }
.stx-lg__b:hover { border-color: var(--line-strong); }
.stx-lg__sw { width: 12px; height: 12px; border-radius: 3px; flex: none; }
.stx-lg__sw--fra { background: #1f4fe0; } .stx-lg__sw--lon { background: #0e8f5f; } .stx-lg__sw--nyc { background: #c2410c; } .stx-lg__sw--sin { background: #7c3aed; } .stx-lg__sw--gru { background: #be185d; }
.stx-seg { display: inline-flex; border: 1px solid var(--line-strong); border-radius: var(--r-sm); overflow: hidden; }
.stx-seg__b { padding: .45rem .85rem; min-height: 34px; border: 0; background: #fff; color: var(--ink-2); font: inherit; font-size: .82rem; font-weight: 600; cursor: pointer; }
.stx-seg__b + .stx-seg__b { border-left: 1px solid var(--line-strong); }
.stx-seg__b[aria-pressed="true"] { background: var(--ink); color: #fff; }
.stx-seg__b:hover:not([aria-pressed="true"]) { background: var(--bg-soft); }
.stx-chart__svg { position: relative; }
.stx-chart.is-loading .stx-chart__svg { opacity: .55; }
.stx-svg { width: 100%; height: auto; display: block; }
.stx-chart__k { margin-top: .6rem; font-size: .78rem; color: var(--ink-3); font-variant-numeric: tabular-nums; }

/* --- 30.7 Cartes d'événement et listes -------------------------------------- */
.stx-list { display: grid; gap: .8rem; }
.stx-ev {
  position: relative; padding: .95rem 1.1rem 1rem 1.25rem; background: #fff;
  border: 1px solid var(--line); border-left: 4px solid var(--st-warn); border-radius: var(--r); box-shadow: var(--shadow-1);
}
.stx-ev--bad { border-left-color: var(--st-bad); } .stx-ev--down { border-left-color: var(--st-down); } .stx-ev--maint { border-left-color: var(--st-maint); }
.stx-ev.is-open { background: #fffdf7; }
.stx-ev__tags { display: flex; flex-wrap: wrap; align-items: center; gap: .35rem .5rem; }
.stx-ev__day { font-size: .8rem; color: var(--ink-3); }
.stx-ev__day time { font-family: var(--mono); }
.stx-tag { display: inline-flex; align-items: center; gap: .35rem; padding: .18rem .5rem; border-radius: 6px; font-size: .78rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; line-height: 1.4; }
.stx-tag--warn  { background: var(--warn-soft); color: #8a5300; }
.stx-tag--bad   { background: #fff1e8; color: #a8420f; }
.stx-tag--down  { background: #fdeded; color: #b53232; }
.stx-tag--maint { background: var(--acc-soft); color: var(--acc-dark); }
.stx-tag--st    { background: var(--bg-sunk); color: var(--ink-2); }
.stx-tag--pm    { background: var(--ok-soft); color: var(--ok); }
.stx-tag--live  { background: var(--ok-soft); color: var(--ok); }
.stx-ev__t { margin-top: .45rem; font-size: 1.02rem; font-weight: 700; line-height: 1.3; }
.stx-ev__t a { color: var(--ink); }
.stx-ev__t a:hover { color: var(--acc); }
.stx-ev__m { display: flex; flex-wrap: wrap; gap: .2rem 1rem; margin-top: .35rem; font-size: .82rem; color: var(--ink-3); }
.stx-ev__m time { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.stx-ev__last { margin-top: .55rem; font-size: .88rem; color: var(--ink-2); max-width: var(--m-note); }
.stx-ev__last b { color: var(--ink); }

.stx-days { margin-top: 1.2rem; border-top: 1px solid var(--line); }
.stx-day { padding: 1rem 0 1.1rem; border-bottom: 1px solid var(--line); }
.stx-day--quiet { display: flex; flex-wrap: wrap; align-items: baseline; gap: .3rem 1rem; padding: .7rem 0; }
.stx-day__d { font-size: .95rem; font-weight: 700; margin-bottom: .6rem; }
.stx-day--quiet .stx-day__d { margin-bottom: 0; font-weight: 600; color: var(--ink-2); min-width: 15rem; }
.stx-day__today { margin-left: .4rem; font-size: .78rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--acc); }
.stx-day__none { font-size: .86rem; color: var(--ink-3); }
.stx-day .stx-ev + .stx-ev { margin-top: .6rem; }
.stx-more { margin-top: 1.3rem; }

.stx-empty { display: flex; align-items: center; gap: .9rem; padding: 1.2rem 1.3rem; border: 1px dashed var(--line-strong); border-radius: var(--r-lg); background: var(--bg-soft); }
.stx-empty__i { flex: none; display: grid; place-items: center; width: 42px; height: 42px; border-radius: 50%; background: #fff; border: 1px solid var(--line); color: var(--acc); }
.stx-empty__t { font-weight: 700; }
.stx-empty__p { margin-top: .2rem; font-size: .88rem; color: var(--ink-2); max-width: var(--m-note); }

.stx-sub { margin-top: 1.6rem; font-size: .78rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-3); }
.stx-mini { margin-top: .5rem; border: 1px solid var(--line); border-radius: var(--r); background: #fff; overflow: hidden; }
.stx-mini li + li { border-top: 1px solid var(--line); }
.stx-mini a { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: .8rem; align-items: center; min-height: 48px; padding: .6rem 1rem; color: var(--ink); font-size: .88rem; }
.stx-mini a:hover { background: var(--bg-soft); color: var(--ink); }
.stx-mini__d { font-family: var(--mono); font-size: .8rem; color: var(--ink-3); white-space: nowrap; }
.stx-mini__t { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.stx-mini__x { font-size: .8rem; color: var(--ink-3); white-space: nowrap; }
@media (max-width: 560px) { .stx-mini a { grid-template-columns: minmax(0, 1fr) auto; } .stx-mini__d { grid-column: 1 / -1; } .stx-mini__t { white-space: normal; } }

/* --- 30.8 La méthode, les flux --------------------------------------------- */
.stx-how { display: grid; gap: .9rem; }
@media (min-width: 900px) { .stx-how { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.stx-how__c { background: #fff; border: 1px solid var(--line); border-radius: var(--r-lg); padding: 1.25rem 1.3rem 1.35rem; min-width: 0; }
.stx-how__i { display: grid; place-items: center; width: 40px; height: 40px; border-radius: 10px; background: var(--acc-soft); color: var(--acc); }
.stx-how__t { margin-top: .85rem; font-size: 1.02rem; font-weight: 700; }
.stx-how__p { margin-top: .45rem; font-size: .9rem; color: var(--ink-2); }

.stx-feeds { display: grid; gap: 1.1rem; margin-top: 1rem; padding: 1.3rem 1.3rem 1.4rem; background: var(--bg-sunk); border: 1px solid var(--line); border-radius: var(--r-lg); }
@media (min-width: 900px) { .stx-feeds { grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr); align-items: start; gap: 2rem; padding: 1.6rem 1.8rem; } }
.stx-feeds__t { font-size: 1.1rem; font-weight: 700; }
.stx-feeds__p { margin-top: .4rem; font-size: .9rem; color: var(--ink-2); }
.stx-feeds__l { display: grid; gap: .55rem; }
@media (min-width: 560px) { .stx-feeds__l { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.stx-feeds__l a { display: flex; align-items: center; gap: .7rem; min-height: 52px; padding: .6rem .9rem; background: #fff; border: 1px solid var(--line); border-radius: var(--r-sm); color: var(--ink); }
.stx-feeds__l a:hover { border-color: var(--acc-line); color: var(--ink); box-shadow: var(--shadow-1); }
.stx-feeds__l .ico { color: var(--acc); flex: none; }
.stx-feeds__l span { display: grid; min-width: 0; }
.stx-feeds__l b { font-size: .9rem; }
.stx-feeds__l small { font-family: var(--mono); font-size: .78rem; color: var(--ink-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.stx-tz { margin-top: 2rem; text-align: center; font-size: .8rem; color: var(--ink-3); }
.stx-tz__b { margin-left: .3rem; padding: .3rem .5rem; min-height: 32px; border: 0; background: transparent; color: var(--acc); font: inherit; font-size: .8rem; font-weight: 600; cursor: pointer; text-decoration: underline; text-underline-offset: .15em; }
.stx-tz__b:hover { color: var(--acc-dark); }

/* --- 30.9 La fenêtre d'abonnement ------------------------------------------ */
.stx-dlg { border: 0; padding: 0; background: transparent; max-width: min(560px, calc(100vw - 2rem)); width: 100%; color: var(--ink); }
.stx-dlg::backdrop { background: rgba(14, 23, 38, .55); backdrop-filter: blur(2px); }
.stx-dlg__box { position: relative; background: #fff; border: 1px solid var(--line); border-radius: var(--r-lg); box-shadow: var(--shadow-2); padding: 1.6rem 1.5rem 1.35rem; }
.stx-dlg__x { position: absolute; top: .6rem; right: .6rem; display: grid; place-items: center; width: 40px; height: 40px; border: 0; border-radius: 8px; background: transparent; color: var(--ink-3); font-size: 1.4rem; cursor: pointer; }
.stx-dlg__x:hover { background: var(--bg-sunk); color: var(--ink); }
.stx-dlg__h { font-size: 1.2rem; font-weight: 700; padding-right: 2.2rem; }
.stx-dlg__p { margin-top: .4rem; font-size: .9rem; color: var(--ink-2); }
.stx-dlg__l { margin-top: 1rem; display: grid; gap: .5rem; }
.stx-dlg__l li { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: .35rem .7rem; align-items: center; padding: .6rem .75rem; border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--bg-soft); }
@media (min-width: 560px) { .stx-dlg__l li { grid-template-columns: 7rem minmax(0, 1fr) auto; } }
.stx-dlg__k { display: inline-flex; align-items: center; gap: .45rem; font-size: .84rem; font-weight: 700; }
.stx-dlg__k .ico { color: var(--acc); }
.stx-dlg__l code { font-family: var(--mono); font-size: .78rem; color: var(--ink-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; grid-column: 1 / -2; }
@media (min-width: 560px) { .stx-dlg__l code { grid-column: 2; } }
.stx-dlg__l .stx-btn { grid-column: 2; grid-row: 1; }
@media (min-width: 560px) { .stx-dlg__l .stx-btn { grid-column: 3; } }
.stx-dlg__f { margin-top: .9rem; font-size: .8rem; color: var(--ink-3); }

/* --- 30.10 L'historique ----------------------------------------------------- */
.stx-mnav { display: grid; grid-template-columns: 1fr auto 1fr; gap: .6rem; align-items: center; padding-top: 1.6rem; }
.stx-mnav > :last-child { justify-self: end; }
.stx-month { padding-top: 1.8rem; }
.stx-month + .stx-month { margin-top: .6rem; border-top: 1px solid var(--line); }
.stx-month__hd { display: flex; flex-wrap: wrap; align-items: baseline; gap: .3rem 1rem; margin-bottom: .9rem; }
.stx-month__t { font-size: clamp(1.25rem, 2.2vw, 1.5rem); text-transform: capitalize; }
.stx-month__s { font-size: .86rem; color: var(--ink-3); }
.stx-month__none { padding: .8rem 0 .4rem; }
.stx-tl { display: grid; gap: 0; }
.stx-tl__i { display: grid; gap: .3rem .9rem; padding: .9rem 0 .95rem .95rem; border-left: 3px solid var(--st-warn); border-bottom: 1px solid var(--line); }
@media (min-width: 720px) { .stx-tl__i { grid-template-columns: 11.5rem minmax(0, 1fr); padding-left: 1.1rem; } }
.stx-tl__i--bad { border-left-color: var(--st-bad); } .stx-tl__i--down { border-left-color: var(--st-down); } .stx-tl__i--maint { border-left-color: var(--st-maint); }
.stx-tl__i.is-open { background: #fffdf7; }
.stx-tl__i:last-child { border-bottom: 0; }
.stx-tl__d { font-family: var(--mono); font-size: .8rem; color: var(--ink-3); font-variant-numeric: tabular-nums; padding-top: .15rem; }
.stx-tl__c { min-width: 0; }
.stx-tl__c .stx-ev__t { margin-top: .3rem; }
.stx-arch { margin-top: 1rem; }
.stx-arch__y { font-size: .78rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-3); margin-bottom: .45rem; }
.stx-arch__l { display: grid; gap: .45rem; grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (min-width: 560px) { .stx-arch__l { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 900px) { .stx-arch__l { grid-template-columns: repeat(6, minmax(0, 1fr)); } }
.stx-arch__l a { display: flex; justify-content: space-between; align-items: center; gap: .5rem; min-height: 46px; padding: .55rem .8rem; background: #fff; border: 1px solid var(--line); border-radius: var(--r-sm); color: var(--ink); font-size: .84rem; text-transform: capitalize; }
.stx-arch__l a:hover { border-color: var(--acc-line); color: var(--ink); }
.stx-arch__l a.is-quiet { color: var(--ink-3); background: var(--bg-soft); }
.stx-arch__l b { font-family: var(--mono); font-size: .78rem; font-weight: 600; color: var(--ink-2); white-space: nowrap; }

/* --- 30.11 La fiche d'un événement ----------------------------------------- */
.phero--inc { border-top: 5px solid var(--st-warn); }
.phero--inc.phero--bad { border-top-color: var(--st-bad); } .phero--inc.phero--down { border-top-color: var(--st-down); } .phero--inc.phero--maint { border-top-color: var(--st-maint); }
.phero--inc .stx-ev__tags { margin-bottom: .8rem; }
.phero__h--inc { max-width: 34ch; font-size: clamp(1.6rem, 3.6vw, 2.4rem); }
.stx-inc { display: grid; gap: 1.6rem; padding-top: 2rem; }
@media (min-width: 1000px) { .stx-inc { grid-template-columns: 300px minmax(0, 1fr); gap: 3rem; align-items: start; } .stx-inc__side { position: sticky; top: calc(var(--hdr-h) + 20px); } }
.stx-facts { display: grid; gap: 0; background: #fff; border: 1px solid var(--line); border-radius: var(--r-lg); overflow: hidden; }
.stx-facts > div { display: grid; grid-template-columns: 7.2rem minmax(0, 1fr); gap: .6rem; padding: .7rem 1rem; border-bottom: 1px solid var(--line); font-size: .88rem; }
.stx-facts > div:last-child { border-bottom: 0; }
.stx-facts dt { font-size: .78rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-3); padding-top: .15rem; }
.stx-facts dd { margin: 0; color: var(--ink); min-width: 0; }
.stx-facts dd time { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.stx-facts dd small { color: var(--ink-3); }
.stx-facts dd code { font-family: var(--mono); font-size: .82rem; }
.stx-facts__c { display: grid; gap: .4rem; }
.stx-facts__c li { display: flex; flex-wrap: wrap; align-items: center; gap: .4rem .6rem; }
.stx-inc__acts { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: .8rem; }
.stx-inc__note { margin-top: .8rem; font-size: .8rem; color: var(--ink-3); }
.stx-inc__h { font-size: 1.15rem; font-weight: 700; margin-bottom: .8rem; }
.stx-inc__body { font-size: .98rem; color: var(--ink-2); max-width: var(--m-read); margin-bottom: 1.8rem; }
.stx-upd { display: grid; gap: 0; border-left: 2px solid var(--line); margin-left: .5rem; }
.stx-upd__i { position: relative; padding: 0 0 1.5rem 1.6rem; }
.stx-upd__i:last-child { padding-bottom: 0; }
.stx-upd__i::before { content: ""; position: absolute; left: -7px; top: .35em; width: 12px; height: 12px; border-radius: 50%; background: #fff; border: 2px solid var(--line-strong); }
.stx-upd__i--resolved::before, .stx-upd__i--completed::before { background: var(--ok); border-color: var(--ok); }
.stx-upd__i--investigating::before { background: var(--st-warn); border-color: var(--st-warn); }
.stx-upd__i--identified::before, .stx-upd__i--in_progress::before { background: var(--acc); border-color: var(--acc); }
.stx-upd__i--monitoring::before, .stx-upd__i--scheduled::before { background: #fff; border-color: var(--acc); }
.stx-upd__hd { display: flex; flex-wrap: wrap; align-items: baseline; gap: .2rem .8rem; }
.stx-upd__s { font-weight: 700; color: var(--ink); }
.stx-upd__t { font-family: var(--mono); font-size: .8rem; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.stx-upd__b { margin-top: .3rem; font-size: .95rem; color: var(--ink-2); max-width: var(--m-read); }
.stx-pm { margin-top: 2rem; padding: 1.3rem 1.4rem 1.4rem; background: var(--bg-soft); border: 1px solid var(--line); border-left: 3px solid var(--ok); border-radius: var(--r-lg); }
.stx-pm__eye { display: flex; align-items: center; gap: .4rem; font-size: .78rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--ok); margin-bottom: .6rem; }
.stx-pm__eye time { font-family: var(--mono); letter-spacing: 0; text-transform: none; color: var(--ink-3); font-weight: 600; }
.stx-pm__h { margin-top: 1rem; font-size: .95rem; font-weight: 700; }
.stx-pm__p { margin-top: .3rem; font-size: .93rem; color: var(--ink-2); max-width: var(--m-read); }
.stx-pm__l { margin-top: .4rem; display: grid; gap: .35rem; padding-left: 1.1rem; list-style: disc; font-size: .93rem; color: var(--ink-2); max-width: var(--m-read); }
.stx-inc__pending { display: flex; align-items: center; gap: .5rem; margin-top: 1.6rem; font-size: .86rem; color: var(--ink-3); }

/* --- 30.12 La ligne d'état de l'en-tête et du pied de page ------------------ */
.topbar__live { display: inline-flex; align-items: center; gap: .5rem; color: inherit; }
.topbar__live:hover { color: inherit; text-decoration: underline; text-underline-offset: .15em; }
.topbar__live--warn .dot, .ft__live--warn .dot { background: #d08a00; box-shadow: 0 0 0 3px rgba(208, 138, 0, .18); }
.topbar__live--down .dot, .ft__live--down .dot { background: #d94141; box-shadow: 0 0 0 3px rgba(217, 65, 65, .18); }
.topbar__live--maint .dot, .ft__live--maint .dot { background: var(--acc); box-shadow: 0 0 0 3px rgba(31, 79, 224, .18); }
.ft__live a { color: inherit; }
.ft__live a:hover { text-decoration: underline; text-underline-offset: .15em; }

/* --- 30.13 Tactile : 44 px partout sous 900 px ------------------------------ */
@media (max-width: 899px) {
  .stx-btn, .stx-lg__b, .stx-seg__b, .stx-tz__b { min-height: 44px; }
  .stx-seg__b { padding-inline: 1rem; }
  .stx-live__acts .stx-btn { flex: 1 1 auto; justify-content: center; }
  /* Les deux liens d'etat de l'en-tete et du pied de page : 44 px de zone
     tactile sans changer la hauteur des barres qui les portent -- la marge
     negative rend a la ligne ce que le remplissage lui prend. */
  .topbar__live { min-height: 44px; margin-block: -11px; }
  .ft__live a { display: inline-flex; align-items: center; min-height: 44px; margin-block: -11px; }
}
@media (max-width: 599px) { .stx-bars { gap: 1px; } }
@media (prefers-reduced-motion: reduce) { .stx-live__dot { animation: none; } }
@media print { .stx-live__acts, .stx-seg, .stx-tz, .stx-feeds { display: none; } .stx-bar { print-color-adjust: exact; -webkit-print-color-adjust: exact; } }
