/* ===========================================================================
   VITRINE PalMapLive
   ---------------------------------------------------------------------------
   Les six pages du tunnel : l'accueil (/), l'offre (/pro), la bienvenue après
   paiement, le parrainage, le widget et les mentions légales. Ce fichier n'est
   PAS chargé par la carte ni par les guides, qui gardent tokens.css et leur
   propre identité.

   L'idée : la vitrine est une PLANCHE DE RELEVÉ de Palpagos. Le produit vend
   « voir son serveur en direct sur une carte », donc la page ouvre sur une
   carte, pas sur un dégradé.

   Les couleurs sont relevées dans la texture de carte du jeu elle-même
   (public/map-world.webp) : encre de l'océan, mer intérieure, masses de terre,
   sommets. Une seule couleur chaude, l'ambre, et une règle stricte :
   L'AMBRE NE SERT QU'À CE QUI EST VIVANT OU CLIQUABLE. Un prix, un titre, une
   bordure décorative ne sont jamais ambre, sinon le vivant ne se voit plus.

   DEUX PAGES, UN SEUL FICHIER : /pro le lie normalement ; l'accueil, généré
   par tools/pod-router.js, le lit sur disque au démarrage et l'INSÈRE dans la
   page (c'est la page d'entrée du site, on ne lui ajoute pas une requête
   bloquante). Modifier ce fichier suffit donc pour les deux, mais l'accueil
   ne change qu'au redémarrage du pod.
   =========================================================================== */

/* ---- Fontes, auto-hébergées : la CSP du site interdit tout domaine tiers.
   Sous-ensemble latin (accents FR et umlauts DE compris), ~58 Ko à quatre. --- */
@font-face{font-family:'Archivo Exp';src:url(/fonts/archivo-exp700.woff2) format('woff2');
  font-weight:700;font-style:normal;font-display:swap}
@font-face{font-family:'Archivo';src:url(/fonts/archivo-400.woff2) format('woff2');
  font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:'Archivo';src:url(/fonts/archivo-600.woff2) format('woff2');
  font-weight:600;font-style:normal;font-display:swap}
@font-face{font-family:'Plex Mono';src:url(/fonts/plexmono-500.woff2) format('woff2');
  font-weight:500;font-style:normal;font-display:swap}

:root{
  /* couleurs prélevées sur la texture du jeu */
  --abysse:#061118;        /* océan hors zone : le fond de la page */
  --fond:#08161e;
  --haut-fond:#0b1f27;     /* mer intérieure : les surfaces */
  --terre:#123c46;
  --terre-clair:#2d5f66;   /* discret : compteurs, puces éteintes */
  --crete:#93a6ad;         /* sommets : texte secondaire (7,5:1 sur le fond) */
  --glacier:#e4edf0;       /* neige : texte courant */
  --balise:#f0a23c;        /* AMBRE : vivant ou cliquable, rien d'autre */
  --balise-encre:#160c00;  /* texte posé SUR l'ambre (8,9:1) */
  --trait:rgba(147,166,173,.14);
  --trait-fort:rgba(147,166,173,.30);

  --d:'Archivo Exp',Impact,'Arial Narrow',sans-serif;   /* titres, lettrage de carte */
  --b:'Archivo',system-ui,'Segoe UI',sans-serif;        /* corps */
  --m:'Plex Mono',ui-monospace,Consolas,monospace;      /* relevés, étiquettes, compteurs */

  /* /pro lie aussi tokens.css : on repointe ce que ses composants partagés
     (.spam-note, focus clavier) lisent, pour qu'ils suivent l'identité. */
  --accent:#f0a23c;
  --muted:#93a6ad;
  /* Les six paliers d'accent transparent de tokens.css sont écrits en rgba
     CYAN figé : sans ces six lignes, les fonds de survol, bordures actives et
     halos restaient bleus au milieu d'une page ambre. */
  --accent-10:rgba(240,162,60,.10);
  --accent-15:rgba(240,162,60,.15);
  --accent-22:rgba(240,162,60,.22);
  --accent-32:rgba(240,162,60,.32);
  --accent-45:rgba(240,162,60,.45);
  --accent-85:rgba(240,162,60,.85);
  --accent-soft:rgba(240,162,60,.14);
  --lueur:0 0 0 3px rgba(240,162,60,.16);

}

