/* style.css — la peau des quatre pages publiques de WiFi Zone.
 *
 * ═══ LE SITE EST UNE CARTE DE RECHARGE ═══
 *
 * Le métier tient dans un objet que tout le monde a déjà eu en main à Niamey :
 * la carte prépayée qu'on achète au coin de la rue, qu'on gratte, dont on tape
 * le code. L'application fabrique exactement ça, en wifi. Le site est donc
 * fait de la même matière : du carton kraft, deux encres — un bleu-noir
 * d'imprimerie et le vermillon d'un tampon —, des filets, des pointillés de
 * déchirure, une rosace de sécurité, des étiquettes tapées à la machine.
 *
 * Ce n'est pas un décor. Chaque forme dit quelque chose de vrai : le coupon
 * qu'on détache est une étape qui se fait dans l'ordre, la case argentée
 * cache un code qui n'existe pas encore, le mot SPÉCIMEN en travers du ticket
 * dit qu'aucun code vrai ne se promène sur une page publique, et le panneau
 * hachuré de la colonne « sans l'application » est un coupon annulé.
 *
 * ═══ AUCUNE REQUÊTE VERS UN TIERS ═══
 *
 * Pas de CDN, pas de Google Fonts, pas de mesure d'audience. La page voisine
 * promet au lecteur qu'aucun tiers ne le suit ici, et une police chargée chez
 * Google enverrait son adresse IP à Google pour lui faire lire cette phrase.
 * Les sept fontes sont servies depuis ce serveur, découpées aux seuls signes
 * que ces quatre pages emploient : 84 ko pour les sept, contre 116 ko pour les
 * quatre TrueType d'avant.
 *
 * ═══ AUCUN SCRIPT NON PLUS ═══
 *
 * La politique de sécurité du site interdit le JavaScript (`script-src
 * 'none'`) et les URI `data:` (`default-src 'self'`). Tout ce qui bouge bouge
 * en CSS ; tout ce qui ne se dessine pas en CSS — le grain du carton, la
 * rosace — est un fichier servi par ce serveur, engendré par
 * `deploy/engendrer-papier.py`.
 */

/* ── LES TROIS ENCRES DU SITE ──────────────────────────────────────────────
 * Barlow Condensed : les titres et les chiffres. Une grotesque condensée est
 *   ce qu'on imprime sur une carte quand la place manque — et la place manque
 *   toujours sur une carte.
 * Courier Prime : les étiquettes, les séries, les mentions. Une machine à
 *   écrire, c'est-à-dire le registre du papier administratif : une souche, un
 *   reçu, un carnet à souches.
 * Public Sans : le texte courant, et lui seul. Un paragraphe se lit en
 *   linéale, pas en condensé ni en chasse fixe.
 */
@font-face {
  font-family: 'Barlow Condensed';
  src: url('/polices/BarlowCondensed-SemiBold.woff2') format('woff2');
  font-weight: 600;
  font-display: swap;
}
@font-face {
  font-family: 'Barlow Condensed';
  src: url('/polices/BarlowCondensed-Bold.woff2') format('woff2');
  font-weight: 700;
  font-display: swap;
}
@font-face {
  font-family: 'Courier Prime';
  src: url('/polices/CourierPrime-Regular.woff2') format('woff2');
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: 'Courier Prime';
  src: url('/polices/CourierPrime-Bold.woff2') format('woff2');
  font-weight: 700;
  font-display: swap;
}
@font-face {
  font-family: 'Public Sans';
  src: url('/polices/PublicSans-Regular.woff2') format('woff2');
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: 'Public Sans';
  src: url('/polices/PublicSans-SemiBold.woff2') format('woff2');
  font-weight: 600;
  font-display: swap;
}
@font-face {
  font-family: 'Public Sans';
  src: url('/polices/PublicSans-Bold.woff2') format('woff2');
  font-weight: 700;
  font-display: swap;
}

/* ── LE CARTON ET LES ENCRES ───────────────────────────────────────────────
 * Les noms disent la matière, pas la valeur : `--encre` est l'encre, quel que
 * soit le thème. La nuit, le carton devient sombre et l'encre devient claire —
 * les rôles ne bougent pas, les valeurs si. C'est ce qui permet d'écrire une
 * règle une seule fois.
 */
:root {
  --fond: #ffffff;          /* la page : une feuille blanche, sans grain */
  --carton: #e7dbc2;        /* le carton : la carte, et les bandes arrachées */
  --carton-sombre: #dcc8a3; /* le verso, et la bande d'appel */
  --coupon: #faf7f1;        /* ce qui est posé sur le blanc : à peine teinté */

  --encre: #1c2230;
  --encre-2: #5c5850;
  --filet: rgba(28, 34, 48, 0.15);
  --filet-fort: rgba(28, 34, 48, 0.34);

  --vermillon: #ff4a17;        /* le tampon — l'orange de l'application */
  --vermillon-fonce: #a02a0d;  /* le même, assombri pour rester lisible en petit corps */
  --vermillon-voile: rgba(255, 74, 23, 0.10);

  --argent: #a3a09a;        /* la case à gratter */
  --vert: #17624a;          /* l'encre du tampon « Actif » */

  --pied-fond: #1c2230;
  --pied-texte: #cfc3ab;
  --pied-titre: #f2e9d7;
  --pied-filet: rgba(242, 233, 215, 0.16);

  --colonne: 1120px;
  --lecture: 66ch;
  --gouttiere: 22px;
  --rayon: 2px;         /* un carton coupé au massicot n'a pas d'angle rond */
  --rayon-petit: 2px;
}

/* La nuit, la carte est photographiée sous une lampe : le carton s'éteint,
 * l'encre s'éclaircit, le vermillon monte d'un ton pour rester un tampon et
 * pas une tache brune. Rien d'autre ne change. */
@media (prefers-color-scheme: dark) {
  :root {
    --fond: #16171b;
    --carton: #21201d;
    --carton-sombre: #191815;
    --coupon: #22242b;

    --encre: #ece2cd;
    --encre-2: #9c9484;
    --filet: rgba(236, 226, 205, 0.18);
    --filet-fort: rgba(236, 226, 205, 0.38);

    --vermillon: #f15f36;
    --vermillon-fonce: #ff7d55;
    --vermillon-voile: rgba(241, 95, 54, 0.12);

    --argent: #6e6c68;
    --vert: #43cb9b;

    --pied-fond: #0f1014;
    --pied-texte: #a49c8c;
    --pied-titre: #ece2cd;
    --pied-filet: rgba(236, 226, 205, 0.14);
  }
}

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

/* LA PAGE EST BLANCHE, et c'est tout ce qu'elle est. Le grain du carton ne
 * s'imprime que sur la carte — cf. .ticket. Du papier partout, c'est du papier
 * nulle part : l'objet ne ressort que si le fond ne prétend pas en être un. */
body {
  margin: 0;
  background-color: var(--fond);
  color: var(--encre);
  font-family: 'Public Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI',
    Roboto, sans-serif;
  font-size: 17px;
  line-height: 1.62;
  -webkit-text-size-adjust: 100%;
  -webkit-font-smoothing: antialiased;
}

/* Les titres sont imprimés, pas écrits : capitales condensées, serrées, comme
 * le recto d'une carte où il faut faire tenir une phrase en trois lignes. Les
 * intertitres (h3), eux, restent en bas de casse — une page entièrement en
 * capitales ne se lit plus, elle se crie. */
h1, h2 {
  font-family: 'Barlow Condensed', 'Public Sans', sans-serif;
  font-weight: 700;
  text-transform: uppercase;
  line-height: 0.98;
  letter-spacing: 0.006em;
  text-wrap: balance;
  margin: 0;
}

