/* =====================================================================
   pavapi.com — page vitrine.
   Réutilise les jetons de assets/css/app.css ; n'ajoute que ce que la
   vitrine a en propre.
   ===================================================================== */

/*
 * `clip`, et surtout PAS `hidden`.
 *
 * `overflow-x:hidden` sur le corps de page en fait un conteneur de
 * défilement. Le `position:sticky` de la barre se met alors à se référer à ce
 * conteneur plutôt qu'à la fenêtre, et cesse de coller sur les navigateurs
 * qui appliquent la règle à la lettre — Safari et iOS en tête. La barre
 * d'apy remontait donc avec la page au lieu de rester en haut, quand celle
 * des pages de rendement, qui ne porte pas cette classe, tenait très bien.
 *
 * `overflow-x:clip` découpe exactement pareil sans créer de conteneur de
 * défilement : la barre reste collée. Sur un navigateur qui ne connaît pas
 * `clip`, la règle est ignorée et rien n'est découpé — ce qui ne coûte rien
 * ici, aucune page ne débordant horizontalement (vérifié sur les 32).
 */
.site{overflow-x:clip;}

/* ---------- en-tête ---------- */
.site-nav{
  position:sticky; top:0; z-index:60;
  background:rgba(20,17,15,0.72); -webkit-backdrop-filter:blur(14px); backdrop-filter:blur(14px);
  border-bottom:1px solid transparent; transition:border-color .2s cubic-bezier(.25,.46,.45,.94), background .2s cubic-bezier(.25,.46,.45,.94);
}
.site-nav.scrolled{border-bottom-color:var(--line); background:rgba(20,17,15,0.92);}
.site-nav .wrap{display:flex; align-items:center; justify-content:space-between; height:76px; gap:20px;}

/* ---------- hero ---------- */
/* Titre centré au-dessus, puis une rangée où la planète — grande — occupe
   le milieu de l'écran, avec les deux chiffres qui comptent posés à sa
   droite. Colonnes symétriques (1fr / auto / 1fr) : la première reste vide
   exprès, pour que la planète se retrouve au centre plutôt que poussée par
   le contenu de la colonne de droite. */
.hero-globe{ position:relative; border-top:none; padding:56px 0; }

.hero-copy{
  max-width:60ch; margin:0 auto; text-align:center;
}

.hero-kicker{
  display:inline-flex; align-items:center; gap:9px;
  font-family:var(--mono); font-size:.76rem; color:var(--paper-dim);
  border:1px solid var(--line-strong); border-radius:0; padding:7px 15px;
  margin-bottom:26px; background:rgba(28,24,21,.6); -webkit-backdrop-filter:blur(6px); backdrop-filter:blur(6px);
}
h1.site-head{
  font-size:clamp(2.2rem,4.6vw,3.6rem); line-height:1.05; letter-spacing:-0.02em;
  margin:0 0 26px; max-width:20ch; margin-inline:auto;
}
/* Le mot mis en italique prend la couleur de LA SECTION, pas celle du site :
   « automatisé » est doré au-dessus des rendements, bleu au-dessus des cours,
   rose au-dessus de l'atelier. C'est la promesse de chaque écran, dans sa
   teinte, au seul endroit du titre où une couleur ne gêne pas la lecture. */
h1.site-head em{font-style:italic; font-weight:400; color:var(--sec, var(--gold));}
.site-cta{display:flex; gap:13px; flex-wrap:wrap; justify-content:center;}
.btn-lg{padding:15px 28px; font-size:.98rem; border-radius:0;}

/* Le bouton d'ouverture d'Apy porte la couleur de son écran — l'or — comme
   celui de Track porte le vert et celui de l'échange le violet. Sans cette
   règle, il héritait du cuivre par défaut des boutons primaires, et les trois
   sections de la vitrine ne disaient plus chacune leur couleur. */