*{box-sizing:border-box;margin:0;padding:0}
/* color-scheme : sans lui, les contrôles natifs (menus déroulants,
   ascenseurs, sélection de texte) restent clairs et trouent la page. */
html{background:var(--abysse);-webkit-text-size-adjust:100%;color-scheme:dark}
/* Le cadran du héros déborde volontairement de la planche : clip horizontal
   pour qu'aucun débordement décoratif ne crée jamais de défilement latéral.
   Sur html ET body : posé sur body seul, le clip ne se propage pas à la
   fenêtre et la page défilait de 18 px vers la droite (constaté en production
   à 930 px de large ; le test initial était passé pour une mauvaise raison,
   la fenêtre d'essai étant trop large pour que quoi que ce soit déborde).
   clip et non hidden : hidden créerait un conteneur de défilement et
   casserait les ancres. */
html,body{overflow-x:clip}
body{font-family:var(--b);color:var(--glacier);line-height:1.55;background:var(--abysse);
  -webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}

/* Le graticule d'une planche : présent assez pour être lu comme un quadrillage
   de carte, effacé avant de gêner la lecture des sections. Deux pseudo-éléments
   fixes plutôt qu'un fond sur .page : ils ne se répètent pas au défilement. */
body::before{content:'';position:fixed;inset:0;z-index:0;pointer-events:none;
  background:
    linear-gradient(rgba(147,166,173,.075) 1px,transparent 1px) 0 0/100% 72px,
    linear-gradient(90deg,rgba(147,166,173,.075) 1px,transparent 1px) 0 0/72px 100%;
  -webkit-mask-image:radial-gradient(1300px 900px at 64% 0%,#000 0%,transparent 82%);
  mask-image:radial-gradient(1300px 900px at 64% 0%,#000 0%,transparent 82%)}
body::after{content:'';position:fixed;inset:0;z-index:0;pointer-events:none;
  background:radial-gradient(1000px 700px at 70% 2%,rgba(18,60,70,.34) 0%,transparent 70%)}

.page{position:relative;z-index:1;max-width:1120px;margin:0 auto;padding:0 28px}

a{color:var(--balise);text-decoration:none}
:where(a,button,input,select,textarea,summary,[tabindex]):focus-visible{
  outline:2px solid var(--balise);outline-offset:3px;border-radius:4px}
:where(h1,h2,h3){text-wrap:balance}
:where(p){text-wrap:pretty}
:where(.n,.cpt,.prix){font-variant-numeric:tabular-nums}

/* ===== cartouche : le bloc-titre de la planche ===== */
.cartouche{display:flex;align-items:center;justify-content:space-between;gap:20px;
  padding:18px 0 13px;border-bottom:1px solid var(--trait)}
.marque{display:flex;align-items:center;gap:10px;font-family:var(--m);font-size:.71rem;
  letter-spacing:.15em;text-transform:uppercase;color:var(--crete);text-decoration:none}
.marque svg{width:22px;height:22px;flex:none}
.marque b{color:var(--glacier);font-weight:500}
.marque i{color:var(--terre-clair);font-style:normal}
.marque:hover b{color:var(--balise)}
/* i18n.js insère son bouton de langue dans nav.topbar quand elle existe
   (sinon il se pose en flottant, avec un style qui vient d'ailleurs) */
.cartouche .topbar{display:flex;align-items:center;gap:16px}
.cartouche .navlink{font-family:var(--m);font-size:.68rem;letter-spacing:.14em;
  color:var(--crete);text-decoration:none;text-transform:uppercase}
.cartouche .navlink:hover{color:var(--balise)}

/* ===== titres ===== */
h1{font-family:var(--d);font-weight:700;font-size:clamp(1.5rem,6.4vw,2.75rem);
  line-height:1;letter-spacing:-.004em;text-transform:uppercase}
h1 em{font-style:normal;color:var(--balise)}
.chapo{color:var(--crete);font-size:1.02rem;margin-top:20px;max-width:36ch}

/* ===== actions ===== */
.actions{display:flex;gap:12px;flex-wrap:wrap;margin-top:30px}
.bouton,.bouton2{display:inline-block;font-family:var(--m);font-size:.75rem;letter-spacing:.13em;
  text-transform:uppercase;text-decoration:none;padding:13px 22px;border-radius:4px;
  font-weight:500;white-space:nowrap;border:1px solid transparent;cursor:pointer;
  transition:filter .2s,transform .12s,border-color .2s,color .2s}
.bouton{background:var(--balise);color:var(--balise-encre)}
.bouton:hover{filter:brightness(1.08)}
.bouton2{color:var(--crete);border-color:var(--trait-fort);background:none}
.bouton2:hover{color:var(--glacier);border-color:var(--crete)}
.bouton:active,.bouton2:active{transform:scale(.98)}

/* ===== la planche : le littoral de Palpagos ===== */
.planche{position:relative;padding:16px;max-width:440px;width:100%;margin-left:auto}
.planche svg.carte{width:100%;height:auto;display:block;overflow:visible}
.cote{fill:rgba(240,162,60,.14);fill-rule:evenodd;stroke:var(--balise);stroke-width:1.1;
  stroke-linejoin:round;opacity:.72;vector-effect:non-scaling-stroke}
/* le cadre est fait de quatre équerres, pas d'un rectangle : une planche se
   cale à ses coins */
.equerre{position:absolute;width:16px;height:16px;border:1px solid var(--trait-fort)}
.equerre.hg{top:0;left:0;border-right:0;border-bottom:0}
.equerre.hd{top:0;right:0;border-left:0;border-bottom:0}
.equerre.bg{bottom:0;left:0;border-right:0;border-top:0}
.equerre.bd{bottom:0;right:0;border-left:0;border-top:0}
.legende{position:absolute;left:16px;right:16px;bottom:-28px;display:flex;
  justify-content:space-between;gap:12px;font-family:var(--m);font-size:.64rem;
  letter-spacing:.13em;color:var(--terre-clair);text-transform:uppercase}
.legende .lecture{display:flex;align-items:center;gap:7px;color:var(--crete)}
.legende .lecture b{color:var(--balise);font-weight:500}
.legende .pt{width:6px;height:6px;border-radius:50%;background:var(--balise);flex:none}
/* la station : le serveur relevé, seule chose vivante de la planche */
.station{position:absolute;left:41%;top:36%}
.station .pt,.station .onde{position:absolute;width:9px;height:9px;margin:-4.5px 0 0 -4.5px;
  border-radius:50%}
.station .pt{background:var(--balise)}
.station .onde{border:1px solid var(--balise);animation:onde 3.4s ease-out infinite}
.station .onde:nth-of-type(2){animation-delay:1.7s}
@keyframes onde{0%{transform:scale(1);opacity:.85}100%{transform:scale(7);opacity:0}}

/* ---- les relevés : trois points de passage qui dérivent sur la planche,
   comme les joueurs sur une vraie carte. C'est le produit en miniature : le
   littoral se trace, la station s'allume, puis le relevé VIT en continu.
   Chaque point est ANCRÉ par cx/cy, sa position sans script ni animation, et
   ne bouge que par translate en DELTAS : mouvement réduit ou script absent
   donnent trois points fixes posés sur leurs îles, jamais un tas dans un
   coin. Ambre : ils sont vivants, la règle du fichier l'exige. La respiration
   passe par le rayon et non l'opacité, deux animations sur la même propriété
   se voleraient la valeur de base. Les durées premières entre elles (59, 76,
   98 s) font que la planche ne repasse jamais par le même tableau. */
.releves{position:absolute;left:16px;top:16px;width:calc(100% - 32px);
  overflow:visible;pointer-events:none}

/* ---- le cadran : la bague graduée de l'instrument de relevé, autour de la
   planche. Deux arcs interrompus qui tournent lentement dans un sens, une
   graduation fine qui tourne dans l'autre : le théodolite est en marche.
   Demandé par le propriétaire (croquis : un grand cercle échancré « un peu
   cyber » autour de la carte) ; la version retenue est plus fine que le
   croquis pour ne pas concurrencer le titre, l'ambre reste réservé à ce qui
   vit et le cadran VIT, il tourne. Débordement volontaire au-delà de la
   planche, contenu par le overflow-x:clip du body. Sous les îles dans
   l'ordre de peinture : c'est une monture, pas un premier plan. */
.cadran{position:absolute;left:50%;top:50%;width:124%;aspect-ratio:1;
  transform:translate(-50%,-50%);overflow:visible;pointer-events:none}
.cadran circle{fill:none;transform-box:fill-box;transform-origin:center}
.cadran .bague{stroke:var(--balise);stroke-width:.4;opacity:.5;
  animation:tourne 52s linear infinite}
.cadran .gradu{stroke:var(--balise);stroke-width:1.1;opacity:.16;
  animation:tourne 140s linear infinite reverse}
/* L'entrée du cadran : la bague SE TRACE, dans la grammaire de la page (le
   littoral se dessine à la plume, la bague se grave au compas). Les deux arcs
   grandissent depuis des points opposés jusqu'à ne laisser que les
   échancrures : c'est une interpolation de stroke-dasharray, de « rien que du
   creux » (0 100) vers l'état nominal (46 4), possible parce que les deux
   valeurs ont le même nombre de composantes et que pathLength vaut 100. Le
   remplissage backwards tient la bague invisible pendant son délai. La
   graduation s'encre APRÈS, comme une gravure qu'on noircit. La rotation
   continue pendant le tracé : 2 degrés en 1,2 s, imperceptible et vivant. */
.js .cadran .bague{animation:tourne 52s linear infinite,
  grave 1.2s 1.7s cubic-bezier(.22,1,.3,1) backwards}
.js .cadran .gradu{opacity:0;animation:tourne 140s linear infinite reverse,
  noircit .9s 2.6s ease forwards}
@keyframes grave{from{stroke-dasharray:0 100}to{stroke-dasharray:46 4}}
@keyframes noircit{to{opacity:.16}}
@keyframes tourne{to{transform:rotate(360deg)}}
.releves .rp{fill:var(--balise);opacity:0}
.js .releves .rp1{animation:apparait .8s 2.2s ease forwards,derive1 76s 2.2s linear infinite,
  respire 6.4s 2.2s ease-in-out infinite}
.js .releves .rp2{animation:apparait .8s 2.7s ease forwards,derive2 98s 2.7s linear infinite,
  respire 8.1s 2.7s ease-in-out infinite}
.js .releves .rp3{animation:apparait .8s 3.1s ease forwards,derive3 59s 3.1s linear infinite,
  respire 5.2s 3.1s ease-in-out infinite}
@keyframes apparait{to{opacity:.85}}
@keyframes respire{50%{r:4.6px}}
/* Dérives : des boucles fermées en unités de la planche, chacune sur son île,
   pourcentages irréguliers pour casser toute sensation de métronome. */
@keyframes derive1{0%{transform:translate(0,0)}14%{transform:translate(28px,26px)}
  31%{transform:translate(52px,8px)}47%{transform:translate(20px,50px)}
  66%{transform:translate(-18px,72px)}82%{transform:translate(-40px,30px)}
  100%{transform:translate(0,0)}}
@keyframes derive2{0%{transform:translate(0,0)}18%{transform:translate(34px,42px)}
  39%{transform:translate(16px,96px)}55%{transform:translate(-24px,74px)}
  74%{transform:translate(-36px,22px)}100%{transform:translate(0,0)}}
@keyframes derive3{0%{transform:translate(0,0)}21%{transform:translate(36px,30px)}
  44%{transform:translate(12px,64px)}63%{transform:translate(-28px,44px)}
  84%{transform:translate(-22px,6px)}100%{transform:translate(0,0)}}

/* ---- le relevé qui change : quand le nombre de joueurs bouge entre deux
   rafraîchissements, le chiffre marque le coup, preuve que la page est bien
   en direct et pas une capture. Une demi-seconde, une seule fois par vrai
   changement (le script compare les totaux, pas les textes : l'observateur
   i18n réécrit le texte sans que rien n'ait changé). */
.lecture .n{display:inline-block}
.lecture .n.tic{animation:tic .5s ease}
@keyframes tic{30%{transform:translateY(-3px);color:var(--balise)}}

/* Le moment de chargement : la planche se TRACE, puis la station s'allume.
   pathLength="1" rend la durée indépendante de la longueur du tracé, et les
   52 îles forment un seul chemin : elles apparaissent ensemble.
   L'état masqué n'est posé que si le document porte .js : sans script, la
   planche est simplement là. */
.js .cote{stroke-dasharray:1;stroke-dashoffset:1;fill-opacity:0;
  animation:plume 1.5s cubic-bezier(.22,1,.3,1) forwards,encre .8s 1.2s ease forwards}
@keyframes plume{to{stroke-dashoffset:0}}
@keyframes encre{from{fill-opacity:0}to{fill-opacity:1}}
.js .station{opacity:0;animation:allume .6s 1.5s ease forwards}
@keyframes allume{to{opacity:1}}

/* ===== intitulés de section ===== */
.rubrique{display:flex;align-items:baseline;gap:16px;margin:62px 0 20px;font-weight:400;
  font-family:var(--m);font-size:.7rem;letter-spacing:.18em;text-transform:uppercase;
  color:var(--crete)}
.rubrique::after{content:'';flex:1;height:1px;background:var(--trait);transform:translateY(-4px)}

/* ---- révélation au défilement : les sections sous le pli se lèvent de 12 px
   en entrant dans la vue, échelonnées par le script du bas de page. Tout est
   opt-in : .reveal n'est posée QUE par le script, et .js-reveal sur <html>
   n'existe que si l'observateur est là et que le mouvement réduit ne s'y
   oppose pas. Sans script, rien n'est jamais caché. */
.js-reveal .reveal{opacity:0;transform:translateY(12px);
  transition:opacity .6s ease,transform .6s cubic-bezier(.22,1,.3,1)}
.js-reveal .reveal.vu{opacity:1;transform:none}
.rubrique .cpt{color:var(--terre-clair);order:3}   /* un compte réel, jamais décoratif */

/* ===== plaques (une carte de serveur, une fonctionnalité) ===== */
.plaque{position:relative;display:flex;flex-direction:column;text-decoration:none;color:inherit;
  background:linear-gradient(180deg,var(--haut-fond),#08161d);border:1px solid var(--trait);
  border-radius:5px;padding:20px;transition:border-color .2s,transform .2s}
a.plaque:hover{border-color:var(--balise);transform:translateY(-2px)}
.plaque .nom{font-family:var(--d);font-weight:700;font-size:1.12rem;text-transform:uppercase;
  color:var(--glacier)}
.plaque .verrou{color:var(--terre-clair);font-family:var(--m);font-size:.62rem;
  letter-spacing:.12em;margin-left:8px;vertical-align:2px;text-transform:uppercase}
.plaque .d{color:var(--crete);font-size:.84rem;margin:7px 0 16px;line-height:1.5}
.plaque .etat{display:flex;align-items:center;gap:8px;margin-top:auto;padding-top:14px;
  border-top:1px solid var(--trait);font-family:var(--m);font-size:.71rem;letter-spacing:.07em;
  text-transform:uppercase;color:var(--crete)}
.plaque .etat b{color:var(--balise);font-weight:500}
.etat .p{width:7px;height:7px;border-radius:50%;background:var(--balise);flex:none}
.etat .p.eteint{background:var(--terre-clair)}
.plaque .fl{margin-left:auto;font-family:var(--m);color:var(--terre-clair);
  transition:color .2s,transform .2s}
a.plaque:hover .fl{color:var(--balise);transform:translateX(3px)}
.cartes{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(262px,100%),1fr));gap:14px}
.off{color:var(--terre-clair)}

/* ===== héros : le discours à gauche, la planche à droite ===== */
.heros{display:grid;grid-template-columns:1.12fr 1fr;gap:56px;align-items:center;padding:56px 0 40px}

/* ===== l'offre ===== */
.offre{display:flex;align-items:center;gap:36px;flex-wrap:wrap;border:1px solid var(--trait);
  border-radius:5px;padding:26px 30px;background:linear-gradient(180deg,var(--haut-fond),#08161d)}
/* Le prix n'est pas ambre : ce n'est pas une action, c'est un fait. L'ambre
   reste au bouton, sinon l'œil ne sait plus où cliquer. */
.prix{font-family:var(--d);font-weight:700;font-size:3rem;line-height:.9;color:var(--glacier)}
.prix small{display:block;margin-top:10px;font-family:var(--m);font-size:.68rem;font-weight:500;
  letter-spacing:.12em;text-transform:uppercase;color:var(--crete)}
.offre p{color:var(--crete);font-size:.93rem;max-width:40ch;flex:1;min-width:230px}

/* ===== liens de guides : une grille dont les filets sont les gouttières ===== */
.guides{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(210px,100%),1fr));gap:1px;
  background:var(--trait);border:1px solid var(--trait);border-radius:5px;overflow:hidden}
.guides a{display:flex;align-items:center;gap:10px;background:var(--fond);padding:13px 15px;
  color:var(--crete);font-size:.87rem;transition:background .18s,color .18s}
.guides a::before{content:'';width:5px;height:5px;border-radius:50%;background:var(--terre-clair);
  flex:none;transition:background .18s}
.guides a:hover{background:var(--haut-fond);color:var(--glacier)}
.guides a:hover::before{background:var(--balise)}

/* ===== pied ===== */
.pied{margin-top:64px;border-top:1px solid var(--trait);padding:20px 0 34px;display:flex;
  gap:18px;flex-wrap:wrap;justify-content:space-between;font-family:var(--m);font-size:.66rem;
  letter-spacing:.1em;text-transform:uppercase;color:var(--terre-clair)}
.pied a{color:var(--crete)}
.pied a:hover{color:var(--balise)}
.pied nav{display:flex;gap:16px;flex-wrap:wrap}

/* ===========================================================================
   PAGES SIMPLES du tunnel : /bienvenue, /parrain, /legal, /widget
   ---------------------------------------------------------------------------
   Elles partagent une même ossature `.wrap > h1 + .sub + .card*`, héritée de
   l'ancienne vitrine. On la garde telle quelle et on l'habille ici : leur
   balisage n'a pas à bouger, et les quatre pages suivront désormais toute
   évolution de l'identité au lieu de dériver chacune de son côté.
   =========================================================================== */
.wrap{position:relative;z-index:1;max-width:820px;margin:0 auto;padding:0 20px 70px}
.wrap>h1{margin:34px 0 8px;font-size:clamp(1.4rem,4.6vw,2rem)}
.wrap>h1 span{color:var(--balise)}
.wrap>h1 img{display:none}          /* le logo est déjà dans le cartouche */
.wrap h2{font-family:var(--d);font-weight:700;font-size:1.05rem;text-transform:uppercase;
  color:var(--glacier);margin:34px 0 12px}
.sub{color:var(--crete);font-size:.95rem;line-height:1.6;margin-bottom:26px;max-width:62ch}
.muted{color:var(--crete);font-size:.88rem;line-height:1.7}
.lbl{color:var(--crete);font-family:var(--m);font-size:.66rem;letter-spacing:.13em;
  text-transform:uppercase;margin-top:18px}

.card{background:linear-gradient(180deg,var(--haut-fond),#08161d);border:1px solid var(--trait);
  border-radius:5px;padding:22px;margin-bottom:16px}
.card h2{margin-top:0;font-size:.95rem}
.card p{color:var(--crete);font-size:.9rem;line-height:1.7}
.card p+p{margin-top:12px}
.card ul,.card ol{color:var(--crete);font-size:.9rem;line-height:1.7;padding-left:20px}
.card b,.card strong{color:var(--glacier);font-weight:600}

/* Champs de saisie : une seule définition pour les trois formulaires du site
   (offre, bienvenue, parrainage), qui doivent se ressembler. */
.wrap label{display:block;font-family:var(--m);font-size:.66rem;color:var(--crete);
  text-transform:uppercase;letter-spacing:.13em;margin:16px 0 6px}
.wrap input,.wrap select,.wrap textarea{width:100%;padding:12px 13px;background:var(--abysse);
  border:1px solid var(--trait-fort);border-radius:4px;color:var(--glacier);font-size:.95rem;
  outline:none;font-family:inherit}
.wrap input::placeholder,.wrap textarea::placeholder{color:var(--terre-clair)}
.wrap input:focus,.wrap select:focus,.wrap textarea:focus{border-color:var(--balise)}
.wrap textarea{min-height:80px;resize:vertical}
/* chevron dessiné : la flèche native d'un select ne suit pas la palette */
.wrap select,.form select{appearance:none;-webkit-appearance:none;padding-right:38px;
  background-image:linear-gradient(45deg,transparent 50%,var(--crete) 50%),
    linear-gradient(135deg,var(--crete) 50%,transparent 50%);
  background-position:calc(100% - 19px) 50%,calc(100% - 13px) 50%;
  background-size:6px 6px,6px 6px;background-repeat:no-repeat}
.wrap .duo{display:flex;gap:10px}
.wrap .duo input{flex:1;min-width:0}
@media(max-width:420px){.wrap .duo{flex-direction:column}}
.wrap form button,.wrap button.principal{margin-top:20px;width:100%;padding:14px;border:none;
  border-radius:4px;background:var(--balise);color:var(--balise-encre);font-family:var(--m);
  font-size:.76rem;letter-spacing:.13em;text-transform:uppercase;font-weight:500;cursor:pointer;
  transition:filter .2s,transform .12s}
.wrap form button:hover,.wrap button.principal:hover{filter:brightness(1.08)}
.wrap form button:active,.wrap button.principal:active{transform:scale(.99)}
.fb,.err{margin-top:14px;font-family:var(--m);font-size:.74rem;letter-spacing:.08em;min-height:20px}
.fb.ok{color:#55d97a}
.fb.err,.err{color:#f0685f}
.foot{margin-top:28px;color:var(--terre-clair);font-family:var(--m);font-size:.68rem;
  letter-spacing:.1em;text-transform:uppercase}
.foot a{color:var(--crete)}
.foot a:hover{color:var(--balise)}

/* ===== carte-porte : code d'accès, carte en pause ===== */
.gcard{position:relative;z-index:1;max-width:380px;width:calc(100% - 36px);margin:11vh auto 0;
  background:linear-gradient(180deg,var(--haut-fond),#08161d);border:1px solid var(--trait);
  border-radius:5px;padding:32px 28px;text-align:center}
.gcard h2{font-family:var(--d);font-weight:700;font-size:1.25rem;text-transform:uppercase;
  margin-bottom:10px}
.gcard p{color:var(--crete);font-size:.88rem;margin-bottom:18px}
.gcard input{width:100%;padding:12px;background:var(--abysse);border:1px solid var(--trait-fort);
  border-radius:4px;color:var(--glacier);font-family:var(--m);font-size:1.05rem;text-align:center;
  letter-spacing:.3em;outline:none}
.gcard input:focus{border-color:var(--balise)}
.gcard button{margin-top:12px;width:100%;padding:13px;background:var(--balise);border:none;
  border-radius:4px;font-family:var(--m);font-size:.76rem;letter-spacing:.13em;
  text-transform:uppercase;font-weight:500;color:var(--balise-encre);cursor:pointer}
.gcard .err{color:#f0685f;font-family:var(--m);font-size:.72rem;letter-spacing:.08em;
  text-transform:uppercase;margin-top:12px}
.gcard .liens{display:flex;flex-direction:column;gap:10px;margin-top:20px;font-family:var(--m);
  font-size:.68rem;letter-spacing:.1em;text-transform:uppercase}
.gcard .liens a{color:var(--crete)}
.gcard .liens a:hover{color:var(--balise)}

/* PAS d'apparition au défilement sur la vitrine, volontairement. Le seul
   mouvement de ces pages est le tracé de la planche au chargement : une
   apparition par bloc dispersait l'attention, et surtout elle rendait du
   contenu invisible quand l'observateur ne se déclenchait pas (le paragraphe
   de référencement de /pro restait à opacité 0 en bas de page). Les autres
   pages du site gardent le mécanisme, défini dans tokens.css. */

@media(max-width:880px){
  .page{padding:0 18px}
  /* le discours passe AVANT la planche : c'est lui qui doit accrocher */
  .heros{grid-template-columns:1fr;gap:34px;padding:30px 0 24px}
  .planche{max-width:330px;margin:0 auto}
  /* sur téléphone la colonne est étroite : le cadran frôle la planche au lieu
     de la déborder, sinon il toucherait les bords de l'écran */
  .cadran{width:106%}
  .offre{gap:22px;padding:22px 20px}
  .legende{position:static;margin-top:14px;flex-direction:column;align-items:flex-start;
    gap:5px;font-size:.6rem}
  .legende>span{white-space:nowrap}
  .rubrique{margin:46px 0 16px}
}
@media(prefers-reduced-motion:reduce){
  *,*::before,*::after{animation:none!important;transition:none!important}
  .js .cote{stroke-dashoffset:0;fill-opacity:1}
  .js .station{opacity:1}
  .js-reveal .reveal{opacity:1;transform:none}
  /* les relevés deviennent trois points fixes sur leurs ancres cx/cy : une
     planche imprimée plutôt qu'une planche vivante, mais complète */
  .releves .rp{opacity:.85}
  /* le cadran s'arrête, monture immobile et complète : la bague retrouve son
     dasharray d'attribut, la graduation son encre */
  .js .cadran .gradu{opacity:.16}
}

/* ---- socle-duo : le texte de fond SEO de l'accueil, en deux volets posés
   dans la mosaïque du site (mêmes joints que les fiches) ---- */
.socle-duo{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(420px,100%),1fr));gap:1px;
  background:var(--trait);border:1px solid var(--trait);border-radius:5px;overflow:hidden;
  margin-top:40px}
.socle-duo>div{background:var(--fond);padding:26px 28px}

/* ===== la preuve : une capture RÉELLE de la carte démo, montée comme une planche.
   Le radar du héros dit l'idée, cet écran montre le produit. Même grammaire :
   quatre équerres, un bandeau de relevé en mono, l'ambre réservé à ce qui
   répond (la flèche au survol). ===== */
.ecran-cadre{position:relative;padding:12px}
.ecran{display:block;text-decoration:none;color:inherit;border:1px solid var(--trait);
  border-radius:5px;overflow:hidden;background:var(--haut-fond);
  transition:border-color .2s,transform .2s}
.ecran:hover{border-color:var(--balise);transform:translateY(-2px)}
.ecran img{display:block;width:100%;height:auto}
.ecran .bandeau{display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding:11px 16px;
  border-top:1px solid var(--trait);font-family:var(--m);font-size:.66rem;letter-spacing:.13em;
  text-transform:uppercase;color:var(--terre-clair)}
.ecran .bandeau .ouvrir{margin-left:auto;color:var(--crete);transition:color .2s}
.ecran .bandeau i{font-style:normal;color:var(--terre-clair);transition:color .2s,transform .2s}
.ecran:hover .ouvrir{color:var(--glacier)}
.ecran:hover .bandeau i{color:var(--balise);transform:translateX(3px)}
.reperes{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(240px,100%),1fr));gap:1px;
  margin-top:14px;background:var(--trait);border:1px solid var(--trait);border-radius:5px;overflow:hidden}
.reperes>div{background:var(--fond);padding:16px 18px}
.reperes b{display:block;font-family:var(--m);font-size:.66rem;letter-spacing:.14em;
  text-transform:uppercase;color:var(--glacier);font-weight:500;margin-bottom:6px}
.reperes p{color:var(--crete);font-size:.86rem;line-height:1.5}

/* ===== ce que ça change : deux relevés, l'un pour les joueurs, l'autre pour
   l'admin. Chaque ligne porte son étiquette en mono, comme une fiche. ===== */
.atouts{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(420px,100%),1fr));gap:1px;
  background:var(--trait);border:1px solid var(--trait);border-radius:5px;overflow:hidden}
.atouts>div{background:var(--fond);padding:22px 26px}
.atouts h3{font-family:var(--d);font-weight:700;font-size:1.05rem;text-transform:uppercase;
  color:var(--glacier);margin:0 0 16px;letter-spacing:.01em}
.atouts ul{list-style:none;margin:0;padding:0;display:grid;gap:12px}
.atouts li{display:grid;grid-template-columns:minmax(98px,auto) 1fr;gap:12px;align-items:baseline;
  color:var(--crete);font-size:.9rem;line-height:1.5}
.atouts li b{font-family:var(--m);font-size:.64rem;letter-spacing:.13em;text-transform:uppercase;
  color:var(--glacier);font-weight:500}
@media(max-width:480px){.atouts li{grid-template-columns:1fr;gap:3px}}
.socle-duo h2{font-family:var(--d);font-weight:700;font-size:1rem;text-transform:uppercase;
  color:var(--glacier);margin:0 0 10px}
.socle-duo p{color:var(--crete);font-size:.9rem;line-height:1.7;margin:0;max-width:62ch}
.socle-duo a{color:var(--balise)}