h3 {
  font-family: 'Barlow Condensed', 'Public Sans', sans-serif;
  font-weight: 600;
  line-height: 1.16;
  letter-spacing: 0.005em;
  text-wrap: balance;
  margin: 0;
}

p { margin: 0 0 16px; max-width: var(--lecture); }
a { color: var(--vermillon-fonce); }

:where(a, button, input, textarea, summary):focus-visible {
  outline: 3px solid var(--vermillon);
  outline-offset: 3px;
  border-radius: 0;
}

strong { font-weight: 700; color: var(--encre); }

/* Un fragment technique — une adresse, une empreinte. Il a sa police à lui,
 * la même que les étiquettes : sur ce site, ce qui est tapé à la machine est
 * ce qui vient d'une machine. */
code {
  font-family: 'Courier Prime', ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.95em;
  background: var(--vermillon-voile);
  padding: 1px 5px;
  border-radius: 0;
  /* Un nom de fichier long n'a pas d'espace où couper : sans cela, il élargit
   * la page d'un téléphone. `anywhere` et non `break-all` : une commande se
   * coupe d'abord à ses espaces, et un mot seulement s'il ne tient pas. */
  overflow-wrap: anywhere;
}

.enveloppe {
  max-width: var(--colonne);
  margin: 0 auto;
  padding: 0 var(--gouttiere);
}

/* L'ÉTIQUETTE DE RUBRIQUE. Le nom du champ sur un formulaire imprimé : à la
 * machine, en capitales, précédé du filet où l'on écrirait à la main. */
.rubrique {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: 'Courier Prime', monospace;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--encre-2);
  margin-bottom: 12px;
}
.rubrique::before {
  content: "";
  width: 22px;
  height: 2px;
  background: var(--vermillon);
  flex: none;
}

/* ══════════════════════════════════════════════════════════════════════════
   LE RECTO DE LA CARTE
   Le bandeau n'est pas un « héros » : c'est le recto, avec sa rosace de
   sécurité qui déborde du bord droit comme sur l'objet, et son filet double
   qui sépare l'en-tête du reste de l'impression.
   ══════════════════════════════════════════════════════════════════════════ */

.seuil {
  position: relative;
  background-color: var(--fond);
  color: var(--encre);
  overflow: hidden;
}


.barre {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
  flex-wrap: wrap;
  padding: 16px 0 14px;
  border-bottom: 3px double var(--filet-fort);
}

.marque {
  display: flex;
  align-items: center;
  gap: 12px;
  font-family: 'Barlow Condensed', sans-serif;
  font-weight: 700;
  font-size: 25px;
  line-height: 1;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--encre);
  text-decoration: none;
}

.marque img {
  width: 40px;
  height: 40px;
  border-radius: 2px;
  display: block;
}

/* LES ONGLETS. Des cases imprimées, pas des pastilles : un filet fin, des
 * angles droits, la machine à écrire. Celle où l'on est a reçu le tampon. */
.onglets { display: flex; flex-wrap: wrap; gap: 6px; }

.onglets a {
  display: inline-block;
  padding: 6px 12px 5px;
  border: 1px solid var(--filet);
  border-radius: 0;
  color: var(--encre-2);
  font-family: 'Courier Prime', monospace;
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
  line-height: 1.5;
  transition: border-color .15s ease, color .15s ease;
}
.onglets a:hover { border-color: var(--filet-fort); color: var(--encre); }

/* `aria-current` porte l'état courant pour un lecteur d'écran ; le tampon le
 * porte pour tous les autres. Une seule source, deux rendus. */
.onglets a[aria-current="page"] {
  background: var(--vermillon);
  border-color: var(--vermillon);
  color: #fdf6e8;
}

@media (max-width: 520px) {
  .onglets a { padding: 5px 9px 4px; font-size: 11.5px; letter-spacing: 0.05em; }
}

/* Le manifeste : la mention légale à gauche, le ticket à droite. Il n'existe
 * que sur l'accueil — une page intérieure n'a que sa barre. */
.manifeste {
  position: relative;
  display: grid;
  gap: 44px;
  align-items: center;
  padding: 44px 0 68px;
  grid-template-columns: 1fr;
}

@media (min-width: 940px) {
  .manifeste {
    grid-template-columns: minmax(0, 1.04fr) minmax(0, 0.96fr);
    gap: 52px;
    padding: 58px 0 86px;
  }
}

/* LA ROSACE. Le seul geste gratuit de la page, et il n'est pas si gratuit :
 * c'est la marque qu'aucune photocopie ne rend, celle qui fait qu'un bout de
 * carton a l'air d'avoir de la valeur. Elle déborde du bord droit et le
 * bandeau la coupe, comme le massicot coupe le motif d'une vraie carte.
 *
 * Elle est accrochée au manifeste et non au bandeau : les trois pages
 * intérieures n'ont qu'une barre de cinquante pixels de haut, et une rosace
 * de cinq cents rognée à cette hauteur ne serait plus une rosace, juste des
 * arcs qui traversent l'en-tête. */
.manifeste::before {
  content: "";
  position: absolute;
  top: -150px;
  right: -230px;
  width: 560px;
  height: 560px;
  background: url('/rosace.svg') no-repeat center / contain;
  opacity: 0.08;
  pointer-events: none;
}
.manifeste > * { position: relative; }
/* Sur un fond blanc et une colonne étroite, elle ne passe plus derrière le
 * titre : elle passe dessus. En dessous de 940 px, elle disparaît. */
@media (max-width: 939px) { .manifeste::before { display: none; } }

/* Le titre tenait dans la colonne de gauche : cinq lignes courtes, l'air d'un
 * bloc de texte. On le sort des deux colonnes et on lui donne toute la largeur
 * du bandeau. Chaque phrase sur sa ligne, en grand — ça respire, et ça se lit
 * comme une affiche, pas comme un paragraphe. */
.manifeste h1 {
  grid-column: 1 / -1;
  font-size: clamp(38px, 6vw, 66px);
  line-height: 0.95;
  letter-spacing: 0.004em;
  max-width: none;
  text-wrap: balance;
}
.manifeste h1 span { display: block; }
.manifeste h1 em { font-style: normal; color: var(--vermillon-fonce); }

/* CE QUE C'EST, DIT AVANT CE QUE ÇA CHANGE. Le slogan ne nomme ni le
 * logiciel, ni le hotspot, ni MikroTik : un moteur de recherche lit le titre
 * de la page pour savoir de quoi elle parle, et un visiteur pressé aussi. La
 * ligne est dans le `h1`, à la machine, comme l'étiquette d'une rubrique. */
.manifeste h1 .surtitre {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 18px;
  font-family: 'Courier Prime', monospace;
  font-size: 13px;
  font-weight: 700;
  line-height: 1.4;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--encre-2);
}
.manifeste h1 .surtitre::before {
  content: "";
  width: 22px;
  height: 2px;
  background: var(--vermillon);
  flex: none;
}

.manifeste .chapeau {
  color: var(--encre-2);
  font-size: 18px;
  max-width: 46ch;
  margin: 22px 0 0;
}

.actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 30px; }

/* Au téléphone, chaque bouton prend toute la ligne : une cible large pour le
 * pouce, et le geste principal ne se tasse pas contre l'autre. Dès qu'il y a
 * la place, ils reprennent leur largeur et se rangent côte à côte. */
.actions .bouton { flex: 1 1 100%; justify-content: center; }
@media (min-width: 521px) { .actions .bouton { flex: 0 1 auto; } }

