/* ═══════════════════════════════════════════════════════════════════════════════
   joynuz.css — SOURCE UNIQUE DU DESIGN
   ═══════════════════════════════════════════════════════════════════════════════
   Pourquoi ce fichier existe (mesuré le 2026-07-12, pas supposé) :
     · 7 pages portaient chacune leur <style> complet, leur :root, leur copie du matériau.
     · 146 copies redondantes / 813 règles = 18 % du CSS était du copier-coller.
     · Le même point-virgule manquant a dû être corrigé 4 fois — c'était UN bug, copié.
     · Et surtout : `.metal` avait TROIS corps différents, `.emboss` TROIS, `.brand` QUATRE.
       Le « matériau platine » n'était pas un matériau : c'en était trois. La dérive était
       invisible parce qu'aucun endroit ne disait ce que le matériau EST.

   Conséquence : ce n'est pas une accumulation de bugs de design, c'est une architecture
   qui rend le bug de design inévitable. Un composant neuf ne peut pas HÉRITER du matériau ;
   il faut le RETAPER — d'où le bouton plat, le trou noir, les champs orphelins.

   Modèle : trois couches (standard de l'industrie — Material, Carbon, Polaris convergent).
     1. PRIMITIVES  — les valeurs brutes (#d54035). Jamais citées par un composant.
     2. SÉMANTIQUE  — le sens (--accent, --danger, --on-light). Ce que les composants citent.
     3. COMPOSANTS  — ne connaissent que le sémantique. Un bouton ne sait pas qu'il est rouge :
                      il sait qu'il porte l'accent. C'est ce qui rend le thème possible DEMAIN
                      sans refonte (un thème = un second bloc de tokens, rien d'autre).

   Joynuz faisait DÉJÀ ça à moitié : `.team-a{--accent:var(--red)}` / `.team-b{...--blue}`.
   L'architecture était juste ; il lui manquait un DOMICILE.
   ═══════════════════════════════════════════════════════════════════════════════ */


/* ─────────────────────────────────────────────────────────────────────────────
   COUCHE 0 — RESET
   Ligne la plus fondamentale de toute base CSS, et pourtant ABSENTE de la première version
   de ce fichier : chaque page la portait dans son propre <style>, l'extraction l'a laissée
   tomber. Conséquence : `.field{width:100%;padding:var(--sp-2) var(--sp-2)}` en content-box débordait sa
   colonne de 26px — les champs prénom/email SE CHEVAUCHAIENT (constaté par Ben, 12/07).
   L'inventaire l'avait pourtant affiché (« * — 2 variantes sur 8 pages ») : la donnée était
   à l'écran, je ne l'ai pas lue. C'est exactement pourquoi render-check.py existe désormais.
   ───────────────────────────────────────────────────────────────────────────── */
*, *::before, *::after{ box-sizing:border-box; }
img, svg{ max-width:100%; }


/* ─────────────────────────────────────────────────────────────────────────────
   COUCHE 1 + 2 — TOKENS
   27 tokens étaient déjà strictement identiques sur les 7 pages : ils sont repris tels quels.
   4 divergeaient : arbitrés ci-dessous, valeur retenue annotée.
   ───────────────────────────────────────────────────────────────────────────── */