.hero-globe .btn-primary{background:var(--gold); color:var(--ink);}
.hero-globe .btn-primary:hover:not(:disabled){background:#F0CB85;}

.hero-stage-row{
  display:grid;
  /* Un plancher sur les colonnes de chiffres : sans lui, la colonne centrale
     (dimensionnée sur le contenu de la planète, pas sur l'espace restant)
     pouvait réclamer sa pleine largeur en `vw` et écraser les deux 1fr à
     rien — un bug qui ne se voyait qu'aux largeurs de bureau courantes
     (~1000-1400px), jamais en plein écran sur un grand moniteur. */
  grid-template-columns:minmax(220px,1fr) auto minmax(220px,1fr);
  align-items:center; gap:32px; margin-top:20px;
}
@media(max-width:980px){
  /* Les deux chiffres passent au-dessus de la planète, empilés pleine
     largeur — sinon, empilés après un globe qui occupe une bonne partie de
     l'écran, ils se perdent en bas de page et on croit qu'ils n'existent
     pas. Jamais côte à côte en dessous de 980px : à moitié de l'écran
     chacune, les cartes ne montrent plus un chiffre, mais un mot par ligne. */
  .hero-stage-row{
    grid-template-columns:1fr;
    grid-template-areas:"ml" "mr" "globe";
    justify-items:center; gap:14px;
  }
  .hero-metric-left{ grid-area:ml; }
  .hero-metric-right{ grid-area:mr; }
  .globe-stage{ grid-area:globe; margin-top:12px; }
}

.globe-stage{
  display:flex; justify-content:center; min-width:0;
  /* `clip`, jamais `hidden` : la même leçon que `.site` plus haut dans ce
     fichier — `overflow-x:hidden` crée un nouveau conteneur de défilement, ce
     qui casse `position:sticky` chez les ancêtres. `clip` ne le fait pas.
     Nécessaire depuis que l'ombre du globe déborde légèrement de sa boîte
     (voir `.globe-wrap::before`) : sur un téléphone étroit, ce léger
     débordement horizontal — quelques pixels de dégradé qui s'éteint avant
     d'être visible de toute façon — poussait la page entière à défiler
     latéralement. */
  overflow-x:clip;
}
.globe-wrap{
  /* Nettement plus grande qu'en colonne : libérée du texte, elle peut
     prendre toute la place disponible en hauteur sans déborder l'écran.
     Le facteur `vw` reste modeste : il mesure la largeur de la FENÊTRE, pas
     celle qui reste après les deux cartes de chiffres — trop haut, la
     planète les repousse à rien avant même que le plancher ci-dessus
     n'intervienne. */
  width:min(50vw,76vh,760px); aspect-ratio:1;
  position:relative;
}
/*
 * L'OMBRE DE LA PLANÈTE — et pourquoi ce n'est plus un `filter`.
 *
 * Elle était posée en `filter:drop-shadow(0 26px 60px …)` sur cette boîte.
 * Un filtre s'applique au rendu FINAL de l'élément et de ses enfants : il
 * doit donc être recalculé à chaque fois que l'un d'eux change. Or l'enfant
 * est un canevas qui se redessine soixante fois par seconde — le navigateur
 * refaisait donc un flou de 60 px de rayon sur une surface de 760 px, à
 * chaque image, pour une ombre qui ne bouge jamais.
 *
 * Le coût, mesuré : la page d'accueil tournait à 41 images par seconde au
 * repos ; en retirant cette seule ligne, 60. C'était, de loin, le premier
 * poste de dépense du site.
 *
 * Ce qui la remplace est un DÉGRADÉ, et non une `box-shadow` : celle-ci a
 * d'abord été essayée, et elle dessinait un anneau sombre visible au bord du
 * carré — une ombre de boîte suit la boîte, alors que `drop-shadow` suivait
 * les pixels réellement peints, c'est-à-dire la planète et ses anneaux. Le
 * dégradé radial, lui, n'a pas de bord : il s'éteint avant d'en atteindre un.
 *
 * Mesuré au pixel près contre l'ombre d'origine : l'écart moyen tombe sous
 * le bruit de scintillement des étoiles. Et il est peint une fois, pas
 * soixante fois par seconde.
 */
.globe-wrap::before{
  content:''; position:absolute; z-index:0; pointer-events:none;
  left:-6%; right:-6%; top:4%; bottom:-10%;
  background:radial-gradient(closest-side, rgba(0,0,0,.55) 0%, rgba(0,0,0,.34) 46%, transparent 78%);
}
.globe-wrap > *{position:relative; z-index:1;}
@media(max-width:980px){ .globe-wrap{width:min(92vw,76vh,620px);} }

.hero-metric{ display:flex; min-width:0; }
.hero-metric-left{ justify-content:flex-end; }
.hero-metric-right{ justify-content:flex-start; }
.hero-metric .cell{
  width:min(400px,100%); text-align:center;
  background:rgba(28,24,21,.82); border:1px solid var(--line); border-radius:0;
  padding:26px 34px; -webkit-backdrop-filter:blur(6px); backdrop-filter:blur(6px);
}
.hero-metric .n{font-family:var(--mono); font-size:clamp(1.3rem,2.1vw,1.7rem); color:var(--paper); line-height:1.1; white-space:nowrap;}
.hero-metric .l{font-size:.76rem; color:var(--paper-dim); margin-top:7px; line-height:1.5;}
@media(max-width:980px){
  .hero-metric{ justify-content:center; width:100%; }
  .hero-metric .cell{ width:min(400px,100%); padding:22px 26px; }
  .hero-metric .n{ white-space:normal; }
}


.tri{display:grid; grid-template-columns:repeat(auto-fit,minmax(min(270px,100%),1fr)); gap:18px;}
.tri .cell,.stack .cell{backface-visibility:hidden;border:1px solid var(--line); border-radius:0; padding:26px; background:var(--surface);}
.tri .cell .k,.stack .cell .k{font-family:var(--mono); color:var(--copper); font-size:.78rem; margin-bottom:12px;}
.tri .cell h3,.stack .cell h3{font-size:1.05rem; margin-bottom:9px;}
.tri .cell p,.stack .cell p{color:var(--paper-dim); font-size:.87rem; line-height:1.7; margin:0;}

/* ---------------------------------------------------------------------
   Cartes empilées au défilement
   Trois cartes côte à côte se lisent dans n'importe quel ordre, donc dans
   aucun. Collées les unes sous les autres, elles imposent leur ordre : la
   carte suivante monte par-dessus la précédente, qui recule (échelle,
   opacité, flou) au lieu de disparaître d'un coup — on garde le contexte de
   ce qu'on vient de lire.

   `--p` (0 → 1) est le taux de recouvrement, calculé au défilement par
   `bindStacks()` (landing.js) : le CSS ne sait pas mesurer la distance entre
   deux cartes, mais il sait tout faire du chiffre une fois posé.
   --------------------------------------------------------------------- */
.stack{
  /* La marge du bas d'une carte EST la course de défilement pendant laquelle
     la suivante vient la recouvrir. Trop courte, l'animation passe
     inaperçue ; trop longue, la section devient un tunnel. */
  --stack-gap:8vh;
  --stack-top:104px;
  display:block; padding-bottom:8px;
}
.stack .cell{backface-visibility:hidden;
  position:sticky;
  /* Toutes les cartes se calent au MÊME point : recouvrement total, sans
     bord de la précédente qui dépasse derrière. */
  top:var(--stack-top);
  /* Ordre de superposition explicite : la carte suivante recouvre la
     précédente. Sans lui, la transparence du flou et de l'opacité laisse
     transparaître le texte de la carte du dessous à travers celle du
     dessus — deux paragraphes lus l'un dans l'autre. */
  z-index:calc(var(--i,0) + 1);
  margin-bottom:var(--stack-gap);
  /* Ancrage en HAUT : une carte qui rétrécit doit reculer dans la pile, pas
     s'écarter de son bord collé. */
  transform-origin:top center;
  opacity:calc(1 - .42 * var(--p,0));
  transform:translateY(calc(-6px * var(--p,0))) scale(calc(1 - .05 * var(--p,0)));
  filter:blur(calc(1.6px * var(--p,0)));
  will-change:transform,opacity;
}
/* La dernière carte garde, elle aussi, sa marge pleine. C'est de la
   géométrie, pas de l'esthétique : une carte collée ne le reste que tant que
   sa BOÎTE DE MARGE tient dans son parent. Marge en moins sous la dernière,
   parent plus court d'autant — et la première carte se décolle avant même
   que la troisième soit arrivée, c'est-à-dire exactement quand la pile
   devait se former. */
/* Entrée : la carte monte à l'écran quand elle y arrive vraiment
   (IntersectionObserver), pas au chargement de la page. */
.stack .cell:not(.in){opacity:0; transform:translateY(42px);}
.stack .cell.in{transition:opacity .55s cubic-bezier(.25,.46,.45,.94), transform .55s cubic-bezier(.25,.46,.45,.94); will-change:opacity,transform;}

@media(max-width:820px){
  .stack{--stack-gap:22vh; --stack-top:88px;}
  .stack .cell{backface-visibility:hidden;padding:22px;}
}
/* Une carte plus haute que l'écran ne peut pas « coller » : sur les écrans
   courts on retombe sur un empilement normal, sans recouvrement. */
@media(max-height:620px), (prefers-reduced-motion:reduce){
  .stack .cell{backface-visibility:hidden;
    position:static; margin-bottom:16px;
    opacity:1; transform:none; filter:none; transition:none;
  }
  .stack .cell:not(.in){opacity:1; transform:none;}
}


/* ---------- Section Track ----------
   La section reprend le bandeau, le titre et la paire de chiffres des
   rendements : ce sont deux vues d'un même sujet, et deux mises en page sans
   rapport les feraient passer pour deux produits. La SCÈNE, elle, diffère
   exprès — une sphère pour « où poser », une ceinture qui tourne pour « où
   ça circule ». C'est la seule divergence voulue ; toute autre est un
   défaut. */
.hero-track{
  /* NI CADRE, NI PANNEAU.
     Cette section portait un aplat bleuté et un filet en haut : deux traits
     qui, ensemble, la découpaient de la page comme une fenêtre posée dessus —
     et le champ d'astéroïdes se retrouvait encadré alors qu'on venait
     justement d'effacer le cadre de son canevas. Un dégradé radial qui
     s'éteint avant les bords remplace l'aplat : il donne à la section sa
     teinte propre sans jamais dessiner de limite, et le filet disparaît. */
  background:radial-gradient(120% 90% at 50% 0%, rgba(126,214,165,.06) 0%, transparent 60%);
  border-top:none;
}

/* LE PASSAGE D'UNE COULEUR À L'AUTRE.
   Les deux modules de la vitrine ont chacun leur teinte — le doré des
   rendements, le vert de Track — et ils se touchaient sans transition : la
   page changeait de couleur d'un bloc à l'autre, comme deux images collées.
   Ce voile enjambe la jointure et fait le fondu, doré en haut, vert en bas,
   éteint aux deux extrémités pour ne dessiner aucune limite. Il tient toute
   la largeur de la SECTION (`left:0; right:0`) : une bande qui s'arrête au
   bord du texte se verrait finir, ce qui reviendrait à tracer le trait qu'on
   cherche justement à effacer.

   ET SURTOUT PAS `width:100vw`, qui fut la version précédente. `vw` mesure la
   fenêtre SCROLLBAR COMPRISE : sur un ordinateur à barres de défilement
   classiques, ce voile dépassait de quinze pixels la largeur utile, et comme
   les sections de la vitrine sont des conteneurs de défilement (voir la
   soupape `overflow-y:auto` plus bas), chacune se retrouvait avec une BARRE
   HORIZONTALE en bas — trois sections sur six, et rien à faire glisser. La
   section fait déjà toute la largeur : deux décalages nuls suffisent. */
.hero-track::before{
  content:''; position:absolute; z-index:0; pointer-events:none;
  left:0; right:0;
  top:-190px; height:380px;
  background:linear-gradient(180deg,
    transparent 0%,
    rgba(228,183,103,.07) 26%,
    rgba(150,200,140,.08) 50%,
    rgba(126,214,165,.10) 74%,
    transparent 100%);
}
/* Le contenu repasse devant le voile — sans quoi le dégradé se poserait
   par-dessus le titre et les chiffres. */
.hero-track > .wrap{position:relative; z-index:1;}
.hero-track .site-head{
  font-size:clamp(1.8rem,3.8vw,2.8rem);
  color:var(--paper);
}
.hero-track .hero-kicker{
  color:var(--paper-dim);
}
.hero-track .site-head em{font-style:italic; font-weight:400; color:#7ED6A5;}
/* Le bouton porte la couleur de la destination, pas celle de la page : c'est
   ce qui fait qu'on sait où l'on va avant d'avoir lu le libellé — et c'est
   déjà la couleur que le voile du passage posera à l'écran suivant. */
.hero-track .btn-primary{background:#7ED6A5; color:var(--ink);}
.hero-track .btn-primary:hover{background:#9BE3BB;}
.hero-track .hero-sub{color:var(--paper-dim); max-width:64ch; margin:0 auto 18px; font-size:.96rem;}
.hero-track .hero-copy{max-width:70ch; margin:0 auto; text-align:center;}

/* La scène de la ceinture : une bande pleine largeur. Le globe des
   rendements, juste au-dessus, tient entre ses deux chiffres ; une pluie,
   non — elle a besoin de toute la largeur. Ses chiffres passent dessous.
   Le masque aux deux bords fait entrer et sortir les rochers sans qu'on voie
   la coupe : c'est ce qui rend la boucle invisible. */
.hero-track .belt-stage{
  position:relative; width:100%; margin-top:24px;
  aspect-ratio:26/9; max-height:min(42vh,380px);
  /* LE CHAMP N'A PAS DE BORD — DEUX MASQUES, UN PAR AXE.
     La version précédente posait une ellipse dont les rayons étaient des
     POURCENTAGES DE LA BOÎTE : `82% 82%` sur une bande de 1156 × 420 donnait
     un rayon vertical de 344 px là où le bord n'est qu'à 210. Le dégradé
     n'atteignait donc jamais zéro en haut ni en bas, et s'y coupait net —
     mesuré : une marche de 5 sur 255, invisible à l'analyse mais bien réelle
     à l'œil, et c'était le cadre qui restait.
     Deux dégradés LINÉAIRES croisés n'ont pas ce défaut : chacun va de bord à
     bord sur son axe, donc chacun atteint zéro là où il faut, par
     construction. `intersect` ne garde que ce que les deux laissent passer.
     `-webkit-` en premier : Safari ne comprend `mask-image` que préfixé. */
  -webkit-mask-image:
    linear-gradient(90deg, transparent 0, #000 11%, #000 89%, transparent 100%),
    linear-gradient(180deg, transparent 0, #000 17%, #000 83%, transparent 100%);
  -webkit-mask-composite:source-in;
          mask-image:
    linear-gradient(90deg, transparent 0, #000 11%, #000 89%, transparent 100%),
    linear-gradient(180deg, transparent 0, #000 17%, #000 83%, transparent 100%);
          mask-composite:intersect;
}
.hero-track .belt-stage canvas{width:100%; height:100%; display:block; cursor:crosshair;}
@media(max-width:720px){ .hero-track .belt-stage{aspect-ratio:16/11;} }

.track-metrics{
  display:grid; grid-template-columns:repeat(auto-fit,minmax(min(220px,100%),1fr));
  gap:14px; margin-top:26px;
}
.track-metrics .cell{
  text-align:center; padding:22px 26px; border-radius:0;
  background:rgba(28,24,21,.88); border:1px solid var(--line-strong);
}
.track-metrics .n{
  font-family:var(--mono); font-size:clamp(1.3rem,2.1vw,1.7rem);
  color:#7ED6A5; line-height:1.1;
}
.track-metrics .l{font-size:.78rem; color:var(--paper-dim); margin-top:7px; line-height:1.5;}

/* La légende de la ceinture : une pastille par famille, et son effectif.
   Sans elle le champ est décoratif — une nuance ne veut rien dire tant que
   la page n'a pas pris la peine de la nommer. */
.track-legend{
  display:flex; flex-wrap:wrap; justify-content:center; gap:8px 18px;
  margin:26px auto 0; max-width:80ch;
}
.tl-item{display:inline-flex; align-items:center; gap:8px; font-size:.78rem; color:var(--paper-dim);}
.tl-item b{font-weight:500; color:var(--paper);}
.tl-item i{
  width:10px; height:10px; border-radius:50%; flex-shrink:0;
  background:var(--c); box-shadow:inset 0 0 0 1.5px var(--r,var(--c));
}
.tl-item.alert i{box-shadow:inset 0 0 0 1.5px var(--r), 0 0 9px -1px var(--r);}
.tl-item > span{font-family:var(--mono); font-size:.7rem; color:var(--paper-faint);}

/* Le tiroir des écrans a déménagé dans assets/css/app.css : il n'est plus
   propre à la vitrine, les quatre écrans le portent. app.css est la seule
   feuille chargée par les quatre — landing.css ne l'est pas par Track ni par
   les pages de coffre, et le tiroir y serait resté sans style. */

/* ---------- LE TROISIÈME MODULE : l'échange ----------
   Même grammaire que les deux précédents — un titre centré, une phrase, un
   bouton à la couleur de la destination — et le même fondu qui enjambe la
   jointure, vert en haut (Track), violet en bas (l'échange). Rompre ici la
   règle posée entre les rendements et Track ferait réapparaître exactement
   le raccord net qu'on venait d'effacer. */
.hero-swap{
  position:relative; padding:90px 0 100px;
  background:radial-gradient(120% 90% at 50% 0%, rgba(169,155,230,.06) 0%, transparent 60%);
}
.hero-swap::before{
  content:''; position:absolute; z-index:0; pointer-events:none;
  left:0; right:0;
  top:-190px; height:380px;
  background:linear-gradient(180deg,
    transparent 0%,
    rgba(126,214,165,.07) 26%,
    rgba(148,186,200,.07) 50%,
    rgba(169,155,230,.10) 74%,
    transparent 100%);
}
.hero-swap > .wrap{position:relative; z-index:1;}
.hero-swap .hero-copy{max-width:70ch; margin:0 auto; text-align:center;}
.hero-swap .site-head{font-size:clamp(1.8rem,3.8vw,2.8rem); color:var(--paper);}
.hero-swap .site-head em{font-style:italic; font-weight:400; color:#A99BE6;}
.hero-swap .hero-kicker{color:var(--paper-dim);}
.hero-swap .hero-sub{color:var(--paper-dim); max-width:64ch; margin:0 auto 18px; font-size:.96rem;}
.hero-swap .btn-primary{background:#A99BE6; color:var(--ink);}
.hero-swap .btn-primary:hover{background:#C0B4F0;}

/* Trois cartes plutôt qu'une scène animée : les deux modules précédents en
   ont chacun une, une troisième ferait une page qui bouge en continu. Elles
   disent ce qui est comparé, ce qui est dit, et ce qui n'est PAS fait — ce
   dernier point étant celui qu'on doit lire avant de cliquer. */
.swap-teaser{
  display:grid; grid-template-columns:repeat(auto-fit,minmax(min(230px,100%),1fr));
  gap:14px; margin-top:34px;
}
.st-card{
  display:flex; flex-direction:column; gap:6px;
  padding:18px; border-radius:0;
  background:var(--surface-2); border:1px solid var(--line);
  border-top:2px solid rgba(169,155,230,.5);
}
.st-lbl{
  font-family:var(--mono); font-size:.72rem; letter-spacing:.06em;
  text-transform:uppercase; color:var(--paper-faint);
}
.st-card b{font-family:'Fraunces',serif; font-weight:500; font-size:1.1rem; color:var(--paper);}
.st-card > span:last-child{font-size:.82rem; line-height:1.6; color:var(--paper-dim);}

/* Les fonds de la vitrine sont revenus à ce qu'ils étaient : chaque module
   porte sa propre teinte en dégradé radial très pâle, et un voile de raccord
   enjambe chaque jointure (voir `.hero-track::before` et `.hero-swap::before`
   plus haut). Un procédé commun les avait remplacés — voiles dimensionnés en
   pourcentage, teintes sombres et saturées — et rendait la page nettement
   plus colorée ; ce n'est pas ce qui était voulu, et le parti pris d'origine
   est restauré tel quel. */

/* ---------- LA SCENE DE L'ECHANGE : la fusion de deux trous noirs ----------
   Le pendant de la ceinture de Track : une bande pleine largeur, mêmes deux
   masques croisés qui effacent la coupe de la boucle aux bords. La teinte, elle,
   est celle de l'écran — le violet, là où la ceinture est verte. La scène ne
   se survole pas : pas de `cursor:crosshair`, pas de projecteur. C'est un
   spectacle, pas un outil. */
.hero-swap .merge-stage{
  position:relative; width:100%; margin-top:30px;
  aspect-ratio:26/9; max-height:min(42vh,380px);
  -webkit-mask-image:
    linear-gradient(90deg, transparent 0, #000 11%, #000 89%, transparent 100%),
    linear-gradient(180deg, transparent 0, #000 17%, #000 83%, transparent 100%);
  -webkit-mask-composite:source-in;
          mask-image:
    linear-gradient(90deg, transparent 0, #000 11%, #000 89%, transparent 100%),
    linear-gradient(180deg, transparent 0, #000 17%, #000 83%, transparent 100%);
          mask-composite:intersect;
}
.hero-swap .merge-stage canvas{width:100%; height:100%; display:block;}
@media(max-width:720px){ .hero-swap .merge-stage{aspect-ratio:16/11;} }

/* ---------- LA SECTION DES COURS ----------
   Le quatrième écran, en tons bleus. Même procédure que les trois
   précédentes : sa teinte en dégradé radial très pâle, un voile de raccord
   enjambe la jointure avec l'échange au-dessus, et le bouton porte la
   couleur de l'écran. La scène n'est pas animée mais un aperçu en direct :
   une grille de cartes, une par cryptomonnaie. */
.hero-price{
  position:relative; padding:90px 0 100px;
  background:radial-gradient(120% 90% at 50% 0%, rgba(91,182,240,.06) 0%, transparent 60%);
}
.hero-price::before{
  content:''; position:absolute; z-index:0; pointer-events:none;
  left:0; right:0;
  top:-190px; height:380px;
  background:linear-gradient(180deg,
    transparent 0%,
    rgba(169,155,230,.07) 26%,
    rgba(120,170,210,.07) 50%,
    rgba(91,182,240,.10) 74%,
    transparent 100%);
}
.hero-price > .wrap{position:relative; z-index:1;}
.hero-price .hero-copy{max-width:70ch; margin:0 auto; text-align:center;}
.hero-price .site-head{font-size:clamp(1.8rem,3.8vw,2.8rem); color:var(--paper);}
.hero-price .site-head em{font-style:italic; font-weight:400; color:#5BB6F0;}
.hero-price .hero-kicker{color:var(--paper-dim);}
.hero-price .hero-sub{color:var(--paper-dim); max-width:64ch; margin:0 auto 18px; font-size:.96rem;}
.hero-price .btn-primary{background:#5BB6F0; color:var(--ink);}
.hero-price .btn-primary:hover{background:#8BCBF6;}

/* La scène : deux ciels des cours — les cryptos, puis les actions et les
   ETF —, un corps par actif, à l'altitude de sa variation. Comme la planète,
   la ceinture et le cycle ont chacun leur scène, la section des cours a la
   sienne : deux champs, côte à côte sur un écran large, l'un sous l'autre
   ailleurs. La boîte reste UNE scène pour la mise en page (c'est elle qui
   cède ou reçoit la hauteur, voir plus bas) ; ce sont ses deux cases qui se
   partagent ce qu'elle reçoit. */
.hero-price .price-scene{
  position:relative; width:100%; margin-top:30px;
  aspect-ratio:26/9; max-height:min(40vh,360px);
  display:grid; grid-template-columns:repeat(2, minmax(0, 1fr));
  grid-template-rows:minmax(0, 1fr); gap:16px;
}
/* Une case : le canevas est posé EN ABSOLU dessus. Il fixe sa taille en
   pixels (voir ui/stage.js) ; dans le flux, cette taille aurait nourri celle
   de la case, qui aurait nourri la sienne au relevé suivant. Hors du flux, la
   case prend ce que la grille lui donne, et le canevas le remplit. */
.hero-price .psky{position:relative; min-width:0; min-height:0;}
/* Les masques croisés fondent les bords de CHAQUE ciel, comme pour les deux
   autres scènes — posés sur la boîte entière, ils laissaient la jointure
   entre les deux champs nette au milieu d'une image fondue partout ailleurs. */
.hero-price .psky canvas{
  position:absolute; inset:0; width:100%; height:100%; display:block;
  /* Le viseur dit que la scène répond au pointeur — comme la ceinture de
     Track, qui porte le même curseur pour la même raison. */
  cursor:crosshair;
  -webkit-mask-image:
    linear-gradient(90deg, transparent 0, #000 11%, #000 89%, transparent 100%),
    linear-gradient(180deg, transparent 0, #000 14%, #000 86%, transparent 100%);
  -webkit-mask-composite:source-in;
          mask-image:
    linear-gradient(90deg, transparent 0, #000 11%, #000 89%, transparent 100%),
    linear-gradient(180deg, transparent 0, #000 14%, #000 86%, transparent 100%);
          mask-composite:intersect;
}
/* Le nom de chaque ciel, en tête : deux champs sans titre se lisent comme un
   seul, coupé en deux. Il ne capte pas le pointeur — le survol des corps
   passe dessous. */
.hero-price .psky-cap{
  position:absolute; top:4px; left:50%; transform:translateX(-50%);
  z-index:1; pointer-events:none; white-space:nowrap;
  padding:3px 9px; font:600 .72rem/1.3 var(--mono, 'IBM Plex Mono', monospace);
  letter-spacing:.04em; color:#5BB6F0;
  background:rgba(20,17,15,.72); border:1px solid rgba(91,182,240,.26);
}
/* Plus étroit, les deux ciels s'empilent : côte à côte, chacun n'aurait plus
   que quelques corps, trop petits pour qu'on reconnaisse une marque. */
@media(max-width:900px){
  .hero-price .price-scene{
    grid-template-columns:minmax(0, 1fr); grid-template-rows:repeat(2, minmax(0, 1fr));
    gap:10px; aspect-ratio:26/16; max-height:min(64vh, 560px);
  }
}
@media(max-width:720px){ .hero-price .price-scene{aspect-ratio:16/15;} }

/* ---------- LA SECTION DES GAINS ----------
   Le sixième écran, en tons corail. Même procédure que les autres : sa
   teinte en dégradé radial très pâle, un bouton à la couleur de l'écran, et
   une scène pleine largeur fondue aux bords — la file des visiteurs, le
   bouclier, l'écran publicitaire et les deux sorties (ui/earnscene.js). */
.hero-earn{
  position:relative; padding:90px 0 100px;
  background:radial-gradient(120% 70% at 50% 0%, rgba(240,138,93,.09), transparent 62%);
}
.hero-earn > .wrap{position:relative; z-index:1;}
.hero-earn .hero-copy{max-width:70ch; margin:0 auto; text-align:center;}
.hero-earn .site-head{font-size:clamp(1.8rem,3.8vw,2.8rem); color:var(--paper);}
.hero-earn .site-head em{font-style:italic; font-weight:400; color:#F08A5D;}
.hero-earn .hero-kicker{color:var(--paper-dim);}
.hero-earn .hero-kicker .live-dot{background:#F08A5D;}
.hero-earn .btn-primary{background:#F08A5D; color:var(--ink);}
.hero-earn .btn-primary:hover{background:#F5A882;}
.hero-earn .earn-stage{
  position:relative; width:100%; margin-top:30px;
  aspect-ratio:26/9; max-height:min(40vh,360px);
  -webkit-mask-image:
    linear-gradient(90deg, transparent 0, #000 6%, #000 94%, transparent 100%),
    linear-gradient(180deg, transparent 0, #000 8%, #000 92%, transparent 100%);
  -webkit-mask-composite:source-in;
          mask-image:
    linear-gradient(90deg, transparent 0, #000 6%, #000 94%, transparent 100%),
    linear-gradient(180deg, transparent 0, #000 8%, #000 92%, transparent 100%);
          mask-composite:intersect;
}
.hero-earn .earn-stage canvas{position:absolute; inset:0; width:100%; height:100%; display:block;}
@media(max-width:720px){ .hero-earn .earn-stage{aspect-ratio:16/11;} }


/* ================= LA FLÈCHE DE DESCENTE =================
   Une page faite d'écrans pleins ne dit pas combien il en reste. La flèche le
   dit, et y emmène (voir ui/scrolldown.js pour la règle de cadrage).

   Elle est DANS LE FLUX, en fin de section, et non posée en absolu par-dessus.
   En absolu elle serait tombée sur une scène ou sur une carte selon la
   hauteur du contenu, et il aurait fallu un décalage par section pour la
   rattraper — soit quatre réglages à tenir au lieu d'une marge. */
.sd-btn{
  display:flex; align-items:center; justify-content:center;
  width:46px; height:46px; margin:42px auto 0; padding:0;
  border-radius:50%; cursor:pointer;
  border:1px solid color-mix(in srgb, var(--sd, var(--paper-faint)) 38%, transparent);
  background:color-mix(in srgb, var(--sd, var(--paper-faint)) 9%, transparent);
  color:var(--sd, var(--paper-dim));
  transition:background .18s, border-color .18s, color .18s, transform .18s;
}
.sd-btn svg{width:22px; height:22px; display:block; animation:sd-bob 2.1s ease-in-out infinite;}
.sd-btn:hover{
  background:color-mix(in srgb, var(--sd, var(--paper-faint)) 18%, transparent);
  border-color:color-mix(in srgb, var(--sd, var(--paper-faint)) 70%, transparent);
  color:var(--paper);
}
.sd-btn:active{transform:translateY(2px);}
.sd-btn:focus-visible{outline:2px solid var(--sd, var(--paper-dim)); outline-offset:3px;}

/* Le battement : trois pixels, pas davantage. Une flèche qui saute attire
   l'œil au détriment de la scène qu'elle accompagne — elle doit signaler
   qu'il y a une suite, pas se disputer la page avec elle. */
@keyframes sd-bob{
  0%,100% { transform:translateY(-2px); }
  50%     { transform:translateY(3px); }
}
@media(prefers-reduced-motion:reduce){
  .sd-btn svg{animation:none;}
  .sd-btn:active{transform:none;}
}

/* Chaque section garde SA couleur, celle de son écran : la flèche appartient
   à la scène qu'elle termine, pas à une barre d'outils commune. */
.hero-globe          { --sd:#E4B767; }   /* les rendements — ambre */
.hero-globe.hero-track{ --sd:#7ED6A5; }  /* Track — vert */
.hero-swap           { --sd:#A99BE6; }   /* l'échange — violet */
.hero-price          { --sd:#5BB6F0; }   /* les cours — bleu */
.hero-earn           { --sd:#F08A5D; }   /* les gains — corail */

@media(max-width:720px){
  .sd-btn{width:42px; height:42px; margin-top:32px;}
  .sd-btn svg{width:20px; height:20px;}
}

/* ================= LA SECTION DE L'ATELIER =================
   La seule scène de la vitrine qui ne montre pas de données — un atelier ne
   montre rien tant qu'on n'y a pas branché sa clé, et une fausse
   conversation de démonstration serait la seule chose inventée de la page.
   Elle montre donc l'OBJET : une console, ses quatre lignes de vocabulaire,
   et le rat qui les tape. Le rose est la couleur de cet écran-là ; les bords
   francs et la fonte pixel sont sa grammaire, reprise telle quelle de
   ai.pavapi.com — deux écrans du même produit ne se présentent pas
   différemment. */
.hero-ai{
  position:relative; padding:78px 0 64px;
  --sd:#E37FB8;
  background:
    radial-gradient(120% 70% at 50% 0%, rgba(227,127,184,.09), transparent 62%);
}
.hero-ai .wrap{display:flex; flex-direction:column; align-items:center;}
.hero-ai .hero-kicker .live-dot{background:#E37FB8;}
.hero-ai .site-head em{color:#E37FB8;}
.hero-ai .btn-primary{background:#E37FB8; border-color:#E37FB8; color:#14110F;}
.hero-ai .btn-primary:hover{background:#F0A0CB; border-color:#F0A0CB;}

.ait-stage{
  display:flex; align-items:stretch; gap:14px; width:100%; max-width:760px;
  margin:30px auto 0;
}
.ait-rat{
  flex:0 0 auto; width:104px; height:auto; min-height:118px;
  background:#0E0C0B; border:2px solid rgba(242,237,230,.14);
  box-shadow:4px 4px 0 rgba(0,0,0,.5);
}
.ait-rat canvas{display:block; image-rendering:pixelated; width:100%; height:100%;}
.ait-screen{
  flex:1 1 auto; min-width:0; min-height:118px;
  display:flex; flex-direction:column; justify-content:center; gap:7px;
  padding:14px 16px;
  background:#0E0C0B; border:2px solid rgba(242,237,230,.14);
  box-shadow:4px 4px 0 rgba(0,0,0,.5);
  /* Les fines rayures d'un tube cathodique : deux pixels, et l'écran cesse
     d'être un rectangle noir. Elles ne bougent pas — une image qui défile
     derrière du texte le rend illisible. */
  background-image:repeating-linear-gradient(
    to bottom, rgba(227,127,184,.05) 0 1px, transparent 1px 3px);
}
.ait-screen b{
  display:block; font-family:'IBM Plex Mono', ui-monospace, monospace;
  font-size:.74rem; line-height:1.5; color:#E0DAD1; white-space:pre-wrap;
  font-weight:400; min-height:1.1em;
}
.ait-screen b::before{content:'> '; color:#E37FB8;}
.ait-screen b.is-typing::after{
  content:'█'; color:#E37FB8; animation:aitCaret .9s steps(2) infinite;
}
@keyframes aitCaret{0%,49%{opacity:1;} 50%,100%{opacity:0;}}
.ait-note{
  max-width:60ch; margin:18px auto 0; text-align:center;
  font-size:.84rem; line-height:1.65; color:var(--paper-faint);
}
@media(max-width:640px){
  .ait-stage{flex-direction:column; align-items:center;}
  .ait-rat{width:96px; min-height:84px;}
  .ait-screen{width:100%; box-sizing:border-box;}
  .ait-screen b{font-size:.75rem;}
}
@media(prefers-reduced-motion:reduce){
  .ait-screen b.is-typing::after{animation:none;}
}

/* LE BADGE DE LA VITRINE. Les cinq autres écrans portent, à côté du mot, un
   petit cadre qui les nomme — « apy », « track », « swap », « price »,
   « ai ». La vitrine n'en avait pas : elle était le seul écran dont la barre
   ne disait pas où l'on se trouve, et son logo paraissait, à côté des autres,
   inachevé. Elle porte donc le sien, dans l'orange qui est sa couleur. */
.logo-suffix-site{
  color:#E8913C;
  border-color:color-mix(in srgb, #E8913C 42%, transparent);
}

/* ================= LA MARQUE DE CHAQUE SECTION =================
   Chaque section de la vitrine présente un écran, et ne le disait que par
   son titre : il fallait lire pour savoir de quoi on parlait. La marque de
   l'écran se pose donc au-dessus du chapeau — la même qu'on retrouvera dans
   la barre une fois arrivé, ce qui en fait un fil plutôt qu'une décoration.
   Le cadre et la lueur prennent la couleur de l'écran présenté, jamais celle
   de la vitrine : c'est la destination qui parle, pas l'endroit d'où l'on
   part. Le dessin est posé par assets/js/landing.js depuis la table des
   écrans — le HTML n'en porte aucune copie. */
.sec-mark{
  display:block; width:46px; height:46px; margin:0 auto 16px;
  display:grid; place-items:center;
  border:1px solid color-mix(in srgb, var(--c, var(--gold)) 34%, transparent);
  border-radius:0;
  background:color-mix(in srgb, var(--c, var(--gold)) 8%, transparent);
  box-shadow:0 0 24px -12px var(--c, var(--gold));
}
.sec-mark svg{width:26px; height:26px; display:block;}
@media(max-width:640px){
  .sec-mark{width:40px; height:40px; margin-bottom:13px;}
  .sec-mark svg{width:22px; height:22px;}
}

/* ------------------------------------------------------------------ *
 *  LE GUIDE — la bête de la section, et ses questions
 * ------------------------------------------------------------------ *
 * Posé SUR LE CÔTÉ, jamais au milieu : il ne coupe pas la lecture d'une
 * section, il l'accompagne. `margin-left:auto` le pousse à droite du bloc de
 * texte sur grand écran ; en dessous de 900 px il repasse en pleine largeur,
 * sous la scène, où il ne dispute la place à personne.
 *
 * `--c` est l'accent de l'écran concerné, posé par le script : l'écureuil de
 * l'apy est doré, le renard de Track est vert. La bête et sa bulle sont donc
 * de la couleur de ce dont elles parlent.
 */
/* CENTRÉ, pas rangé à droite. Poussé contre le bord, le guide avait l'air
   d'une note de bas de page ; au milieu, sous le contenu de la section, il
   se lit comme ce qu'il est — l'endroit où l'on pose ses questions. */
.sec-guide{
  display:flex; align-items:flex-start; gap:14px;
  margin:26px auto 0; max-width:560px; width:100%;
  padding:14px 16px;
  background:color-mix(in srgb, var(--c,#E4B767) 7%, rgba(28,24,21,.72));
  border:1px solid color-mix(in srgb, var(--c,#E4B767) 26%, transparent);
  border-radius:0;
  -webkit-backdrop-filter:blur(6px); backdrop-filter:blur(6px);
}
.guide-pet{
  flex:0 0 76px; width:76px; height:70px;
  display:flex; align-items:center; justify-content:center;
  background:rgba(10,8,7,.45); border-radius:0;
}
.guide-pet canvas{display:block; image-rendering:pixelated;}
.guide-talk{flex:1 1 auto; min-width:0;}
.guide-say{
  margin:0 0 10px; font-size:.84rem; line-height:1.6; color:var(--paper-dim);
  min-height:3.2em;
}
.guide-who{
  display:inline-block; margin-right:7px; font:600 .72rem/1 var(--mono);
  letter-spacing:.09em; text-transform:uppercase; color:var(--c,#E4B767);
  border:1px solid currentColor; border-radius:0; padding:3px 6px;
  vertical-align:1px;
}
.guide-qs{display:flex; flex-wrap:wrap; gap:6px;}
.guide-q{
  font:400 .74rem/1.2 'Inter',sans-serif; text-align:left;
  background:transparent; color:var(--paper-faint);
  border:1px solid var(--line); border-radius:0;
  padding:6px 11px; cursor:pointer;
  transition:border-color .15s var(--ease,ease), color .15s var(--ease,ease), background .15s var(--ease,ease);
}
.guide-q:hover{border-color:var(--c,#E4B767); color:var(--paper);}
.guide-q.is-on{
  border-color:var(--c,#E4B767); color:var(--c,#E4B767);
  background:color-mix(in srgb, var(--c,#E4B767) 12%, transparent);
}
.guide-q:focus-visible{outline:2px solid var(--c,#E4B767); outline-offset:2px;}
@media(max-width:900px){
  .sec-guide{max-width:100%;}
}
@media(max-width:480px){
  .sec-guide{gap:10px; padding:12px;}
  .guide-pet{flex-basis:60px; width:60px; height:58px;}
  .guide-say{font-size:.8rem;}
}

/* ══════════════════════════════════════════════════════════════════════
 *  LA COUCHE PIXEL — ce que l'accueil emprunte à l'atelier d'IA
 * ══════════════════════════════════════════════════════════════════════
 *
 * L'atelier (`ai.pavapi.com`) a trouvé une langue que le reste du site
 * n'avait pas : des cadres FRANCS — deux pixels, aucun arrondi — des ombres
 * qui sont des décalages pleins plutôt que des flous, et une typographie
 * pixel réservée aux étiquettes. Ça marche parce que c'est une COUCHE posée
 * sur la sobriété du site, pas un déguisement qui la remplace.
 *
 * L'accueil la reprend ici, avec la même retenue et les mêmes limites :
 *
 *   — la fonte pixel ne touche QUE les étiquettes (le bandeau de section, le
 *     nom de la bête). Jamais un titre, jamais un paragraphe : un texte en
 *     fonte pixel ne se lit pas, et cette page existe pour être lue ;
 *   — les scènes animées — planète, ceinture, passage, ciel des cours — ne
 *     changent PAS. Elles sont ce que l'accueil a de plus vivant, et les
 *     encadrer reviendrait à mettre un cadre autour d'une fenêtre ;
 *   — les couleurs restent celles de chaque section. Rien de rose ici : le
 *     rose est à l'atelier.
 */

/* Le bandeau de section : la pastille ronde devient l'étiquette carrée des
   blocs de l'atelier, dans la teinte de la section. */
.hero-kicker{
  font-family:'Press Start 2P','IBM Plex Mono',ui-monospace,monospace;
  font-size:.7rem; letter-spacing:-0.03em; line-height:1.9;
  border:2px solid var(--line-strong); border-radius:0;
  padding:9px 14px;
  box-shadow:4px 4px 0 rgba(0,0,0,.42);
}
.hero-globe .hero-kicker,
.hero-swap .hero-kicker,
.hero-price .hero-kicker,
.hero-earn .hero-kicker,
.hero-ai .hero-kicker{ border-color:color-mix(in srgb, var(--sec, var(--gold)) 38%, transparent); }

/* Les chiffres de part et d'autre des scènes : mêmes cadres francs. */
.hero-metric .cell{
  border:2px solid var(--px-line,rgba(242,237,230,0.14)); border-radius:0;
  box-shadow:6px 6px 0 rgba(0,0,0,.34);
}
.hero-metric .l{font-family:var(--mono); font-size:.72rem;}

/* La marque de section : carrée comme un bloc de l'atelier, plus ses
   deux pixels de bord. Elle reste la marque — seule sa monture change. */
.sec-mark{
  border-width:2px; border-radius:0;
  box-shadow:5px 5px 0 rgba(0,0,0,.34), 0 0 26px -14px var(--c, var(--gold));
}

/* Le bouton d'entrée d'une section : l'ombre pleine et l'enfoncement au
   clic des boutons de l'atelier. Réservé à `.site-cta` — les boutons du
   reste du site gardent leur forme. */
.site-cta .btn-lg{
  border-radius:0; border-width:2px;
  box-shadow:5px 5px 0 rgba(0,0,0,.45);
  transition:transform .1s var(--ease,ease), box-shadow .1s var(--ease,ease), filter .15s var(--ease,ease);
}
.site-cta .btn-lg:hover{filter:brightness(1.08);}
.site-cta .btn-lg:active{transform:translate(5px,5px); box-shadow:0 0 0 rgba(0,0,0,0);}

/* Le guide et son nom : même monture franche, même étiquette pixel. */
.sec-guide{
  border-width:2px; border-radius:0;
  box-shadow:6px 6px 0 rgba(0,0,0,.30);
}
.guide-pet{border-radius:0; border:2px solid var(--px-line,rgba(242,237,230,0.14));}
.guide-who{
  font-family:'Press Start 2P','IBM Plex Mono',ui-monospace,monospace;
  font-size:.7rem; letter-spacing:-0.03em; border-radius:0; border-width:2px;
}
.guide-q{border-radius:0; border-width:2px;}

/* La marque des écrans, dans le tiroir et le pied : la même monture carrée
   que sur l'accueil, pour que le même objet se présente pareil partout. */
.scr-badge{border-radius:0; border-width:2px;}

@media(prefers-reduced-motion:reduce){
  .site-cta .btn-lg{transition:none;}
}

/* ------------------------------------------------------------------ *
 *  LE FONDU DE SECTION — celui de l'atelier, partout
 * ------------------------------------------------------------------ *
 * La section de l'atelier porte un halo qui descend du haut et s'éteint à
 * mi-hauteur. C'est ce qui sépare visuellement les sections sans trait de
 * séparation : on voit qu'on change d'écran avant d'avoir lu le titre. Les
 * autres l'avaient en deux fois plus pâle, et le changement ne se voyait pas.
 *
 * IL SE POSE SUR LE FOND DE LA SECTION, PAS EN PSEUDO-ÉLÉMENT — et c'est la
 * correction. Une première version l'avait mis en `::before` : or Track,
 * l'échange et les cours en ont DÉJÀ un, celui qui enjambe la jointure entre
 * deux sections (voir `.hero-track::before` plus haut). Deux règles pour un
 * seul pseudo-élément, et la seconde effaçait la première : les trois
 * fondus de jointure disparaissaient, et l'`isolation` ajoutée au passage
 * remettait à plat l'empilement du canevas et du texte.
 *
 * Chaque section garde donc son `::before` de jointure, et porte le halo
 * dans son propre `background` — à la même opacité que l'atelier.
 */
.hero-globe{
  background:radial-gradient(120% 70% at 50% 0%, rgba(228,183,103,.09), transparent 62%);
}
.hero-track{
  background:radial-gradient(120% 70% at 50% 0%, rgba(126,214,165,.09), transparent 62%);
}
.hero-swap{
  background:radial-gradient(120% 70% at 50% 0%, rgba(169,155,230,.09), transparent 62%);
}
.hero-price{
  background:radial-gradient(120% 70% at 50% 0%, rgba(91,182,240,.09), transparent 62%);
}

/* ==================================================================== *
 *  LA VITRINE SE LIT ÉCRAN PAR ÉCRAN
 * ==================================================================== *
 *
 * Six scènes à la suite, et chacune faisait une fois et demie la hauteur de
 * la fenêtre : on arrivait au milieu de la suivante sans avoir fini la
 * précédente, la page entière tenait sur neuf à dix écrans, et le seul repère
 * était la barre de défilement. Une vitrine se regarde ; elle ne se parcourt
 * pas comme un document.
 *
 * Chaque section occupe donc EXACTEMENT la fenêtre, sous la barre, et le
 * défilement s'arrête pile sur la suivante. C'est l'accrochage natif du
 * navigateur (`scroll-snap`), pas une interception de la molette :
 *
 *   — la molette, le pavé tactile, le doigt, les touches Page suiv./Début/Fin
 *     et la barre de défilement continuent de faire ce qu'ils font partout
 *     ailleurs. Un défilement réécrit en JavaScript casse au moins l'un des
 *     six, et toujours celui qu'on n'avait pas testé ;
 *   — l'inertie du doigt reste celle du système, donc juste sur iOS comme sur
 *     Android ;
 *   — rien ne dépend d'un script : sans JavaScript, la page s'accroche quand
 *     même.
 *
 * `scroll-snap-stop: always` est ce qui interdit de sauter une scène d'un
 * geste trop ample — sans lui, un défilement rapide traverse trois sections
 * et l'accrochage ne fait que choisir où il s'arrête.
 *
 * LES FLÈCHES RESTENT (voir ui/scrolldown.js), en second : elles disent qu'il
 * y a quelque chose en dessous, ce que l'accrochage ne dit pas.
 *
 * `dvh`, et ni `vh` ni `svh`. Les trois mesurent la même fenêtre à des
 * moments différents, et sur téléphone ce moment change tout seul :
 *
 *   — `vh` est la fenêtre BARRES RÉTRACTÉES. Barres visibles, la section
 *     dépasse de leur hauteur : on ne voit jamais son bas ;
 *   — `svh` est la fenêtre BARRES VISIBLES. C'était la version précédente, et
 *     c'est le défaut qu'on voyait sur un vrai téléphone : dès le premier
 *     geste, la barre d'adresse se rétracte, la fenêtre grandit de soixante à
 *     cent points — et la section, elle, garde sa taille d'avant. Il restait
 *     donc en bas de l'écran une tranche de la section SUIVANTE, sous celle
 *     qu'on lisait. « Une section, un écran » cessait d'être vrai au premier
 *     défilement, c'est-à-dire tout le temps ;
 *   — `dvh` est la fenêtre MAINTENANT. Elle suit la rétractation des barres,
 *     donc la section fait toujours exactement l'écran visible, avant comme
 *     après. C'est la seule des trois qui tienne la promesse.
 *
 * Le prix de `dvh` est une remesure pendant que les barres glissent. Elle ne
 * coûte rien ici : les scènes sont des canevas qui se remesurent déjà seuls
 * (`ResizeObserver`), et l'accrochage recalcule ses points au même instant.
 *
 * La règle ne s'applique qu'à partir d'une fenêtre assez haute : sur un
 * téléphone couché, une scène pleine hauteur ne laisse plus la place de lire
 * son titre, et un accrochage qui coince est pire que pas d'accrochage.
 */
/*
 * LE PLANCHER DE LISIBILITÉ NE SE NÉGOCIE PAS.
 *
 * Tout ce qui suit resserre la vitrine pour la faire tenir en un écran. Deux
 * réglages étaient descendus à dix pixels, et l'audit les a rattrapés : un
 * texte qu'on ne lit pas ne fait pas gagner de place, il fait perdre la
 * phrase. Rien ici ne passe sous 0,7 rem — onze pixels et deux dixièmes.
 */
/*
 * QUAND LA VITRINE SE LIT ÉCRAN PAR ÉCRAN — DEUX CONDITIONS, PAS UNE.
 *
 * Le seuil était une hauteur seule : 660 points, et l'accrochage s'allumait.
 * Il manquait la LARGEUR, parce que c'est elle qui décide du nombre de
 * lignes. À 360 points de large, le titre passe à trois lignes, la légende
 * de Track à trois, le mot du guide à trois : soixante points de plus à
 * loger que sur un téléphone de 393, pour exactement le même texte. Track y
 * débordait encore de trente points une fois toutes les marges au minimum,
 * et le seul cran suivant aurait été de descendre les corps sous le plancher
 * de lisibilité — c'est-à-dire de rendre la page illisible pour qu'elle
 * tienne. C'est le contraire de ce qu'on cherche.
 *
 * Un téléphone ÉTROIT demande donc plus de hauteur qu'un large avant qu'on
 * lui impose une scène par écran : 700 points au lieu de 660. En dessous, il
 * retrouve le défilement ordinaire — la même réponse que pour un téléphone
 * couché, et pour la même raison : une page plus longue vaut mieux qu'une
 * page écrasée.
 */
@media (min-height: 660px) and (min-width: 371px), (min-height: 700px){
  html[data-screen="site"]{
    scroll-snap-type:y mandatory;
    scroll-padding-top:var(--nav-h);
  }
  /*
   * UNE HAUTEUR FIXE, ET UNE SCÈNE QUI PREND CE QUI RESTE.
   *
   * `min-height` ne suffisait pas : chaque scène débordait de cent à trois
   * cents pixels, et il aurait fallu régler une vingtaine de tailles à la
   * main — puis les régler de nouveau au premier mot ajouté. La section fait
   * donc EXACTEMENT la fenêtre moins la barre, et c'est le canevas qui
   * absorbe la différence : le texte prend la hauteur qu'il lui faut, la
   * scène prend le reste. Quelle que soit la fenêtre, la somme tombe juste,
   * et une phrase de plus rétrécit l'image au lieu de pousser la page.
   *
   * `overflow-y:auto` est la soupape : si les blocs de texte seuls
   * dépassaient déjà (très petite fenêtre, fonte agrandie par le système),
   * la section défile en elle-même au lieu de couper. Le défilement
   * s'enchaîne ensuite sur la page — donc sur la section suivante — ce qui
   * est exactement le geste attendu.
   */
  .site > section{
    scroll-snap-align:start;
    scroll-snap-stop:always;
    height:calc(100dvh - var(--nav-h));
    /*
     * LES DEUX AXES SONT DÉCLARÉS, ET CE N'EST PAS UNE REDONDANCE.
     *
     * `overflow-y:auto` seul ne laisse pas l'autre axe à `visible` : la règle
     * de cascade des débordements le passe à `auto` en silence. Chaque
     * section devenait donc aussi un conteneur de défilement HORIZONTAL — et
     * le jour où un voile a réclamé `100vw` (quinze pixels de plus que la
     * largeur utile, barre de défilement comprise), trois sections se sont
     * retrouvées avec une barre horizontale en bas sans que rien ne le dise.
     *
     * L'axe est donc fermé explicitement. Ce n'est pas qu'un pansement :
     * `hidden` retire la section de l'exemption « ça glisse » de l'audit
     * (tools/audit.mjs), qui contrôle de nouveau ce qui dépasse à droite.
     */
    overflow-x:hidden;
    overflow-y:auto;
    /*
     * JAMAIS `justify-content:center` SUR UNE BOÎTE QUI PEUT DÉBORDER.
     *
     * Un conteneur flex qui centre et dont le contenu dépasse le pousse des
     * DEUX CÔTÉS — et le débordement du haut devient inatteignable : il n'y
     * a pas de défilement négatif. Sur téléphone, le bandeau d'état
     * (« lecture des marchés… ») était coupé net par le bord supérieur, sans
     * aucun moyen d'aller le voir.
     *
     * Le contenu part donc du haut. Le centrage, quand il y a de la place,
     * vient de la scène qui s'étire (`flex:1 1 auto` plus bas) : elle prend
     * l'espace restant, ce qui pose le texte au milieu sans jamais rien
     * repousser hors d'atteinte.
     */
    display:flex; flex-direction:column; justify-content:flex-start;
    padding-top:16px; padding-bottom:16px;
  }
  .site > section > .wrap{
    display:flex; flex-direction:column; justify-content:flex-start;
    flex:1 1 auto; min-height:0; width:100%;
  }
  /* Les quatre scènes, et la liste des dons : ce sont elles qui cèdent. */
  /*
   * C'EST LA RANGÉE QUI CÈDE, PAS LA SCÈNE QU'ELLE CONTIENT.
   *
   * `.globe-stage` était marquée souple, mais elle vit DANS `.hero-stage-row`,
   * qui est l'enfant direct du bloc. La rangée, elle, se dimensionnait sur son
   * contenu : la planète prenait sa largeur maximale, donc autant de hauteur
   * (elle est carrée), et la section débordait de deux cent soixante pixels
   * sur un petit téléphone sans que rien ne puisse rétrécir.
   */
  .hero-globe .hero-stage-row,
  .hero-track .belt-stage,
  .hero-swap .merge-stage,
  .hero-earn .earn-stage,
  .hero-price .price-scene{ flex:1 1 auto; min-height:0; }
  /*
   * LA RANGÉE DE LA PLANÈTE A AUTANT DE PISTES QUE SES ZONES EN COMPTENT —
   * PAS UNE DE PLUS.
   *
   * `.hero-stage-row` change de forme selon la largeur : une seule ligne à
   * trois colonnes sur ordinateur (« ml globe mr »), trois lignes empilées
   * sur tablette (« ml » « mr » « globe »), deux lignes sur téléphone
   * (« ml mr » « globe globe »). Une seule déclaration de pistes servait
   * partout — deux pistes fixes — et sur ordinateur, où la grille n'a
   * pourtant qu'UNE SEULE ligne de contenu, la seconde piste restait vide et
   * absorbait la moitié de la hauteur disponible : la planète, confinée à la
   * première, rétrécissait d'autant. Chaque forme reçoit donc son propre
   * compte de pistes, toutes flexibles sur la dernière — celle qui porte la
   * planète — pour qu'elle absorbe l'espace qui reste après les chiffres.
   */
  .hero-globe .hero-stage-row{ grid-template-rows:minmax(0, 1fr); }
  /*
   * `margin-top:0`, ET C'EST LA LIGNE QUI RÉPARE LA PLANÈTE SUR TÉLÉPHONE.
   *
   * En dessous de 980 points, `.globe-stage` porte encore `margin-top:12px`
   * — posé pour l'ancien empilement, où la rangée n'avait pas de hauteur
   * fixe et cette marge n'était qu'un peu d'air entre les chiffres et la
   * planète. Ici la boîte porte aussi `height:100%` : une marge AJOUTÉE à
   * une hauteur qui vaut déjà cent pour cent de la piste la fait déborder de
   * sa propre marge, systématiquement — la planète débordait de douze
   * pixels sous la ligne de sa rangée, recouverte par la carte du guide
   * posée juste en dessous. L'air voulu vient du `gap` de la grille, déjà
   * posé à côté ; cette marge-ci ne fait plus que déborder.
   */
  .hero-globe .globe-stage{ min-height:0; height:100%; margin-top:0; }
  /*
   * LA CONSOLE DE L'ATELIER NE S'ÉTIRE PAS.
   *
   * Elle absorbait la place restante comme les autres scènes, mais elle n'est
   * pas un canevas : ses quatre lignes ne grandissent pas avec elle, et on
   * obtenait un terminal de cinq cents pixels avec trois lignes en son
   * milieu. Elle garde donc sa taille, et c'est l'espace AUTOUR qui se
   * répartit — des marges automatiques, qui valent zéro quand il n'y a rien à
   * répartir et ne poussent donc jamais rien hors d'atteinte.
   */
  .hero-ai .ait-stage{ flex:0 0 auto; margin-block:auto; min-height:0; }
  .hero-ai .ait-screen{ min-height:0; overflow:hidden; }
  /* L'`aspect-ratio` fixait la hauteur depuis la largeur : il empêchait
     précisément la scène de céder. Le canevas se remesure tout seul (voir le
     `ResizeObserver` de ui/planet.js), donc rien d'autre à prévenir. */
  .hero-track .belt-stage,
  .hero-swap .merge-stage,
  .hero-earn .earn-stage,
  .hero-price .price-scene{ aspect-ratio:auto; }
  /* La flèche est un enfant direct de la section, donc un élément flexible :
     elle se faisait comprimer à vingt-deux pixels de haut sur téléphone, en
     dessous de toute cible tactile raisonnable. Elle ne cède pas. */
  .site > section > .sd-btn{ flex:0 0 auto; min-height:44px; }
  /* LE PIED EST LA DERNIÈRE SCÈNE. Il porte « Soutenir pavapi » depuis que
     les dons y vivent sur toutes les pages (ui/donate.js) : sur la vitrine,
     il occupe donc un écran comme les autres et pose son contenu au milieu —
     des marges automatiques, qui valent zéro quand il n'y a rien à répartir.
     Il s'accroche par le BAS : là où un pied porte en plus la description
     de sa page et dépasse l'écran, c'est la fin — les dons et les mentions —
     qui tombe entière dans la fenêtre. */
  .site > footer.site-foot{
    scroll-snap-align:end; scroll-snap-stop:always;
    min-height:calc(100dvh - var(--nav-h));
    display:flex; flex-direction:column;
    padding-top:12px; padding-bottom:12px;
  }
  .site > footer.site-foot > .wrap{ margin-block:auto; width:100%; }

  /* Tout ce qui suit sert une seule chose : faire tenir chaque scène dans
     l'écran qu'on vient de lui donner. Ce sont des hauteurs, jamais des
     contenus retirés — une vitrine plus courte qui dirait moins ne serait pas
     plus courte, elle serait plus pauvre. */
  .hero-globe{ padding:20px 0; }
  /* La planète reste RONDE : c'est sa hauteur qui cède, et sa largeur suit.
     Posée en largeur, elle devenait une ellipse de 300 sur 200. */
  .globe-stage{ align-items:center; justify-content:center; }
  /* `max-width:100%` en plus de la borne en `vw` : la planète est dimensionnée
     par sa HAUTEUR (carré), et sur une fenêtre large mais courte elle devenait
     plus large que la scène qui la porte — dont le `overflow-x:clip` lui
     rognait alors dix-huit pixels sur la droite, en silence. */
  .globe-wrap{ height:100%; width:auto; aspect-ratio:1; max-width:min(52vw, 100%, 560px); }
  .hero-stage-row{ margin-top:12px; gap:20px; }
  .hero-kicker{ margin-bottom:16px; }
  h1.site-head{ margin:0 0 16px; }

  .hero-track, .hero-swap, .hero-price, .hero-earn, .hero-ai{ padding:20px 0; }
  /* Un plancher pour les scènes : sans lui, une section bavarde réduisait la
     ceinture à une bande de cent pixels — la scène cesse alors d'être une
     scène. En dessous de ce plancher, c'est la soupape de la section qui
     prend le relais. La planète ne le porte pas : carrée, un plancher en
     hauteur la ferait grandir en largeur au même rythme — donc en surface au
     carré — et la moindre valeur généreuse la fait vite pousser plus loin
     que la place vraiment laissée par le texte, jusqu'à recouvrir ce qui
     suit ou forcer la section à défiler en elle-même. Elle garde donc son
     seul mécanisme, plus sûr : la rangée qui cède (ci-dessus), pas un
     minimum qui pourrait déborder. */
  .hero-track .belt-stage,
  .hero-swap .merge-stage,
  .hero-earn .earn-stage,
  .hero-price .price-scene{ min-height:min(24svh, 240px); }

  /*
   * LA PLANÈTE, ELLE, GAGNE DE LA PLACE PLUTÔT QU'UN PLANCHER.
   *
   * Carrée, un plancher en hauteur la fait grandir en surface au carré (voir
   * la note ci-dessus) : trop risqué pour un simple filet de sécurité. Ce
   * qu'elle reçoit à la place, c'est un peu de l'air que le texte au-dessus
   * et le guide en dessous lui cédaient sans le savoir — le même geste que
   * les paliers plus bas (860, 790 points de haut), juste un cran plus tôt
   * et rien que sur cette scène : les mille points de haut, c'est un
   * portable ordinaire, pas encore un écran « court », et les quatre autres
   * scènes n'ont pas besoin de cet air-là pour tenir. La planète, elle, en
   * profite d'autant : chaque pixel rendu au canevas double sa surface, il
   * n'en va pas de même pour une bande pleine largeur.
   */
  @media (min-width: 721px) and (max-height: 1000px){
    .hero-globe .hero-copy{ margin-bottom:0; }
    .hero-globe .hero-sub{ margin-bottom:10px !important; }
    .hero-globe .sec-guide{ margin-top:10px; padding:10px 13px; }
  }

  /*
   * LES ÉCRANS D'ORDINATEUR COURTS — un portable de 800 points de haut n'en
   * laisse que 723 sous la barre, moins qu'un téléphone récent. Le plancher
   * des scènes et l'air autour du texte y cèdent d'un cran, sans quoi
   * l'échange et Track débordaient d'une cinquantaine de pixels.
   */
  @media (min-width: 721px) and (max-height: 860px){
    .hero-copy{ margin-bottom:0; }
    .hero-sub{ font-size:.88rem; margin-bottom:10px !important; }
    /* `.site-head` et non `h1.site-head` : la vitrine n'a qu'un `h1`, et les
       quatre autres titres sont des `h2` qui n'avaient jamais rien reçu de
       ces paliers — ils gardaient la marge de `h2`. Voir la note détaillée au
       palier téléphone, plus bas. */
    .site-head{ margin-bottom:12px; }
    .hero-kicker{ margin-bottom:12px; }
    .sec-guide{ margin-top:12px; padding:9px 12px; }
    .guide-say{ font-size:.8rem; line-height:1.5; margin:0 0 7px; }
    .hero-swap .swap-teaser{ margin-top:12px; }
    .hero-swap .st-card{ padding:9px 12px; }
    .hero-track .track-metrics{ margin-top:12px; }
    .hero-track .belt-stage,
    .hero-swap .merge-stage,
    .hero-earn .earn-stage,
    .hero-price .price-scene{ min-height:min(20svh, 190px); }
  }

  /* Et un cran de plus sous 790 points : un portable en 1366×768 — encore la
     définition la plus répandue — ne laisse que six cent quatre-vingt-onze
     pixels sous la barre. Le palier a d'abord été posé à 760, et 768 passait
     juste au-dessus : il débordait de deux pixels, ce qui suffit à rendre une
     section défilable et à faire hésiter l'accrochage. */
  @media (min-width: 721px) and (max-height: 790px){
    .site > section{ padding-top:10px; padding-bottom:10px; }
    h1.site-head{ font-size:clamp(1.35rem, 2.6vw, 1.95rem); }
    /* Le corps des quatre `h2` se règle à la même spécificité que la règle
       qui le pose (deux classes), sinon elle l'emporterait. */
    .hero-track .site-head, .hero-swap .site-head,
    .hero-price .site-head, .hero-ai .site-head{ font-size:clamp(1.3rem, 2.5vw, 1.85rem); }
    .site-head{ margin-bottom:9px; }
    .hero-sub{ font-size:.84rem; margin-bottom:8px !important; }
    .hero-kicker{ margin-bottom:9px; padding:5px 12px; }
    .btn-lg{ padding:9px 18px; font-size:.88rem; }
    .sec-guide{ margin-top:9px; padding:8px 11px; }
    .guide-say{ font-size:.77rem; margin:0 0 5px; }
    .guide-pet{ width:48px; height:48px; }
    .hero-swap .st-card{ padding:8px 10px; }
    .hero-swap .st-card > span:last-child{ font-size:.75rem; line-height:1.35; }
    .hero-swap .st-lbl{ font-size:.7rem; }
    .hero-swap .st-card b{ font-size:1rem; }
    .hero-swap .swap-teaser{ margin-top:9px; gap:10px; }
    .hero-globe .hero-stage-row{ gap:14px; margin-top:8px; }
    .hero-metric .cell{ padding:11px 16px; }
    .hero-track .belt-stage,
    .hero-swap .merge-stage,
    .hero-earn .earn-stage,
    .hero-price .price-scene{ min-height:min(17svh, 150px); }
    /* Track porte un bloc de plus que les autres — deux chiffres ET une
       légende — et c'est elle qui débordait encore d'une dizaine de points
       sur une fenêtre de 720. Sa légende gardait vingt-six points d'air
       au-dessus d'elle, hérités de la mise en page longue. */
    .hero-track .track-metrics{ margin-top:10px; }
    .hero-track .track-legend{ margin-top:10px; }

  }
  .guide-say{ min-height:0; }
  .hero-track .track-legend{ font-size:.72rem; }

  /* Le texte de tête : mêmes mots, moins d'air. C'est là que se gagnent les
     cent premiers pixels, et c'est le seul endroit où on peut les prendre
     sans rien retirer. */
  h1.site-head{ font-size:clamp(1.5rem, 3.1vw, 2.35rem); }
  .hero-track .site-head, .hero-swap .site-head,
  .hero-price .site-head, .hero-ai .site-head{ font-size:clamp(1.4rem, 2.9vw, 2.1rem); }
  .hero-sub{ font-size:.9rem; margin-bottom:12px !important; }
  .hero-copy p{ line-height:1.55; }
  .btn-lg{ padding:11px 22px; font-size:.92rem; }
  .site-cta{ gap:10px; }

  /* Le guide et sa bête : il doit rester lisible, pas occuper un cinquième
     de la scène. */
  .sec-guide{ margin-top:14px; padding:10px 12px; gap:10px; }
  .guide-pet{ width:56px; height:56px; }
  .guide-ask{ gap:6px; }
  .sec-guide p{ font-size:.82rem; line-height:1.5; }

  /* Les blocs propres à une scène. */
  .hero-metric .cell{ padding:16px 22px; }
  .hero-track .track-metrics{ gap:10px; }
  .hero-swap .swap-teaser{ margin-top:16px; gap:10px; }
  .hero-swap .st-card{ padding:11px 13px; gap:3px; }
  .hero-swap .st-card b{ font-size:1rem; }
  .hero-swap .st-card > span:last-child{ font-size:.78rem; line-height:1.45; }
  .hero-track .track-metrics .cell{ padding:10px 14px; }

  /* ---------------- la tablette ----------------
     Entre 721 et 980 points, `.hero-stage-row` empile trois zones en une
     seule colonne (« ml » « mr » « globe », posées par la règle générale de
     ce fichier) : les deux chiffres l'un sous l'autre, puis la planète. Les
     chiffres gardent leur taille de contenu, la dernière piste — la
     planète — prend ce qui reste, comme sur téléphone juste en dessous et
     comme sur ordinateur juste au-dessus, chacun avec son propre compte de
     pistes. */
  @media (max-width: 980px){
    .hero-globe .hero-stage-row{ grid-template-rows:auto auto minmax(0, 1fr); }
  }

  /* ---------------- le téléphone ----------------
     La fenêtre y est deux fois plus courte et tout se met en colonne : ce qui
     coûtait trente pixels sur un écran large en coûte cent ici. Le guide, ses
     questions et les cartes de don sont les trois blocs qui décident si une
     scène tient. */
  @media (max-width: 720px){
    /*
     * LA FLÈCHE DISPARAÎT SUR TÉLÉPHONE.
     *
     * Elle et sa marge prenaient près de quatre-vingts pixels — sur un écran
     * où il en manquait cent, c'était le premier poste à couper. Et elle ne
     * servait plus : écrasée en bas de section, elle chevauchait le guide.
     * Ce qu'elle disait (« il y a quelque chose en dessous »), l'accrochage
     * le dit tout seul au premier geste, et le doigt n'a jamais eu besoin
     * d'un bouton pour faire défiler. Elle reste sur les écrans larges, où
     * la place ne manque pas et où la souris, elle, apprécie le raccourci.
     */
    .site > section > .sd-btn{ display:none; }

    /*
     * LES DEUX CHIFFRES CÔTE À CÔTE.
     *
     * Empilés, ils faisaient deux cents pixels à eux seuls — la moitié de ce
     * qui manquait à la première scène. Côte à côte, quatre-vingt-dix. La
     * règle générale les empile en dessous de 980 points parce qu'à moitié
     * d'écran chacun, un chiffre passait à la ligne ; avec la typographie
     * réduite ci-dessous, il tient.
     */
    .hero-stage-row{
      grid-template-columns:1fr 1fr;
      grid-template-areas:"ml mr" "globe globe";
      gap:8px;
    }
    /* Deux lignes ici (les chiffres côte à côte, puis la planète) : la
       piste des chiffres garde sa taille de contenu, celle de la planète
       prend ce qui reste. Voir la note plus haut, à la déclaration générale
       qu'elle remplace à cette largeur. */
    .hero-globe .hero-stage-row{ grid-template-rows:auto minmax(0, 1fr); }
    /* Même hauteur pour les deux : l'un tient sur deux lignes, l'autre sur
       trois, et deux cadres inégaux côte à côte se lisent comme un défaut. */
    .hero-stage-row{ align-items:stretch; }
    .hero-metric{ justify-content:stretch; align-items:stretch; }
    .hero-metric .cell{ width:100%; height:100%; padding:8px 10px;
      display:flex; flex-direction:column; justify-content:center; }
    .hero-track .track-metrics .cell{ display:flex; flex-direction:column; justify-content:center; }
    .hero-metric .n{ font-size:1rem; white-space:normal; }
    .hero-metric .k{ font-size:.7rem; line-height:1.35; }

    /* Les trois cartes de l'échange, et la légende de Track : mêmes mots,
       moins d'interligne et moins de marges. */
    .hero-swap .st-card{ padding:7px 10px; gap:1px; }
    .hero-swap .st-card b{ font-size:.9rem; }
    .hero-swap .st-card > span:last-child{ font-size:.71rem; line-height:1.35; }
    .hero-swap .st-lbl{ font-size:.7rem; }
    .hero-track .track-metrics{ gap:7px; }
    .hero-track .track-metrics .cell{ padding:7px 10px; }
    .hero-track .track-legend{ font-size:.7rem; line-height:1.3; gap:4px; margin-top:6px; }
    .hero-track .sec-guide{ margin-top:8px; }
    .hero-ai .ait-note{ font-size:.74rem; line-height:1.45; }

    /*
     * LES TROIS CARTES DE L'ÉCHANGE EN UNE RANGÉE QUI GLISSE.
     *
     * Empilées, elles faisaient deux cent soixante-six pixels — le tiers d'un
     * écran de téléphone pour trois encarts. En rangée, on en voit une et
     * demie et on fait glisser pour les autres : la hauteur ne dépend plus du
     * NOMBRE de cartes, et aucun mot n'est retiré. C'est le geste déjà appris
     * juste en dessous, sur les questions des guides.
     */
    .hero-swap .swap-teaser{
      display:flex; flex-wrap:nowrap; gap:8px;
      /* `overflow-x:auto` seul rend l'axe Y « auto » par défaut : la rangée
         devenait défilable de douze pixels en hauteur, donc un conteneur
         vertical de plus à disputer au doigt. On le ferme explicitement. */
      overflow-x:auto; overflow-y:hidden;
      scrollbar-width:none; -webkit-overflow-scrolling:touch;
      scroll-snap-type:x proximity;
    }
    .hero-swap .swap-teaser::-webkit-scrollbar{ display:none; }
    .hero-swap .st-card{ flex:0 0 82%; scroll-snap-align:start; }

    /* Les deux chiffres de Track, côte à côte eux aussi. */
    /* Track porte un bloc de plus que les autres (deux chiffres ET une
       légende) : c'est la seule scène qui demande encore un cran de moins. */
    .hero-track .hero-copy{ margin-bottom:0; }
    .hero-track .hero-sub{ font-size:.8rem; margin-bottom:9px !important; }
    .hero-track .track-metrics{ grid-template-columns:1fr 1fr; gap:6px; margin-top:9px; }
    .hero-track .track-metrics .cell{ padding:8px 10px; }
    .hero-track .track-metrics .n{ font-size:1rem; white-space:normal; }
    .hero-track .track-metrics .k{ font-size:.7rem; line-height:1.35; }

    /* La console de l'atelier : la même, en plus courte. */
    .hero-ai .ait-stage{ margin-top:14px; gap:10px; }
    .hero-ai .ait-rat{ width:74px; min-height:64px; }
    .hero-ai .ait-screen{ padding:10px 12px; font-size:.7rem; line-height:1.55; }

    .sec-guide{ gap:10px; padding:10px 11px; margin-top:12px; }
    .guide-pet{ flex-basis:48px; width:48px; height:48px; }
    .guide-say{ font-size:.78rem; line-height:1.45; margin:0 0 7px; min-height:0; }
    /* Les questions en UNE rangée qui glisse, plutôt qu'en trois lignes qui
       empilent : on en voit deux, on fait glisser pour les autres, et la
       hauteur ne dépend plus du nombre de questions. */
    .guide-qs{
      flex-wrap:nowrap; overflow-x:auto; padding-bottom:2px;
      scrollbar-width:none; -webkit-overflow-scrolling:touch;
    }
    .guide-qs::-webkit-scrollbar{ display:none; }
    .guide-q{ flex:0 0 auto; padding:5px 9px; font-size:.72rem; }

    h1.site-head{ font-size:clamp(1.35rem, 6.4vw, 1.9rem); margin-bottom:12px; }
    .hero-sub{ font-size:.84rem; }
    .hero-kicker{ margin-bottom:12px; padding:5px 11px; font-size:.7rem; }
    .hero-metric .cell{ padding:11px 14px; }
    .hero-stage-row{ gap:10px; margin-top:8px; }
    .globe-wrap{ max-width:min(86vw, 420px); }
    .hero-track .belt-stage,
    .hero-swap .merge-stage,
    .hero-earn .earn-stage,
    .hero-price .price-scene{ min-height:min(24svh, 190px); }
    .hero-swap .swap-teaser{ margin-top:12px; gap:8px; }
    .hero-swap .st-card{ padding:9px 11px; }
    /*
     * LA LISTE DES DONS NE DÉFILE PLUS DANS ELLE-MÊME.
     *
     * Elle était un second conteneur de défilement à l'intérieur d'une
     * section qui défile déjà : au doigt, un glissement vertical était capté
     * par la liste, et la page ne bougeait pas. Les cartes tiennent
     * maintenant dans l'écran — les deux boutons passent côte à côte, ce qui
     * rend à chaque carte les soixante-dix pixels qu'ils prenaient empilés.
     */
  }

  /* Les téléphones les plus étroits : à 360 points de large, deux scènes
     dépassaient encore de quelques dizaines de pixels — la soupape les
     rendait défilables, ce qui marche mais se sent. Quelques points de moins
     sur les blocs de texte, et elles tombent juste elles aussi. */
  @media (max-width: 400px){
    .hero-sub{ font-size:.8rem; }
    .hero-copy p{ line-height:1.45; }
    .sec-guide{ padding:9px 10px; margin-top:10px; }
    .guide-say{ font-size:.75rem; }
    .hero-swap .st-card{ padding:8px 10px; }
    .hero-swap .st-card b{ font-size:.92rem; }
    .hero-swap .st-card > span:last-child{ font-size:.73rem; }
    .btn-lg{ padding:10px 18px; font-size:.87rem; }
    .hero-kicker{ margin-bottom:9px; }
    h1.site-head{ margin-bottom:9px; }
    .hero-stage-row{ margin-top:4px; gap:8px; }
    .hero-metric .cell{ padding:9px 12px; }
    .hero-swap .swap-teaser{ margin-top:9px; gap:6px; }
    .guide-say{ margin:0 0 5px; }
    /* Le plancher des scènes cède aussi : sur 360 points de large, il entrait
       en concurrence avec le texte, et c'est le texte qui doit gagner. */
    .hero-track .belt-stage,
    .hero-swap .merge-stage,
    .hero-earn .earn-stage,
    .hero-price .price-scene{ min-height:min(15svh, 112px); }
  }

  /* ---------------- LE TÉLÉPHONE RÉEL, BARRES COMPRISES ----------------
   *
   * C'est le palier qui manquait, et il manquait parce qu'on ne mesurait pas
   * le bon écran. Un iPhone de 393 × 852 points ne donne pas 852 points à la
   * page : la barre d'état en haut, la barre d'adresse et sa barre d'outils
   * en bas en prennent près de deux cents. Il reste SIX CENT SOIXANTE-TREIZE
   * points — moins que le plus petit format que la vérification d'interface
   * regardait. Au-dessus de 660, l'accrochage est actif : chaque scène doit
   * donc tenir dans cinq cent quatre-vingt-dix-sept points, barre du site
   * déduite. Track en réclamait six cent quarante-cinq.
   *
   * L'AUTRE MOITIÉ DE L'ÉCART VENAIT DES FONTES. Les mesures se faisaient
   * sans réseau, donc sans les fontes du site : les replis système sont plus
   * étroits, et le bandeau d'état tenait sur une ligne en essai quand il en
   * prend deux chez le visiteur — « Suivi des adresses et transparence » en
   * IBM Plex Mono déborde de la largeur d'un téléphone. Vingt-deux points de
   * plus par section, invisibles à la mesure.
   *
   * Rien n'est retiré ici, et aucun texte ne passe sous 0,7 rem (le plancher
   * de lisibilité, voir plus haut) : ce sont des marges, des emplissages et
   * des interlignes. Ce qu'ils rendent, les scènes le prennent.
   */
  @media (max-width: 720px) and (max-height: 780px){
    /* Le chapeau : la marque de l'écran, le bandeau d'état, le titre et le
       bouton. C'est là que se trouve le plus gros de l'air disponible. */
    .sec-mark{ width:26px; height:26px; margin-bottom:6px; }
    .sec-mark svg{ width:15px; height:15px; }
    /* Le titre d'un cran : il tient toujours sur deux lignes, en plus
       serrées. C'est le plus gros bloc de texte de la section. */
    .site-head{ font-size:clamp(1.22rem, 5.4vw, 1.6rem); line-height:1.2; }
    /* Le bandeau passe à deux lignes chez le visiteur : on ne l'en empêche
       pas — couper la phrase serait pire — on resserre ce qui l'entoure. */
    .hero-kicker{ padding:4px 9px; line-height:1.35; margin-bottom:8px; gap:7px; }
    /*
     * `.site-head`, ET NON `h1.site-head` — LE DÉFAUT QUI SE CACHAIT LÀ.
     *
     * Tous les resserrements de ce fichier visent `h1.site-head`. Or la
     * vitrine n'a qu'un seul `h1`, celui de la première scène : les quatre
     * autres titres sont des `h2` et n'ont jamais rien reçu. Ils gardaient la
     * marge de `h2` — douze points — pendant que le titre de la planète
     * descendait à huit. Quatre points par section, sur les sections qui
     * justement débordaient. On vise donc la classe, qui porte les cinq.
     */
    .site-head{ margin-bottom:8px; }
    .btn-lg{ padding:9px 16px; }    /* reste au-dessus du seuil tactile de 36 points */

    /* Les scènes reprennent l'air qu'on vient de libérer : leurs marges
       d'approche valaient jusqu'à trente points pour un simple espace. */
    .hero-globe .hero-stage-row{ margin-top:6px; }
    .hero-track .belt-stage{ margin-top:10px; }
    .hero-swap .merge-stage, .hero-earn .earn-stage{ margin-top:10px; }
    .hero-ai .ait-stage{ margin-top:10px; }
    .hero-ai .ait-note{ margin-top:10px; line-height:1.4; }

    /* La légende de Track tient sur deux lignes : c'est l'interligne, pas le
       corps, qui la faisait haute. */
    .hero-track .track-legend{ line-height:1.25; gap:3px; margin-top:5px; }

    /* Le guide : même texte, même bête, moins de cadre autour. */
    .sec-guide{ padding:8px 10px; margin-top:8px; gap:8px; }
    .guide-pet{ flex-basis:40px; width:40px; height:40px; }
    .guide-say{ line-height:1.4; margin:0 0 5px; }
    .guide-qs{ gap:5px; }

    /* Et les scènes gagnent un plancher un peu plus haut que celui des
       téléphones étroits : l'air rendu ci-dessus leur revient. Au-dessus de
       400 points de large SEULEMENT — en dessous, le palier étroit garde le
       sien, plus bas, parce que là c'est le texte qui manque de place et
       c'est lui qui doit gagner (voir le palier `max-width:400px`). */
    @media (min-width: 401px){
      .hero-track .belt-stage,
      .hero-swap .merge-stage,
      .hero-earn .earn-stage,
      .hero-price .price-scene{ min-height:min(19svh, 132px); }
    }

    /*
     * LE TÉLÉPHONE ÉTROIT ET COURT — deux contraintes à la fois.
     *
     * À 360 points de large, tout ce qui est une phrase prend une ligne de
     * plus : le titre passe à trois lignes, la légende de Track à trois, le
     * mot du guide à trois. Soixante points de plus à trouver, et les trouver
     * dans les marges ne suffit plus — elles sont déjà au minimum. Ce sont
     * donc les corps et les interlignes qui cèdent d'un cran ici, jamais
     * sous 0,7 rem.
     */
    @media (max-width: 400px){
      .site-head{ font-size:clamp(1.25rem, 5.6vw, 1.7rem); }
      .guide-say{ line-height:1.35; }
      .hero-track .track-legend{ line-height:1.2; gap:3px; }
      /* La console de l'atelier : quatre lignes, moins d'air entre elles. */
      .hero-ai .ait-rat{ width:64px; min-height:56px; }
      .hero-ai .ait-screen{ padding:8px 10px; line-height:1.45; gap:5px; }
    }

    /*
     * TRACK PORTE UN BLOC DE PLUS QUE LES AUTRES, ET C'EST TOUJOURS ELLE QUI
     * DÉBORDE EN DERNIER.
     *
     * Les quatre autres scènes ont un titre, une image et un guide. Track a
     * en plus DEUX chiffres et une légende de six entrées — cent quarante
     * points que personne d'autre ne paie. Elle reçoit donc le même geste
     * qu'ailleurs dans ce fichier : un cran de plus, rien qu'elle, et sur ses
     * blocs à elle plutôt que sur le texte commun.
     */
    .hero-track .track-metrics{ margin-top:6px; }
    .hero-track .track-metrics .cell{ padding:6px 9px; }
    .hero-track .track-metrics .n{ line-height:1.2; }
    .hero-track .sec-guide{ margin-top:6px; }
    /* Sa ceinture cède un peu plus que les trois autres scènes : une bande
       pleine largeur reste lisible là où un carré ne le serait plus. */
    .hero-track .belt-stage{ min-height:min(15svh, 106px); }
  }

  /* ================================================================== *
   *  LA SCÈNE NE RÉTRÉCIT PLUS — ELLE A UNE TAILLE, ET C'EST LA MÊME
   * ================================================================== *
   *
   * Jusqu'ici, sur téléphone, la scène était le SEUL bloc souple de la
   * section : tout ce que le texte réclamait, elle le cédait. Deux effets,
   * tous deux visibles et tous deux faux.
   *
   *   — ELLE RÉTRÉCISSAIT TOUTE SEULE. Le mot du guide fait deux lignes tant
   *     qu'on ne lui demande rien et cinq dès qu'on touche une question :
   *     quarante points de plus, pris à la planète, sous les yeux de celui
   *     qui vient de toucher. Une image qui change de taille parce qu'on a
   *     lu une phrase à côté n'a pas l'air vivante, elle a l'air cassée.
   *   — ELLE N'AVAIT PAS LA MÊME TAILLE D'UNE SECTION À L'AUTRE. Track porte
   *     deux chiffres et une légende, l'échange trois cartes, les cours rien
   *     du tout : la place restante allait de cent à trois cents points, si
   *     bien que la ceinture était un ruban là où le ciel des cours était
   *     une fresque. Quatre scènes d'un même site doivent se présenter
   *     pareil.
   *
   * La scène reçoit donc une HAUTEUR, `--scene-h`, la même pour les quatre,
   * et cesse d'être souple. Ce qui varie, c'est le texte autour : c'est lui
   * qui se resserre (les paliers ci-dessus), et c'est le guide qui RÉSERVE
   * d'avance la place de sa plus longue réponse plutôt que de la prendre à
   * l'image au moment où on la lui demande.
   *
   * `svh` et non `dvh` pour cette hauteur-ci : elle doit être stable pendant
   * qu'on lit. Les barres du navigateur qui se rétractent changent `dvh` —
   * et on retomberait sur une scène qui change de taille toute seule, ce
   * qu'on vient justement de corriger. La section, elle, garde `dvh` : c'est
   * elle qui doit coller à l'écran.
   */
  @media (max-width: 720px){
    .site > section{ --scene-h:clamp(118px, 21svh, 186px); }

    .hero-track .belt-stage,
    .hero-swap .merge-stage,
    .hero-earn .earn-stage,
    .hero-price .price-scene{
      flex:0 0 auto; height:var(--scene-h); min-height:var(--scene-h);
    }
    /* SAUF LES COURS, QUI EN PORTENT DEUX, EMPILÉS. Une demi-scène chacun
       aurait donné deux bandeaux de soixante points où plus aucune altitude
       ne se lit. La section des cours est aussi celle qui porte le moins de
       texte (voir plus haut) : c'est elle qui a la place de les recevoir. */
    .hero-price .price-scene{
      height:calc(var(--scene-h) * 1.7); min-height:calc(var(--scene-h) * 1.7);
    }
    /* La planète vit dans une grille : c'est sa PISTE qui prend la hauteur,
       et la boîte carrée la remplit déjà (`height:100%`). */
    .hero-globe .hero-stage-row{
      flex:0 0 auto; grid-template-rows:auto var(--scene-h);
    }
    /*
     * ET PLUS RIEN D'AUTRE NE SE FAIT ÉCRASER À SA PLACE.
     *
     * Une scène fixe, c'est un bloc souple de moins : le premier voisin
     * capable de céder prend tout ce que la scène ne cède plus. Les trois
     * cartes de l'échange, qui sont une rangée qui glisse (donc de taille
     * minimale nulle), sont tombées à quatre points de haut — un liseré.
     * Elles gardent leur taille ; si la place manque vraiment, c'est la
     * soupape de la section qui prend le relais, comme partout ailleurs.
     */
    .hero-swap .swap-teaser,
    .hero-track .track-metrics,
    .hero-track .track-legend,
    .hero-ai .ait-note,
    .sec-guide{ flex:0 0 auto; }

    /*
     * LE GUIDE RÉSERVE L'ESSENTIEL DE SA PLUS LONGUE RÉPONSE.
     *
     * Les salutations font soixante-dix signes, les réponses de cent
     * cinquante à deux cent vingt-cinq : deux lignes contre cinq. Sans
     * réserve, la carte grandissait de trois lignes au premier contact.
     *
     * Elle en réserve quatre, pas cinq. Réserver le pire cas coûtait
     * cinquante points sur CHAQUE section, y compris sur celles où personne
     * ne touchera jamais une question — plus que tout ce qu'on a gagné en
     * resserrant le reste. Quatre lignes couvrent la grande majorité des
     * réponses ; la plus longue en ajoute une, et comme la scène ne cède
     * plus rien (ci-dessus), cette ligne-là ne se prend plus sur l'image :
     * elle fait défiler la section d'une ligne, et c'est tout.
     */
    .guide-say{ font-size:.73rem; line-height:1.4; min-height:5.2em; margin:0 0 6px; }
    .guide-q{ padding:4px 9px; }

    /*
     * LA LÉGENDE DE TRACK EN UNE RANGÉE QUI GLISSE.
     *
     * Six entrées, trois lignes, cinquante-huit points — sur la section qui
     * porte déjà un bloc de plus que les autres. En rangée, on en voit trois
     * et on fait glisser pour les autres : même contenu, une ligne, et le
     * geste est celui qu'on vient d'apprendre juste au-dessus sur les
     * questions du guide.
     */
    .hero-track .track-legend{
      display:flex; flex-wrap:nowrap; overflow-x:auto; overflow-y:hidden;
      scrollbar-width:none; -webkit-overflow-scrolling:touch;
      gap:10px; margin-top:6px;
      /*
       * ET LA RANGÉE EST TENUE PAR SA BOÎTE, PAS PAR SON CONTENU.
       *
       * La règle générale la centre avec `margin:26px auto 0`. Des marges
       * automatiques sur l'axe transverse d'un conteneur flex ANNULENT
       * l'étirement : la boîte reprend la taille de son contenu. Tant que la
       * légende revenait à la ligne, cela ne se voyait pas ; en rangée d'un
       * seul tenant, elle réclamait ses cinq cent quatre-vingt-sept points
       * de large, et `overflow-x:auto` n'avait plus rien à découper — c'est
       * la SECTION qui cachait le débordement, en silence. La vérification
       * d'interface l'a vu sur les cinq largeurs de téléphone.
       */
      width:100%; max-width:100%; margin-inline:0;
      /* `flex-start`, ET SURTOUT PAS LE `center` DE LA RÈGLE GÉNÉRALE.
         C'est le piège déjà rencontré sur la rangée des dons, quelques
         lignes plus bas : centrée, une rangée plus large que sa fenêtre
         pousse ses premières entrées en abscisse NÉGATIVE, où aucun
         glissement ne va les chercher. « Baleines 127 » commençait à moins
         quatre-vingt-dix, et la légende s'ouvrait sur « 27 ». */
      justify-content:flex-start;
    }
    .hero-track .track-legend::-webkit-scrollbar{ display:none; }
    .hero-track .track-legend > *{ flex:0 0 auto; white-space:nowrap; }
  }
}

/* Sous cette hauteur (téléphone couché, très petite fenêtre), on revient au
   défilement ordinaire : mieux vaut une page longue qu'une scène dont on ne
   voit que le milieu. */
/*
 * SOUS 620 POINTS DE HAUT, ON REVIENT AU DÉFILEMENT ORDINAIRE.
 *
 * Le seuil a d'abord été posé à 560, puis 620 : à chaque fois une hauteur
 * réelle passait juste au-dessus et se faisait écraser — 568 (un vieil
 * iPhone), puis 640. Sous 660 points, il reste moins de six cents pixels
 * utiles sous la barre : un titre, une scène et un guide n'y tiennent pas, et
 * les faire entrer de force revenait à tout écraser. Une page plus longue y
 * est meilleure qu'une page illisible. Même raison sur un téléphone couché.
 */
@media (max-height: 659px), (max-width: 370px) and (max-height: 699px){
  html[data-screen="site"]{ scroll-snap-type:none; }
}

/* ==================================================================== *
 *  L'ARRIVÉE D'UNE SECTION
 * ==================================================================== *
 *
 * L'accrochage dépose la section suivante pile sous la barre, mais elle
 * arrivait TOUTE FAITE : on changeait d'écran comme on change de page, d'un
 * coup sec. Ses blocs se posent maintenant en fondu, décalés de quelques
 * dizaines de millisecondes les uns des autres — le temps que le défilement
 * finisse sa course, et jamais plus.
 *
 * Ce que ces règles ne font PAS : elles ne retiennent pas le défilement, ne
 * remplacent pas l'accrochage, et ne s'appliquent que si `ui/sectionplay.js`
 * a posé `sec-play` sur `html`. Sans script, ou en mouvement réduit, la page
 * est exactement celle d'avant — rien n'est masqué par une règle que personne
 * ne viendrait lever.
 *
 * VERS LE BAS, et pas vers le haut comme le reste du site (`.rv`) : les
 * sections portent une soupape `overflow-y:auto`, et un contenu décalé vers
 * le bas rallonge leur débordement défilable d'autant. Chaque section serait
 * devenue défilable de treize pixels — une section qui ne tient plus dans son
 * écran. Un décalage vers le haut ne rallonge rien.
 */
html.sec-play .site > section > .wrap > *,
html.sec-play .site > section > .sd-btn{
  /* Une entrée COURTE et douce : un léger recul d'échelle plutôt qu'un
     glissement, qui se lit comme une caméra qui fait le point sur l'écran
     suivant. La courbe décélère fort — l'essentiel du mouvement se fait
     dans le premier tiers, pendant que l'accrochage finit sa course. */
  opacity:0; transform:translate3d(0,-18px,0) scale(.94);
  transition:opacity .55s cubic-bezier(.2,.7,.2,1) var(--sp-d,0ms),
             transform .7s cubic-bezier(.16,1,.3,1) var(--sp-d,0ms);
}
html.sec-play .site > section.sec-on > .wrap > *,
html.sec-play .site > section.sec-on > .sd-btn{
  opacity:1; transform:none;
}
/* Le filet de la feuille de style : même si le module restait en place, un
   réglage de mouvement réduit rend tout visible et immobile sur-le-champ. */
@media (prefers-reduced-motion: reduce){
  html.sec-play .site > section > .wrap > *,
  html.sec-play .site > section > .sd-btn{
    opacity:1; transform:none; transition:none;
  }
}

/* ==================================================================== *
 *  LA PLANÈTE D'APY, PLUS GRANDE SUR TÉLÉPHONE — SANS DÉBORDER
 * ==================================================================== *
 *
 * La hauteur commune des scènes (`--scene-h`) est calée sur un ruban — la
 * ceinture de Track, le passage de l'échange. Une sphère ne se lit pas dans
 * un ruban : la planète d'Apy tenait de la vignette.
 *
 * Une hauteur fixe plus grande l'a agrandie, mais elle faisait DÉBORDER la
 * section de quatre-vingts points sur un vrai téléphone : l'écran d'accueil
 * défilait en lui-même, et chez certains la planète sortait du premier
 * écran. Elle prend donc désormais TOUT ce qui reste — ni plus (la section
 * ne déborde plus), ni moins (elle est aussi grande que l'écran le permet) —
 * avec un plancher de cent quarante points. Les deux chiffres se font petits
 * pour lui laisser la place.
 */
@media (max-width: 720px){
  .hero-globe .hero-stage-row{
    flex:1 1 auto; min-height:0;
    grid-template-rows:auto minmax(140px, 1fr);
    gap:6px; margin-top:4px;
  }
  /* La planète prend le PLUS PETIT des deux côtés de sa piste : sa hauteur
     sur un téléphone long, sa largeur sur un large — carrée dans tous les
     cas, et jamais plus large que l'écran. */
  /* `justify-self:stretch` : `container-type:size` retire au cadre toute
     taille propre, et la grille, qui centre ses enfants, le réduisait à zéro
     de large — la planète disparaissait. */
  .hero-globe .globe-stage{ height:100%; min-height:0; margin-top:0; container-type:size;
    justify-self:stretch; width:100%; }
  .hero-globe .globe-wrap{ width:min(100cqw, 100cqh); height:auto; aspect-ratio:1; max-width:none; }
  /* Le canevas prend la taille de son cadre (ui/stage.js) : dans le flux, il
     l'allongeait à son tour, et le cadre cessait d'être carré. */
  .hero-globe .globe-wrap > canvas{ position:absolute; inset:0; }
  .hero-globe .hero-metric .cell{ padding:4px 8px; box-shadow:3px 3px 0 rgba(0,0,0,.34); }
  .hero-globe .hero-metric .n{ font-size:.84rem; line-height:1.15; }
  .hero-globe .hero-metric .l{ font-size:.7rem; margin-top:1px; line-height:1.2; }
  .hero-globe .sec-mark{ display:none; }
  .hero-globe .hero-kicker{ margin-bottom:6px; }
}

/* ---------- les repères de section (voir ui/sectionplay.js) ---------- */
.sec-dots{
  position:fixed; right:7px; top:50%; transform:translateY(-50%); z-index:30;
  display:flex; flex-direction:column; gap:6px; padding:6px 3px;
}
.sec-dots button{
  /* La cible fait 36 points de côté ; le repère dessiné, lui, reste petit. */
  width:36px; height:36px; padding:0; border:0; background:none; cursor:pointer;
  display:flex; align-items:center; justify-content:center;
}
.sec-dots{ gap:0; padding:0; right:0; }
.sec-dots button::before{
  content:''; width:6px; height:6px; background:var(--paper-faint); opacity:.45;
  transition:height .28s cubic-bezier(.2,.7,.2,1), background .28s, opacity .28s;
}
.sec-dots button.is-on::before{ height:16px; opacity:1; background:var(--dot, var(--gold)); box-shadow:0 0 8px var(--dot, var(--gold)); }
.sec-dots button:focus-visible{ outline:2px solid var(--paper); outline-offset:-4px; }
/* Sur téléphone aussi : sans eux, rien ne disait sur quel écran on se
   trouve. Une colonne plus étroite (28 points, le plancher tactile en
   largeur) pour mordre le moins possible sur le contenu. */
@media (max-width: 720px){
  .sec-dots button{ width:28px; }
  .sec-dots button::before{ width:5px; height:5px; }
  .sec-dots button.is-on::before{ height:14px; }
}
@media (prefers-reduced-motion: reduce){ .sec-dots button::before{ transition:none; } }

/* Sous 680 points de haut, l'échange débordait encore de quelques points :
   ses deux marges d'approche cèdent ce qu'il manquait. */
@media (max-width: 720px) and (max-height: 680px){
  .hero-swap .merge-stage, .hero-earn .earn-stage{ margin-top:6px; }
  .hero-swap .swap-teaser{ margin-top:6px; }
  .hero-ai .ait-stage{ margin-top:6px; }
  .hero-ai .ait-note{ margin-top:4px; }
}

/* ==================================================================== *
 *  LE PASSAGE SUIT LE DOIGT
 * ==================================================================== *
 *
 * L'arrivée en fondu (plus haut) se déclenche à un seuil : entre deux
 * sections, rien ne bougeait avec le geste. Ici l'animation est liée au
 * défilement lui-même — la section qui sort recule et s'éteint, celle qui
 * entre avance, au rythme exact du doigt. Au repos, sur une section accrochée,
 * tout est à l'identité. Le navigateur la calcule hors du fil principal ; là
 * où il ne sait pas le faire, la page reste celle d'avant. L'entrée ne
 * descend pas, elle rétrécit : un décalage vers le bas rallongerait le
 * débordement de la section (voir « L'ARRIVÉE D'UNE SECTION »).
 */
@keyframes sec-depth{
  entry 0%   { opacity:0; transform:scale(.9); }
  entry 100% { opacity:1; transform:none; }
  exit 0%    { opacity:1; transform:none; }
  exit 100%  { opacity:0; transform:translate3d(0,-24px,0) scale(.9); }
}
@supports (animation-timeline: view()){
  @media (prefers-reduced-motion: no-preference) and (min-height: 660px) and (min-width: 371px),
         (prefers-reduced-motion: no-preference) and (min-height: 700px){
    html[data-screen="site"] .site > section{ view-timeline:--sec block; }
    html[data-screen="site"] .site > section > .wrap{
      animation:sec-depth linear both;
      animation-timeline:--sec;
    }
  }
}

/* Sans accrochage (fenêtre courte), la rangée n'a plus de hauteur fixe : le
   cadre mesuré en `cqh` y valait zéro, et la planète disparaissait. Elle
   reprend une largeur d'écran. */
@media (max-width: 720px) and (max-height: 659px), (max-width: 370px) and (max-height: 699px){
  .hero-globe .globe-stage{ container-type:normal; height:auto; }
  .hero-globe .globe-wrap{ width:min(78vw, 360px); }
}

/* LA BULLE DU GUIDE A UNE HAUTEUR FIXE SUR TÉLÉPHONE. La scène prend la place
   qui reste sous le texte : une réponse d'une ligne de plus que le bonjour
   faisait rétrécir la planète à chaque question, puis regrandir. La bulle
   réserve donc quatre lignes, et une réponse plus longue défile en elle. */
@media (max-width: 720px) and (min-height: 660px) and (min-width: 371px),
       (max-width: 720px) and (min-height: 700px){
  .site > section .guide-say{ height:calc(4 * 1.4em + 6px); overflow-y:auto; line-height:1.4; }
  /* Ces quatre lignes réservées se reprennent sur la marque de l'écran, déjà
     retirée de la planète pour la même raison : le bandeau d'état et le
     titre disent déjà où l'on est. */
  .site > section .sec-mark{ display:none; }
}

/* ==================================================================== *
 *  CENTRAGE DES SECTIONS DE LA VITRINE
 * ==================================================================== */

/* Le bandeau d'état : le point à gauche décalait tout le texte vers la
   droite dès qu'il passait sur deux lignes. Un vide de la même largeur, à
   droite, rend le texte au centre. */
.site > section .hero-kicker::after{ content:''; width:7px; flex:none; }
.site > section .hero-kicker{ text-align:center; }


/* La légende de Track : centrée quand elle tient dans sa rangée. Des marges
   automatiques sur la première et la dernière entrée, et non `center` : si
   la rangée déborde (téléphone), elles valent zéro et le glissement repart
   du début. La passer sur plusieurs lignes faisait déborder la section sur
   les téléphones courts, la ceinture étant déjà à sa taille minimale. */
.hero-track .track-legend > :first-child{ margin-left:auto; }
.hero-track .track-legend > :last-child{ margin-right:auto; }


/* LES COMPAGNONS AU MÊME ENDROIT DANS CHAQUE SECTION. Les scènes ont une
   hauteur fixe ; la place qui reste dépend du texte de la section, et la
   carte du guide flottait plus ou moins haut (quatre-vingt-dix points de
   vide sous elle sur Price, quinze ailleurs). Elle est ancrée en bas : la
   même place, écran après écran. */
@media (min-height: 660px) and (min-width: 371px), (min-height: 700px){
  .site > section .sec-guide{ margin-top:auto; }
  /* Le contenu remplit la section : sans cela, « en bas du contenu » n'était
     pas « en bas de l'écran » dans les sections plus courtes. */
  .site > section > .wrap{ flex:1 1 auto; }
  /* La flèche « section suivante » réservait quatre-vingt-dix points sous le
     guide dans certaines sections et le chevauchait dans d'autres. En mode
     « un écran par section », les repères de droite disent déjà ce qui suit
     et y mènent d'un toucher : elle se retire, comme sur téléphone. */
  .site > section > .sd-btn{ display:none; }
}
/* Et sur grand écran, la bulle réserve la hauteur de SA PLUS LONGUE
   RÉPONSE, mesurée à sa largeur réelle (`--say-h`, voir ui/guide.js) : la
   carte ne varie pas d'une question à l'autre — ni la planète ou le ciel
   des cours avec elle — et aucune réponse n'a à défiler. Deux lignes fixes,
   l'ancien réglage, coupaient la plupart des réponses en leur milieu. */
@media (min-width: 721px) and (min-height: 660px){
  .site > section .guide-say{ height:auto; min-height:var(--say-h, calc(2 * 1.55em + 4px)); line-height:1.55; overflow:visible; }
}
/* Plus large sur grand écran : à 560 px, une réponse de trois phrases
   prenait cinq lignes dans une bulle qui en montrait deux. À 920, elle en
   prend trois, et les questions tiennent sur une seule rangée. */
@media (min-width: 1000px){
  .site > section .sec-guide{ max-width:min(920px, 100%); }
}

/* Grand écran bas (portable 1280 × 800) : Track et les dons remplissaient
   déjà tout l'écran, et leur compagnon tombait six à onze points plus bas
   que dans les autres sections. Un peu d'air repris ici le remet au même
   endroit. */
@media (min-width: 721px) and (min-height: 660px) and (max-height: 820px){
  .hero-track .belt-stage{ min-height:min(17svh, 150px); }
}

/* Les tuiles des actus dans la légende de Track : le même carré que dans la
   ceinture — X en noir, l'institution en or, la rédaction en papier. */
.tl-news i{
  width:13px; height:13px; border-radius:3px; box-shadow:none;
  background:#F2EDE6 center/9px 9px no-repeat;
}
.tl-news.tl-x i{background-color:#0F0F0F; background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23F2EDE6' d='M17.8 3h3.1l-6.8 7.8L22 21h-6.2l-4.9-6.4L5.3 21H2.2l7.3-8.3L2 3h6.4l4.4 5.8zm-1.1 16.2h1.7L7.4 4.7H5.6z'/%3E%3C/svg%3E"); outline:1px solid rgba(242,237,230,.4);}
.tl-news.tl-official i{background-color:#E4B767; background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%2314110F' d='M3 9.5 12 4l9 5.5v1H3zM5 11.5h2v6H5zM9.5 11.5h2v6h-2zM13.5 11.5h2v6h-2zM17.5 11.5h2v6h-2zM3 18.5h18V20H3z'/%3E%3C/svg%3E");}
.tl-news.tl-press i{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%2314110F' d='M4 5h12v14H6a2 2 0 0 1-2-2zM16 9h4v8a2 2 0 0 1-4 0zM6.5 8h7v1.6h-7zM6.5 11.2h7v1.6h-7zM6.5 14.4h4.5V16H6.5z'/%3E%3C/svg%3E");}