/* L'essai, dit avant le bouton qui l'ouvre : c'est lui qui fait cliquer. */
.manifeste .essai {
  margin: 26px 0 0;
  max-width: 46ch;
  font-size: 17px;
  color: var(--encre);
}
.manifeste .essai strong {
  font-family: 'Barlow Condensed', sans-serif;
  font-size: 22px;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--vermillon-fonce);
}
.manifeste .essai + .actions { margin-top: 16px; }

/* Les deux applications, en lien simple sous la mention : on les cherche une
 * fois le compte ouvert, pas avant. */
.applis { margin: 12px 0 0; font-size: 15px; color: var(--encre-2); }
.applis a { font-weight: 700; }

/* Ce qu'on télécharge, dit sous le bouton et pas dedans : un bouton dont le
 * libellé porte un numéro de version se relit mal. La ligne, elle, se corrige
 * à chaque publication. Elle est présentée comme la petite mention d'une
 * carte : au-dessus d'un filet, à la machine. */
.mention-fichier {
  margin-top: 18px;
  padding-top: 10px;
  border-top: 1px dashed var(--filet);
  max-width: 44ch;
  font-family: 'Courier Prime', monospace;
  font-size: 12.5px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--encre-2);
}

/* LES BOUTONS. Un tampon plein pour le geste principal, un cadre à l'encre
 * pour les autres. Ni l'un ni l'autre n'est arrondi : ce qui est imprimé sur
 * du carton a des angles. */
.bouton {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-family: 'Barlow Condensed', sans-serif;
  font-weight: 700;
  font-size: 18px;
  line-height: 1;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  padding: 15px 24px 13px;
  border-radius: 0;
  border: 1.5px solid transparent;
  transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}
.bouton-plein {
  background: var(--vermillon);
  border-color: var(--vermillon);
  color: #fdf6e8;
}
.bouton-plein:hover { background: var(--vermillon-fonce); border-color: var(--vermillon-fonce); }
.bouton-creux {
  background: transparent;
  color: var(--encre);
  border-color: var(--filet-fort);
}
.bouton-creux:hover { border-color: var(--encre); }

/* ══════════════════════════════════════════════════════════════════════════
   LE TICKET
   Un spécimen, et il le dit : le mot est imprimé en travers, comme sur les
   cartes de démonstration qu'un opérateur laisse au comptoir. La case à
   gratter est à moitié grattée — ce qui est dessous n'est pas un vrai code,
   et rien de vrai ne se promène sur une page publique.
   ══════════════════════════════════════════════════════════════════════════ */

.ticket {
  position: relative;
  /* Le seul carton de la page, et le seul grain : le reste est blanc, donc la
   * carte n'a plus à se détacher d'un fond qui lui ressemblait. */
  background-color: var(--carton);
  background-image: url('/grain.png');
  border: 1px solid var(--filet-fort);
  border-radius: var(--rayon);
  padding: 22px 24px 20px;
  max-width: 420px;
  width: 100%;
  justify-self: center;
  box-shadow: 0 16px 30px rgba(46, 32, 10, 0.14);
}

/* Le mot en travers. `aria-hidden` n'existe pas sur du contenu engendré, et
 * c'est très bien : un lecteur d'écran doit l'entendre comme les autres le
 * voient — ce ticket n'en est pas un. */
.ticket::after {
  content: "SPÉCIMEN";
  position: absolute;
  top: 76%;
  left: 50%;
  transform: translate(-50%, -50%) rotate(-13deg);
  font-family: 'Barlow Condensed', sans-serif;
  font-weight: 700;
  font-size: clamp(38px, 7vw, 54px);
  letter-spacing: 0.14em;
  color: var(--vermillon);
  opacity: 0.11;
  pointer-events: none;
  white-space: nowrap;
  z-index: 0;
}

/* Tout ce qui est imprimé passe au-dessus du filigrane — c'est ce qui en fait
 * un filigrane et non une rature. */
.ticket > * { position: relative; z-index: 1; }

.ticket-haut {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  margin-bottom: 16px;
}

.ticket-haut .nom {
  font-family: 'Courier Prime', monospace;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--encre-2);
}

/* LE TAMPON D'ÉTAT. Sa couleur ne dit rien toute seule — le mot « Actif » est
 * écrit dedans, parce qu'un lecteur qui ne distingue pas le vert doit pouvoir
 * lire l'état quand même. Il est de travers : un tampon posé à la main l'est
 * toujours un peu. */
.puce {
  display: inline-block;
  padding: 4px 9px 3px;
  border: 1.5px solid var(--vert);
  border-radius: 0;
  font-family: 'Courier Prime', monospace;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--vert);
  transform: rotate(-3deg);
}

/* LA CASE À GRATTER. Le code est écrit en clair dessous ; l'argenté en couvre
 * la fin, avec une arête oblique — le geste s'arrête toujours en biais. */
.ticket-code {
  position: relative;
  font-family: 'Courier Prime', monospace;
  font-size: clamp(28px, 5.6vw, 37px);
  font-weight: 700;
  letter-spacing: 0.14em;
  color: var(--encre);
  font-variant-numeric: tabular-nums;
  margin: 0 0 6px;
  padding: 6px 10px;
  border: 1px dashed var(--filet);
  max-width: 100%;
}
.ticket-code::after {
  content: "";
  position: absolute;
  top: -1px;
  bottom: -1px;
  right: -1px;
  width: 46%;
  background:
    repeating-linear-gradient(-52deg,
      rgba(255, 255, 255, 0.22) 0 3px, transparent 3px 7px),
    var(--argent);
  clip-path: polygon(16% 0, 100% 0, 100% 100%, 3% 100%);
  pointer-events: none;
}

.ticket-sous {
  font-family: 'Courier Prime', monospace;
  font-size: 12px;
  letter-spacing: 0.04em;
  color: var(--encre-2);
  margin: 0 0 18px;
  max-width: none;
}

/* LA PERFORATION : des demi-lunes de la couleur du carton mordues dans le
 * coupon, le trait discontinu entre les deux, et deux encoches sur les côtés.
 * Une seule règle, aucune image. */
.perforation {
  position: relative;
  height: 15px;
  margin: 0 -24px 16px;
  background-image:
    radial-gradient(circle at 9px 50%, var(--fond) 0 4.5px, transparent 5px),
    linear-gradient(to right, var(--filet-fort) 0 5px, transparent 5px 11px);
  background-size: 18px 15px, 11px 1px;
  background-position: 0 0, 0 50%;
  background-repeat: repeat-x, repeat-x;
}
.perforation::before, .perforation::after {
  content: "";
  position: absolute;
  top: 50%;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--fond);
  transform: translateY(-50%);
}
.perforation::before { left: -11px; }
.perforation::after { right: -11px; }

/* LA SOUCHE : ce qui reste au commerçant quand le client est parti avec son
 * code. Trois cases, comme au dos d'un carnet. */
.ticket-bas {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px;
  margin: 0;
}
.ticket-bas div { min-width: 0; }
.ticket-bas dt {
  font-family: 'Courier Prime', monospace;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--encre-2);
  margin-bottom: 2px;
}
.ticket-bas dd {
  margin: 0;
  font-family: 'Barlow Condensed', sans-serif;
  font-weight: 700;
  font-size: 23px;
  line-height: 1.1;
  color: var(--encre);
  font-variant-numeric: tabular-nums;
}

/* Le numéro de série, tout en bas, à la machine : la ligne qu'on lit au
 * téléphone quand une carte pose problème. */
.serie {
  margin: 14px 0 0;
  padding-top: 10px;
  border-top: 1px dashed var(--filet);
  font-family: 'Courier Prime', monospace;
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--encre-2);
  max-width: none;
}