:root{
  /* — primitives : fonds & encres — */
  --bg:#0c0d10;
  --surface-2:#1e2128;
  --ink:#f4f6f8;
  --ink-muted:#9aa4ad;
  --white:#ffffff;                 /* ARBITRÉ : #fff / #ffffff → normalisé */
  --on-white:#0c0d10;
  --on-light:#16181d;              /* encre sur surface claire (bouton .cta) */
  --field-placeholder:#7d848c;     /* texte indicatif des champs */

  /* — primitives : couleurs d'équipe —
     ⚠ 30/07 — `--red` ASSOMBRI : #e8463a → #d54035 (arbitrage Ben). MOTIF : le blanc sur l'ancien rouge
     plafonnait à 3.91, sous le seuil AA de 4.5 ; il est à 4.55. Valeur choisie comme la PLUS CLAIRE qui
     passe (recherche pas-à-pas sur la formule de tests/legibility.py) — délibérément pas plus sombre.
     ⚠ `--red-text` (#ff6a5e) N'A PAS BOUGÉ : c'est le rouge du TEXTE sur fond sombre, un autre besoin.
     Conséquence à connaître : l'avertissement de `.btn.danger` (« Annuler ma place ») N'EST PAS fermé —
     son dégradé démarre sur `--red-text`, où le blanc plafonne à 2.81. Le fermer voudrait dire toucher
     `--red-text`, donc le titre de la vitrine : autre décision. */
  --red:#d54035;      --red-text:#ff6a5e;
  --blue:#3b7bf0;     --blue-text:#5b93f7;
  /* palette de groupe complète (5 couleurs). Valeurs = celles DÉJÀ rendues en prod par GR_COLORS (JS) :
     pastilles de groupe, eyebrow, titres. green/purple/amber sont assez clairs sur fond sombre pour servir
     AUSSI de --accent-text (pas de variante -text distincte ; si Ben en veut de plus claires, c'est 3 hex). */
  --green:#3fb950;    --purple:#8b5cf6;    --amber:#f4c150;
  --success-text:#4ade80;
  --danger-text:#e8574c;
  --danger-deep:#c23a2f;           /* ARBITRÉ : #c23a2f (organizer) / #d23a2e (manage) */

  /* — primitives : matière — */
  --line:#2a2e36;
  --shade:#000;              /* utilisé par .preview-flag (group.html) */
  --focus:#8ab4ff;
  --metal-grad:linear-gradient(135deg,#3b3f47 0%,#2a2d33 30%,#34373f 50%,#202327 72%,#2e3138 100%);
  --code-grad:linear-gradient(180deg,#fdfdfe 0%,#d6dade 55%,#c3c9d1 100%);
  --metal-light:#e9edf1;
  --metal-hi:#41454d;
  --emboss-ink:#eef1f4;
  --metal-muted:#c2c8cf;
  --chip:#c9cdd4;
  --chip-line:#80858d;

  /* — typographie — */
  --font-body:'Inter',system-ui,sans-serif;
  --font-display:'Archivo',system-ui,sans-serif;
  --font-mono:'DM Mono',ui-monospace,monospace;

  /* — géométrie & mouvement — */
  --radius:18px;
  --radius-sm:10px;
  --r-md:14px;                     /* AJOUTÉ 14/07 : échelle complète — 6 pages l'utilisaient, valeur unanime. */
  --r-lg:18px;                     /* défaut APP (arch-task/arch-app) ; arch-read le repasse à 20px (§ archétype, mesuré 14/07). */
  --ease:cubic-bezier(.2,.8,.25,1);/* ARBITRÉ : 5 pages sur 6 → la courbe la plus vive */
  /* Échelle d'espacement : toute marge, tout padding et tout écart passe par ces 6 marches (2 px reste écrit). */
  --sp-0:4px;
  --sp-1:8px;
  --sp-2:12px;
  --sp-3:18px;
  --sp-4:24px;                     /* CORRIGÉ 14/07 : 16px était un FANTÔME — 0 page ne l'utilisait, toutes à 24px. */
  --sp-5:36px;
  /* Échelle typographique : toute taille de texte passe par ces 7 marches. */
  --fs-1:.72rem;   /* 11,5 px */
  --fs-2:.8rem;    /* 12,8 px */
  --fs-3:.9rem;    /* 14,4 px */
  --fs-4:1rem;     /* 16 px */
  --fs-5:1.12rem;  /* 17,9 px */
  --fs-6:1.4rem;   /* 22,4 px */
  --fs-7:1.9rem;   /* 30,4 px */

  /* — SÉMANTIQUE par défaut : l'accent est ROUGE tant qu'aucune équipe n'est déclarée — */
  --accent:var(--red);
  --accent-text:var(--red-text);
}

/* NOTE : `--surface` (#16181d) a été SUPPRIMÉ. Il était déclaré sur les 7 pages et utilisé
   ZÉRO fois — c'est le fond plat que design-lint interdit (§7). La règle a gagné : plus
   personne ne s'en sert. On ne garde pas un token mort qui invite à la faute. */

/* Couche sémantique scopée — le composant cite var(--accent), il ignore la couleur. */
.team-a{ --accent:var(--red);  --accent-text:var(--red-text); }
.team-b{ --accent:var(--blue); --accent-text:var(--blue-text); }

/* Palette de groupe VALUE-DRIVEN (5 couleurs) — le client émet class="acc-{accent}" (acc-red … acc-amber),
   sans if/else 2-couleurs. Ajouter une couleur = un primitive ci-dessus + une règle ici. team-a/team-b
   restent comme alias red/blue (scaffolding statique + contrat CSS). Corrige « palette non rendue » (Ben 21/07). */
.acc-red{    --accent:var(--red);    --accent-text:var(--red-text);  }
.acc-blue{   --accent:var(--blue);   --accent-text:var(--blue-text); }
.acc-green{  --accent:var(--green);  --accent-text:var(--green);     }
.acc-purple{ --accent:var(--purple); --accent-text:var(--purple);   }
.acc-amber{  --accent:var(--amber);  --accent-text:var(--amber);    }


/* ─────────────────────────────────────────────────────────────────────────────
   DOCTRINE D1 — BUDGET DE LARGEUR PAR ARCHÉTYPE
   Avant : 5 pages, 5 valeurs de --maxw (620 / 640 / 640 / 1040 / 1120), aucune justifiée.
   La page paraissait « étriquée » ou « île sur l'océan » selon l'humeur du fichier.
   Trois archétypes, un budget chacun, DÉCLARÉ par une classe sur <body> ou <main>.
   Élargir n'est PAS toujours mieux : au-delà de ~75 caractères par ligne, la lecture chute.
   ───────────────────────────────────────────────────────────────────────────── */
.arch-read{ --maxw:clamp(320px, 92vw, 720px); --r-lg:20px; }  /* landing, confidentialité, mentions — un texte suivi ; coin plus rond que l'app (§ archétype, mesuré 14/07) */
.arch-task{ --maxw:clamp(320px, 92vw, 820px);  }  /* bookings, manage — un flux, une action */
.arch-app { --maxw:clamp(320px, 94vw, 1280px); }  /* group, organizer — colonnes, listes, densité */

/* GOUTTIÈRE — un token, pas une constante enfouie dans .wrap.
   Défaut mesuré le 12/07 : sur un écran de 390px, `94vw` donnait 366px, MOINS 16px de padding de
   chaque côté → la carte ne faisait que 334px, avec 28px perdus par bord. 14 % de l'écran, pour
   rien. Sur mobile, le contenu VAUT la largeur : la gouttière se réduit et --maxw prend tout. */
:root{ --gutter:16px; }
@media (max-width:640px){
  :root{ --gutter:6px; }   /* « Maxi » — choix de Ben (12/07) : la carte prend 97 % de l'écran,
                             mais garde son bord : un liseré + une ombre portée qui touchent le
                             bord de l'écran cessent d'exister, et le matériau avec eux. */
  .arch-read, .arch-task, .arch-app{ --maxw:100vw; }
}

.wrap{ max-width:var(--maxw); margin:0 auto; padding:0 var(--gutter); }


/* ─────────────────────────────────────────────────────────────────────────────
   COUCHE 3 — PRIMITIVES DE MATÉRIAU (§7)
   CANON = variante V1 (majoritaire ET la plus riche : bookings, group, index, manage).
   Diff assumé : les pages légales gagnent une bordure et une vraie gravure (elles avaient
   un métal SANS bordure et un emboss SANS drop-shadow — dégradés en silence) ; l'organizer
   change d'ombre portée (il avait `0 18px 50px -22px #000`, sans ombre interne basse).
   ───────────────────────────────────────────────────────────────────────────── */
.metal{
  position:relative; overflow:hidden;
  background:
    linear-gradient(106deg,rgba(255,255,255,.11) 0%,rgba(255,255,255,0) 16%,rgba(255,255,255,.05) 29%,rgba(255,255,255,0) 44%,rgba(255,255,255,.05) 61%,rgba(255,255,255,0) 76%,rgba(255,255,255,.07) 100%),
    repeating-linear-gradient(116deg,rgba(255,255,255,.028) 0 1px,rgba(0,0,0,.03) 1px 2.5px),
    var(--metal-grad);
  border:1px solid rgba(255,255,255,.09);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.16), inset 0 -1px 0 rgba(0,0,0,.4), 0 16px 34px rgba(0,0,0,.5);
}
/* ─────────────────────────────────────────────────────────────────────────────
   DOCTRINE D8 — PROFONDEURS (arbitrées par Ben sur planche A-D, 2026-07-12 : « code en C,
   JuZ en A »). MÉTHODE, apprise à nos dépens : les effets ton-sur-ton sont perceptuellement
   BISTABLES (creusé ou bombé selon la direction de lumière que le cerveau suppose). Trois fois
   le vocabulaire a menti (« gravé »/.emboss, « membre », « enfoncé »/« relief »). Règle : un
   effet entre ici uniquement DÉSIGNÉ par Ben sur un rendu qu'il a vu — jamais nommé d'après
   une prédiction de perception. Je ne perçois pas le rendu.
   ───────────────────────────────────────────────────────────────────────────── */

/* ── .relief-1 (= A, l'effet HISTORIQUE du site) — titres, libellés, montants secondaires,
      et la MARQUE JuZ sur la carte platine (désignation Ben). Contraste ≈ 7,8:1. ── */
.relief-1, .emboss{        /* `.emboss` : alias de compatibilité, les 7 pages l'utilisent. */
  color:var(--emboss-ink);
  background:var(--code-grad);
  -webkit-background-clip:text; background-clip:text;
  -webkit-text-fill-color:transparent;
  filter:drop-shadow(0 1px 0 rgba(0,0,0,.7)) drop-shadow(0 2px 2px rgba(0,0,0,.45));
}

/* ── .estampe (= C) — le CODE de réservation et les valeurs de la carte platine (désignation
      Ben). Ton-sur-ton : la face reste dans les gris du métal (à peine plus claire), seules les
      arêtes parlent — le traitement du numéro d'une carte bancaire réelle (face grise, arêtes
      brillantes), référence photo Visa Platinum de Ben.
      ⚠ CONTRASTE DE FACE ≈ 2,1:1 — sous WCAG AA (4,5:1). DÉROGATION ASSUMÉE ET BORNÉE :
      uniquement sur la carte platine, et uniquement parce que le code y est DUPLIQUÉ ailleurs
      en clair (mail de confirmation, page /b/, communication de virement). Si le code devient
      l'unique affichage lisible quelque part, l'estampé y est INTERDIT. ── */
.estampe{
  color:transparent;
  background:linear-gradient(180deg,#565b63 0%,#484d55 45%,#3a3e46 55%,#4d525a 100%);
  -webkit-background-clip:text; background-clip:text;
  -webkit-text-fill-color:transparent;
  filter:
    drop-shadow(0 -1px 0 rgba(255,255,255,.28))
    drop-shadow(0 1.5px 1px rgba(0,0,0,.8))
    drop-shadow(0 3px 4px rgba(0,0,0,.45));
}

/* ── .card — la CARTE : rayon + rembourrage. Supprimée par accident le 12/07 (une expression
      régulière gourmande, lancée pour retirer deux effets écartés, a emporté la règle qui suivait).
      Résultat : tous les angles droits, sur toutes les cartes. Verrouillé désormais par
      render-check (rayon calculé) ET par le contrat de feuille (la règle DOIT exister). ── */
.card{ border-radius:var(--radius); padding:var(--sp-4); margin-bottom:var(--sp-2); }

/* ── ÉCARTÉS (planche A-D) : B (foil brillant) — trop clinquant ; D (arêtes inversées) —
      bistable, lu « relief » par Ben alors que je l'annonçais « enfoncé ». Ne pas réintroduire. ── */

/* ─────────────────────────────────────────────────────────────────────────────
   DOCTRINE D5 — SHEEN : UN SEUL REFLET PAR PAGE, JAMAIS EN mix-blend-mode
   Le reflet de la landing était en `mix-blend-mode:soft-light` : sur une surface sombre, le
   delta produit est minuscule — invisible sur téléphone. Ici, alpha simple.
   Un seul par page : c'est sa RARETÉ qui le rend beau. Douze reflets = un sapin de Noël
   (et un coût GPU réel sur mobile).
   ───────────────────────────────────────────────────────────────────────────── */
.sheen{ position:relative; }
.sheen::after{
  content:""; position:absolute; top:-40%; left:0; width:34%; height:180%;
  pointer-events:none; z-index:1;
  background:linear-gradient(105deg,transparent 0%,rgba(255,255,255,.05) 42%,rgba(255,255,255,.22) 50%,rgba(255,255,255,.05) 58%,transparent 100%);
  transform:rotate(9deg) translateX(-160%);
  animation:jz-sweep 9s ease-in-out infinite;
}
@keyframes jz-sweep{
  0%{transform:rotate(9deg) translateX(-160%); opacity:0}
  14%{opacity:1}
  54%{transform:rotate(9deg) translateX(420%); opacity:1}
  66%{opacity:0}
  100%{transform:rotate(9deg) translateX(420%); opacity:0}
}
/* Le sourire du JuZ respire au même rythme que le reflet (9 s). BUG DU 12/07 : la règle qui
   DÉSACTIVE cette animation existait, mais l'animation elle-même n'avait jamais été définie. */
/* AMPLITUDE ASSUMÉE. La première version (scaleY 1.32 sur 9 s) était si discrète que Ben devait
   se concentrer pour la voir : « soit tu la rends notable, soit on conclut qu'elle est inutile ».
   Il a raison — une animation qu'on ne remarque pas ne fait qu'ajouter du coût sans bénéfice.
   Ici : le sourire s'élargit ET se creuse, en deux temps (un vrai sourire, pas un frémissement),
   avec un rebond. Cycle raccourci à 6 s pour qu'il se produise pendant qu'on regarde. */
@keyframes jz-grin{
  0%, 62%, 100%{ transform:scaleY(1) scaleX(1) }
  70%{ transform:scaleY(1.75) scaleX(1.12) }
  80%{ transform:scaleY(1.45) scaleX(1.06) }
  88%{ transform:scaleY(1.62) scaleX(1.09) }
  96%{ transform:scaleY(1) scaleX(1) }
}
.brandmark .bm-u{
  transform-origin:50% 10%;
  animation:jz-grin 6s cubic-bezier(.34,1.56,.64,1) infinite;   /* rebond : il « éclate » */
}

@media (prefers-reduced-motion:reduce){
  .sheen::after{ animation:none; opacity:0 }
  .brandmark .bm-u{ animation:none; transform:none }
}


/* ─────────────────────────────────────────────────────────────────────────────
   CONTRÔLES — boutons en relief (§7), jamais plats
   ───────────────────────────────────────────────────────────────────────────── */
.btn{
  appearance:none; -webkit-appearance:none; font:inherit; cursor:pointer;
  font-weight:600; font-size:var(--fs-3); color:var(--ink);
  min-height:44px; padding:var(--sp-2) var(--sp-3); border-radius:var(--radius-sm);
  display:inline-flex; align-items:center; justify-content:center; gap:var(--sp-1);
  border:1px solid rgba(255,255,255,.12);
  background:linear-gradient(180deg,#41454c,#2a2d32);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.18), 0 3px 0 rgba(0,0,0,.45), 0 8px 16px rgba(0,0,0,.32);
  transition:transform .08s var(--ease), box-shadow .08s var(--ease);
}
.btn:active{ transform:translateY(1px); box-shadow:inset 0 1px 0 rgba(255,255,255,.12), 0 1px 0 rgba(0,0,0,.45); }
.btn.ghost{ background:linear-gradient(180deg,rgba(255,255,255,.06),rgba(255,255,255,.02)); }
/* Contour à l'accent du groupe : inviter, partager. Pendant clair dans light.css. */
.btn.outline{ background:transparent; border:1.5px solid var(--accent); color:var(--accent-text); box-shadow:none; }
.btn.sm{ min-height:44px; padding:var(--sp-1) var(--sp-2); font-size:var(--fs-2); }   /* 44px : WCAG 2.1 (§8).
   Était à 36px — violation trouvée par render-check, que ni Ben ni moi n'avions vue à l'œil. */
.btn[disabled]{ opacity:.45; cursor:default; }

/* Action principale : le seul bouton CLAIR. Son encre est --on-light — c'est le token qui,
   tué par un point-virgule manquant, rendait « Je réserve » illisible (contraste 1,54:1). */
.cta{
  appearance:none; -webkit-appearance:none; font:inherit; cursor:pointer;
  font-family:var(--font-body); font-weight:800; font-size:var(--fs-3);
  min-height:48px; padding:var(--sp-2) var(--sp-3); border-radius:var(--radius-sm);
  display:inline-flex; align-items:center; justify-content:center; gap:var(--sp-1);
  border:1px solid rgba(255,255,255,.5); text-decoration:none; white-space:nowrap;
  background:linear-gradient(180deg,var(--ink) 0%,#dde1e6 46%,#c3c9d1 54%,#cfd5db 100%);
  color:var(--on-light);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.95), inset 0 -2px 3px rgba(0,0,0,.22), 0 5px 12px rgba(0,0,0,.5);
  transition:transform .06s var(--ease);
}
@media (hover: hover){ .cta:hover{ filter:brightness(1.03); } }
.cta:active{ transform:translateY(1px); }
.cta[disabled]{ opacity:.45; cursor:default; }

/* DOCTRINE D2 — un champ de saisie n'est JAMAIS orphelin : il vit dans une carte platine.
   L'encastré translucide est réservé aux CHAMPS (§7 item 5) — jamais aux surfaces de contenu. */
.field{
  width:100%; font:inherit; font-size:var(--fs-3); color:var(--ink);
  padding:var(--sp-2) var(--sp-2); border-radius:11px; border:0;
  background:rgba(0,0,0,.2);
  box-shadow:inset 0 1px 3px rgba(0,0,0,.45);
}
.field::placeholder{ color:var(--field-placeholder); }
.field:focus-visible,
.btn:focus-visible, .cta:focus-visible{ outline:2px solid var(--focus); outline-offset:2px; }

/* DOCTRINE D3 — toute SURFACE CLIQUABLE porte le matériau, quel que soit son tag.
   `<a>`, `<label>`, `<div>` compris : c'est l'angle mort qui a laissé passer « Mes places »
   (un <a> en trou noir : le lint exigeait `cursor:pointer` écrit, que l'auteur n'écrit jamais
   sur un lien puisque le navigateur le fournit). Une surface cliquable a du RELIEF, pas un trou. */
.surface{
  border-radius:12px; padding:var(--sp-2) var(--sp-2);
  /* D3 EST TENUE ICI : le grain brossé 116deg, pas seulement du relief. Sans lui, la surface
     est un dégradé plat — c'est le défaut « le platine disparaît sur la liste » (12/07) : ma
     propre primitive ne respectait pas ma propre règle. */
  background:
    repeating-linear-gradient(116deg,rgba(255,255,255,.026) 0 1px,rgba(0,0,0,.03) 1px 2.5px),
    linear-gradient(180deg,rgba(255,255,255,.06),rgba(255,255,255,.018));
  border:1px solid rgba(255,255,255,.07);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.10);
  transition:background .12s var(--ease);
}
@media (hover: hover){
.surface:hover{
  background:
    repeating-linear-gradient(116deg,rgba(255,255,255,.03) 0 1px,rgba(0,0,0,.03) 1px 2.5px),
    linear-gradient(180deg,rgba(255,255,255,.09),rgba(255,255,255,.035));
}
}
/* Une surface portée par un <a> ne doit PAS hériter du bleu souligné du navigateur.
   Défaut constaté : « Brussels Ping-Pong » en bleu souligné dans « Mes places » — ce n'était pas
   une couleur du thème, c'était le style d'usine, jamais neutralisé. */
a.surface, a.surface:link, a.surface:visited,
a.row, a.row:link, a.row:visited{ color:inherit; text-decoration:none; }

/* DOCTRINE D4 — flex : le TEXTE cède, les ACTIONS non.
   `.gr-item` (liste des groupes) était un flex où les boutons portaient `flex:none` et où le
   nom n'avait ni `flex:1` ni `min-width:0` : sur mobile, « Brussels Ping-Pong » se brisait sur
   trois lignes pendant que les boutons gardaient leur largeur. */
.row{ display:flex; align-items:center; gap:var(--sp-2); }
.row > .row-text{ flex:1; min-width:0; }          /* le texte cède et tronque proprement */
.row > .row-acts{ flex:none; display:flex; gap:var(--sp-1); }
@media (max-width:520px){
  .row{ flex-wrap:wrap; }
  /* Le repli en pleine largeur ne vaut QUE pour de vraies ACTIONS (des boutons). Appliqué à tout,
     il éjectait le PRIX sur sa propre ligne (« 6,50 € » décalé, constaté le 12/07) : la règle était
     juste, sa portée était trop large. */
  .row > .row-acts:has(button){ width:100%; justify-content:flex-start; }
}

/* Chiffres alignés : le prix reste sur la même ligne que son libellé, et l'€ ne « saute » plus.
   `tabular-nums` garde les colonnes de chiffres alignées sans imposer une chasse fixe au symbole. */
.num{
  font-family:var(--font-mono);
  font-variant-numeric:tabular-nums;
  white-space:nowrap;          /* un nombre ne se sépare JAMAIS de son unité : « 6,50 » / « € » */
}


/* ─────────────────────────────────────────────────────────────────────────────
   DOCTRINE D7 — LE LIEU N'EST PAS L'ADRESSE
   `events.location` valait « Centre Sportif Mounier — Woluwé-Saint-Lambert » : un NOM DE LIEU.
   Une seule page (index.html) le passait à Google Maps en recherche floue ; les autres
   l'affichaient en texte mort. Deux défauts en un : l'adresse n'était pas cliquable là où on en
   a besoin, et le géocodage par nom peut atterrir n'importe où pour une salle peu référencée —
   défaut qui ne se voit qu'un samedi à 15h25, quand quelqu'un est au mauvais endroit.
   Modèle retenu (B) : `location` = le NOM (affiché, lisible), `address` = l'ADRESSE POSTALE
   (qui porte le lien). L'adresse est TOUJOURS un <a>, jamais un texte mort.
   ───────────────────────────────────────────────────────────────────────────── */
.place{ display:flex; flex-direction:column; gap:2px; }
.place .venue{ font-size:var(--fs-3); color:var(--ink); font-weight:600; }
.geo{
  display:inline-flex; align-items:center; gap:var(--sp-1);
  min-height:44px;                        /* cible tactile (§8) */
  font-size:var(--fs-2); color:var(--ink-muted);
  text-decoration:none; border-radius:8px;
  transition:color .12s var(--ease);
}
.geo:focus-visible{ color:var(--accent-text); }
@media (hover: hover){ .geo:hover{ color:var(--accent-text); } }
.geo .pin{ width:15px; height:15px; flex:none; stroke:currentColor; fill:none; stroke-width:1.7; }
.geo .txt{ text-decoration:underline; text-underline-offset:3px; text-decoration-color:rgba(255,255,255,.25); }


/* ─────────────────────────────────────────────────────────────────────────────
   IDENTITÉ — le J, le sourire rouge, le Z. Tracé SVG, jamais un glyphe (§7 item 3).
   ───────────────────────────────────────────────────────────────────────────── */
.brand{ display:flex; justify-content:center; align-items:center; gap:var(--sp-2); }
.brandmark{
  display:flex; align-items:flex-end; gap:1px;
  font-family:var(--font-display); font-weight:900;
  letter-spacing:-.05em; line-height:1; font-size:var(--fs-7);
}
.brandmark .bm-u{ width:30px; height:auto; margin:0 1px var(--sp-0); overflow:visible; }  /* CORRIGÉ 14/07 : .72em/-.06em était un FANTÔME (les 7 pages à 30px/5px ; planche A désignée par Ben). */
.brandmark .bm-u path{ stroke:var(--accent); }
.brand .tag{
  font-size:var(--fs-1); letter-spacing:.24em; text-transform:uppercase;
  color:var(--metal-muted); font-weight:700;
}


/* ─────────────────────────────────────────────────────────────────────────────
   PIED DE PAGE — GLOBAL. Jamais dans une vue masquable : il vivait dans #view-login
   et disparaissait à la connexion. Les mentions légales sont une obligation (§9.7).
   ───────────────────────────────────────────────────────────────────────────── */
.foot{
  text-align:center; color:var(--metal-muted); font-size:var(--fs-1);
  padding:var(--sp-4) var(--sp-3) var(--sp-5); border-top:1px solid var(--line); margin-top:var(--sp-5);
}
a.jz-legal:link, a.jz-legal:visited{ color:var(--ink-muted); text-decoration:underline; }
@media (hover: hover){ a.jz-legal:hover{ color:var(--ink); } }

.hidden{ display:none !important; }

/* JZ-LOCK:accent-value-driven → voir docs/LOCKS.md (registre des verrous) */

/* ══ BASCULE DE THÈME (19/09) — style de base, VALABLE DANS LES DEUX THÈMES ══════════════════════
   AJOUTÉ en fin de feuille, jamais inséré dans une règle existante : c'est la voie que la constitution
   autorise après l'incident du 19/09.
   ⚠ LE BOUTON VIT SUR LA MÊME LIGNE QUE LE SÉLECTEUR DE LANGUE, dans un conteneur qui les réunit.
   Première version : un bloc centré inséré À CÔTÉ du sélecteur. Sur les 7 pages applicatives il tombait
   au-dessus, et sur la vitrine — dont l'en-tête est une rangée marque-à-gauche / langue-à-droite — il
   atterrissait au milieu, sans rapport avec la pastille (constat de Ben, 19/09).
   ⚠ La marge du conteneur est RECOPIÉE depuis celle que portait le sélecteur (js/theme.js) : chaque page
   garde ainsi exactement le placement qu'elle avait, au lieu d'un centrage imposé qui casse la vitrine.
   ⚠ Dans le FLUX, jamais en position absolue : le patron absolu a fait recouvrir le titre des pages
   légales le 07/09. Hauteur alignée sur la pastille, cible tactile ≥ 44px (WCAG, vérifié par render-check). */
.jz-controls{ display:flex; align-items:center; justify-content:center; gap:var(--sp-1); width:max-content; }
/* ⚠ DANS LE CONTENEUR, LE SÉLECTEUR REVIENT DANS LE FLUX. `group.html` et `bookings.html` le gardaient
   en `position:absolute` — la fragilité notée au backlog le 07/09, quand ce même patron avait fait
   recouvrir le titre des pages légales. Hors du flux, il ne peut pas s'aligner avec quoi que ce soit :
   le bouton de thème atterrissait 164 px à sa gauche (mesuré). Cette ligne ferme l'item du backlog. */
.jz-controls > .jz-lang, .jz-controls > .lp-lang{ margin:0; position:static; transform:none; }
/* ⚠ `transform:none` AUSSI : le patron absolu portait `translateY(-50%)`, qui survivait au retour
   dans le flux et décalait la pastille d'une demi-hauteur (25 px mesurés sur group et bookings). */
.jz-theme-btn{ appearance:none; -webkit-appearance:none; border:0; cursor:pointer; font-family:inherit;
  font-size:var(--fs-4); line-height:1; color:var(--ink-muted); min-height:50px; min-width:50px;
  border-radius:999px; display:grid; place-items:center; flex:none;
  background:rgba(0,0,0,.22); box-shadow:inset 0 1px 2px rgba(0,0,0,.5); }
@media (hover: hover){ .jz-theme-btn:hover{ color:var(--ink); } }
.jz-theme-btn:focus-visible{ outline:2px solid var(--focus); outline-offset:1px; }

/* ══ HACHURAGE : LE MOTIF DEVIENT UN TOKEN (19/09) ═══════════════════════════════════════════════
   Les rayures obliques du platine étaient écrites en dur dans chaque règle de surface. Le thème clair
   doit pouvoir les INVERSER (sur fond clair, c'est la ligne sombre qui grave) : sans token, il faudrait
   réécrire chaque règle, soit exactement l'opération qui a détruit 403 déclarations le 19/09.
   ⚠ AJOUTÉ EN FIN DE FEUILLE, dans un second bloc `:root` : les règles existantes gardent leur valeur
   écrite en dur, rien n'est réécrit. Seules les règles NOUVELLES consomment le token.
   ⚠ GÉOMÉTRIE : sur fond sombre la bande SOMBRE est la plus large (1px de clair, 1,5px de sombre).
   Le thème clair miroite cette proportion — c'est la bande CLAIRE qui s'élargit (constat de Ben, 19/09). */
:root{ --hachure:repeating-linear-gradient(116deg,rgba(255,255,255,.028) 0 1px,rgba(0,0,0,.03) 1px 2.5px); }

/* « Mes places » n'avait QUE le dégradé de base : ni reflet ni hachure, dans les deux thèmes. Écart
   préexistant, repéré par Ben le 19/09. On l'aligne sur `.bookbar`, dont il est le voisin direct.
   ⚠ `a.myplaces` et non `.myplaces` : la règle de page vit dans un <style> qui vient APRÈS ce fichier ;
   à spécificité égale elle gagnerait. L'élément est un <a>, la spécificité (0,1,1) tranche proprement. */
a.myplaces{
  background:
    linear-gradient(106deg,rgba(255,255,255,.11) 0%,rgba(255,255,255,0) 16%,rgba(255,255,255,.05) 30%,
                    rgba(255,255,255,0) 46%,rgba(255,255,255,.06) 64%,rgba(255,255,255,0) 100%),
    var(--hachure),
    var(--metal-grad);
}

/* ═══════════════════════════════════════════════════════════════════════════════════════════════
   POLICES HÉBERGÉES SUR JOYNUZ — plus aucune requête vers Google
   Recopie EXACTE des déclarations que sert fonts.googleapis.com pour Archivo 600-900, Inter 400-700 et
   DM Mono 400-500 : mêmes fichiers woff2, mêmes graisses, mêmes plages unicode-range, même font-display:
   swap. Seule l'adresse change (/fonts/…). Le rendu est donc identique ; le navigateur ne télécharge
   un fichier que si la page contient un caractère de sa plage (cyrillique, grec, vietnamien compris).
   Licence : SIL Open Font License 1.1, jointe dans /fonts/licences/ comme elle l'exige.
   ⚠ La CSP servie par Caddy doit autoriser font-src 'self' : sinon ces fichiers sont BLOQUÉS et tout le
   site retombe sur la police de secours. prod-check le vérifie avant chaque déploiement.
   ═══════════════════════════════════════════════════════════════════════════════════════════════ */
/* vietnamese */
@font-face{
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 600;
  font-stretch: 100%;
  font-display: swap;
  src: url(/fonts/archivo-vietnamese.woff2) format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face{
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 600;
  font-stretch: 100%;
  font-display: swap;
  src: url(/fonts/archivo-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face{
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 600;
  font-stretch: 100%;
  font-display: swap;
  src: url(/fonts/archivo-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* vietnamese */
@font-face{
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 700;
  font-stretch: 100%;
  font-display: swap;
  src: url(/fonts/archivo-vietnamese.woff2) format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face{
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 700;
  font-stretch: 100%;
  font-display: swap;
  src: url(/fonts/archivo-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face{
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 700;
  font-stretch: 100%;
  font-display: swap;
  src: url(/fonts/archivo-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* vietnamese */
@font-face{
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 800;
  font-stretch: 100%;
  font-display: swap;
  src: url(/fonts/archivo-vietnamese.woff2) format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face{
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 800;
  font-stretch: 100%;
  font-display: swap;
  src: url(/fonts/archivo-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face{
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 800;
  font-stretch: 100%;
  font-display: swap;
  src: url(/fonts/archivo-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* vietnamese */
@font-face{
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 900;
  font-stretch: 100%;
  font-display: swap;
  src: url(/fonts/archivo-vietnamese.woff2) format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face{
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 900;
  font-stretch: 100%;
  font-display: swap;
  src: url(/fonts/archivo-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face{
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 900;
  font-stretch: 100%;
  font-display: swap;
  src: url(/fonts/archivo-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@font-face{
  font-family: 'DM Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/dmmono-latin-ext-400.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face{
  font-family: 'DM Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/dmmono-latin-400.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@font-face{
  font-family: 'DM Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(/fonts/dmmono-latin-ext-500.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face{
  font-family: 'DM Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(/fonts/dmmono-latin-500.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face{
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/inter-cyrillic-ext.woff2) format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face{
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/inter-cyrillic.woff2) format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face{
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/inter-greek-ext.woff2) format('woff2');
  unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face{
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/inter-greek.woff2) format('woff2');
  unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face{
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/inter-vietnamese.woff2) format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face{
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/inter-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face{
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/inter-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face{
  font-family: 'Inter';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(/fonts/inter-cyrillic-ext.woff2) format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face{
  font-family: 'Inter';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(/fonts/inter-cyrillic.woff2) format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face{
  font-family: 'Inter';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(/fonts/inter-greek-ext.woff2) format('woff2');
  unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face{
  font-family: 'Inter';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(/fonts/inter-greek.woff2) format('woff2');
  unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face{
  font-family: 'Inter';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(/fonts/inter-vietnamese.woff2) format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face{
  font-family: 'Inter';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(/fonts/inter-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face{
  font-family: 'Inter';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(/fonts/inter-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face{
  font-family: 'Inter';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(/fonts/inter-cyrillic-ext.woff2) format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face{
  font-family: 'Inter';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(/fonts/inter-cyrillic.woff2) format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face{
  font-family: 'Inter';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(/fonts/inter-greek-ext.woff2) format('woff2');
  unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face{
  font-family: 'Inter';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(/fonts/inter-greek.woff2) format('woff2');
  unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face{
  font-family: 'Inter';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(/fonts/inter-vietnamese.woff2) format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face{
  font-family: 'Inter';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(/fonts/inter-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face{
  font-family: 'Inter';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(/fonts/inter-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face{
  font-family: 'Inter';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(/fonts/inter-cyrillic-ext.woff2) format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face{
  font-family: 'Inter';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(/fonts/inter-cyrillic.woff2) format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face{
  font-family: 'Inter';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(/fonts/inter-greek-ext.woff2) format('woff2');
  unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face{
  font-family: 'Inter';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(/fonts/inter-greek.woff2) format('woff2');
  unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face{
  font-family: 'Inter';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(/fonts/inter-vietnamese.woff2) format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face{
  font-family: 'Inter';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(/fonts/inter-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face{
  font-family: 'Inter';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(/fonts/inter-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* SÉLECTEUR DE LANGUE : un menu déroulant, cible ≥ 44 × 44 px. La pastille (.jz-lang / .lp-lang) reste déclarée
   par chaque page. */
.jz-lang-box{ position:relative; display:inline-flex; }   /* porte la flèche ; .jz-lang reste en position statique */
.jz-lang-sel{
  appearance:none; -webkit-appearance:none; border:0; background:transparent; cursor:pointer;
  font-family:inherit; font-size:var(--fs-1); font-weight:800; letter-spacing:.04em; color:var(--ink);
  min-height:44px; min-width:58px; width:auto; padding:0 var(--sp-4) 0 var(--sp-2); border-radius:999px; box-shadow:none;
}
.jz-lang-sel:focus-visible{ outline:2px solid var(--focus); outline-offset:1px; }
.jz-lang-sel option{ color:var(--ink); background-color:var(--bg); }
.jz-lang-box::after{
  content:""; position:absolute; right:14px; top:50%; width:5px; height:5px; margin-top:-4px;
  border-right:2px solid var(--ink); border-bottom:2px solid var(--ink); transform:rotate(45deg); pointer-events:none;
}

/* Liens du pied de page : zone tactile de 44 px de haut, marge intérieure compensée (aucun changement à l'écran).
   Pieds seulement : dans un paragraphe, inline-block empêcherait un lien long de passer à la ligne. */
.foot a.jz-legal, .footer a.jz-legal{ display:inline-block; padding-block:14px; margin-block:-14px; }

/* MATIÈRE MÉTAL SUR UNE CARTE TRÈS HAUTE : les hachures (2e couche) sont peintes par blocs de 571 px répétés, au
   lieu d'une seule image aussi haute que la carte. Safari iOS ne peint plus cette couche sur une carte de plusieurs
   milliers de pixels (vue Argent) : il ne restait que le reflet. 571 px = 100 périodes de la hachure à 116deg :
   les blocs se raccordent sans couture visible. Reflet et fond gardent leur taille. */
.metal{ background-size:auto, 100% 571px, auto; background-repeat:no-repeat, repeat, no-repeat; }

/* ══ PLATINE CLAIRE ════════════════════════════════════════════════════════════════════════════════
   Carte claire posée sur la page, dans les DEUX thèmes : carte d'accueil et formulaire de contact de la
   vitrine. Encres propres à cette carte (--platine-*), jamais --ink : elle reste claire quand la page
   est sombre. `.platine-dot` est la petite pièce du même métal (pastilles numérotées, boutons neutres).
   Ajouté en fin de feuille, dans un second bloc `:root` : rien d'existant n'est réécrit. */
:root{
  --platine-grad:linear-gradient(180deg,#eef0f3 0%,#c9cdd3 56%,#dee1e6 100%);
  --platine-dot-grad:linear-gradient(180deg,#f3f4f6 0%,#bec3ca 100%);
  --platine-ink:#15171b;
  --platine-text:#353a42;
  --platine-muted:#4a5059;
  --platine-base:#d9dce1;        /* teinte moyenne du métal : fond de repli, sous les dégradés */
}
.platine{
  position:relative; color:var(--platine-ink);
  background:
    linear-gradient(105deg,rgba(255,255,255,.6) 0%,rgba(255,255,255,0) 32%,rgba(255,255,255,0) 62%,rgba(255,255,255,.4) 76%,rgba(255,255,255,0) 90%),
    repeating-linear-gradient(116deg,rgba(255,255,255,.07) 0 1px,rgba(0,0,0,.035) 1px 3px),
    var(--platine-grad);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.95), inset 0 -1px 0 rgba(0,0,0,.25), 0 16px 34px -18px rgba(0,0,0,.85);
}
.platine-dot{
  color:var(--platine-ink);
  background:repeating-linear-gradient(116deg,rgba(255,255,255,.07) 0 1px,rgba(0,0,0,.04) 1px 3px), var(--platine-dot-grad);
  background-color:var(--platine-base);   /* repli sans dégradé ; c'est aussi lui que lit l'oracle de lisibilité */
  box-shadow:inset 0 1px 0 rgba(255,255,255,.95), inset 0 -1px 0 rgba(0,0,0,.3), 0 2px 6px rgba(0,0,0,.5);
}
@media (hover: hover){ a.platine-dot:hover, button.platine-dot:hover{ filter:brightness(1.03); } }
button.platine-dot[disabled]{ opacity:.6; cursor:default; }

/* ACTION PRINCIPALE À L'ACCENT DU GROUPE (« Je réserve » de /g/, « Voir les séances » de la vitrine).
   Le haut du dégradé est l'accent assombri à 92 % : le texte blanc y tient 4,6:1 sur le bleu (4,5 requis à
   16 px gras), 5,2 sur le rouge, 4,9 sur le violet. ⚠ Le vert (3,0) et l'ambre (2,0) restent sous le seuil,
   comme avant cette règle : défaut connu, à trancher à part. */
.cta.cta-accent{
  background:linear-gradient(180deg,color-mix(in srgb,var(--accent) 92%,var(--shade)) 0%,color-mix(in srgb,var(--accent) 70%,var(--shade)) 100%);
  color:var(--white);
  border:1px solid color-mix(in srgb,var(--accent) 70%,var(--shade));
  box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 4px 10px rgba(0,0,0,.35);
}

/* ── .estampe-claire — le CODE de réservation sur la carte PLATINE CLAIRE (/r/). Face assombrie dans la teinte
      de la platine, arêtes claire et sombre. ⚠ MÊME DÉROGATION BORNÉE que `.estampe` (D8) : face ≥ 2,1:1 au point
      le plus sombre de la platine (#808996 sur #c9cdd3 : 2,2), et seulement là où le code est AUSSI écrit en clair
      sur la page (la communication du virement). ── */
:root{ --estampe-claire:#808996; }
.estampe-claire{ color:var(--estampe-claire); text-shadow:0 1px 0 rgba(255,255,255,.95), 0 -1px 0 rgba(0,0,0,.42); }

/* MARQUE COMPACTE : sur un en-tête qui porte aussi langue, thème et une action (console), la marque prend une
   marche de moins sur téléphone pour que la rangée tienne sur une ligne. */
.brandmark.bm-compact{ flex:none; }
@media (max-width:560px){
  .brandmark.bm-compact{ font-size:var(--fs-6); }
  .brandmark.bm-compact .bm-u{ width:22px; }
}

/* Pied B : les liens sur une ligne espacée, cibles de 44 px sans marge négative ; « © 2026 Joynuz » seul dessous. */
.foot .foot-links{ display:flex; flex-wrap:wrap; justify-content:center; column-gap:var(--sp-4); }
.foot .foot-links a.jz-legal{ display:inline-flex; align-items:center; min-height:44px; padding-block:0; margin-block:0; }
.foot .foot-copy{ margin:var(--sp-1) 0 0; }

/* Encart « Qui tu emmènes ? » de /b/ : titre, texte, bouton sur toute la largeur. */
.inv-card{ display:flex; flex-direction:column; gap:var(--sp-2); padding:var(--sp-2) var(--sp-3); border-radius:20px; }
.inv-card .inv-h{ margin:0; font-family:var(--font-display); font-weight:800; font-size:var(--fs-5); color:var(--ink); }
.inv-card p{ margin:0; font-size:var(--fs-3); line-height:1.4; color:var(--ink); }
.foot-invite{ min-height:44px; padding:0 var(--sp-3); border-radius:22px; font-weight:700; font-size:var(--fs-3); cursor:pointer; font-family:inherit; background:transparent; }

/* Retour d'un niveau, en haut à gauche de /b/ (Séances) et de /r/ (Mes places, ou Séances) : un seul retour par page. */
.r-back{ display:inline-flex; align-items:center; gap:var(--sp-0); min-height:44px; margin-right:auto; color:var(--ink); font-weight:600; font-size:var(--fs-3); text-decoration:none; white-space:nowrap; }
.r-back[hidden]{ display:none; }

/* ══ JOYFUL — vitrine et /host (règles : docs/MARQUE-joyful-2026-11.md) ══
   Ajouts seulement. Images servies depuis /img/ (nom = empreinte), police manuscrite réduite aux annotations. */
@font-face{
  font-family:'Caveat'; font-style:normal; font-weight:500; font-display:swap;
  src:url('/fonts/caveat-script-500.woff2') format('woff2');
}
:root{
  --font-script:'Caveat',cursive;
  /* icônes de « Ce qui change ici » : ≥ 4:1 sur .surface dans les deux thèmes */
  --ocre:#a76900; --petrole:#008489; --vert-fonce:#00893e; --prune:#b24cb9;
  /* pastille bleue : chiffre blanc à 4,63:1 (sur --blue il plafonne à 3,98) */
  --blue-fill:#2f6fe6;
  --pastille-1:var(--amber); --pastille-2:var(--blue-fill); --pastille-3:var(--green); --pastille-4:var(--red);
  --pastille-ink-dark:var(--on-white); --pastille-ink-light:var(--white);
}
/* Signature du héros : le sourire du logo à gauche, une annotation manuscrite à droite. */
.jz-sign{ display:flex; align-items:flex-start; justify-content:space-between; gap:var(--sp-1); margin-top:var(--sp-1); }
.jz-smile{ display:block; width:56px; height:18px; flex:none; }
.jz-smile path{ fill:none; stroke:var(--red); stroke-width:5; stroke-linecap:round; }
.jz-script{ display:inline-block; font-family:var(--font-script); font-weight:500; font-size:var(--fs-6); line-height:1.05;
  color:var(--platine-ink); transform:rotate(-6deg); text-align:left; }
/* Mosaïque : chaque photo entière. La première sur toute la largeur ; les deux suivantes (même format) côte à côte,
   posées sur son bas avec un liseré de la teinte de la carte. Le retrait vertical (en % de la largeur d'une
   colonne) recouvre environ le dernier tiers de la première photo. */
.jz-mosaic{ display:grid; grid-template-columns:1fr 1fr; gap:var(--sp-1); margin:var(--sp-3) 0 var(--sp-0); }
.jz-mosaic > picture{ display:block; min-width:0; }
.jz-mosaic > picture:first-child{ grid-column:1 / -1; }
.jz-mosaic > picture + picture{ position:relative; margin-top:calc(-50% - var(--sp-1)); }
.jz-mosaic img{ display:block; width:100%; height:auto; border-radius:14px; }
.jz-mosaic > picture + picture img{ box-shadow:0 0 0 3px var(--platine-base); }
/* Image dans une carte. */
.jz-media{ display:block; margin:var(--sp-3) 0 var(--sp-2); }
.jz-media img{ display:block; width:100%; height:auto; aspect-ratio:16/9; object-fit:cover; border-radius:16px; }
/* Deux images l'une sous l'autre, chacune à son format (fichiers déjà recadrés). */
.jz-media-pair{ display:grid; gap:var(--sp-1); }
.jz-media-pair img{ aspect-ratio:auto; border-radius:14px; }
/* Image pleine largeur qui se fond dans le fond de page, sans cadre. */
.jz-fade{ display:block; margin-inline:calc(-1 * var(--gutter)); }
.jz-fade img{ display:block; width:100%; height:auto; object-fit:cover;
  -webkit-mask-image:linear-gradient(to bottom,transparent 0,#000 18%,#000 68%,transparent 100%);
          mask-image:linear-gradient(to bottom,transparent 0,#000 18%,#000 68%,transparent 100%); }
/* Bandeau de trois messages. */
.jz-band{ display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:var(--sp-1); margin-top:calc(-1 * var(--sp-4)); position:relative; }
.jz-band > div{ display:flex; flex-direction:column; align-items:center; gap:var(--sp-0); min-width:0; text-align:center;
  font-size:var(--fs-3); line-height:1.3; color:var(--ink); }
.jz-band svg{ width:30px; height:30px; color:var(--ink-muted); }
.jz-band svg.jz-band-smile{ color:var(--red); }
/* Icône de carte, au-dessus du titre. */
.jz-ic{ display:block; width:26px; height:26px; margin-bottom:var(--sp-0); fill:none; stroke-width:1.8; stroke-linecap:round; stroke-linejoin:round; }
.jz-ic-1{ stroke:var(--ocre); } .jz-ic-2{ stroke:var(--petrole); } .jz-ic-3{ stroke:var(--vert-fonce); }
.jz-ic-4{ stroke:var(--prune); } .jz-ic-5{ stroke:var(--blue); } .jz-ic-6{ stroke:var(--red); }
/* Pastilles numérotées en couleur (« Comment ça marche ») : pas une action, pas de matière (D3). */
.jz-step{ border:0; box-shadow:0 2px 6px rgba(0,0,0,.28); }
.jz-step-1{ background:var(--pastille-1); color:var(--pastille-ink-dark); }
.jz-step-2{ background:var(--pastille-2); color:var(--pastille-ink-light); }
.jz-step-3{ background:var(--pastille-3); color:var(--pastille-ink-dark); }
.jz-step-4{ background:var(--pastille-4); color:var(--pastille-ink-light); }
/* Étiquettes non cliquables (onglets de la console sur /host). */
.jz-tags{ display:flex; flex-wrap:wrap; gap:var(--sp-1); list-style:none; margin:var(--sp-2) 0 0; padding:0; }
.jz-tags li{ padding:var(--sp-0) var(--sp-2); border-radius:999px; border:1px solid var(--line); font-size:var(--fs-3); color:var(--ink); }
/* Bandeau de quatre messages, en 2×2, icône à gauche. */
.jz-band-4{ grid-template-columns:repeat(2,minmax(0,1fr)); row-gap:var(--sp-2); column-gap:var(--sp-2); }
.jz-band-4 > div{ flex-direction:row; align-items:center; gap:var(--sp-1); text-align:left; }
.jz-band-4 svg{ flex:none; }
/* Fondu d'une phrase posée sur le bas d'une photo, vers le fond de la carte. */
:root{ --photo-fade:rgba(22,24,28,.94); }
/* Fond plein sous le métal de la platine, caché par le dégradé opaque : c'est lui que lit l'oracle de lisibilité. */
.platine{ background-color:var(--platine-base); }
/* Étiquettes posées sur la platine : encres de la carte, jamais --ink (claire en thème sombre). */
.platine .jz-tags li{ color:var(--platine-text); border-color:var(--platine-muted); }