/* LA DÉCHIRURE entre le recto et le reste : la même perforation, à la largeur
 * de l'écran. `.retournee` mord vers le haut, pour la frontière inverse. */
.dechirure {
  height: 17px;
  background-color: var(--carton);
  background-image:
    radial-gradient(circle at 11px 100%, var(--fond) 0 8px, transparent 8.5px),
    linear-gradient(to right, var(--filet) 0 6px, transparent 6px 13px);
  background-size: 22px 17px, 13px 1px;
  background-position: 0 0, 0 3px;
  background-repeat: repeat-x, repeat-x;
}
.dechirure.retournee {
  background-color: var(--carton-sombre);
  background-image:
    radial-gradient(circle at 11px 0, var(--fond) 0 8px, transparent 8.5px),
    linear-gradient(to right, var(--filet) 0 6px, transparent 6px 13px);
  background-position: 0 0, 0 calc(100% - 3px);
}

/* ══════════════════════════════════════════════════════════════════════════
   L'IMPRIMÉ — le corps de la page
   Pas de cartes blanches posées sur un fond gris : le texte est imprimé
   directement sur le papier, et ce qui est encadré est ce qui se détache.
   ══════════════════════════════════════════════════════════════════════════ */

.section { padding: 58px 0; }
.section + .section { border-top: 1px dashed var(--filet); }

.section h2 { font-size: clamp(28px, 4.4vw, 42px); margin-bottom: 14px; }
.section .intro { color: var(--encre-2); font-size: 17.5px; }

/* LES GESTES. La numérotation encode une SUITE réelle : on ne vend pas un code
 * avant d'avoir un forfait, ni un forfait avant d'avoir un routeur. Chaque
 * geste est donc un coupon d'un carnet, avec son numéro imprimé sur l'onglet
 * et son bord gauche en pointillé — le côté par lequel on l'arrache.
 * `auto-fit` compte les éléments à notre place : trois sur l'accueil, deux sur
 * la page de test. */
.gestes {
  list-style: none;
  counter-reset: geste;
  padding: 0;
  margin: 34px 0 0;
  display: grid;
  gap: 16px;
  grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr));
}

/* Dans la colonne de lecture des pages intérieures, 260 px ne laissent passer
 * que deux coupons sur trois : la troisième se retrouve seule sur sa ligne. */
.politique .gestes { grid-template-columns: repeat(auto-fit, minmax(min(210px, 100%), 1fr)); }

.gestes li {
  counter-increment: geste;
  position: relative;
  background: var(--coupon);
  border: 1px solid var(--filet);
  border-left: 2px dashed var(--filet-fort);
  border-radius: var(--rayon);
  padding: 38px 22px 24px;
  transition: border-color .15s ease;
}
.gestes li:hover { border-left-color: var(--vermillon); }

.gestes li::before {
  content: "Geste " counter(geste);
  position: absolute;
  top: 0;
  left: 0;
  padding: 5px 11px 4px;
  background: var(--encre);
  color: var(--coupon);
  font-family: 'Courier Prime', monospace;
  font-weight: 700;
  font-size: 11px;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
}

/* Les trois coupons ont la même hauteur mais pas la même quantité de texte :
 * le premier est long, les deux autres respirent. Plutôt que de laisser un
 * grand vide en bas, on y pose le chiffre du geste en filigrane — gros, pâle,
 * posé dans le coin comme le numéro de série d'un vrai coupon. Le vide devient
 * voulu. z-index négatif : le filigrane passe sous le texte, jamais dessus. */
.gestes li::after {
  content: counter(geste);
  position: absolute;
  right: 16px;
  bottom: 4px;
  z-index: 0;
  font-family: 'Barlow Condensed', sans-serif;
  font-weight: 700;
  font-size: 128px;
  line-height: 0.8;
  color: var(--encre);
  opacity: 0.05;
  pointer-events: none;
}
.gestes strong,
.gestes span { position: relative; z-index: 1; }

.gestes strong {
  display: block;
  font-family: 'Barlow Condensed', sans-serif;
  font-weight: 600;
  font-size: 22px;
  line-height: 1.15;
  margin-bottom: 8px;
}
.gestes span { display: block; color: var(--encre-2); font-size: 16px; }

/* LE FACE-À-FACE. « Un mot de passe circule, un ticket non » est une
 * comparaison : elle se lit en deux colonnes, pas en deux paragraphes qui se
 * suivent et qu'on ne relie qu'en les ayant tous les deux en tête.
 *
 * La colonne de gauche est un coupon ANNULÉ : hachuré, bordé de pointillés,
 * posé à même le papier. Celle de droite est valable, et encadrée à l'encre
 * pleine. La forme dit le propos avant que le titre soit lu. */
.face-a-face {
  display: grid;
  gap: 16px;
  margin-top: 34px;
  grid-template-columns: 1fr;
}
@media (min-width: 800px) {
  .face-a-face { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.volet {
  border-radius: var(--rayon);
  padding: 24px 24px 26px;
  border: 1.5px solid var(--encre);
  background: var(--coupon);
}
.volet.retenue {
  background-color: transparent;
  background-image: repeating-linear-gradient(45deg,
    var(--filet) 0 1px, transparent 1px 11px);
  border: 1px dashed var(--filet-fort);
}
.volet h3 { font-size: 21px; margin-bottom: 4px; }
.volet .quoi {
  display: inline-block;
  font-family: 'Courier Prime', monospace;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--encre-2);
  border-bottom: 1px solid var(--filet);
  padding-bottom: 3px;
  margin-bottom: 14px;
}
.volet.appuyee .quoi { color: var(--vermillon-fonce); border-bottom-color: var(--vermillon); }

.tirets { list-style: none; padding: 0; margin: 16px 0 0; display: grid; gap: 11px; }
.tirets li {
  display: grid;
  grid-template-columns: 16px 1fr;
  gap: 12px;
  align-items: start;
  color: var(--encre-2);
  font-size: 16px;
}
.tirets li::before {
  content: "";
  width: 12px;
  height: 2px;
  margin-top: 12px;
  background: var(--filet-fort);
}
.volet.appuyee .tirets li::before { background: var(--vermillon); }

/* LES FORFAITS : trois EXEMPLES, pas un barème. Le prix appartient au
 * commerçant, et le troisième bloc le dit en toutes lettres. Ce sont des
 * coupures — la valeur faciale d'une carte — avec les équerres de repérage
 * que l'imprimeur laisse dans les coins. */
.forfaits {
  display: grid;
  gap: 14px;
  margin-top: 32px;
  grid-template-columns: repeat(auto-fit, minmax(min(210px, 100%), 1fr));
}
.forfait {
  position: relative;
  background: var(--coupon);
  border: 1px solid var(--filet-fort);
  border-radius: var(--rayon-petit);
  padding: 22px 22px 20px;
}
.forfait::before, .forfait::after {
  content: "";
  position: absolute;
  width: 11px;
  height: 11px;
  border: 1.5px solid var(--vermillon);
}
.forfait::before { top: 5px; left: 5px; border-right: 0; border-bottom: 0; }
.forfait::after { bottom: 5px; right: 5px; border-left: 0; border-top: 0; }

.forfait .prix {
  display: block;
  font-family: 'Barlow Condensed', sans-serif;
  font-weight: 700;
  font-size: 38px;
  line-height: 1;
  letter-spacing: 0.01em;
  font-variant-numeric: tabular-nums;
  margin-bottom: 6px;
}
.forfait .duree {
  display: block;
  font-family: 'Courier Prime', monospace;
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--encre-2);
}
.forfait.libre .prix { color: var(--vermillon-fonce); font-size: 30px; }

/* L'ABONNEMENT : le prix que le commerçant paie, par paliers. Trois reçus. Le
 * premier palier est tamponné plein au vermillon — c'est celui que la plupart
 * prennent. Chaque reçu porte le mensuel en grand, puis le tarif à l'année sous
 * un filet perforé, avec la pastille d'économie. */
.abonnements {
  display: grid;
  gap: 16px;
  margin-top: 32px;
  grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr));
}
.abo {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--coupon);
  border: 1px solid var(--filet-fort);
  border-radius: var(--rayon-petit);
  padding: 24px 22px;
}
.abo .palier {
  font-family: 'Courier Prime', monospace;
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--encre-2);
}
.abo .mensuel {
  display: block;
  margin-top: 12px;
  font-family: 'Courier Prime', monospace;
  font-size: 13px;
  letter-spacing: 0.04em;
  color: var(--encre-2);
}
.abo .mensuel strong {
  display: block;
  font-family: 'Barlow Condensed', sans-serif;
  font-weight: 700;
  font-size: 46px;
  line-height: 1;
  letter-spacing: 0.01em;
  font-variant-numeric: tabular-nums;
  color: var(--encre);
  margin-bottom: 4px;
}
.abo .annuel {
  margin-top: 18px;
  padding-top: 16px;
  border-top: 1px dashed var(--filet-fort);
  display: flex;
  flex-direction: column;
  gap: 5px;
}
.abo .annuel .label {
  font-family: 'Courier Prime', monospace;
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--encre-2);
}
.abo .annuel .taux {
  font-family: 'Barlow Condensed', sans-serif;
  font-weight: 700;
  font-size: 27px;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  color: var(--encre);
}
.abo .annuel .taux small {
  font-family: 'Courier Prime', monospace;
  font-weight: 400;
  font-size: 12px;
  letter-spacing: 0.04em;
  color: var(--encre-2);
}
.abo .annuel .total {
  font-size: 13px;
  color: var(--encre-2);
}
.abo .annuel .economie {
  align-self: flex-start;
  margin-top: 6px;
  padding: 3px 10px;
  border-radius: var(--rayon-petit);
  background: var(--vermillon-voile);
  color: var(--vermillon-fonce);
  font-family: 'Courier Prime', monospace;
  font-size: 11px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

/* Le palier mis en avant : tampon plein, texte en réserve. */
.abo.en-avant {
  background: var(--vermillon);
  border-color: var(--vermillon);
}
.abo.en-avant .palier,
.abo.en-avant .mensuel,
.abo.en-avant .mensuel strong,
.abo.en-avant .annuel .label,
.abo.en-avant .annuel .taux,
.abo.en-avant .annuel .taux small,
.abo.en-avant .annuel .total { color: #fff; }
.abo.en-avant .annuel { border-top-color: rgba(255, 255, 255, 0.45); }
.abo.en-avant .annuel .economie {
  background: #fff;
  color: #a02a0d;
}

/* Les garanties : des pastilles de souche sous la grille. */
.abo-garanties {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin: 22px 0 0;
  padding: 0;
  list-style: none;
}
.abo-garanties li {
  position: relative;
  padding: 8px 14px 8px 30px;
  background: var(--coupon);
  border: 1px solid var(--filet);
  border-radius: var(--rayon-petit);
  font-family: 'Courier Prime', monospace;
  font-size: 12px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--encre);
}
.abo-garanties li::before {
  content: "";
  position: absolute;
  left: 14px;
  top: 50%;
  width: 7px;
  height: 7px;
  margin-top: -3.5px;
  border-radius: 50%;
  background: var(--vermillon);
}
.abo-cta { margin-top: 24px; }

/* LE PRÉ-REQUIS, en lignes de souche : un lecteur qui cherche « quel routeur »
 * ne doit pas lire un paragraphe pour trouver le mot MikroTik. */
.specs {
  margin: 30px 0 0;
  border-top: 1px solid var(--filet-fort);
}
.specs > div {
  display: grid;
  grid-template-columns: 1fr;
  gap: 4px;
  padding: 16px 0;
  border-bottom: 1px dashed var(--filet);
}
@media (min-width: 700px) {
  .specs > div { grid-template-columns: 210px 1fr; gap: 24px; align-items: baseline; }
}
.specs dt {
  font-family: 'Courier Prime', monospace;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--encre-2);
}
.specs dd { margin: 0; }
.specs dd p:last-child { margin-bottom: 0; }

/* ══════════════════════════════════════════════════════════════════════════
   CE QUE L'APPLICATION FAIT
   Six lignes, et ce sont exactement les six paragraphes de la fiche Play. Une
   fiche et un site qui promettent deux choses différentes, c'est la fiche qui
   a raison : autant qu'ils disent la même.

   Pas de cartes : six entrées séparées par un filet, comme le verso d'une
   notice. L'icône est un SVG écrit dans la page — pas de fichier à charger,
   pas de police d'icônes, et `currentColor` la fait suivre le thème comme le
   texte. `aria-hidden` la retire de la lecture à voix haute : elle répète le
   titre, elle ne l'ajoute pas.
   ══════════════════════════════════════════════════════════════════════════ */
.capacites {
  display: grid;
  gap: 0 34px;
  margin-top: 30px;
  border-top: 1px solid var(--filet-fort);
  grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
}

.capacite {
  display: grid;
  grid-template-columns: 26px 1fr;
  gap: 0 14px;
  align-items: start;
  /* Sans ceci, une entrée voisine plus haute étire les lignes de celle-ci et
   * éloigne le paragraphe de son titre : la grille répartit le vide. */
  align-content: start;
  padding: 20px 0 22px;
  border-bottom: 1px dashed var(--filet);
}

.capacite svg {
  display: block;
  grid-column: 1;
  grid-row: 1 / span 2;
  width: 22px;
  height: 22px;
  margin-top: 3px;
  color: var(--vermillon);
}

.capacite h3 {
  grid-column: 2;
  font-size: 21px;
  margin-bottom: 6px;
}
.capacite p {
  grid-column: 2;
  margin: 0;
  max-width: none;
  color: var(--encre-2);
  font-size: 16px;
}

/* ══════════════════════════════════════════════════════════════════════════
   TROIS COMPTOIRS
   Pour qui c'est fait, et ce que le métier change au comptoir. Cette section
   a longtemps tenu la place des témoignages, faute d'en avoir de vrais : une
   citation inventée est un faux que le lecteur repère. Les vrais ont
   maintenant leur section, `#avis`, plus haut dans la page ; celle-ci reste
   pour ce qu'elle dit des métiers.
   ══════════════════════════════════════════════════════════════════════════ */
.comptoirs {
  display: grid;
  gap: 16px;
  margin-top: 34px;
  grid-template-columns: repeat(auto-fit, minmax(min(268px, 100%), 1fr));
}

.comptoir {
  background: var(--coupon);
  border: 1px solid var(--filet);
  border-radius: var(--rayon);
  padding: 22px 22px 24px;
}

.comptoir .lieu {
  display: block;
  font-family: 'Barlow Condensed', sans-serif;
  font-size: 22px;
  font-weight: 600;
  line-height: 1.1;
  padding-bottom: 10px;
  margin-bottom: 12px;
  border-bottom: 1px solid var(--filet);
}
.comptoir p { margin: 0 0 16px; max-width: none; color: var(--encre-2); font-size: 16px; }

/* LE GAIN, au tampon. Trois angles différents : un tampon posé à la main ne
 * retombe jamais deux fois au même. */
.comptoir .gain {
  display: inline-block;
  border: 1.5px solid var(--vermillon);
  padding: 5px 9px 4px;
  font-family: 'Courier Prime', monospace;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--vermillon-fonce);
}
.comptoir:nth-child(1) .gain { transform: rotate(-2.4deg); }
.comptoir:nth-child(2) .gain { transform: rotate(1.6deg); }
.comptoir:nth-child(3) .gain { transform: rotate(-1.1deg); }

/* ══════════════════════════════════════════════════════════════════════════
   LES AVIS
   Les mots de commerçants qui vendent avec l'application, signés de leur
   commerce. Pas d'étoiles : cinq sur cinq partout, sur le site de l'éditeur,
   ne prouve rien à personne. Une citation et un nom, oui.

   Les avis ont été donnés de vive voix, parfois dans une autre langue que le
   français, puis traduits et resserrés avec l'accord de chacun. Trois
   seulement sont affichés : une rangée pleine sur grand écran, pas un mur.

   Chaque avis est un coupon de la même famille que le ticket du haut : un
   liseré vermillon, la citation, une perforation avec ses deux encoches, et
   sur la souche le tampon rond aux initiales du commerce.

   Au téléphone, les coupons défilent de côté et le suivant dépasse du bord,
   ce qui dit qu'il y en a d'autres : des cartes empilées feraient un long
   tunnel à faire défiler du pouce. Seule la rangée défile, jamais la page.
   Au-delà, deux puis trois par rangée, et la dernière rangée, si elle est
   incomplète, se centre au lieu de rester collée à gauche.
   ══════════════════════════════════════════════════════════════════════════ */
.avis {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: min(84%, 330px);
  gap: 14px;
  margin: 30px calc(-1 * var(--gouttiere)) 0;
  padding: 12px var(--gouttiere) 24px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-padding: 0 var(--gouttiere);
  overscroll-behavior-x: contain;
  scrollbar-width: none;
}
.avis::-webkit-scrollbar { display: none; }

@media (min-width: 700px) {
  .avis {
    grid-auto-flow: row;
    grid-auto-columns: auto;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 22px;
    margin: 36px 0 0;
    padding: 0;
    overflow: visible;
    scroll-snap-type: none;
  }
  .avis-carte { grid-column: span 2; }
  .avis-carte:last-child:nth-child(odd) { grid-column: 2 / span 2; }
}
@media (min-width: 1024px) {
  .avis { grid-template-columns: repeat(6, minmax(0, 1fr)); }
  .avis-carte:last-child:nth-child(odd) { grid-column: span 2; }
  .avis-carte:nth-child(3n+1):nth-last-child(2) { grid-column: 2 / span 2; }
  .avis-carte:nth-child(3n+1):last-child { grid-column: 3 / span 2; }
}

.avis-carte {
  position: relative;
  margin: 0;
  display: flex;
  flex-direction: column;
  scroll-snap-align: start;
  background: var(--coupon);
  border: 1px solid var(--filet-fort);
  border-top: 4px solid var(--vermillon);
  border-radius: var(--rayon);
  padding: 48px 22px 18px;
  box-shadow: 0 10px 24px rgba(46, 32, 10, 0.10);
  transition: transform .2s ease, box-shadow .2s ease;
}
@media (hover: hover) {
  .avis-carte:hover {
    transform: translateY(-4px);
    box-shadow: 0 18px 32px rgba(46, 32, 10, 0.16);
  }
}

/* Le grand guillemet ouvrant, à l'encre du tampon. Il est dessiné, pas écrit :
 * la citation elle-même reste dans son `<blockquote>`, sans signe ajouté. */
.avis-carte::before {
  content: "«";
  position: absolute;
  top: -12px;
  left: 18px;
  font-family: 'Barlow Condensed', 'Public Sans', sans-serif;
  font-weight: 700;
  font-size: 72px;
  line-height: 1;
  color: var(--vermillon);
  pointer-events: none;
}

.avis-carte blockquote { margin: 0 0 22px; flex: 1; }
.avis-carte blockquote p {
  margin: 0;
  max-width: none;
  font-size: 17px;
  line-height: 1.6;
  color: var(--encre);
}

/* LA SOUCHE : la perforation en pointillés, deux encoches mordues dans les
 * bords (la moitié intérieure d'un rond de la couleur de la page), puis le
 * tampon et le nom. */
.avis-carte figcaption {
  position: relative;
  display: flex;
  align-items: center;
  gap: 14px;
  margin: 0 -22px;
  padding: 16px 22px 0;
  border-top: 1.5px dashed var(--filet-fort);
}
.avis-carte figcaption::before,
.avis-carte figcaption::after {
  content: "";
  position: absolute;
  top: -12px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--fond);
  border: 1px solid var(--filet-fort);
}
.avis-carte figcaption::before { left: -12px; clip-path: inset(0 0 0 50%); }
.avis-carte figcaption::after { right: -12px; clip-path: inset(0 50% 0 0); }

/* Le tampon rond, double filet, posé de travers comme la puce « Actif ». Les
 * initiales sont un ornement : le nom est écrit en entier juste à côté. */
.avis-tampon {
  flex: none;
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  border: 2px solid var(--vermillon);
  box-shadow: inset 0 0 0 3px var(--coupon), inset 0 0 0 4px var(--vermillon);
  font-family: 'Barlow Condensed', sans-serif;
  font-weight: 700;
  font-size: 17px;
  letter-spacing: 0.04em;
  color: var(--vermillon-fonce);
  transform: rotate(-9deg);
}
.avis-nom {
  font-family: 'Barlow Condensed', sans-serif;
  font-size: 20px;
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--encre);
}


/* ══════════════════════════════════════════════════════════════════════════
   LA FAQ
   `<details>` et `<summary>` : le navigateur ouvre et referme tout seul, sans
   une ligne de JavaScript — ce qui tombe bien, la page n'a pas le droit d'en
   charger. Une réponse reste donc atteignable même si tout le reste échoue,
   et la recherche du navigateur (Ctrl+F) trouve dans les blocs fermés sur les
   moteurs récents.
   ══════════════════════════════════════════════════════════════════════════ */
.faq {
  margin-top: 30px;
  border-top: 1px solid var(--filet-fort);
}

.question { border-bottom: 1px dashed var(--filet); }

.question summary {
  display: grid;
  grid-template-columns: 1fr 22px;
  gap: 18px;
  align-items: center;
  padding: 17px 0;
  cursor: pointer;
  font-family: 'Barlow Condensed', sans-serif;
  font-weight: 600;
  font-size: 20px;
  line-height: 1.2;
  list-style: none;
}
/* Les deux façons dont les navigateurs dessinent le triangle par défaut. */
.question summary::-webkit-details-marker { display: none; }
.question summary::marker { content: ""; }

.question summary:hover { color: var(--vermillon-fonce); }

/* Le plus qui devient un moins : deux traits, dont le vertical se rétracte à
 * l'ouverture. Le signe dit l'état — ouvert, fermé — sans mot à traduire.
 * (Le faire pivoter d'un quart de tour ne servirait à rien : une croix qui
 * tourne de 90° est la même croix.) */
.question summary::after {
  content: "";
  width: 13px;
  height: 13px;
  justify-self: end;
  background-image:
    linear-gradient(var(--vermillon), var(--vermillon)),
    linear-gradient(var(--vermillon), var(--vermillon));
  background-position: center, center;
  background-repeat: no-repeat;
  background-size: 13px 2px, 2px 13px;
  transition: background-size .18s ease;
}
.question[open] summary::after { background-size: 13px 2px, 2px 0; }
.question[open] summary { color: var(--vermillon-fonce); }

.question .reponse { padding: 0 0 20px; }
.question .reponse p { margin: 0 0 12px; color: var(--encre-2); font-size: 16px; }
.question .reponse p:last-child { margin-bottom: 0; }

/* ══ LA BANDE D'APPEL ══ Le verso de la carte : le carton un ton plus foncé,
   la rosace de l'autre côté. C'est le geste que la page attend, il a droit à
   sa propre pièce. ══════════════════════════════════════════════════════ */
.appel {
  position: relative;
  background-color: var(--carton-sombre);
  color: var(--encre);
  padding: 54px 0 58px;
  overflow: hidden;
}
.appel::before {
  content: "";
  position: absolute;
  bottom: -220px;
  left: -160px;
  width: 520px;
  height: 520px;
  background: url('/rosace.svg') no-repeat center / contain;
  opacity: 0.22;
  pointer-events: none;
}
.appel .enveloppe { position: relative; }
.appel h2 { font-size: clamp(28px, 4.4vw, 42px); margin-bottom: 12px; }
.appel .intro { color: var(--encre-2); }

/* Deux cartes, les deux magasins : Google Play et l'App Store. Le fichier
 * Android du site n'a pas de carte : il ne sert qu'aux téléphones sans Google
 * Play, et il a sa ligne dessous (`.plus-tard`). */
.plateformes {
  display: grid;
  gap: 14px;
  margin-top: 30px;
  grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr));
}
.plateformes a {
  display: block;
  background: var(--coupon);
  border: 1px solid var(--filet);
  border-left: 2px dashed var(--filet-fort);
  border-radius: var(--rayon);
  padding: 20px 22px 22px;
  text-decoration: none;
  color: inherit;
  transition: border-color .15s ease;
}
.plateformes a:hover { border-left-color: var(--vermillon); }
.plateformes strong {
  display: block;
  font-family: 'Barlow Condensed', sans-serif;
  font-weight: 600;
  font-size: 21px;
  line-height: 1.15;
  color: var(--encre);
  margin-bottom: 7px;
}
.plateformes span { display: block; color: var(--encre-2); font-size: 15.5px; }
.plus-tard { margin: 18px 0 0; max-width: 62ch; font-size: 15px; color: var(--encre-2); }
.plus-tard a { font-weight: 700; }
.plateformes .mention {
  display: inline-block;
  margin-top: 14px;
  padding-top: 9px;
  border-top: 1px dashed var(--filet);
  font-family: 'Courier Prime', monospace;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--vermillon-fonce);
}

/* ══ LE PIED ══ Le bloc d'encre du bas de la carte : celui où l'imprimeur met
   son nom, l'adresse, et les mentions qu'on lit à la loupe. ═══════════════ */
footer {
  background-color: var(--pied-fond);
  color: var(--pied-texte);
  padding: 44px 0 50px;
  font-size: 15px;
}
footer .colonnes {
  display: grid;
  gap: 30px;
  grid-template-columns: 1fr;
  padding-bottom: 28px;
  border-bottom: 1px solid var(--pied-filet);
}
@media (min-width: 760px) {
  footer .colonnes { grid-template-columns: 1.3fr 1fr 1fr; gap: 40px; }
}
footer .marque { font-size: 22px; color: var(--pied-titre); margin-bottom: 12px; }
footer .devise { max-width: 34ch; }
footer h2 {
  font-family: 'Courier Prime', monospace;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.16em;
  color: var(--pied-titre);
  margin-bottom: 12px;
}
footer nav { display: grid; gap: 9px; justify-items: start; }
footer a { color: var(--pied-texte); text-decoration: none; }
footer a:hover { color: var(--pied-titre); text-decoration: underline; }
footer .signature {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 20px;
  justify-content: space-between;
  padding-top: 20px;
  font-family: 'Courier Prime', monospace;
  font-size: 11.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
footer .signature p { margin: 0; max-width: none; }

/* ══ LE BOUTON WHATSAPP ══ Toujours en bas à droite, sur chaque page du site :
   la question qu'on n'ose pas poser par courriel se pose là. Rond et vert, parce
   que c'est la forme que tout le monde reconnaît, pas celle de la carte. ═════ */
.whatsapp-flottant {
  position: fixed;
  right: calc(16px + env(safe-area-inset-right, 0px));
  bottom: calc(16px + env(safe-area-inset-bottom, 0px));
  z-index: 50;
  display: grid;
  place-items: center;
  width: 58px;
  height: 58px;
  border-radius: 50%;
  background-color: #25d366;
  color: #ffffff;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.28);
  transition: transform .15s ease-out, background-color .15s ease-out;
}
/* Page tout en bas, la dernière ligne du pied reste lisible au-dessus du
 * bouton. Seulement là où il est : l'espace partage cette feuille sans lui. */
body:has(> .whatsapp-flottant) footer { padding-bottom: 104px; }
.whatsapp-flottant svg { width: 34px; height: 34px; fill: currentColor; }
.whatsapp-flottant:hover { background-color: #1ebe5d; transform: scale(1.06); }
.whatsapp-flottant:focus-visible { outline: 3px solid var(--encre); outline-offset: 3px; }
@media print {
  .whatsapp-flottant { display: none; }
}

/* ══ L'ESSAI, À PORTÉE DE POUCE ══ Sur l'accueil seulement, en bas à gauche,
   en face du bouton WhatsApp et centré sur lui. Le site n'exécute aucun script
   (`script-src 'none'`) : le bouton ne sait pas se cacher quand « Créer mon
   compte » est déjà à l'écran, et reste donc toujours là. Il garde la forme des
   autres boutons du site ; seul le corps se resserre pour tenir à côté du rond
   vert sur un petit téléphone. ═══════════════════════════════════════════════ */
.essai-flottant {
  position: fixed;
  left: calc(16px + env(safe-area-inset-left, 0px));
  bottom: calc(21px + env(safe-area-inset-bottom, 0px));
  z-index: 50;
  font-size: 16px;
  padding: 14px 16px 12px;
  white-space: nowrap;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.22);
}
@media (max-width: 359px) {
  .essai-flottant { font-size: 14px; letter-spacing: 0.03em; padding: 13px 12px 11px; bottom: calc(23px + env(safe-area-inset-bottom, 0px)); }
}
@media print {
  .essai-flottant { display: none; }
}

/* ══════════════════════════════════════════════════════════════════════════
   LES PAGES DE TEXTE — confidentialité, suppression du compte, formulaire.
   Elles ne prennent pas la largeur de l'accueil : une ligne de soixante-dix
   caractères se lit, une ligne de cent-vingt se relit.
   ══════════════════════════════════════════════════════════════════════════ */

.politique {
  max-width: 820px;
  padding-top: 38px;
  padding-bottom: 24px;
}

.politique h1 { font-size: clamp(32px, 5.4vw, 50px); margin-bottom: 10px; }

.date {
  font-family: 'Courier Prime', monospace;
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--encre-2);
  margin-bottom: 32px;
}

/* Le numéro d'article vit dans sa propre colonne : les titres s'alignent entre
 * eux, que l'article porte un chiffre ou deux. */
.politique h2 {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 14px;
  align-items: baseline;
  font-size: 25px;
  margin: 38px 0 12px;
}
.politique h2 .rang {
  font-family: 'Courier Prime', monospace;
  color: var(--vermillon-fonce);
  font-size: 16px;
  font-variant-numeric: tabular-nums;
}

.politique ul { margin: 0 0 16px; padding-left: 22px; max-width: var(--lecture); }
.politique li { margin-bottom: 8px; }

.cadre {
  background: var(--coupon);
  border: 1px solid var(--filet);
  border-left: 2px dashed var(--filet-fort);
  border-radius: var(--rayon);
  padding: 20px 22px;
  margin-bottom: 20px;
}
.cadre p:last-child { margin-bottom: 0; }

/* Un tableau doit pouvoir défiler seul : le corps de la page, jamais. */
.defile {
  overflow-x: auto;
  margin: 18px 0 22px;
  border: 1px solid var(--filet);
  border-radius: var(--rayon-petit);
}

table {
  border-collapse: collapse;
  width: 100%;
  min-width: 460px;
  font-size: 15px;
  background: var(--coupon);
}

/* Trois colonnes courtes : sur un téléphone, le montant doit se lire sans
   faire défiler le tableau. */
table.paiements { min-width: 0; }
.paiements th, .paiements td { padding-left: 9px; padding-right: 9px; }

th, td {
  text-align: left;
  padding: 11px 15px;
  border-bottom: 1px dashed var(--filet);
  vertical-align: top;
}

th {
  font-family: 'Courier Prime', monospace;
  font-weight: 700;
  font-size: 11px;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--encre-2);
  border-bottom: 1px solid var(--filet-fort);
}

tr:last-child td { border-bottom: 0; }

.retour {
  display: inline-block;
  margin-bottom: 26px;
  font-family: 'Courier Prime', monospace;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-decoration: none;
}
.retour:hover { text-decoration: underline; }

/* ══════════════════════════════════════════════════════════════════════════
   LE FORMULAIRE DE DEMANDE D'ACCÈS AU TEST
   Servi par node (voir src/http/rejoindre.js), mais il charge CETTE feuille :
   une deuxième feuille pour une page de plus voudrait dire deux palettes à
   garder d'accord, et elles divergeraient.

   C'est un bulletin : un cadre à l'encre, des champs à angles droits, des
   intitulés à la machine. Rien ici ne suppose de script — ce qui valide, c'est
   le navigateur (`type=email`, `required`) puis le serveur, jamais du code à
   nous chargé dans la page.
   ══════════════════════════════════════════════════════════════════════════ */

.demande {
  max-width: 560px;
  margin: 28px 0 40px;
  background: var(--coupon);
  border: 1.5px solid var(--encre);
  border-radius: var(--rayon);
  padding: 24px 24px 26px;
}

.demande label {
  display: block;
  font-family: 'Barlow Condensed', sans-serif;
  font-weight: 600;
  font-size: 19px;
  letter-spacing: 0.01em;
  margin-bottom: 2px;
}

/* La phrase qui explique le champ. Elle vient AVANT la case et non après :
 * « ce doit être l'adresse Gmail du téléphone » se lit avant d'avoir tapé, ou
 * ne sert à rien. */
.aide { color: var(--encre-2); font-size: 15px; margin: 0 0 9px; }

.demande input[type="email"],
.demande input[type="text"],
.demande input[type="password"],
.demande textarea {
  display: block;
  width: 100%;
  font-family: 'Courier Prime', monospace;
  font-size: 15px;
  color: var(--encre);
  background: var(--fond);
  border: 1px solid var(--filet-fort);
  border-radius: 0;
  padding: 11px 13px;
  margin-bottom: 20px;
}

.demande textarea { resize: vertical; min-height: 88px; }

.demande input[type="email"]:focus-visible,
.demande input[type="text"]:focus-visible,
.demande input[type="password"]:focus-visible,
.demande textarea:focus-visible {
  outline: 3px solid var(--vermillon);
  outline-offset: 1px;
  border-color: var(--vermillon);
}

.demande fieldset { border: 0; padding: 0; margin: 0 0 20px; }
.demande legend {
  padding: 0;
  font-family: 'Barlow Condensed', sans-serif;
  font-weight: 600;
  font-size: 19px;
  margin-bottom: 8px;
}

/* Le libellé enveloppe son bouton radio : toute la ligne devient cliquable, ce
 * qui compte sur un téléphone où viser un cercle de 14 px au pouce est un
 * exercice. */
.choix {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: 'Public Sans', sans-serif;
  font-size: 17px;
  font-weight: 400;
  background: var(--fond);
  border: 1px solid var(--filet);
  border-radius: 0;
  padding: 11px 13px;
  margin-bottom: 8px;
  cursor: pointer;
}
.choix:hover { border-color: var(--vermillon); }
.choix input { accent-color: var(--vermillon); width: 18px; height: 18px; margin: 0; }

.demande button {
  font-family: 'Barlow Condensed', sans-serif;
  font-weight: 700;
  font-size: 18px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #fdf6e8;
  background: var(--vermillon);
  border: 1.5px solid var(--vermillon);
  border-radius: 0;
  padding: 14px 26px 12px;
  cursor: pointer;
}
.demande button:hover { background: var(--vermillon-fonce); border-color: var(--vermillon-fonce); }

.doux { color: var(--encre-2); font-weight: 400; }

/* La déconnexion de l'espace commerçant (src/http/espace.js). Un formulaire,
 * parce qu'elle écrit ; dessinée comme un bouton creux, parce qu'elle n'est
 * pas le geste que la page attend. */
.sortie { margin: 34px 0 40px; }
.sortie button {
  font-family: 'Barlow Condensed', sans-serif;
  font-weight: 700;
  font-size: 17px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--encre);
  background: transparent;
  border: 1.5px solid var(--filet-fort);
  border-radius: 0;
  padding: 12px 22px 10px;
  cursor: pointer;
}
.sortie button:hover { border-color: var(--encre); }

/* LES ÉCRANS. La page montre enfin l'application elle-même : trois captures
 * réelles, pas une maquette. Le téléphone est un objet, donc il a le droit
 * d'avoir des angles ronds là où le reste de la page est coupé au massicot ;
 * le cadre reprend le noir de la carte du tableau de bord, ce qui pose les
 * captures claires sur le papier blanc sans qu'elles flottent. */
.telephones {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 38px 34px;
  margin-top: 36px;
}
.telephone { margin: 0; width: 232px; max-width: 74vw; }
.telephone .cadre {
  background: #0e1017;
  border-radius: 30px;
  padding: 9px;
  box-shadow: 0 22px 46px rgba(28, 34, 48, 0.22);
}
.telephone img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 22px;
}
.telephone figcaption {
  margin-top: 15px;
  text-align: center;
  font-family: 'Courier Prime', ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.82rem;
  line-height: 1.4;
  color: var(--encre-2);
}
/* La nuit, le cadre noir se confond presque avec le fond : un filet discret le
 * détache, sans l'allumer. */
@media (prefers-color-scheme: dark) {
  .telephone .cadre {
    box-shadow: 0 22px 46px rgba(0, 0, 0, 0.5);
    outline: 1px solid rgba(236, 226, 205, 0.10);
    outline-offset: -1px;
  }
}

/* LE CHAMP-PIÈGE. Hors de l'écran plutôt que `display:none` : un robot un peu
 * soigneux ignore ce qui est masqué, et celui-ci ne doit justement pas
 * paraître masqué. `aria-hidden` sur le conteneur et `tabindex=-1` sur la case
 * font que ni un lecteur d'écran ni la touche Tab ne l'atteignent — un piège
 * qui attrape un humain aveugle n'est pas un piège, c'est un mur. */
.piege {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* L'ENTRÉE EN SCÈNE. Une seule, courte, et coupée dès que le système demande
 * moins de mouvement — un utilisateur qui a réglé ça sur son téléphone l'a
 * fait pour une raison qui ne nous regarde pas. */
@media (prefers-reduced-motion: no-preference) {
  .manifeste > * { animation: monte .5s ease-out both; }
  .manifeste > *:nth-child(2) { animation-delay: .09s; }
}

@keyframes monte {
  from { opacity: 0; transform: translateY(14px); }
  to { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .001ms !important; transition-duration: .001ms !important; }
}
