/* ABC Canada 2027 — homepage.
   Implementation of "Homepage ABC Canada 2027.dc.html" (Claude Design).
   Everything here builds on assets/css/modernist.css — colors, type, spacing
   and radius come from its tokens. The few literal values that remain are the
   ones the design itself sets: the fluid clamp() ramps and the section rules. */

/* ── Fluid ramps used across the page ─────────────────────────────────── */
:root {
  --pad-x: clamp(20px, 5vw, 80px);
  --section-y: clamp(72px, 9vw, 132px);
  --section-y-tight: clamp(56px, 6vw, 88px);
  --wrap: 1280px;
  /* Le rail : le bord gauche du contenu, partout et à toutes les largeurs.
     C'est exactement ce que produit le patron « padding sur la section, .wrap
     centré dedans » — la gouttière tant qu'elle mène, la marge du .wrap une
     fois qu'il plafonne. Les blocs pleine largeur (l'en-tête, la bande des
     ambassadeurs) s'y raccrochent au lieu de recalculer leur propre inset.
     Le pourcentage se résout sur le bloc conteneur : à ne poser que sur un
     élément aussi large que la page. */
  --rail: max(var(--pad-x), calc((100% - var(--wrap)) / 2));

  --rule: 2px solid rgba(32, 30, 29, .4);
  --rule-soft: 2px solid rgba(32, 30, 29, .15);
  --hair: 1px solid rgba(32, 30, 29, .2);
  --rule-inverse: 2px solid rgba(243, 242, 242, .25);

  /* Accessible text colours. The Modernist readme is explicit that the raw
     accent only clears 3:1 on this ground — fine for display type, chrome and
     icons, not for label-size text — so small accent text uses the deep ramp
     step it prescribes. The muted inks are set at the lowest alpha that still
     clears 4.5:1, since WCAG AA is a requirement of the brief. */
  /* Le rouge du Canada, pour les boutons. Pantone 186 C — celui des équipes
     nationales — plutôt que le 032 C du drapeau imprimé (#ef3340) : ce dernier
     ne tient que 3.6:1 sous une étiquette claire, quand le 186 en tient 5.27.
     La rampe entière reste au-dessus de 4.5:1, donc les libellés de boutons
     passent AA — ce que le rouge vermillon de la maquette ne faisait pas. */
  --canada-deep: #8f0a24;                          /* 7.05:1 */
  --canada-red: #c8102e;                           /* 5.27:1 */
  --canada-lift: #d81b34;                          /* 4.55:1 */
  --canada-grad: linear-gradient(100deg,
    var(--canada-deep) 0%, var(--canada-red) 30%, var(--canada-lift) 50%,
    var(--canada-red) 70%, var(--canada-deep) 100%);

  --accent-text: var(--color-accent-700);          /* 6.41:1 on --color-bg */
  --ink-muted: rgba(32, 30, 29, .65);              /* 4.96:1 on --color-bg */
  --ink-60: rgba(32, 30, 29, .65);
  --ink-50: rgba(32, 30, 29, .65);
  --ground-70: rgba(243, 242, 242, .7);
  --ground-55: rgba(243, 242, 242, .55);
}

/* L'en-tête est mesuré par site.js (--header-h) : un décalage écrit en dur
   laisse l'ancre sous le bandeau sur mobile, où il ne fait plus 82px. */
html { scroll-behavior: smooth; scroll-padding-top: calc(var(--header-h, 82px) + 14px); }
body { overflow-x: hidden; }

/* Skip link — first stop for keyboard and screen-reader users. */
.skip-link {
  position: absolute; left: var(--space-2); top: -100px; z-index: 200;
  padding: var(--space-3) var(--space-4);
  background: var(--color-text); color: var(--color-bg);
  font-weight: var(--font-heading-weight); text-decoration: none;
  transition: top .15s ease;
}
.skip-link:focus { top: var(--space-2); }

.wrap { max-width: var(--wrap); margin: 0 auto; }
/* Un .wrap posé dans une section sans padding porte lui-même la gouttière.
   Le plafond monte alors de deux gouttières : sinon le contenu perd
   2 × --pad-x et démarre plus à droite que le reste de la page. */
.wrap--padded {
  max-width: calc(var(--wrap) + 2 * var(--pad-x));
  padding-inline: var(--pad-x);
}
.section { padding: var(--section-y) var(--pad-x); border-bottom: var(--rule); }
.section--flush { padding: 0; border-bottom: var(--rule); }
.eyebrow {
  margin: 0 0 20px; font-size: 12px; letter-spacing: .18em;
  font-weight: 600; color: var(--accent-text);
}
.eyebrow--inverse { color: var(--color-accent-400); }

/* Section headline: light by default, the emphasised half in 800.
   Never centred — Modernist keeps everything flush left. */
.h-section {
  margin: 0; font-weight: 400; letter-spacing: -.025em; line-height: 1.04;
  font-size: clamp(30px, 3.6vw, 52px);
}
.h-section strong { font-weight: var(--font-heading-weight); }
.h-section--lg { font-size: clamp(34px, 4.4vw, 64px); line-height: 1.02; }
.h-section--gap { margin-bottom: 48px; }

/* Texte réservé aux lecteurs d'écran — libellés de champs et annonces live. */
.u-sr {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; white-space: nowrap; border: 0; clip-path: inset(50%);
}

/* ── Boutons ──────────────────────────────────────────────────────────────
   modernist.css pose `.btn-primary { background: var(--color-accent) }` ; on
   passe devant avec la rampe canadienne. Le survol se joue au filtre plutôt
   qu'à la couleur : un `background-image` ne s'interpole pas, une luminosité
   si. */
.btn-primary { background: var(--canada-grad); color: var(--color-bg); }
.btn-primary:hover { background: var(--canada-grad); filter: brightness(1.08) saturate(1.03); }
.btn-primary:active { background: var(--canada-grad); filter: brightness(.93); }

/* Les boutons « prendre mes billets ». Le dégradé y respire : une nappe plus
   large que le bouton, translatée d'un bord à l'autre en aller-retour — c'est
   une transformation, donc composée par le GPU, sans repeindre à chaque image.
   `z-index: -1` sous `isolation: isolate` la garde derrière le libellé sans
   sortir du bouton. */
.btn-cta { position: relative; isolation: isolate; overflow: hidden; }
.btn-cta::before {
  content: ""; position: absolute; inset: 0 -45%; z-index: -1;
  background: var(--canada-grad);
  animation: cta-drift 9s ease-in-out infinite alternate;
}
@keyframes cta-drift {
  from { transform: translateX(-13%); }
  to   { transform: translateX(13%); }
}

/* Le reflet : une seule passe au survol et au focus, pas une boucle. */
.btn-cta::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(100deg,
    transparent 38%, rgba(255, 255, 255, .26) 50%, transparent 62%);
  transform: translateX(-130%);
  pointer-events: none;
}
.btn-cta:hover::after,
.btn-cta:focus-visible::after { animation: cta-sheen .72s ease-out; }
@keyframes cta-sheen {
  from { transform: translateX(-130%); }
  to   { transform: translateX(130%); }
}

.dagger { color: var(--accent-text); font-size: .55em; }
.dagger--inverse { color: var(--color-accent-500); }

/* ── Image slot ───────────────────────────────────────────────────────────
   The design's <image-slot>. Renders the photograph when it exists and the
   art-direction brief when it does not, so a missing asset degrades into a
   legible placeholder rather than a broken image. */
.slot {
  position: relative; width: 100%; height: 100%; overflow: hidden;
  background: var(--color-neutral-300);
}
.slot img { width: 100%; height: 100%; object-fit: cover; }
.slot-note {
  position: absolute; inset: 0; margin: 0;
  display: none; align-items: flex-end;
  padding: var(--space-4);
  font-size: 12px; letter-spacing: .06em; text-transform: uppercase;
  color: var(--color-neutral-700);
  background:
    repeating-linear-gradient(
      -45deg,
      transparent 0 14px,
      rgba(32, 30, 29, .05) 14px 15px);
}
.slot[data-missing] img { display: none; }
.slot[data-missing] .slot-note { display: flex; }

/* Full-bleed slots sit under white type, so an empty one has to stay dark
   enough for the headline over it to remain readable. */
.hero .slot, .bleed .slot { background: var(--color-neutral-800); }
.hero .slot-note, .bleed .slot-note {
  align-items: flex-start;
  color: var(--color-neutral-400);
  background: repeating-linear-gradient(
    -45deg, transparent 0 14px, rgba(243, 242, 242, .06) 14px 15px);
}

/* ── Header ───────────────────────────────────────────────────────────── */
.site-header {
  position: sticky; top: 0; z-index: 50;
  display: flex; flex-wrap: wrap; align-items: center; gap: 16px 40px;
  /* 6px en haut et en bas, pas 12 : depuis que la marque n'est plus que le
     sceau, c'est lui qui prend la hauteur — plus grand, dans la meme barre. */
  min-height: 80px; padding: 6px var(--rail);
  background: var(--color-bg); border-bottom: var(--rule);
}
.brand {
  display: flex; align-items: center; gap: 14px;
  text-decoration: none; color: inherit; margin-right: auto; flex: none;
}
.brand img { width: 48px; height: 48px; object-fit: contain; }

/* ── Le sceau : le logo Binam Canada et son cartouche « GrassfieldLand » ──
   Le meme partout (abc2027_sceau()) : cadre marine, lettrage rouge et gras,
   les couleurs du cartouche du logo ABC. Le logo garde la taille de son
   contexte ; la lettre du cartouche ne descend jamais sous 8px (`--sceau-nom`),
   la ou une simple reduction l'aurait rendue illisible a cote d'un logo de 32.
   La version de l'affiche de la prevente, construite sur la geometrie exacte
   du logo ABC, est a part (.prevente-logo-binam). */
.sceau {
  --sceau-nom: 9px;
  display: inline-flex; flex-direction: column; align-items: center; gap: 3px; flex: none;
}
.sceau > img { display: block; }
.sceau-nom {
  display: block; padding: .15em .45em;
  border: max(1.5px, .14em) solid #232a78; background: #fff; color: #c62034;
  font-size: var(--sceau-nom); line-height: 1.15; font-weight: 800;
  letter-spacing: 0; white-space: nowrap;
}
/* L'en-tete garde sa hauteur : le logo cede ce que le cartouche prend. */
.sceau--tete { --sceau-nom: 10px; gap: 2px; }
.brand .sceau--tete > img { width: 50px; height: 50px; }
/* Le sceau ressort du bandeau clair comme il ressort de l'encre au pied :
   la-bas un halo clair, ici son pendant — une ombre douce qui suit le cercle
   (drop-shadow, pas box-shadow), et le cartouche pose dessus. */
.sceau--tete > img {
  filter: drop-shadow(0 0 1px rgba(32, 30, 29, .35)) drop-shadow(0 3px 8px rgba(32, 30, 29, .25));
}
/* Le menu mobile est a l'encre : le halo clair du pied de page. */
.sceau--menu > img {
  filter: brightness(1.08) drop-shadow(0 0 1px rgba(243, 242, 242, .55)) drop-shadow(0 0 10px rgba(243, 242, 242, .18));
}
.sceau--tete > .sceau-nom { box-shadow: 0 2px 6px rgba(32, 30, 29, .14); position: relative; }
.sceau--orga { --sceau-nom: 8px; }
/* Le menu se pose sur le bandeau mobile : meme sceau, au pixel pres. */
.sceau--menu { --sceau-nom: 8.5px; gap: 2px; }
.mobile-menu-brand .sceau--menu > img { width: 43px; height: 43px; }
.sceau--fiche { --sceau-nom: 9.5px; }
.sceau--pied { --sceau-nom: 12px; gap: 5px; margin-bottom: 18px; }
.sceau--pied > .footer-sceau { margin-bottom: 0; }
.brand-lines { display: flex; flex-direction: column; line-height: 1.05; }
.brand-name {
  font-weight: var(--font-heading-weight); font-size: 15px;
  letter-spacing: -.01em; white-space: nowrap;
}
.brand-name-short { display: none; }
.brand-edition {
  font-size: 11px; letter-spacing: .16em; color: var(--accent-text); font-weight: 600;
}

.nav-main { display: flex; flex-wrap: wrap; gap: 12px 26px; font-size: 14px; }
.nav-main a { color: inherit; text-decoration: none; white-space: nowrap; }
.nav-main a:hover,
.nav-main a[aria-current="true"] { color: var(--accent-text); }

.header-end { display: flex; align-items: center; gap: 18px; flex: none; }

.btn-ticket {
  height: 48px; padding: 0 26px; font-size: 14px;
  letter-spacing: .04em; white-space: nowrap; flex: none;
}

/* ── Panier ───────────────────────────────────────────────────────────────
   Le seul chemin de retour vers une commande commencée. Il reste dans le
   bandeau à toutes les largeurs — le bouton billets, lui, s'efface sous 760px,
   mais un panier qu'on ne retrouve plus est un panier qu'on abandonne.

   Icône seule dans le bandeau, jamais sans nom : le libellé complet est porté
   par .cart-link-sr, qui donne au lien le nom « Panier, 3 billets ». La
   pastille rouge n'est qu'un doublon visuel de ce nom — d'où aria-hidden. */
.cart-link {
  position: relative; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  width: 48px; height: 48px;
  color: inherit; text-decoration: none;
}
.cart-link-icon { display: block; width: 22px; height: 22px; }
.cart-link:hover,
.cart-link[aria-current="page"] { color: var(--accent-text); }
.cart-link:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }
/* Le compte. Carré, comme tout le reste du système : --radius-md vaut 0. */
.cart-link-count {
  position: absolute; top: 5px; right: 1px;
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 18px; height: 18px; padding: 0 4px;
  background: var(--canada-red); color: var(--color-bg);
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 11px; line-height: 1; letter-spacing: 0;
}
/* Le nom du lien, lu et non vu. */
.cart-link-sr {
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

/* Hamburger — only below the desktop breakpoint. */
.nav-toggle {
  display: none; width: 48px; height: 48px; padding: 0;
  align-items: center; justify-content: center;
  background: none; border: 0; cursor: pointer; color: inherit;
}
.nav-toggle span {
  display: block; width: 26px; height: 2px; background: currentColor;
  position: relative;
}
.nav-toggle span::before,
.nav-toggle span::after {
  content: ""; position: absolute; left: 0; width: 26px; height: 2px;
  background: currentColor;
}
.nav-toggle span::before { top: -8px; }
.nav-toggle span::after { top: 8px; }

/* ── Hero (photo treatment — the design's default) ────────────────────── */
/* Le hero occupe exactement ce qui reste sous l'en-tête : une vue pleine,
   rien à faire défiler pour la voir entière. La hauteur d'en-tête est
   mesurée par site.js — l'écrire en dur casserait dès que la navigation
   passe sur deux lignes — et ces valeurs sont le repli avant la mesure.
   --hero-safe-b réserve la barre de billets fixe du mobile, sinon elle
   recouvre le rail. */
:root {
  --header-h: 82px;
  --hero-safe-b: 0px;
  --hero-fade: 620ms cubic-bezier(.22, 1, .36, 1);
}

.hero {
  position: relative;
  /* svh est la hauteur de vue barre d'adresse déployée : le hero ne se
     recadre donc pas quand elle se rétracte en cours de défilement. */
  height: calc(100vh - var(--header-h));
  height: calc(100svh - var(--header-h));
  display: flex;
  border-bottom: var(--rule);
}
.hero-media {
  position: absolute; inset: 0; overflow: hidden; z-index: 0;
  background: var(--color-neutral-800);
}
/* Une vue par cadre, empilés. Le cadre sortant garde son opacité pleine sous
   le cadre entrant le temps du fondu (is-prev) : sans lui les deux sont
   translucides en même temps et le fond sombre du média traverse. */
.hero-frame {
  position: absolute; inset: 0; z-index: 0;
  opacity: 0;
  transition: opacity var(--hero-fade);
}
.hero-frame.is-prev { opacity: 1; z-index: 1; }
.hero-frame.is-current { opacity: 1; z-index: 2; }

.hero-img,
.hero-video {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover;
}
/* La vidéo se pose sur l'image de sa propre vue et n'est révélée qu'une fois
   qu'elle joue réellement : un autoplay refusé ou un départ lent ne montre
   jamais une image vide, la photographie tient la vue. */
.hero-video { z-index: 1; opacity: 0; transition: opacity var(--hero-fade); }
.hero-video.is-playing { opacity: 1; }

/* The scrim stretches over the whole hero and fades to nothing at the top.
   In the design it was only as tall as its own content box, which put a hard
   78%-black edge across the photograph; this keeps the same darkness behind
   the type and removes the seam. */
.hero-overlay {
  position: relative; z-index: 1;
  align-self: stretch;
  width: 100%;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  /* Les marges suivent la hauteur de vue autant que la largeur : sur un
     portable en paysage, un padding en vw seul mange toute la place. */
  padding:
    clamp(32px, 6vh, 96px)
    var(--pad-x)
    calc(clamp(20px, 3.4vh, 44px) + var(--hero-safe-b));
  /* Two axes, not one. A single bottom-up scrim heavy enough to carry the type
     also buries the video. The column layer darkens the left, where the type
     actually sits, and releases the right where the faces are; the base layer
     only weights the lower band, so the top of the frame stays clear. */
  background:
    /* A pool anchored to the bottom-left, where the type sits. Being radial it
       falls off in both directions at once — a second linear axis would have
       darkened the top-left too, which is frame nobody is reading over. */
    /* Centred on the text block rather than the very bottom edge. The bottom
       was carrying 13:1 where 4.5 is needed — that surplus is better spent up
       at the eyebrow, which is the one line the scrim actually struggles with. */
    radial-gradient(105% 135% at 0% 86%,
      rgba(32, 30, 29, .86) 0%,
      rgba(32, 30, 29, .72) 34%,
      rgba(32, 30, 29, .36) 62%,
      rgba(32, 30, 29, 0) 88%),
    /* Base weight on the lower band only, so the top of the frame stays clear. */
    linear-gradient(to top,
      rgba(32, 30, 29, .80) 0%,
      rgba(32, 30, 29, .74) 30%,
      rgba(32, 30, 29, .60) 52%,
      rgba(32, 30, 29, .36) 68%,
      rgba(32, 30, 29, .12) 85%,
      rgba(32, 30, 29, 0) 100%);
}
.hero-inner {
  width: 100%; max-width: var(--wrap); margin-inline: auto;
  color: var(--color-bg);
}
.hero .eyebrow { color: var(--color-bg); }
/* La rampe tient sur les deux axes. min(vw, vh) fait céder celui qui manque :
   un 1440×700 prend la mesure en hauteur, un téléphone celle en largeur. */
/* Réglé pour de la casse mixte, pas pour des capitales : les bas-de-casse
   n'ont ni la chasse ni la hauteur des capitales, donc l'approche de -.035em
   collait les lettres de « Bamiléké » et l'interligne de .9 — calculé sur des
   capitales sans jambages — ouvrait un trou entre les deux lignes. */
.hero h1 {
  margin: 0; font-size: clamp(40px, min(8vw, 12.4vh), 124px); line-height: .85;
  letter-spacing: -.022em; font-weight: var(--font-heading-weight);
}
/* La signature d'edition. Elle appartient au titre et doit peser : deux fois
   la taille d'un cartouche discret, en capitales largement espacees, tenue par
   deux filets rouges qui l'inscrivent dans la largeur.

   Le lettrage reste clair — sur la video du hero, un texte rouge tombe sous
   4.5:1 selon l'image qui defile dessous. Le festif vient d'un reflet dore qui
   traverse les lettres : il ECLAIRCIT, donc il ne peut pas degrader le
   contraste, contrairement a une couleur de remplissage.

   Le fond degrade est decoupe sur le texte ; sans le support de
   background-clip, la couleur unie du repli s'applique et rien ne disparait. */
.hero-edition {
  display: flex; align-items: center; gap: clamp(12px, 1.6vw, 26px);
  margin-top: clamp(8px, 1.4vh, 18px);
  font-size: clamp(19px, min(3.3vw, 4.6vh), 52px);
  letter-spacing: .26em; text-transform: uppercase;
  font-weight: var(--font-heading-weight);
  /* Le titre est en line-height .85, et splitLines() masque chaque ligne par un
     overflow:hidden. A cette hauteur, l'accent d'un E majuscule sort de la boite
     et se fait rogner : « MONTREAL » au lieu de « MONTRÉAL ». */
  line-height: 1.3;
  color: var(--color-bg);
  white-space: nowrap;
}
/* Les deux filets : celui de gauche fixe, celui de droite prend le reste de la
   ligne. La signature occupe alors toute la largeur du titre. */
.hero-edition::before,
.hero-edition::after {
  content: ""; display: block; height: clamp(3px, .5vh, 6px);
  background: var(--canada-grad);
}
.hero-edition::before { width: clamp(30px, 5vw, 96px); flex: none; }
.hero-edition::after { flex: 1 1 auto; min-width: 20px; opacity: .5; }

@supports (background-clip: text) or (-webkit-background-clip: text) {
  .hero-edition {
    background-image: linear-gradient(
      100deg,
      var(--color-bg) 0%, var(--color-bg) 42%,
      #ffd98a 50%,
      var(--color-bg) 58%, var(--color-bg) 100%
    );
    background-size: 320% 100%;
    background-position: 100% 0;
    -webkit-background-clip: text; background-clip: text;
    -webkit-text-fill-color: transparent; color: transparent;
    animation: hero-edition-reflet 7s ease-in-out 1.4s infinite;
  }
  /* Les filets ne sont pas du texte : ils reprennent leur propre fond. */
  .hero-edition::before,
  .hero-edition::after { -webkit-text-fill-color: initial; }
}

@keyframes hero-edition-reflet {
  0%, 62%, 100% { background-position: 100% 0; }
  92%           { background-position: 0 0; }
}

/* Les dates, seconde ligne de la signature. Le meme registre — capitales
   largement espacees — mais a un tiers de sa taille et sans le reflet : elles
   precisent, elles ne signent pas. Le retrait reprend le filet de gauche et
   son ecart, pour qu'elles tombent sous « MONTRÉAL » et se lisent avec lui,
   non comme une troisieme accroche calee a gauche entre le titre et la
   devise. Le lettrage reste clair, pour la meme raison que la signature. */
.hero-dates {
  margin: clamp(4px, .8vh, 10px) 0 0;
  padding-left: calc(clamp(30px, 5vw, 96px) + clamp(12px, 1.6vw, 26px));
  font-size: clamp(13px, min(1.35vw, 1.9vh), 20px);
  letter-spacing: .22em; text-transform: uppercase; font-weight: 600;
  line-height: 1.3;
  color: var(--color-bg);
}

.hero-tagline {
  margin: clamp(12px, 2.6vh, 28px) 0 0;
  font-size: clamp(17px, min(2.2vw, 3.1vh), 30px); font-weight: 400;
}
.hero-tagline strong { font-weight: var(--font-heading-weight); }
.hero-actions {
  display: flex; flex-wrap: wrap; gap: clamp(10px, 1.6vh, 16px);
  margin-top: clamp(18px, 3.2vh, 32px);
}
.hero-actions .btn { height: clamp(46px, 7vh, 56px); font-size: clamp(14px, 1.8vh, 16px); }
.hero-actions .btn-primary { padding: 0 32px; letter-spacing: .04em; }

/* ── Le spot de presentation ───────────────────────────────────────────
   Une icone, poussee a droite, pas un troisieme bouton texte : les deux CTA
   garderaient sinon a se partager l'attention. Les ondes appellent le clic.

   Carrees et non rondes : le systeme pose --radius-md a 0, tout y est a angles
   vifs. Un rond ici serait la seule exception de la page.

   Masquee hors .js, ou elle n'ouvrirait rien. */
.hero-spot { display: none; }
.js .hero-spot {
  position: relative; flex: none; margin-left: auto;
  display: grid; place-items: center; padding: 0;
  width: clamp(52px, 8vh, 64px); height: clamp(52px, 8vh, 64px);
  background: none; border: 0; color: var(--color-bg); cursor: pointer;
}
/* WCAG 2.2 : l'anneau reste visible et contraste. */
.js .hero-spot:focus-visible,
.spot-close:focus-visible { outline: 2px solid currentColor; outline-offset: 3px; }

.hero-spot-play {
  position: relative; z-index: 1;
  display: grid; place-items: center; width: 100%; height: 100%;
  background: var(--canada-red); color: var(--color-bg);
  transition: transform .18s ease, filter .18s ease;
}
.js .hero-spot:hover .hero-spot-play,
.js .hero-spot:focus-visible .hero-spot-play { transform: scale(1.07); filter: brightness(1.1); }

/* Deux ondes decalees d'une demi-periode : il y en a toujours une en train de
   s'ouvrir, sans que l'ensemble clignote. */
.hero-spot-onde {
  position: absolute; inset: 0; z-index: 0;
  border: 1px solid var(--canada-red);
  animation: hero-spot-onde 2.4s ease-out infinite;
}
.hero-spot-onde:nth-of-type(2) { animation-delay: 1.2s; }
@keyframes hero-spot-onde {
  0%   { transform: scale(1); opacity: .6; }
  100% { transform: scale(2.2); opacity: 0; }
}

/* La fenetre. showModal() la place dans le top layer : ni transformation ni
   debordement d'ancetre ne peuvent la rogner. */
.spot-modal {
  padding: 0; border: 0; background: var(--color-text);
  width: min(92vw, 1100px); max-height: 88vh;
  color: var(--color-bg);
}
.spot-modal::backdrop { background: rgba(20, 19, 18, .88); }
.spot-video { display: block; width: 100%; height: auto; max-height: 88vh; background: #000; }
.spot-close {
  position: absolute; top: 0; right: 0; z-index: 2;
  display: grid; place-items: center; width: 44px; height: 44px;
  background: var(--color-text); border: 0; color: var(--color-bg); cursor: pointer;
}
.spot-close:hover { background: var(--canada-red); }

@media (max-width: 760px) {
  /* Empiles, des boutons de largeurs differentes donnent des bords en escalier.
     Pleine largeur : une seule colonne, un seul alignement. */
  .hero-actions .btn { width: 100%; }
  .js .hero-spot { margin-left: auto; }
  .spot-modal { width: 100vw; }
}

@media (prefers-reduced-motion: reduce) {
  .hero-edition { animation: none; background-position: 100% 0; }
  .hero-spot-onde { animation: none; opacity: .45; }
  .hero-spot-play { transition: none; }
  .js .hero-spot:hover .hero-spot-play,
  .js .hero-spot:focus-visible .hero-spot-play { transform: none; }
}

/* ── Rail des vues ─────────────────────────────────────────────────────────
   Deux vues nommées, pas des pastilles : le rail dit ce que l'on regarde et
   laisse y revenir. La règle de 2px du système — celle qui sépare déjà toutes
   les sections — y sert de jauge : elle se remplit à l'accent pendant la vue
   en cours. Le bouton de pause n'est pas une option : une vue qui se change
   toute seule doit pouvoir être arrêtée (WCAG 2.2.2).
   Hors .js le rail ne pilote rien, donc il ne s'affiche pas. */
.hero-rail { display: none; }
.js .hero-rail {
  display: flex; align-items: flex-end; gap: clamp(16px, 3vw, 32px);
  width: 100%; max-width: var(--wrap); margin: clamp(20px, 3.4vh, 44px) auto 0;
}
.hero-views {
  display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
  gap: clamp(12px, 2vw, 24px);
  flex: 1 1 auto; min-width: 0; max-width: 560px;
  list-style: none; margin: 0; padding: 0;
}
.hero-view {
  display: grid; grid-template-columns: auto 1fr; align-items: baseline;
  column-gap: 10px; width: 100%; text-align: left;
  margin: 0; padding: 10px 0 0; border: 0; background: none;
  font: inherit; color: var(--ground-70); cursor: pointer;
  transition: color 200ms ease;
}
.hero-view:hover { color: var(--color-bg); }
.hero-view[aria-current="true"] { color: var(--color-bg); }
/* L'anneau de focus global est à l'accent ; sur une photographie sombre le
   blanc du fond est le seul contraste garanti. */
.hero-view:focus-visible,
.hero-toggle:focus-visible { outline: 2px solid var(--color-bg); outline-offset: 3px; }

.hero-view-rule {
  grid-column: 1 / -1;
  display: block; height: 2px; margin-bottom: 12px;
  /* Assez clair pour tenir les 3:1 des éléments non textuels même quand le
     bas de la photographie est presque blanc sous le voile. */
  background: rgba(243, 242, 242, .45);
  overflow: hidden;
}
.hero-view-fill {
  display: block; height: 100%; width: 100%;
  background: var(--color-accent);
  transform: scaleX(0); transform-origin: left center;
}
@keyframes hero-fill { from { transform: scaleX(0); } to { transform: scaleX(1); } }
/* La jauge n'anime que pendant la rotation. data-hold la met en pause là où
   elle est — survol, focus, hors écran — sans rien changer d'autre. */
.js .hero-rail[data-autoplay="on"]:not([data-user-paused="true"])
  .hero-view[aria-current="true"] .hero-view-fill {
  animation: hero-fill var(--hero-dur, 6s) linear forwards;
}
/* Doit rester plus spécifique que la règle ci-dessus : la forme raccourcie
   `animation:` y remet animation-play-state à `running`, donc une règle moins
   spécifique ne mettrait jamais la jauge en pause. */
.js .hero-rail[data-autoplay="on"]:not([data-user-paused="true"])[data-hold="true"]
  .hero-view[aria-current="true"] .hero-view-fill {
  animation-play-state: paused;
}
/* Plus de rotation : la règle ne compte plus le temps, elle dit seulement
   quelle vue est à l'écran. */
.js .hero-rail[data-autoplay="off"] .hero-view[aria-current="true"] .hero-view-fill,
.js .hero-rail[data-user-paused="true"] .hero-view[aria-current="true"] .hero-view-fill {
  animation: none;
  transform: scaleX(1);
}

.hero-view-n {
  font-size: 12px; font-weight: var(--font-heading-weight);
  letter-spacing: .02em; font-variant-numeric: tabular-nums;
}
.hero-view-label {
  font-size: clamp(12px, 1.5vh, 14px); line-height: 1.25;
  overflow-wrap: anywhere;
}

/* Le rail tient toute la largeur du contenu : les vues nommées à gauche, sur
   l'axe du titre, la commande de transport à droite, sur celui du bouton
   billets de l'en-tête. */
.hero-toggle {
  flex: none; margin-left: auto; width: 44px; height: 44px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  background: none; color: var(--color-bg); cursor: pointer;
  border: 1px solid rgba(243, 242, 242, .45);
  transition: background-color 200ms ease, border-color 200ms ease;
}
.hero-toggle:hover { background: rgba(243, 242, 242, .14); border-color: var(--color-bg); }
.hero-toggle svg { width: 15px; height: 15px; fill: currentColor; }
.hero-toggle .hero-toggle-play { display: none; }
/* L'icône ne suit que la suspension demandée : au survol le rail se met en
   pause aussi, mais faire basculer le bouton sous le curseur serait un piège. */
.hero-rail[data-user-paused="true"] .hero-toggle-pause { display: none; }
.hero-rail[data-user-paused="true"] .hero-toggle-play { display: block; }
/* Sans rotation possible — mouvement réduit, économie de données — il n'y a
   rien à suspendre : le rail reste un sélecteur de vues. */
.hero-rail[data-autoplay="off"] .hero-toggle { display: none; }

.btn-on-dark {
  padding: 0 28px; color: var(--color-bg); border: 1px solid rgba(243, 242, 242, .5);
}
.btn-on-dark:hover { background: rgba(243, 242, 242, .12); }

/* Le filet du hero laissait passer son fond gris entre la vidéo et le ruban :
   un liseré clair à la jointure de deux noirs. Le ruban sépare déjà. */
.hero:has(+ .vote-band) { border-bottom: 0; }

/* ── Le ruban de campagne ─────────────────────────────────────────────────
   L'aspect fixe est ici ; le défilement, la feuille qui balance, le reflet et
   les pointillés sont dans motion.css. Retirez la couche motion et il reste
   une banderole immobile qui dit la même chose — rien de ce qui suit ne
   dépend d'une animation.

   Il a remplacé le bandeau d'informations et repris son encre et son patron
   d'inset : padding sur la section, .wrap centré dedans, donc le même bord
   gauche que le reste de la page à toutes les largeurs. Pas de filet en bas —
   c'est le changement de fond qui sépare, et un filet sombre sur fond sombre
   ne se voit pas.

   Le rouge ne disparaît pas pour autant : il passe dans les feuilles et une
   part des confettis, qui sont les seules choses de la page à le porter sur
   fond sombre. */
.vote-band {
  position: relative;
  overflow: hidden;
  background: var(--color-text);
  color: var(--color-bg);
  border-bottom: 0;
  padding: clamp(19px, 1.9vw, 26px) var(--pad-x);
  /* L'écart entre deux mentions. Il sert deux fois : en `gap` dans la course,
     et en `padding-inline-end` pour que la copie suivante hérite du même
     souffle. Une marge ferait un trou au raccord — `translateX(-100%)` compte
     la boîte de bordure, pas la marge. */
  --vote-gap: clamp(20px, 2.6vw, 44px);
}
.vote-wrap { position: relative; }
/* Le porte-symbole de la feuille : hors flux, sans taille, jamais peint. */
.vote-sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

.vote-viewport { overflow: hidden; }
.vote-track { display: flex; width: max-content; }
.vote-run {
  display: flex; align-items: center; flex: none;
  margin: 0; gap: var(--vote-gap); padding-inline-end: var(--vote-gap);
}

/* Trois registres pour un seul message : l'appel en gras, la phrase longue en
   texte — c'est celle qu'on lit vraiment —, et la reprise en contour. Le même
   contraste graisse/valeur que « 7ᵉ édition » dans la bande du dessus. */
.vote-item {
  flex: none; white-space: nowrap;
  font-size: clamp(24px, 3.1vw, 46px);
  font-weight: var(--font-heading-weight);
  letter-spacing: -.02em; line-height: 1.06;
  text-transform: uppercase;
}
.vote-item--light { font-weight: 400; letter-spacing: -.01em; }
/* `color: transparent` sans le tracé donnerait une phrase invisible : la règle
   ne s'applique que là où le tracé existe. Épaisseur en `em` — un contour de
   2px sur des lettres de 21px sur téléphone serait une tache. */
@supports (-webkit-text-stroke: 1px currentColor) {
  .vote-item--outline {
    color: transparent;
    -webkit-text-stroke: .045em var(--color-bg);
  }
}

/* Le rouge canadien, à la marche la plus claire de la rampe : sur l'encre il
   tient 3.27:1, au-dessus du seuil des éléments non textuels, là où le rouge
   plein virerait au brun. */
.vote-leaf {
  flex: none; width: .72em; height: .72em;
  font-size: clamp(24px, 3.1vw, 46px);
  fill: var(--canada-lift);
}

/* Le bouton se range sur le bord droit de la colonne de contenu, à l'aplomb
   du bouton billets de l'en-tête. Fond opaque à l'encre du ruban : le filet
   seul se voit, et le texte passe derrière sans transparaître. */
.vote-toggle {
  position: absolute; right: 0; top: 50%; z-index: 3;
  transform: translateY(-50%);
  display: none; align-items: center; justify-content: center;
  width: 44px; height: 44px; padding: 0;
  background: var(--color-text); color: var(--color-bg); cursor: pointer;
  border: 1px solid rgba(243, 242, 242, .45);
  transition: background-color 200ms ease, border-color 200ms ease;
}
.vote-toggle:hover { background: rgba(243, 242, 242, .14); border-color: var(--color-bg); }
/* L'anneau global est à l'accent ; sur l'encre le blanc est le seul contraste
   garanti — même arbitrage que sur le rail du hero. */
.vote-toggle:focus-visible { outline: 2px solid var(--color-bg); outline-offset: 3px; }
.vote-toggle svg { width: 15px; height: 15px; fill: currentColor; }
.vote-toggle .vote-toggle-play { display: none; }
/* L'icône ne suit que la suspension demandée : le survol met aussi le ruban en
   pause, mais faire basculer le bouton sous le curseur serait un piège. */
.vote-band[data-user-paused="true"] .vote-toggle-pause { display: none; }
.vote-band[data-user-paused="true"] .vote-toggle-play { display: block; }

/* ── Manifesto ────────────────────────────────────────────────────────── */
.manifesto {
  display: grid;
  column-gap: clamp(32px, 6vw, 96px);
  align-items: start;
}
/* Deux colonnes seulement quand chacune peut porter le titre sans le hacher.
   L'`auto-fit` d'avant basculait dès 762px : le titre se cassait dans 336px.
   Le surtitre prend la première rangée pour lui : le titre et le paragraphe
   partagent alors la seconde et démarrent sur la même ligne, sans décalage
   réglé à la main — l'alignement tient quelle que soit la taille fluide. */
@media (min-width: 1080px) {
  .manifesto { grid-template-columns: 1fr 1fr; }
  .manifesto > .eyebrow { grid-area: 1 / 1; }
  .manifesto > .h-section { grid-area: 2 / 1; }
  .manifesto > .manifesto-body { grid-area: 2 / 2; margin-top: 0; }
}
.manifesto .h-section--lg { font-size: clamp(34px, 4.4vw, 64px); }
/* Empilé, le paragraphe reprend l'écart que portait la grille avant que le
   surtitre ne devienne une rangée à lui. */
.manifesto-body {
  margin-top: clamp(32px, 6vw, 96px);
  display: flex; flex-direction: column;
}
.manifesto-body p:first-child {
  margin: 0 0 20px; font-size: 19px; line-height: 1.5; max-width: 44ch;
}
.manifesto-body .hr { margin: 28px 0; }
.manifesto-signature {
  margin: 0; font-size: 13px; letter-spacing: .14em;
  font-weight: 600; color: var(--ink-50);
}

/* ── Les ambassadeurs ─────────────────────────────────────────────────────
   Une bande de visages sur l'encre. Le cadre décoratif de la campagne est
   magnifique une fois et assourdissant huit fois de suite : les vignettes
   sont donc recadrées dans l'image vive (x 250→1688, y 264→980 du master),
   et le cadre revient entier dans le lecteur. La bande déborde volontairement
   à droite — elle dit qu'il y en a d'autres, avant même qu'on la touche. */
.amb {
  background: var(--color-text); color: var(--color-bg);
  /* La bande doit tenir dans la vue avec son chapeau : sur un écran large mais
     bas, 34vw donnait des visages de 430px et renvoyait le bas de la bande
     sous la ligne de flottaison. La hauteur de fenêtre entre donc dans le calcul. */
  --amb-h: clamp(300px, min(34vw, 42svh), 430px);
}
.amb .h-section { color: var(--color-bg); }

/* Le chapeau tient sur un seul axe, à gauche, comme tout le reste du système.
   La version en deux colonnes calait le titre sur le bas et le paragraphe sur
   le haut : deux blocs sans ligne commune, et un trou entre eux. */
.amb-head { padding-top: var(--section-y-tight); }
.amb-deck {
  margin: 18px 0 0; max-width: 64ch;
  font-size: 18px; line-height: 1.55; color: var(--ground-70);
}

/* La barre : ce qu'il y a à voir, de quoi le parcourir, et le filet qui les
   rattache à la bande. Les flèches y touchent enfin ce qu'elles commandent —
   posées dans la colonne de droite du chapeau, elles flottaient à 90 px des
   visages, sans rien pour dire ce qu'elles déplaçaient. */
.amb-bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 24px; flex-wrap: wrap;
  margin-top: clamp(22px, 2.6vw, 32px); padding-bottom: 14px;
}
.amb-count { margin: 0; font-size: 13px; letter-spacing: .04em; color: var(--ground-55); }

.amb-arrows { display: none; gap: 2px; }
.js .amb-arrows { display: flex; }
.amb-arrow {
  width: 52px; height: 44px; display: inline-flex; align-items: center; justify-content: center;
  background: transparent; color: var(--color-bg); cursor: pointer;
  border: 2px solid rgba(243, 242, 242, .3);
}
.amb-arrow svg { width: 18px; height: 12px; fill: currentColor; }
.amb-arrow:hover:not(:disabled) { background: var(--canada-red); border-color: var(--canada-red); }
/* Au bout de la bande la flèche ne disparaît pas — elle s'éteint. Un bouton
   qui s'évapore déplace l'autre et fait douter de ce qu'on vient de cliquer. */
.amb-arrow:disabled { color: rgba(243, 242, 242, .38); border-color: rgba(243, 242, 242, .12); cursor: default; }

/* La bande commence à l'aplomb du texte et court jusqu'au bord de l'écran. */
.amb-strip {
  list-style: none; margin: 0; display: flex; gap: 2px;
  overflow-x: auto; overscroll-behavior-x: contain;
  scroll-snap-type: x proximity;
  /* La marge d'entrée est aussi la marge d'accrochage : sans elle, le premier
     visage se colle au bord de l'écran dès que le défilement s'aligne. */
  --amb-pad: var(--rail);
  padding-inline: var(--amb-pad);
  scroll-padding-inline: var(--amb-pad);
  padding-block: clamp(18px, 2vw, 24px) clamp(20px, 2.4vw, 28px);
  border-top: var(--rule-inverse);
}
/* La barre de défilement est une affordance : on ne la retire que lorsque les
   flèches sont là pour la remplacer. */
.js .amb-strip { scrollbar-width: none; }
.js .amb-strip::-webkit-scrollbar { display: none; }

.amb-item { flex: 0 0 auto; scroll-snap-align: start; }
/* `relative` n'est pas décoratif : sans bloc conteneur positionné, le libellé
   `.u-sr` de chaque vignette — absolu, hors flux — se rattache au corps de la
   page et échappe au découpage de la bande. Les huit décalaient le document à
   1610px de large sur un écran de 375 ; `overflow-x: hidden` sur le corps le
   cachait, mais un iPhone pose alors ses éléments fixes contre cette largeur-là
   et non contre l'écran. */
.amb-card { position: relative; display: block; text-decoration: none; color: inherit; }
.amb-card-media { display: block; position: relative; }
.amb-card img { display: block; height: var(--amb-h); width: auto; }

/* Le carré de lecture. Une vignette recadrée sur un visage ressemble à une
   photographie : sans cette marque, rien ne dit qu'il y a un film derrière —
   et une marque qui n'apparaît qu'au survol ne dit rien à un doigt. Elle est
   donc posée dès le premier regard, dans l'angle, à l'écart des visages.
   Carré parce que le système n'a pas un arrondi ; rouge du drapeau parce que
   c'est déjà la couleur de tout ce qui se clique sur cette page. */
.amb-card-play {
  position: absolute; left: 0; bottom: 0;
  width: clamp(42px, 3.4vw, 54px); height: clamp(42px, 3.4vw, 54px);
  display: flex; align-items: center; justify-content: center;
  background: var(--canada-red);
}
/* Un triangle centré à la règle penche à gauche : sa masse est du côté de
   la pointe. On le décale d'un huitième de sa largeur pour qu'il tombe
   juste à l'œil. */
.amb-card-play svg { width: 32%; height: auto; fill: var(--color-bg); display: block; transform: translateX(8%); }
.amb-card:hover .amb-card-play,
.amb-card:focus-visible .amb-card-play { background: var(--canada-lift); }

/* Le filet sous la vignette. Il ne porte plus de durée — un chiffre posé sous
   chaque visage faisait compter le temps avant d'avoir regardé qui parle —
   mais il reste : c'est lui qui passe au rouge et qui dit que ça se clique. */
.amb-card-foot {
  display: block; margin-top: 12px;
  border-top: 2px solid rgba(243, 242, 242, .22);
}
.amb-card:hover .amb-card-foot,
.amb-card:focus-visible .amb-card-foot {
  color: var(--color-bg); border-top-color: var(--canada-red);
}

.amb-note {
  margin: 0; padding-bottom: var(--section-y-tight);
  font-size: 13px; color: var(--ground-55); max-width: 60ch;
}

/* ── Le lecteur ─────────────────────────────────────────────────────────── */
.amb-player {
  width: min(1120px, calc(100vw - 32px)); max-width: none;
  padding: 0; border: 0; margin: auto;
  background: var(--color-text); color: var(--color-bg);
  box-shadow: var(--shadow-lg);
}
.amb-player::backdrop { background: rgba(12, 11, 11, .88); }
.amb-player video { display: block; width: 100%; height: auto; aspect-ratio: 1280 / 722; background: #000; }
.amb-player-bar {
  display: flex; align-items: center; justify-content: space-between; gap: 20px;
  padding: 14px 18px; border-top: var(--rule-inverse);
}
.amb-player-cap { margin: 0; font-size: 13px; color: var(--ground-70); }
.amb-player-close {
  flex: none; min-height: 44px; padding: 0 20px; cursor: pointer;
  background: transparent; color: var(--color-bg);
  border: 2px solid rgba(243, 242, 242, .3);
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 13px; letter-spacing: .06em;
}
.amb-player-close:hover { background: var(--canada-red); border-color: var(--canada-red); }
/* L'ouverture est la seule animation de la section : elle répond à un clic et
   montre d'où vient le lecteur. Tout le reste est immobile. */
.amb-player { opacity: 0; transition: opacity .18s ease; }
.amb-player[open] { opacity: 1; }
@starting-style { .amb-player[open] { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .amb-player { transition: none; } }

/* ── Four pillars ─────────────────────────────────────────────────────── */
.pillars-head {
  max-width: calc(var(--wrap) + 2 * var(--pad-x));
  padding: var(--section-y-tight) var(--pad-x) 0;
}
.pillars {
  max-width: calc(var(--wrap) + 2 * var(--pad-x)); margin: 0 auto;
  padding: 0 var(--pad-x) var(--section-y-tight);
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr));
}
.pillar {
  display: flex; flex-direction: column; gap: 18px;
  padding: 0 26px 26px; border-left: var(--rule-soft);
  text-decoration: none; color: inherit;
}
.pillar:hover { background: rgba(32, 30, 29, .04); }
.pillar-media { width: 100%; height: 200px; }
.pillar h3 { margin: 0; font-size: 26px; letter-spacing: -.01em; }
.pillar p { margin: 0; font-size: 14px; color: var(--ink-muted); flex: 1; }
.pillar-arrow { font-size: 14px; font-weight: var(--font-heading-weight); color: var(--accent-text); }

/* ── Programme ──────────────────────────────────────────────────────────
   La feuille de route d'une édition : une fiche par jour, la date à gauche,
   et trois colonnes annoncées une fois en tête de fiche — programme,
   description, heure. La barre d'outils et les dépliages n'existent que si
   programme.js tourne : tout ce qui les concerne est porté par .js, et la
   section reste la liste statique des quatre jours sans lui.

   Les fiches sont le fond clair posé sur le fond teinté de la section, comme
   .stay-card dans le module Séjour : c'est l'idiome du site pour « des fiches
   sur un fond », plutôt qu'une matière nouvelle. */
.programme { background: var(--color-surface); }
.programme [hidden] { display: none !important; }

.prog-head {
  display: flex; flex-wrap: wrap; align-items: flex-end;
  justify-content: space-between; gap: 28px; margin-bottom: 36px;
}
.prog-title { display: flex; flex-direction: column; gap: 12px; }
.prog-lede { margin: 0; font-size: 15px; color: var(--ink-muted); }
.prog-view {
  display: none; align-items: center; gap: 8px; min-height: 44px;
  padding: 0; border: 0; background: none; cursor: pointer;
  font-family: var(--font-heading); font-size: 14px;
  font-weight: var(--font-heading-weight);
  color: var(--accent-text); letter-spacing: .04em;
}
.js .prog-view { display: inline-flex; }
.prog-view:hover [data-label] { text-decoration: underline; text-underline-offset: 4px; }

.prog-chip {
  display: inline-flex; align-items: center; gap: 8px;
  min-height: 44px; padding: 0 16px;
  border: var(--hair); background: transparent; cursor: pointer;
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 12px; letter-spacing: .1em; color: var(--color-text);
  transition: background .18s ease, color .18s ease, border-color .18s ease;
}
.prog-chip:hover { background: rgba(32, 30, 29, .07); }
.prog-chip:disabled { opacity: .45; cursor: not-allowed; }
.prog-chip:disabled:hover { background: transparent; }
.prog-chip--sm { font-size: 11px; padding: 0 14px; }

/* Une seule rangee, toujours : l'encre de l'onglet actif (motion.js) ne
   glisse que de gauche a droite, et deux rangees la posaient en travers de
   l'onglet du dessous — le dimanche disparaissait sous le mercredi, une fois
   le programme passe a six jours. Trop de jours pour la largeur : la rangee
   defile, elle ne passe plus a la ligne. */
.day-tabs {
  display: flex; flex-wrap: nowrap;
  overflow-x: auto; overscroll-behavior-x: contain;
  scroll-snap-type: x proximity; scrollbar-width: none;
  border-top: var(--rule); border-bottom: var(--rule);
}
.day-tabs::-webkit-scrollbar { display: none; }
.day-tab {
  position: relative; flex: 1 0 150px; min-width: 150px; scroll-snap-align: start;
  display: flex; flex-direction: column; align-items: flex-start; gap: 4px;
  padding: 20px 48px 20px 24px; border: 0; border-left: var(--rule-soft);
  cursor: pointer; font-family: inherit; text-align: left;
  background: transparent; color: var(--color-text);
}
.day-tab[aria-selected="true"] { background: var(--color-text); color: var(--color-bg); }
.day-tab-kicker { font-size: 11px; letter-spacing: .14em; font-weight: 600; opacity: .65; white-space: nowrap; }
.day-tab-label { font-size: 22px; font-weight: var(--font-heading-weight); letter-spacing: -.01em; white-space: nowrap; }
/* Six jours sur une tablette ou un petit portable : les marges se resserrent
   avant que la rangee ne se mette a defiler. */
@media (min-width: 761px) and (max-width: 1200px) {
  .day-tab { padding: 18px 32px 18px 14px; }
  .day-tab-count { top: 16px; right: 12px; }
}
.day-tab-count {
  position: absolute; top: 18px; right: 18px;
  font-size: 12px; font-weight: 600; letter-spacing: .04em; opacity: .6;
}
.programme[data-view="all"] .day-tabs { display: none; }

/* En-tête de jour : masqué tant que les onglets sont là, c'est leur libellé
   qui porte l'information. Il ne sert que dans la vue « les quatre jours ». */
.sessions { margin-top: 16px; }
.sessions-day {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 14px;
  margin: 44px 0 0; padding: 14px 0 12px;
  font-size: 13px; letter-spacing: .16em; font-weight: 600;
}
#panel-day-0 .sessions-day { margin-top: 0; }
.sessions-day span {
  font-size: 13px; font-weight: 400; letter-spacing: .02em; color: var(--ink-muted);
}

/* La fiche du jour. Un jour que le filtre vide n'a pas de fiche à montrer :
   c'est l'état vide qui prend sa place, et programme.js écrit le compte. */
.day-card {
  display: grid; grid-template-columns: 152px 1fr;
  background: var(--color-bg);
}
.sessions[data-count="0"] .day-card { display: none; }

.day-date {
  display: flex; flex-direction: column; gap: 3px; margin: 0;
  padding: 26px 22px 26px 28px; border-right: var(--rule-soft);
}
.day-date-dow, .day-date-month {
  font-size: 11px; letter-spacing: .16em; font-weight: 600; color: var(--ink-muted);
}
.day-date-num {
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: clamp(42px, 4vw, 58px); line-height: .88; letter-spacing: -.04em;
}

.day-list { min-width: 0; padding: 0 28px 4px; }

/* Les trois libellés annoncés une fois par fiche, et la grille qu'ils
   annoncent. Une seule déclaration de colonnes pour les deux, sinon la ligne
   de session dérive de son en-tête à la première retouche. */
.day-cols, .session-main {
  display: grid; gap: 8px 28px;
  grid-template-columns: minmax(170px, 1fr) minmax(200px, 1.2fr) 86px;
}
.day-cols {
  margin: 0; padding: 22px 0 12px;
  font-size: 11px; letter-spacing: .14em; font-weight: 600; color: var(--accent-text);
}
.day-cols span:last-child { text-align: right; }

.session { border-top: var(--hair); }
.session-main { align-items: baseline; padding: 20px 0; }
.session-head { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.session-title {
  margin: 0; font-size: clamp(15px, 1.3vw, 18px);
  font-weight: var(--font-heading-weight); letter-spacing: .02em;
  line-height: 1.25; text-transform: uppercase;
}
/* La feuille d'agent utilisateur pose `text-transform: none` sur les boutons,
   et ça passe devant l'héritage : sans la reprise explicite, le titre perd ses
   capitales à la seconde où programme.js en fait un bouton. */
.session-toggle {
  display: inline-flex; align-items: baseline; gap: 10px;
  margin: 0; padding: 0; border: 0; background: none; cursor: pointer;
  font: inherit; letter-spacing: inherit; text-transform: inherit;
  color: inherit; text-align: left;
}
.session-toggle::after {
  content: "+"; font-size: .78em; font-weight: 600; color: var(--accent-text);
}
.session-toggle[aria-expanded="true"]::after { content: "−"; }
.session-toggle:hover { text-decoration: underline; text-underline-offset: 5px; }
.session-room { margin: 0; font-size: 13px; color: var(--ink-muted); }
.session-track { margin: 0; justify-self: start; }
.session-track .tag { font-size: 11px; letter-spacing: .08em; }
.session-desc { margin: 0; font-size: 14px; line-height: 1.45; color: var(--ink-muted); }
.session-time {
  display: flex; flex-direction: column; align-items: flex-end; gap: 2px; margin: 0;
  font-size: 15px; font-weight: var(--font-heading-weight); letter-spacing: -.01em;
  white-space: nowrap;
}
.session-end { font-size: 12px; font-weight: 400; letter-spacing: .02em; color: var(--ink-muted); }

/* Le détail. Présent et lisible sans JavaScript ; replié dès que le module
   tourne, avec le titre pour bouton. La description, elle, reste sur la ligne :
   c'est une colonne de la feuille de route, pas un repli. */
.session-detail { max-width: 74ch; padding: 0 0 22px; }
.js .session-detail:not([hidden]) { animation: prog-detail-in .22s ease both; }
@keyframes prog-detail-in { from { opacity: 0; transform: translateY(-5px); } }
.session-meta {
  display: flex; flex-wrap: wrap; gap: 10px 32px;
  margin: 0; padding: 0; list-style: none; font-size: 14px;
}
.session-meta span {
  display: block; font-size: 11px; letter-spacing: .14em;
  font-weight: 600; color: var(--accent-text);
}
.session-detail-actions { display: flex; flex-wrap: wrap; gap: 8px; margin: 18px 0 0; }

.sessions-empty {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px 18px;
  margin: 0; padding: 32px 28px; background: var(--color-bg);
  font-size: 15px; color: var(--ink-muted);
}

/* ── Culture bleed ────────────────────────────────────────────────────── */
.bleed {
  position: relative;
  min-height: 66vh;
  min-height: 66svh;
  display: flex;
  border-bottom: var(--rule);
}
.bleed-media { position: absolute; inset: 0; }
/* The photograph is 3:2 and the band is far wider than that, so `cover` throws
   away a third of the height. Framing off-centre keeps the headdresses, the
   flag and the skyline inside the crop; the horizontal share only comes into
   play on phones, where the band is taller than it is wide and the crop has to
   favour the group over the empty water on the left. The vertical share also
   leaves headroom for the parallax overscale, which eats another 6% off the
   top before anything moves. */
.bleed .slot img { object-position: 68% 14%; }

/* Same treatment as the hero. The design's scrim reached zero opacity below
   where this headline sits, leaving white type resting on whatever the
   photograph happened to be — legible only by luck. */
.bleed-overlay {
  position: relative;
  align-self: stretch;
  width: 100%;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: clamp(40px, 6vw, 96px) var(--pad-x);
  background: linear-gradient(to top,
    rgba(32, 30, 29, .88) 0%,
    rgba(32, 30, 29, .80) 38%,
    rgba(32, 30, 29, .66) 60%,
    rgba(32, 30, 29, .34) 80%,
    rgba(32, 30, 29, .10) 93%,
    rgba(32, 30, 29, 0) 100%);
}
.bleed-inner {
  width: 100%; max-width: var(--wrap); margin-inline: auto;
  color: var(--color-bg);
}
.bleed h2 {
  margin: 0; max-width: 20ch; font-size: clamp(30px, 4vw, 60px);
  line-height: 1.04; letter-spacing: -.025em; font-weight: 400;
}
.bleed h2 strong { font-weight: var(--font-heading-weight); }
.link-underline {
  display: inline-block; margin-top: 26px; font-size: 15px;
  font-weight: var(--font-heading-weight); color: var(--color-bg);
  text-decoration: none; border-bottom: 2px solid var(--color-accent);
  padding-bottom: 3px;
}

/* ── Tickets ──────────────────────────────────────────────────────────── */
.tickets { background: var(--color-text); color: var(--color-bg); }
.tickets .h-section--lg { color: var(--color-bg); margin-bottom: 14px; }
.tickets-head {
  display: flex; flex-wrap: wrap; align-items: flex-end;
  justify-content: space-between; gap: 28px; margin-bottom: 52px;
}
.tickets-head p { margin: 0; font-size: 18px; color: var(--ground-70); max-width: 46ch; }
.tickets-head .btn { height: 56px; padding: 0 32px; font-size: 16px; letter-spacing: .04em; }

/* ── Le compte a rebours ───────────────────────────────────────────────────
   Il occupe la fente de droite de `.tickets-head`, alignee sur le pied du
   titre — d'ou `align-items: flex-end` deja pose plus haut.

   Les chiffres reprennent l'echelle et la graisse des prix des cartes, deux
   blocs plus bas : la section se lit alors comme une seule famille, le temps en
   haut, le prix en bas. C'est ce qui evite au compteur de ressembler a un
   gadget colle sur une page qui ne l'attendait pas.

   Pas de deux-points entre les unites, des filets : le meme trait que celui qui
   separe les cartes. Et pas de fond, pas de cadre, pas de pastille — sur cette
   encre, la typographie suffit.

   `tabular-nums` est la seule chose qui empeche le bloc de trembler : sans lui,
   un 1 plus etroit qu'un 8 fait danser la ligne entiere chaque seconde. Le
   `min-width` en em fait le reste — 359 jours passera a 99 sans que rien ne
   bouge. */
/* Tout au fer a gauche a l'interieur du bloc, y compris le surtitre : c'est le
   groupe entier que la fente de `.tickets-head` pousse a droite, pas son
   contenu. Cale a droite, « AVANT L'OUVERTURE » surplombait les secondes au
   lieu des jours — le regard commencait la lecture par la fin. */
.countdown { display: flex; flex-direction: column; align-items: flex-start; gap: 14px; }
.countdown .countdown-kicker {
  margin: 0; font-size: 11px; letter-spacing: .18em; font-weight: 600;
  color: var(--color-accent-400);
}
.countdown-grille { display: flex; align-items: flex-end; }
.countdown-unite {
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  padding-inline: clamp(14px, 1.8vw, 26px);
  border-left: var(--rule-inverse);
}
.countdown-unite:first-child { border-left: 0; padding-inline-start: 0; }
.countdown-unite:last-child { padding-inline-end: 0; }
.countdown-num {
  display: block; min-width: 1.9em; text-align: center;
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: clamp(34px, 4vw, 52px); line-height: .88; letter-spacing: -.04em;
  font-variant-numeric: tabular-nums; font-feature-settings: "tnum" 1;
  color: var(--color-bg);
}
.countdown-lib {
  font-size: 11px; letter-spacing: .14em; font-weight: 600;
  text-transform: uppercase; color: var(--ground-55);
}
.countdown .countdown-fini {
  margin: 0; font-size: 15px; color: var(--color-accent-400); max-width: none;
}

/* Une fois l'evenement commence, le compteur s'efface au lieu d'afficher quatre
   zeros sous « AVANT L'OUVERTURE » — il ne reste que la phrase. Le script du
   parent ne pose sa classe que sur la grille ; le surtitre la precede, d'ou le
   `:has()` sur le bloc entier. La ou il n'est pas compris, on retombe sur
   l'ancien comportement : des zeros et le message, lisible, pas casse. */
.countdown:has(.se-countdown--ended) .countdown-kicker,
.countdown .se-countdown--ended { display: none; }

/* Le chiffre tombe de sa propre hauteur et se pose : un compteur mecanique, pas
   un clignotement. `home-countdown.js` du parent pose et retire `.is-flip` a
   chaque changement de valeur. */
@keyframes abc-countdown-tick {
  from { opacity: .2; transform: translateY(-.14em); }
  to   { opacity: 1; transform: none; }
}
.countdown-num.is-flip { animation: abc-countdown-tick .32s cubic-bezier(.22, .7, .28, 1); }
@media (prefers-reduced-motion: reduce) {
  .countdown-num.is-flip { animation: none; }
}

@media (max-width: 560px) {
  .countdown-num { font-size: clamp(28px, 8.5vw, 40px); }
  .countdown-unite { padding-inline: clamp(9px, 3vw, 16px); gap: 6px; }
  .countdown-lib { font-size: 9px; letter-spacing: .1em; }
}
/* Les cartes sont blanches, la section reste encre. Elles se fondaient dans leur
   fond : encre sur encre, seuls des filets clairs les separaient, et ce qui est
   a vendre avait exactement le poids de ce qui l'entoure. En blanc sur encre,
   l'offre se detache de la page — c'est le seul endroit du site ou l'on demande
   une decision.

   Les filets passent donc de `--rule-inverse` (clair, pour un fond sombre) a
   `--rule` (encre) : ils ne separent plus une carte de la page, ils separent
   deux cartes blanches l'une de l'autre. Ceux qui tombent au bord du bloc se
   fondent dans l'encre de la section — c'est le blanc de la carte qui fait la
   limite, aucun cadre a dessiner. Les deux sections qui portent ces cartes,
   `.tickets` et `.pass-others`, sont encre toutes les deux. */
.passes { display: flex; flex-wrap: wrap; }
.pass {
  flex: 1 1 280px; display: flex; flex-direction: column; gap: 16px;
  padding: 36px 32px; background: #fff; color: var(--color-text);
  border-left: var(--rule); border-top: var(--rule);
  position: relative; overflow: hidden;
  --pass-motif: var(--color-text);
}
/* Le ndop en filigrane : le tissu de la convention. Le fichier est trace en
   blanc pur — il servait sur fond encre. Plutot que d'en versionner un second
   en encre, on l'utilise en MASQUE : seule sa forme compte, la couleur vient du
   CSS. Un seul fichier, deux fonds, et `--pass-motif` laisse la carte mise en
   avant reprendre un trace clair sur son aplat accent.

   6 %, et pas 8. Un trace sombre sur blanc pese plus lourd a l'oeil que le
   trace clair sur encre d'ou vient ce motif : a 8 %, un glyphe de `--ink-60`
   tombant sur un trait descendait a 4.37:1, sous la barre que ce projet tient.
   A 6 % il remonte a 4.60:1, et le motif reste parfaitement lisible.

   Le motif passe par un pseudo-element — appliquer l'opacite au fond de la
   carte l'aurait appliquee aussi a son contenu. */
.pass::before {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background-color: var(--pass-motif);
  -webkit-mask-image: url(../img/ndop-motif.svg);
          mask-image: url(../img/ndop-motif.svg);
  -webkit-mask-size: 168px 168px;
          mask-size: 168px 168px;
  opacity: .06;
}
.pass > * { position: relative; z-index: 1; }
.pass--featured {
  background: var(--color-accent); color: var(--color-bg);
  --pass-motif: var(--color-bg);
}
.pass-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.pass-label { font-size: 11px; letter-spacing: .14em; font-weight: 600; color: var(--ink-60); }
.pass--featured .pass-label { color: rgba(243, 242, 242, .8); }
/* Le badge s'inverse avec la carte : sur blanc, c'est lui qui porte l'aplat.
   L'accent est pris a son cran 700 — le 500 de la marque sous du texte blanc
   ne donne que 3.5:1, sous la barre pour 10 px. Le 700 en donne 7.2:1. */
.pass-badge {
  font-size: 10px; letter-spacing: .12em; font-weight: var(--font-heading-weight);
  background: var(--color-accent-700); color: #fff; padding: 4px 9px;
}
.pass--featured .pass-badge { background: var(--color-bg); color: var(--color-accent-700); }
.pass-badge--out {
  background: transparent; border: 1px solid rgba(32, 30, 29, .5);
  color: var(--ink-60);
}
/* Le badge « PAUSE » : un ruban rouge, pas un cartouche gris. C'est
   l'information de la carte tant que la pause dure, il doit se voir avant le
   prix. Les deux bouts sont fendus en queue de ruban ; le rouge est celui des
   boutons, le lettrage clair par-dessus. */
.pass-badge--pause {
  background: var(--canada-red); color: var(--color-bg); border: 0;
  padding: 8px 26px; font-size: 12px; letter-spacing: .2em;
  clip-path: polygon(0 0, 100% 0, calc(100% - 10px) 50%, 100% 100%, 0 100%, 10px 50%);
}
/* La raison d'une vente suspendue, sous le prix : une ligne, au rouge de la
   marque, qui dit « bientot » la ou un gris dirait « fini ». */
.pass-pause {
  margin: 10px 0 0; font-size: 14px; font-weight: 600; line-height: 1.35;
  color: var(--accent-text);
}
.pass--featured .pass-pause { color: var(--color-bg); }
/* « BIENTÔT DE RETOUR » se lit en entier : ce n'est pas un bouton en panne,
   c'est l'etat de l'offre. Une plaque d'encre pleine, jamais estompee — et
   pas le rouge, qui est reserve a l'action qu'on peut faire a cote. */
.pass[data-state="paused"] .btn[aria-disabled="true"] {
  opacity: 1; background: var(--color-text); color: var(--color-bg);
  border-color: var(--color-text);
}
.pass--featured[data-state="paused"] .btn[aria-disabled="true"] {
  background: var(--color-bg); color: var(--color-text); border-color: var(--color-bg);
}
.pass-price {
  margin: 0; font-size: clamp(38px, 4vw, 56px); line-height: 1;
  font-weight: var(--font-heading-weight); letter-spacing: -.03em;
}
.pass-summary { margin: 0; font-size: 14px; color: var(--ink-60); }
.pass--featured .pass-summary { color: rgba(243, 242, 242, .85); }
.pass ul {
  margin: 8px 0 0; padding: 0; list-style: none;
  display: flex; flex-direction: column; gap: 9px; font-size: 14px; flex: 1;
}
.pass .btn {
  height: 48px; justify-content: flex-start; padding: 0 22px; font-size: 14px;
  color: var(--color-text); border: 1px solid rgba(32, 30, 29, .45);
}
.pass .btn:hover { background: rgba(32, 30, 29, .07); }
.pass--featured .btn { background: var(--color-bg); color: var(--color-text); border-color: transparent; }
.pass--featured .btn:hover { background: #fff; }
.pass .btn[aria-disabled="true"] { opacity: .45; pointer-events: none; }
.tickets-note { margin: 24px 0 0; font-size: 13px; color: var(--ground-55); }

/* ── Billetterie fermee : l'affiche de la prevente ──────────────────────────
   Le panneau des offres, sans offre a acheter : l'affiche du 15 octobre 2026
   transcrite en page — titre, deux dates en bandeaux, le message, les trois
   tarifs, KeyZane, ce que le pass comprend, la carte et les porteurs. Rien
   n'est cliquable : il n'y a rien a decider avant l'ouverture, tout a lire.
   Les couleurs des pastilles sont celles de l'affiche ; le rouge est celui
   des boutons du site (--canada-red), qui tient le texte blanc a 5.27:1. */
/* Trois classes, pas deux : la grille de « Une offre unique » est declaree
   plus bas dans cette feuille, et a specificite egale elle l'emporterait. */
.passes--solo .pass.pass--fermee {
  display: flex; flex-direction: column; gap: 18px;
  padding: clamp(32px, 4.5vw, 64px) clamp(20px, 4vw, 56px);
}
.pass-fermee-titre {
  margin: 0; max-width: 18ch;
  font-size: clamp(32px, 4vw, 56px); line-height: 1.02; letter-spacing: -.025em;
  font-weight: var(--font-heading-weight);
}
.pass-fermee-texte { max-width: 64ch; }
.pass-fermee-texte p {
  margin: 0; font-size: clamp(17px, 1.5vw, 21px); line-height: 1.5;
}
.pass-fermee-texte p + p { margin-top: 14px; font-weight: 600; }

.prevente-sprite { position: absolute; width: 0; height: 0; overflow: hidden; }
.prevente-ico {
  width: 24px; height: 24px; flex: none;
  fill: none; stroke: currentColor; stroke-width: 1.8;
  stroke-linecap: round; stroke-linejoin: round;
}

/* L'en-tete de l'affiche : la convention a gauche, Binam Canada a droite,
   comme sur l'image qui circule. */
.prevente-tete {
  display: flex; align-items: center; gap: clamp(16px, 2.4vw, 32px);
}
.prevente-tete > div { display: flex; flex-direction: column; gap: 10px; flex: 1 1 auto; }
.prevente-label { display: inline-flex; align-items: center; gap: 8px; color: var(--accent-text); }
.prevente-label::before {
  content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--canada-red);
}
/* Le logo Binam et son cartouche « GrassfieldLand », construits sur la
   geometrie du logo ABC d'en face pour que les deux se repondent : meme
   largeur, meme rapport (320 × 291), cercle de meme diametre, cartouche de
   meme taille a la meme hauteur. Les mesures sont relevees sur abc-logo.webp
   et exprimees en largeur du bloc (cqw) : cercle 61 %, a 4,4 % du haut ;
   cartouche 92,5 % de large, 21 % de haut, pose a 62,5 % ; cadre 1,25 %.
   Couleurs du logo ABC : cadre marine, lettrage rouge et gras. */
.prevente-logo-abc,
.prevente-logo-binam { flex: none; width: clamp(96px, 9vw, 128px); }
.prevente-logo-abc { height: auto; }
.prevente-logo-binam {
  position: relative; margin: 0; aspect-ratio: 320 / 291;
  container-type: inline-size;
}
.prevente-logo-binam img {
  position: absolute; top: 4.4cqw; left: 19.5cqw; width: 61cqw; height: auto;
}
.prevente-logo-binam figcaption {
  position: absolute; top: 62.5cqw; left: 3.75cqw; width: 92.5cqw; height: 21.25cqw;
  box-sizing: border-box; display: flex; align-items: center; justify-content: center;
  border: 1.25cqw solid #232a78; background: #fff;
  font-size: 10cqw; line-height: 1; font-weight: 800; letter-spacing: 0;
  white-space: nowrap; color: #c62034;
}

/* Les deux dates : la vente, en aplat rouge — c'est l'information du jour —,
   l'evenement en filet. */
.prevente-dates { display: flex; flex-wrap: wrap; gap: 12px; }
.prevente-date {
  display: flex; align-items: center; gap: 12px; margin: 0;
  padding: 12px 16px; border-radius: 8px;
  font-size: clamp(13px, 1.1vw, 15px); line-height: 1.25; letter-spacing: .02em;
  text-transform: uppercase; font-weight: 600;
}
.prevente-date strong { font-weight: var(--font-heading-weight); }
.prevente-date--vente { background: var(--canada-red); color: #fff; }
.prevente-date--evenement { border: 2px solid rgba(32, 30, 29, .35); color: var(--color-text); }

/* Le message a gauche, les tarifs a droite ; en colonne sous 1000px. */
.prevente-corps {
  display: grid; grid-template-columns: minmax(0, .9fr) minmax(0, 1.4fr);
  gap: clamp(24px, 3vw, 48px); align-items: start; margin-top: 8px;
}
.pass--prevente .pass-fermee-texte p + p { color: var(--canada-deep); }
.prevente-tarifs { display: flex; flex-direction: column; gap: 16px; }
.pass--prevente ul.prevente-offres {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px;
  margin: 0; padding: 0; list-style: none; flex: none;
}
.prevente-offre {
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  padding: 18px 12px 16px; text-align: center;
  background: #fff; border: 1px solid rgba(200, 16, 46, .22); border-radius: 10px;
  box-shadow: 0 6px 18px rgba(32, 30, 29, .06);
}
.prevente-offre-ico {
  display: grid; place-items: center; width: 46px; height: 46px; margin-bottom: 4px;
  border: 2px solid var(--canada-red); border-radius: 50%; color: var(--canada-red);
}
.prevente-offre-label {
  font-size: 12px; letter-spacing: .1em; font-weight: 700; text-transform: uppercase;
  color: var(--color-text);
}
.prevente-offre-prix {
  font-size: clamp(26px, 2.5vw, 36px); line-height: 1.05; letter-spacing: -.02em;
  font-weight: var(--font-heading-weight); color: var(--canada-red);
  white-space: nowrap;
}
.prevente-offre-note { font-size: 13px; color: var(--ink-60); }
.prevente-offre-note del { text-decoration-color: var(--canada-red); text-decoration-thickness: 2px; }
.prevente-offre-note--fort { font-weight: 600; color: var(--canada-deep); }
.prevente-keyzane {
  display: flex; flex-direction: column; align-items: center; gap: 12px;
  padding: 12px 0 14px; border-block: 1px solid rgba(32, 30, 29, .14);
  text-align: center;
}
.prevente-keyzane-tete {
  display: flex; align-items: center; justify-content: center; gap: 16px; flex-wrap: wrap;
  margin: 0; font-size: clamp(14px, 1.3vw, 17px); font-weight: 600;
}
.prevente-keyzane-tete img { width: 180px; height: auto; }
.prevente-keyzane-tete span { padding-left: 16px; border-left: 2px solid rgba(32, 30, 29, .2); }
/* Le bouton prend la largeur des trois tarifs au-dessus : c'est leur suite.
   Deux classes devant : `.pass .btn` (le bouton encre des cartes d'offre)
   l'emporterait, et le libelle passait en encre sur le rouge. */
.pass .prevente-keyzane-btn {
  width: 100%; height: auto; min-height: 52px; padding: 12px 24px;
  justify-content: center; text-align: center;
  font-size: 15px; letter-spacing: .04em; text-transform: uppercase;
  color: #fff; border-color: transparent;
}
.pass .prevente-keyzane-btn:hover { background: var(--canada-grad); }
.prevente-keyzane-magasins { margin: 0; font-size: 14px; color: var(--ink-60); }
.prevente-keyzane-magasins a { color: var(--color-text); font-weight: 600; text-underline-offset: 3px; white-space: nowrap; }
.prevente-keyzane-magasins a:hover { color: var(--canada-red); }
/* Quand la colonne des tarifs se resserre, la phrase passe sous le logo : son
   filet resterait suspendu dans le vide, on le retire. */
@media (max-width: 1280px) {
  .prevente-keyzane-tete { flex-direction: column; gap: 8px; }
  .prevente-keyzane-tete span { padding-left: 0; border-left: 0; }
}

.prevente-h {
  margin: 14px 0 0; font-size: clamp(18px, 1.8vw, 24px); letter-spacing: .02em;
  text-transform: uppercase; font-weight: var(--font-heading-weight);
}

/* Ce que le pass comprend : trois colonnes separees d'un filet, une pastille
   coloree par moment, comme sur l'affiche. */
.pass--prevente ul.prevente-programme {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  margin: 0; padding: 0; list-style: none; gap: 0; flex: none; font-size: 15px;
}
.prevente-programme li {
  display: flex; align-items: center; gap: 14px;
  padding: 10px clamp(10px, 1.6vw, 22px);
  border-bottom: 1px solid rgba(32, 30, 29, .1);
}
.prevente-programme li:not(:nth-child(3n + 1)) { border-left: 1px solid rgba(32, 30, 29, .14); }
.prevente-programme li:nth-child(3n + 1) { padding-left: 0; }
.prevente-pastille {
  display: grid; place-items: center; flex: none;
  width: 46px; height: 46px; border-radius: 50%; color: #fff;
}
.prevente-pastille .prevente-ico { width: 24px; height: 24px; }
.prevente-teinte--rose   { background: #d81b60; }
.prevente-teinte--rouge  { background: var(--canada-red); }
.prevente-teinte--vert   { background: #2e7d32; }
.prevente-teinte--violet { background: #6a1b9a; }
.prevente-teinte--or     { background: #c27c0e; }
.prevente-teinte--orange { background: #e2570f; }
.prevente-moment { display: flex; flex-direction: column; gap: 2px; line-height: 1.3; }
.prevente-moment strong { font-weight: 700; }
.prevente-moment span { font-size: 14px; color: var(--ink-60); }

/* La carte : six options en ligne, filets entre elles, prix au rouge. */
.pass--prevente ul.prevente-carte {
  display: grid; grid-template-columns: repeat(6, minmax(0, 1fr));
  margin: 0; padding: 0; list-style: none; gap: 0; flex: none; font-size: 15px;
}
.prevente-carte li {
  display: grid; grid-template-columns: auto 1fr; column-gap: 10px; row-gap: 2px;
  align-items: center; padding: 6px clamp(8px, 1.2vw, 16px);
}
.prevente-carte li + li { border-left: 1px solid rgba(32, 30, 29, .14); }
.prevente-carte li:first-child { padding-left: 0; }
.prevente-carte .prevente-ico { grid-row: 1 / span 2; color: var(--canada-red); }
.prevente-carte-nom { line-height: 1.2; }
.prevente-carte-prix {
  font-size: clamp(17px, 1.6vw, 21px); font-weight: var(--font-heading-weight);
  color: var(--canada-red); white-space: nowrap;
}

/* Les porteurs : le bandeau rouge qui ferme l'affiche. */
.prevente-porteurs {
  display: flex; align-items: center; justify-content: center; flex-wrap: wrap;
  gap: 8px 14px; margin: 10px 0 0; padding: 14px 20px; border-radius: 8px;
  background: var(--canada-red); color: #fff; text-align: center;
  font-size: clamp(14px, 1.3vw, 17px);
}
.prevente-porteurs .prevente-ico { width: 22px; height: 22px; }

@media (max-width: 1000px) {
  .prevente-corps { grid-template-columns: 1fr; }
  .pass--prevente ul.prevente-programme { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .prevente-programme li:nth-child(n) { border-left: 0; padding-left: 0; }
  .prevente-programme li:nth-child(2n) { border-left: 1px solid rgba(32, 30, 29, .14); padding-left: 16px; }
  .pass--prevente ul.prevente-carte { grid-template-columns: repeat(3, minmax(0, 1fr)); row-gap: 14px; }
  .prevente-carte li:nth-child(n) { border-left: 0; padding-left: 0; }
  .prevente-carte li:not(:nth-child(3n + 1)) { border-left: 1px solid rgba(32, 30, 29, .14); padding-left: 12px; }
}
@media (max-width: 640px) {
  .prevente-tete { flex-wrap: wrap; }
  .prevente-tete > div { order: 3; flex-basis: 100%; }
  .prevente-logo-binam { margin-left: auto; }
  .prevente-date { width: 100%; }
  .pass--prevente ul.prevente-offres { grid-template-columns: 1fr; }
  .prevente-offre {
    display: grid; grid-template-columns: auto 1fr; column-gap: 14px; row-gap: 2px;
    text-align: left; align-items: center; justify-items: start;
  }
  .prevente-offre-ico { grid-row: 1 / span 3; margin: 0; }
  .pass--prevente ul.prevente-programme { grid-template-columns: 1fr; }
  .prevente-programme li:nth-child(n) { border-left: 0; padding-left: 0; }
  .pass--prevente ul.prevente-carte { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .prevente-carte li:nth-child(n) { border-left: 0; padding-left: 0; }
  .prevente-carte li:nth-child(2n) { border-left: 1px solid rgba(32, 30, 29, .14); padding-left: 12px; }
  .prevente-carte-prix { white-space: normal; }
  /* Les deux porteurs passent l'un sous l'autre : la puce qui les separait
     en ligne resterait seule au bout de la premiere. */
  .prevente-porteurs { flex-direction: column; }
  .prevente-porteurs .prevente-puce { display: none; }
}

/* ── L'echeance de la prevente ────────────────────────────────────────────
   Tant qu'elle court, la note n'est plus une mention en petit gris : c'est
   une echeance, elle se lit en clair et a la taille du texte courant. Deux
   mouvements pour qu'on la voie, tous deux deja dans le vocabulaire de la
   page : le temoin rouge qui bat, comme les ondes du spot du hero, et le
   reflet dore qui traverse la date, comme il traverse « MONTRÉAL 2027 ».
   En mouvement reduit tout s'arrete ; la ligne reste, aussi lisible. */
.tickets-note--prevente {
  display: flex; align-items: flex-start; gap: 16px;
  margin-top: 28px;
  font-size: clamp(16px, 1.5vw, 20px); line-height: 1.5;
  color: var(--color-bg);
}
.tickets-note-onde {
  position: relative; flex: none; width: 12px; height: 12px;
  margin-top: .5em; background: var(--canada-red);
}
.tickets-note-onde::before,
.tickets-note-onde::after {
  content: ""; position: absolute; inset: 0;
  border: 1px solid var(--canada-red);
  animation: hero-spot-onde 2.4s ease-out infinite;
}
.tickets-note-onde::after { animation-delay: 1.2s; }
.tickets-note-date { font-weight: var(--font-heading-weight); color: var(--color-bg); }
@supports (background-clip: text) or (-webkit-background-clip: text) {
  .tickets-note-date {
    background-image: linear-gradient(
      100deg,
      var(--color-bg) 0%, var(--color-bg) 42%,
      #ffd98a 50%,
      var(--color-bg) 58%, var(--color-bg) 100%
    );
    background-size: 320% 100%;
    background-position: 100% 0;
    -webkit-background-clip: text; background-clip: text;
    -webkit-text-fill-color: transparent; color: transparent;
    animation: hero-edition-reflet 6s ease-in-out 1.5s infinite;
  }
}
/* Le code de la devise garde sa petite taille ; le montant, lui, se lit
   en gras comme la date, c'est l'autre moitie de l'echeance. */
.tickets-note--prevente .woocommerce-Price-amount { font-weight: var(--font-heading-weight); }
@media (prefers-reduced-motion: reduce) {
  .tickets-note-onde::before,
  .tickets-note-onde::after { animation: none; opacity: .45; }
  .tickets-note-date { animation: none; background-position: 100% 0; }
}

/* ── Une offre unique ──────────────────────────────────────────────────
   Trois cartes se comparent cote a cote. Une seule, laissee dans la meme
   grille, s'etire en bandeau : prix minuscule perdu dans la largeur, action
   echouee a gauche. Elle devient donc un panneau a deux colonnes — l'offre a
   gauche, le prix et la decision a droite — puisqu'il n'y a plus rien a
   comparer, seulement a decider.

   Le prix double de taille : sans concurrent, c'est lui l'information, pas
   l'ecart entre formules. */
/* Le ndop et l'inversion des couleurs sont montes sur `.pass` : toutes les
   cartes les portent, seule ou non. Ne reste ici que la mise en page. */
.passes--solo .pass {
  flex: 1 1 100%;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(240px, 20vw);
  grid-template-rows: auto auto 1fr;
  column-gap: clamp(32px, 5vw, 80px);
  row-gap: 20px;
  padding: clamp(40px, 4.5vw, 64px) clamp(32px, 4vw, 56px);
}
/* Le libelle vit dans .pass-head quand il y a un badge, seul sinon. */
.passes--solo .pass-head,
.passes--solo > .pass > .pass-label { grid-column: 1; grid-row: 1; }
.passes--solo .pass-head { justify-content: flex-start; gap: 14px; }
.passes--solo .pass-price {
  grid-column: 2; grid-row: 1;
  font-size: clamp(52px, 6.5vw, 88px);
  text-align: right;
  display: flex; flex-direction: column; align-items: flex-end; gap: 2px;
}
/* Le tarif plein : barre, en retrait, au-dessus du prix reel. Il informe, il ne
   crie pas — c'est le 150 qui doit rester l'information principale. */
.pass-price-plein {
  font-size: .34em; line-height: 1.1; letter-spacing: -.01em;
  color: var(--ink-60); text-decoration-thickness: .08em;
}
.pass--featured .pass-price-plein,
.pass--featured .pass-price-place { color: rgba(243, 242, 242, .75); }
.pass-price-actuel { display: block; }
.passes--solo .pass-summary { grid-column: 1; grid-row: 2; font-size: 17px; max-width: 54ch; }
.passes--solo .pass ul { grid-column: 1; grid-row: 3; font-size: 15px; }
.passes--solo .pass .btn {
  grid-column: 2; grid-row: 2 / -1;
  align-self: start; justify-content: center;
  height: 56px; padding: 0 28px; font-size: 15px;
  border-color: transparent;
}

@media (max-width: 760px) {
  /* En colonne, l'ordre du DOM suffit : libelle, prix, promesse, details,
     action. Le prix reste haut, la ou il est attendu. */
  .passes--solo .pass {
    display: flex; flex-direction: column;
  }
  .passes--solo .pass-price { text-align: left; font-size: clamp(46px, 13vw, 64px); }
  .passes--solo .pass-summary { max-width: none; }
}

/* ── Deux offres ───────────────────────────────────────────────────────
   Un billet a l'unite et une table de dix ne se comparent pas colonne par
   colonne comme trois formules : ce sont deux decisions differentes, posees
   cote a cote. La base flex suffit — on ne fait que fermer le bloc a droite,
   que la grille de trois laissait ouverte, et repousser le point de rupture :
   a 280px de base, deux cartes tenaient encore la ligne a 600px, ou le prix et
   la liste se marchaient dessus. */
.passes--duo .pass { flex: 1 1 340px; }

/* Le prix a la place, sous le total. Petit et gris : c'est un repere de
   comparaison, pas la deuxieme moitie d'un prix. */
.pass-price-place {
  display: block; margin-top: 8px;
  font-size: .28em; line-height: 1.25; letter-spacing: 0;
  font-weight: 400; color: var(--ink-60);
}

/* ── Le code de la devise ──────────────────────────────────────────────
   « $150 USD ». Le code suit chaque montant que WooCommerce formate
   (abc2027_prix_devise(), inc/tickets.php), en capitales espacees a un
   tiers du corps du prix — jamais sous 11px : dans un tableau de panier a
   14px, le tiers ne laisserait que 4px — et cale sur la ligne de base. Une
   precision, pas la moitie du prix : plus leger, l'approche negative du prix
   annulee. Il ne suit pas le tarif barre, qui n'est qu'un repere : le code
   va avec le prix qu'on paie, juste a cote. */
.prix-devise {
  font-size: max(.32em, 11px);
  font-weight: 600; letter-spacing: .08em; line-height: 1;
  vertical-align: baseline; opacity: .72;
}
del .prix-devise { display: none; }

/* En-tete de page sans photographie : le bandeau tire son fond de son image,
   il faut donc le lui donner autrement. */
.page-hero--sobre { background: var(--color-text); }
.page-hero--sobre .page-hero-inner { color: var(--color-bg); }

/* Les photographies. Grille fluide : les images gardent leur proportion, la
   rangee s'ajuste. Pas de recadrage carre — on ne coupe pas des visages. */
.photos-grille {
  list-style: none; margin: clamp(24px, 3vw, 40px) 0 0; padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr));
  gap: clamp(14px, 1.8vw, 24px);
}
.photos-item { margin: 0; min-width: 0; background: var(--color-text); }
.photos-item img { display: block; width: 100%; height: auto; }

/* ── La galerie ────────────────────────────────────────────────────────
   Deux paysages et un portrait, pris au telephone. Recadrer tout au carre
   couperait les visages et mentirait sur l'origine des images : la grille
   accepte donc les deux formats. Le portrait prend deux rangees, les paysages
   une — c'est lui qui donne sa hauteur a la colonne de droite. */
.galerie-deck { margin: 0 0 clamp(24px, 3vw, 40px); font-size: 17px; color: var(--ink-muted); max-width: 56ch; }

.galerie-grille {
  list-style: none; margin: 0; padding: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(18px, 2.4vw, 34px);
  align-items: start;
}
.galerie-item { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.galerie-item--portrait { grid-row: span 2; }

.galerie-vignette {
  position: relative; display: block; width: 100%; padding: 0;
  border: 0; background: var(--color-text); cursor: pointer; overflow: hidden;
}
.galerie-item--paysage .galerie-vignette { aspect-ratio: 16 / 9; }
/* 3/4 et non 9/16 : au format natif, la vignette portrait faisait 997px pour
   une colonne voisine a 815 — elle ecrasait la grille. Le recadrage par
   object-fit prend sur le haut et le bas, jamais sur les visages au centre. */
.galerie-item--portrait .galerie-vignette { aspect-ratio: 3 / 4; }
.galerie-vignette img {
  display: block; width: 100%; height: 100%; object-fit: cover;
  transition: transform .45s ease, filter .3s ease;
}
.galerie-vignette:hover img,
.galerie-vignette:focus-visible img { transform: scale(1.04); filter: brightness(.8); }
.galerie-vignette:focus-visible { outline: 2px solid var(--color-accent); outline-offset: -2px; }

.galerie-play {
  position: absolute; top: 50%; left: 50%; translate: -50% -50%;
  display: grid; place-items: center; width: 60px; height: 60px;
  background: var(--canada-red); color: var(--color-bg);
  transition: transform .2s ease, filter .2s ease;
}
.galerie-vignette:hover .galerie-play { transform: scale(1.08); filter: brightness(1.1); }
.galerie-duree {
  position: absolute; right: 0; bottom: 0;
  padding: 6px 12px; background: var(--color-text); color: var(--color-bg);
  font-size: 11px; letter-spacing: .1em; font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.galerie-titre { margin: 0; font-size: 17px; font-weight: var(--font-heading-weight); }
.galerie-legende { margin: 0; font-size: 14px; line-height: 1.5; color: var(--ink-muted); }

@media (max-width: 760px) {
  /* Une colonne : le portrait n'a plus a s'aligner sur rien, il reprend sa
     place normale. */
  .galerie-grille { grid-template-columns: 1fr; }
  .galerie-item--portrait { grid-row: auto; }
  .galerie-play { width: 52px; height: 52px; }
}

@media (prefers-reduced-motion: reduce) {
  .galerie-vignette img, .galerie-play { transition: none; }
  .galerie-vignette:hover img,
  .galerie-vignette:focus-visible img { transform: none; }
  .galerie-vignette:hover .galerie-play { transform: none; }
}

/* ── Le lieu ───────────────────────────────────────────────────────────
   Deux cellules separees par le filet de 2px, comme les cartes du sejour : la
   video et la fiche se lisent comme deux pages voisines, pas deux encadres. */
.lieu-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(280px, 1fr);
  gap: 2px; background: rgba(32, 30, 29, .4);
  margin-top: clamp(28px, 4vw, 44px);
}

/* La façade video. Bouton et non lien : elle ne mene nulle part, elle agit. */
.lieu-play {
  position: relative; display: block; width: 100%; padding: 0;
  border: 0; background: var(--color-text); cursor: pointer;
  aspect-ratio: 16 / 9; overflow: hidden;
}
.lieu-play img {
  display: block; width: 100%; height: 100%; object-fit: cover;
  transition: transform .4s ease, filter .3s ease;
}
.lieu-play:hover img, .lieu-play:focus-visible img { transform: scale(1.03); filter: brightness(.82); }
.lieu-play:focus-visible { outline: 2px solid var(--color-accent); outline-offset: -2px; }

.lieu-play-mark {
  position: absolute; top: 50%; left: 50%; translate: -50% -50%;
  display: grid; place-items: center; width: 72px; height: 72px;
  background: var(--canada-red); color: var(--color-bg);
  transition: transform .2s ease, filter .2s ease;
}
.lieu-play:hover .lieu-play-mark { transform: scale(1.08); filter: brightness(1.1); }
.lieu-play-note {
  position: absolute; left: 0; bottom: 0;
  padding: 9px 16px; background: var(--color-text); color: var(--color-bg);
  font-size: 11px; letter-spacing: .14em; font-weight: 600;
}
/* Une fois la video chargee, l'iframe remplace l'image dans le meme cadre. */
.lieu-media iframe { display: block; width: 100%; aspect-ratio: 16 / 9; border: 0; }

.lieu-fiche {
  background: var(--color-bg);
  padding: clamp(28px, 3vw, 44px) clamp(24px, 2.6vw, 38px);
  display: flex; flex-direction: column; gap: 14px;
}
.lieu-kicker { margin: 0; font-size: 11px; letter-spacing: .14em; font-weight: 600; color: var(--accent-text); }
.lieu-nom { margin: 0; font-size: clamp(26px, 2.4vw, 34px); line-height: 1.1; }
.lieu-adresse { font-style: normal; font-size: 15px; line-height: 1.6; color: var(--ink-muted); }
.lieu-liens { display: flex; flex-wrap: wrap; gap: 10px; margin-top: auto; padding-top: 8px; }
.lieu-liens .btn { height: 48px; padding: 0 22px; }
.lieu-liens .btn:not(.btn-primary) { border-color: var(--color-divider); }

@media (max-width: 860px) {
  .lieu-grid { grid-template-columns: 1fr; }
  .lieu-play-mark { width: 58px; height: 58px; }
  .lieu-liens .btn { width: 100%; }
}

@media (prefers-reduced-motion: reduce) {
  .lieu-play img, .lieu-play-mark { transition: none; }
  .lieu-play:hover img, .lieu-play:focus-visible img { transform: none; }
  .lieu-play:hover .lieu-play-mark { transform: none; }
}

/* ── Séjour ───────────────────────────────────────────────────────────── */
.stay { background: var(--color-surface); }
.stay-cards {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr));
  gap: 2px; background: rgba(32, 30, 29, .4);
}
.stay-card {
  --stay-card-pad-y: 34px; --stay-card-pad-x: 32px;
  background: var(--color-bg);
  padding: var(--stay-card-pad-y) var(--stay-card-pad-x);
  display: flex; flex-direction: column; gap: 16px;
}
/* La photo est en pleine largeur de la carte : elle ressort du padding pour
   venir sous le filet de 2px de la grille, pour que les deux cartes se lisent
   comme deux pages voisines et non comme deux encadrés. */
.stay-card-media {
  margin: calc(var(--stay-card-pad-y) * -1) calc(var(--stay-card-pad-x) * -1) 0;
  aspect-ratio: 16 / 9;
}
.stay-card-kicker { font-size: 11px; letter-spacing: .14em; font-weight: 600; color: var(--accent-text); }
.stay-card h3 { margin: 0; font-size: 28px; }
.stay-card p { margin: 0; font-size: 15px; color: var(--ink-muted); flex: 1; }
.stay-card .btn { height: 48px; justify-content: flex-start; padding: 0 22px; }

/* L'état « pas encore ouvert ». Même idiome que les pass complets : le lien
   perd son href — il n'est donc ni focalisable ni activable — et son libellé
   dit l'état au lieu de promettre une action. La ligne de statut le double en
   clair, pour que l'état ne tienne pas au seul gris du bouton. */
.stay-card .stay-card-status {
  flex: none; display: flex; align-items: flex-start; gap: 8px;
  margin: 0; font-size: 13px; color: var(--ink-muted);
}
/* Le carre se cale sur la premiere ligne : sur mobile la phrase passe sur deux
   lignes, et un marqueur centre sur le bloc flotte alors entre les deux. */
.stay-card .stay-card-status::before {
  content: ""; width: 8px; height: 8px; flex: none; margin-top: 6px;
  background: var(--color-divider);
}
.stay-card .btn[aria-disabled="true"] {
  color: var(--ink-muted); border-color: var(--color-divider);
  cursor: default; pointer-events: none;
}

.community {
  margin-top: clamp(48px, 6vw, 88px);
  border-top: var(--rule); padding-top: 44px;
}
.community-head {
  display: flex; flex-wrap: wrap; align-items: flex-end;
  justify-content: space-between; gap: 24px; margin-bottom: 32px;
}
.community-head h3 {
  margin: 0; font-size: clamp(24px, 2.6vw, 36px);
  letter-spacing: -.02em; font-weight: 400;
}
.community-head h3 strong { font-weight: var(--font-heading-weight); }
.stay-tabs { display: flex; border: 2px solid var(--color-text); }
.stay-tab {
  padding: 12px 22px; min-height: 44px; border: 0; cursor: pointer;
  font-family: inherit; font-size: 13px;
  font-weight: var(--font-heading-weight); letter-spacing: .04em;
  background: transparent; color: var(--color-text);
}
.stay-tab[aria-selected="true"] { background: var(--color-text); color: var(--color-bg); }
.flow {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr));
  border-top: var(--rule);
}
.flow-step { padding: 26px 24px; border-left: var(--rule-soft); }
.flow-n {
  margin: 0 0 14px; font-size: 12px; letter-spacing: .14em;
  font-weight: var(--font-heading-weight); color: var(--accent-text);
}
.flow-step h4 { margin: 0 0 8px; font-size: 19px; }
.flow-step p { margin: 0; font-size: 13px; color: var(--ink-60); }
.community-actions {
  display: flex; flex-wrap: wrap; align-items: center; gap: 18px; margin-top: 32px;
}
.community-actions .btn { height: 48px; padding: 0 24px; letter-spacing: .04em; }
.community-actions p {
  margin: 0; font-size: 13px; color: var(--ink-muted); max-width: 52ch;
}

/* ── Partenaires ──────────────────────────────────────────────────────────
   La section est une échelle, pas une grille de six cases identiques : deux
   partenariats titres, puis quatre partenariats de programme. Le rang se lit
   avant le texte — d'abord par la taille de la carte, ensuite par le fond
   encre du Presenting Partner, le même que celui de la section Billets. */
.partners-head {
  display: flex; flex-wrap: wrap; align-items: flex-end;
  justify-content: space-between; gap: 28px 48px; margin-bottom: 56px;
}
.partners-intro { flex: 1 1 520px; min-width: 0; }
.partners-head h2 { max-width: 22ch; margin-bottom: 18px; text-wrap: balance; }
.partners-lede { margin: 0; font-size: 17px; line-height: 1.5; color: var(--ink-muted); max-width: 52ch; }
.partners-head .btn { height: 48px; padding: 0 24px; }
.partners-actions { display: flex; flex-wrap: wrap; gap: 14px; }

/* Une légende posée sur un filet : elle annonce le groupe qui suit sans
   ajouter un niveau de titre au plan du document. */
.rule-cap {
  margin: 0 0 2px; padding-top: 14px; border-top: var(--rule);
  font-size: 11px; letter-spacing: .14em; font-weight: 600; color: var(--ink-50);
}
.rule-cap--spaced { margin-top: 72px; }

/* Quatre colonnes déclarées, comme les partenariats de programme plus bas.
   `auto-fit` faisait retomber la quatrième statistique seule sur un second
   rang, avec son filet gauche et ses 24px de retrait alors qu'elle se trouvait
   sur le bord de la section : le seul reset était `:first-child`, qui ne
   connaît pas le début de rang. Les paliers sont désormais tenus à la main. */
.stats {
  display: grid; grid-template-columns: repeat(4, 1fr);
  border-bottom: var(--rule);
}
.stat { padding: 30px 24px 34px; border-left: var(--rule-soft); }
.stat:first-child { padding-left: 0; border-left: 0; }
.stat-value {
  margin: 0; font-size: clamp(40px, 4.6vw, 68px); line-height: 1;
  font-weight: var(--font-heading-weight); letter-spacing: -.035em;
  /* Chiffres à chasse fixe : pendant le décompte, un « 1 » et un « 8 » ne
     font plus bouger les chiffres voisins. Archivo porte `tnum`. */
  font-variant-numeric: tabular-nums;
}
/* Le compteur réserve sa largeur finale avant de partir de zéro (motion.js) :
   sans `inline-block`, `min-width` ne s'applique pas et le « + » recule d'un
   caractère à chaque image. */
.stat-value .m-count { display: inline-block; }
.stat-label {
  margin: 10px 0 0; font-size: 13px; letter-spacing: .12em;
  font-weight: 600; color: var(--ink-50);
}
.stat-note { margin: 6px 0 0; font-size: 13px; line-height: 1.45; color: var(--ink-muted); max-width: 26ch; }

/* Les deux titres : deux cartes de plein format, contreparties comprises.
   Le lecteur n'a plus à télécharger le dossier pour savoir ce qu'il achète. */
.tiers { display: grid; grid-template-columns: repeat(2, 1fr); gap: 2px; }
.tier {
  display: flex; flex-direction: column;
  padding: 32px 30px 34px; border: var(--hair);
}
.tier--lead { background: var(--color-text); color: var(--color-bg); border-color: transparent; }
.tier-n {
  margin: 0 0 20px; font-size: 12px; letter-spacing: .14em;
  font-weight: var(--font-heading-weight); color: var(--accent-text);
}
.tier--lead .tier-n { color: var(--color-accent-400); }
.tier-head {
  display: flex; flex-wrap: wrap; align-items: baseline;
  justify-content: space-between; gap: 8px 16px;
}
.tier-head h3 { margin: 0; font-size: clamp(24px, 2.4vw, 32px); line-height: 1.08; letter-spacing: -.02em; }
/* « Une seule place » est l'argument le plus fort de la carte : il était posé
   en 11px gris, plus discret que la mention la moins utile. Cartouche carré —
   pas de pilule, le reste de la page n'en a aucune — et `nowrap` pour qu'il
   passe à la ligne entier plutôt que coupé en deux. */
.tier-slots {
  flex: none; padding: 5px 9px; border: var(--hair);
  font-size: 12px; letter-spacing: .1em; text-transform: uppercase;
  font-weight: 600; color: var(--ink-50); white-space: nowrap;
}
.tier--lead .tier-slots {
  border-color: var(--color-accent-400); color: var(--color-accent-400);
}
/* La marge basse est portée par le chapô : combinée au `margin-top: auto` de
   la liste, elle garde 26px minimum tout en poussant les contreparties en pied
   de carte. Les deux cartes ont quatre lignes chacune — leurs listes démarrent
   donc exactement à la même hauteur, même quand un chapô tient sur trois
   lignes et l'autre sur deux. */
.tier-line { margin: 14px 0 26px; font-size: 15px; line-height: 1.5; color: var(--ink-60); max-width: 40ch; }
.tier--lead .tier-line { color: var(--ground-70); }
.tier-list {
  margin: auto 0 0; padding: 0; list-style: none;
  border-top: var(--hair); font-size: 14px; line-height: 1.45;
}
.tier--lead .tier-list, .tier--lead .tier-list li { border-color: rgba(243, 242, 242, .22); }
.tier-list li { padding: 12px 0; border-bottom: var(--hair); }
.tier-list li:last-child { border-bottom: 0; padding-bottom: 0; }

/* Le point de décision est ici, pas 64px plus bas après quatre autres cartes.
   Hauteur 44px : la cible tactile minimale, soulignement décalé pour rester
   lisible sous les jambages. */
.tier-cta {
  display: inline-flex; align-items: center; gap: 10px;
  align-self: flex-start; min-height: 44px; margin-top: 24px;
  font-size: 14px; font-weight: 600; color: var(--accent-text);
  text-decoration: underline; text-underline-offset: 4px;
  text-decoration-thickness: 1px;
}
.tier-cta:hover { text-decoration-thickness: 2px; }
.tier-cta-arrow { transition: transform .18s ease; }
.tier-cta:hover .tier-cta-arrow { transform: translateX(4px); }
.tier--lead .tier-cta { color: var(--color-accent-400); }

/* Quatre partenariats thématiques : un rang de quatre, sans orphelin. */
.packages { display: grid; grid-template-columns: repeat(4, 1fr); margin-top: 2px; }
.package {
  display: flex; flex-direction: column;
  padding: 28px 24px 30px; border-left: var(--rule-soft); border-bottom: var(--hair);
}
.package:first-child { padding-left: 0; border-left: 0; }
.package .tier-n { margin-bottom: 16px; }
.package h3 { margin: 0 0 8px; font-size: 19px; line-height: 1.15; text-wrap: balance; }
.package-line { margin: 0 0 auto; font-size: 13px; line-height: 1.5; color: var(--ink-60); }
.package-scope {
  margin: 18px 0 0; padding-top: 12px; border-top: var(--hair);
  font-size: 12px; line-height: 1.4; color: var(--ink-muted);
}

/* Le pas suivant, là où le lecteur est convaincu — pas seulement en haut de
   section, où il ne l'était pas encore. C'est la cible des deux boutons. */
.partners-cta {
  display: flex; flex-wrap: wrap; align-items: flex-end;
  justify-content: space-between; gap: 24px 48px;
  margin-top: 64px; padding: 40px; background: var(--color-surface);
  scroll-margin-top: 112px;
}
.partners-cta-copy { flex: 1 1 460px; min-width: 0; }
.partners-cta h3 { margin: 0 0 12px; font-size: clamp(22px, 2.2vw, 30px); line-height: 1.1; letter-spacing: -.02em; }
.partners-cta p { margin: 0; font-size: 14px; line-height: 1.55; color: var(--ink-muted); max-width: 58ch; }
.partners-cta-actions { display: flex; flex-wrap: wrap; gap: 14px; }
.partners-cta .btn { height: 48px; padding: 0 24px; }

/* ── Closing banner ───────────────────────────────────────────────────── */
.closer {
  background: var(--color-accent); color: var(--color-bg);
  padding: clamp(80px, 11vw, 168px) var(--pad-x); border-bottom: var(--rule);
}
.closer .eyebrow { color: rgba(243, 242, 242, .75); margin-bottom: 28px; }
.closer h2 {
  margin: 0; font-size: clamp(44px, 7.4vw, 124px); line-height: .94;
  letter-spacing: -.035em; font-weight: 400; color: var(--color-bg);
}
.closer h2 strong { font-weight: var(--font-heading-weight); }
.closer-foot {
  display: flex; flex-wrap: wrap; align-items: flex-end;
  justify-content: space-between; gap: 36px; margin-top: 52px;
}
.closer-motto { margin: 0; font-size: clamp(18px, 2vw, 26px); color: rgba(243, 242, 242, .85); }
.closer-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 24px; }
.closer-actions .btn {
  height: 60px; padding: 0 34px; background: var(--color-bg);
  color: var(--color-text); font-size: 17px; letter-spacing: .04em;
}
.closer-actions .btn:hover { background: #fff; }
.closer-links { display: flex; flex-wrap: wrap; gap: 16px; font-size: 14px; font-weight: 600; }
.closer-links a {
  color: var(--color-bg); text-decoration: none;
  border-bottom: 1px solid rgba(243, 242, 242, .5);
}

/* ── Footer ───────────────────────────────────────────────────────────────
   Quatre étages, dans l'ordre où on en a besoin en bas de page : l'infolettre,
   les coordonnées, le plan du site, les mentions. Chacun porte son propre
   fond et son propre filet — c'est ce qui les sépare, pas une marge. */
.site-footer { background: var(--color-text); color: var(--color-bg); }

/* L'infolettre. Le seul étage à porter une image : une photographie très
   assombrie et désaturée, qui donne de la profondeur au bandeau sans
   concurrencer le champ. Décorative — alt vide, aria-hidden, et le dégradé
   ramène le fond à l'encre du reste du pied de page sur les bords. */
.footer-news {
  position: relative; isolation: isolate; overflow: hidden;
  padding: clamp(56px, 7vw, 104px) var(--pad-x);
  background: var(--color-text); text-align: center;
}
.footer-news-bed { position: absolute; inset: 0; z-index: -1; display: block; }
.footer-news-bed img {
  width: 100%; height: 100%; object-fit: cover; object-position: center 38%;
  filter: grayscale(1) contrast(1.06); opacity: .5;
}
.footer-news::after {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: radial-gradient(118% 92% at 50% 42%,
    rgba(32, 30, 29, .62) 0%, rgba(32, 30, 29, .82) 48%, var(--color-text) 100%);
}
.footer-news-inner { max-width: 720px; margin-inline: auto; }
.footer-news h2 {
  margin: 0 0 14px; font-weight: 400; letter-spacing: -.025em; line-height: 1.04;
  font-size: clamp(28px, 3.4vw, 48px);
}
.footer-news h2 strong { font-weight: var(--font-heading-weight); }
.footer-news-lede {
  margin: 0 auto 28px; max-width: 54ch; font-size: 16px;
  color: rgba(243, 242, 242, .88);
}

/* Le champ et le bouton sur une seule ligne, comme la maquette de référence —
   mais à angles vifs : Modernist pose --radius-md à 0 et le pied de page n'est
   pas l'endroit où en sortir. */
.news-form { max-width: 580px; margin-inline: auto; }
.news-field { display: flex; flex-wrap: wrap; gap: 10px; }
.news-field .input {
  flex: 1 1 240px; min-height: 56px; padding: 12px 16px; font: inherit; font-size: 15px;
  color: var(--color-text); background: var(--color-bg);
  border: 2px solid transparent; border-radius: 0;
}
.news-field .input::placeholder { color: var(--ink-muted); }
.news-field .input:focus-visible {
  border-color: var(--canada-lift);
  outline: 2px solid var(--color-bg); outline-offset: 2px;
}
.news-field .btn { flex: 0 0 auto; min-height: 56px; padding-inline: 26px; letter-spacing: .04em; }
.news-form[data-invalid] .input { border-color: var(--canada-lift); }
/* Une seule zone d'annonce : elle porte l'erreur comme la confirmation, et
   `role="status"` la fait lire sans voler le focus au champ. */
.news-status {
  margin: 14px 0 0; min-height: 1.25em; font-size: 13px; font-weight: 600;
  color: rgba(243, 242, 242, .88);
}
.news-status[data-state="error"] { color: var(--color-accent-400); }
.news-status[data-state="ok"] { color: var(--color-bg); }
.news-legal { margin: 10px 0 0; font-size: 12px; color: rgba(243, 242, 242, .9); }

/* ── Le pied de page ──────────────────────────────────────────────────────
   Il portait trois colonnes de trois liens, un sceau de 72px et beaucoup
   d'air. Ce qui suit lui donne du poids sans lui donner du bruit :

   - LE FILET ROUGE en haut. La rampe canadienne signe le bas de page comme
     elle signe les boutons. Deux pixels : une signature, pas une barre.
   - LE SCEAU RESPIRE, a 88px, avec le halo de la fiche revendeur — sans lui,
     un blason sombre sur l'encre du pied n'est qu'une tache.
   - LES FAITS. Quand, ou, a qui ecrire : c'est ce qu'on vient chercher en bas
     d'une page, et ce n'etait nulle part.
   - LA GRILLE tient a `auto-fit` : trois colonnes de liens, les faits, et les
     reseaux quand ils existent. Une colonne de plus ne casse rien.
   ───────────────────────────────────────────────────────────────────────── */
.site-footer { position: relative; }
.site-footer::before {
  content: ""; position: absolute; inset: 0 0 auto; height: 2px;
  background: var(--canada-grad);
}

.footer-main { padding: clamp(56px, 6.5vw, 96px) var(--pad-x) 30px; }
/* La grille monte par PALIERS EXPLICITES, et chaque piste est en
   `minmax(0, 1fr)`.

   C'est le seul garde-fou qui tienne. `minmax(200px, …)` garde ses 200px quel
   que soit le conteneur : a 375px la grille debordait de 53px et la page
   partait en travers. Et `min(200px, 100%)` ne sauve rien ici — il ne cede
   que si le CONTENEUR fait moins de 200px, ce qui n'arrive jamais. Seul
   `minmax(0, …)` autorise une piste a se serrer autant qu'il faut.

   Mesure a chaque palier : 375, 414, 600, 768, 1024, 1280, 1440. */
.footer-grid {
  display: grid; grid-template-columns: minmax(0, 1fr);
  gap: 34px; padding-bottom: 46px; border-bottom: var(--rule-inverse);
}
@media (min-width: 560px) {
  .footer-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 36px 32px; }
}
@media (min-width: 900px) {
  .footer-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
/* Au large, la marque prend une piste et demie : elle porte un sceau, un nom,
   une edition et une devise, la ou les autres portent quatre liens. */
@media (min-width: 1180px) {
  .footer-grid { grid-template-columns: 1.5fr repeat(4, minmax(0, 1fr)); gap: 40px 36px; }
}

/* La marque. Le nom en capitales d'affiche, l'edition en rouge, la devise en
   italique claire : trois poids, trois encres, une seule voix. */
.footer-brand { display: flex; flex-direction: column; align-items: flex-start; gap: 0; }
.footer-sceau {
  width: 88px; height: 88px; object-fit: contain; margin-bottom: 18px;
  filter: brightness(1.08)
          drop-shadow(0 0 1px rgba(243, 242, 242, .55))
          drop-shadow(0 0 14px rgba(243, 242, 242, .18));
}
.footer-brand-nom {
  margin: 0; font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 17px; line-height: 1.2; letter-spacing: -.01em; color: var(--color-bg);
}
.footer-brand-edition {
  margin: 4px 0 0; font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 12px; letter-spacing: .16em; color: var(--color-accent-400);
}
.footer-brand-devise {
  margin: 16px 0 0; max-width: 26ch; font-size: 14px; line-height: 1.5;
  color: rgba(243, 242, 242, .82);
}
.footer-brand-orga {
  margin: 10px 0 0; font-size: 12px; color: rgba(243, 242, 242, .5);
}

/* L'etiquette de colonne prend le rouge et son filet. inline-block pour que
   le filet s'arrete au mot plutot que de traverser la colonne — un trait
   pleine largeur se lirait comme une separation de bloc. */
.footer-col-titre {
  display: inline-block; margin: 0 0 16px; padding-bottom: 8px;
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 11px; letter-spacing: .14em;
  color: var(--color-accent-400); border-bottom: 2px solid rgba(255, 151, 131, .4);
}
.footer-col ul {
  margin: 0; padding: 0; list-style: none;
  display: flex; flex-direction: column; gap: 11px; font-size: 14px;
}
/* Le soulignement se peint au survol depuis la gauche, au lieu d'apparaitre
   d'un coup : c'est le meme geste que `u-anim` dans le bandeau du haut. */
.footer-col a {
  display: inline-block; color: var(--color-bg); text-decoration: none;
  background-image: linear-gradient(currentColor, currentColor);
  background-repeat: no-repeat; background-position: 0 100%; background-size: 0 1px;
  transition: background-size .24s ease, color .18s ease;
}
.footer-col a:hover,
.footer-col a:focus-visible { color: var(--color-accent-400); background-size: 100% 1px; }

/* Les faits : la ligne des dates en capitales, le lieu en clair, l'adresse en
   dessous et plus discrete, le courriel en dernier. */
.footer-faits .footer-fait { margin: 0 0 12px; font-size: 14px; line-height: 1.45; }
.footer-faits .footer-fait:last-child { margin-bottom: 0; }
/* Les dates en casse de phrase et SANS interlettrage : « Du 2 au 5 septembre »
   n'est pas une etiquette, c'est une phrase. L'interlettrage large est
   reserve aux eyebrows en capitales — applique a une phrase, il la fait
   bégayer. L'annee prend le rouge : c'est elle qu'on cherche. */
.footer-fait--dates {
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 15px; line-height: 1.35; letter-spacing: 0; color: var(--color-bg);
}
.footer-fait--dates span { color: var(--color-accent-400); }
.footer-fait a { color: var(--color-bg); text-decoration: none; }
.footer-fait a:hover,
.footer-fait a:focus-visible { color: var(--color-accent-400); }
.footer-fait-adresse {
  display: block; margin-top: 3px; font-size: 12.5px; line-height: 1.45;
  color: rgba(243, 242, 242, .55); overflow-wrap: break-word;
}
/* `overflow-wrap: anywhere` : une adresse de courriel est un seul mot de
   vingt caracteres, et un mot insecable impose un plancher a sa colonne —
   c'est lui qui faisait deborder la grille a 1180px, pile au palier ou la
   cinquieme piste apparait. Une adresse coupee en deux se lit tres bien ;
   une grille qui deborde, non. */
.footer-courriel {
  border-bottom: 1px solid rgba(255, 151, 131, .45);
  overflow-wrap: anywhere;
}

/* Les reseaux : le pictogramme et le nom, alignes sur la meme ligne de base
   que les autres colonnes. */
.footer-reseaux ul { gap: 12px; }
.footer-reseaux a { display: inline-flex; align-items: center; gap: 10px; }
.pied-reseau-icone { width: 17px; height: 17px; flex: none; opacity: .8; }
.footer-reseaux a:hover .pied-reseau-icone,
.footer-reseaux a:focus-visible .pied-reseau-icone { opacity: 1; }

.footer-foot { padding-top: 24px; }
.footer-foot p { margin: 0; font-size: 12px; color: rgba(243, 242, 242, .6); max-width: 70ch; }
.footer-foot .dagger { color: var(--color-accent-500); font-size: 1em; }

/* La barre de bas de page : la mention légale, la langue et la signature. */
.footer-legal {
  padding: 16px var(--pad-x); border-top: var(--rule-inverse);
  background: rgba(0, 0, 0, .3);
}
.footer-legal-inner {
  display: flex; flex-wrap: wrap; align-items: center;
  justify-content: space-between; gap: 10px 24px;
}
.footer-legal p { margin: 0; font-size: 12px; color: var(--ground-70); }
.footer-legal-end { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 20px; }
.footer-credit a {
  color: var(--color-bg); font-weight: 600; text-decoration: none;
  border-bottom: 1px solid var(--color-accent-500);
}
.footer-credit a:hover { color: var(--color-accent-400); border-bottom-color: currentColor; }

/* ── Mobile menu (the design's screen 02) ─────────────────────────────── */
.mobile-menu {
  /* --menu-pad-x porte le retrait latéral : l'encoche du paysage repousse le
     texte sans déplacer les filets, qui restent bord à bord.
     100dvh cale la feuille sur la vue réellement visible — avec la seule
     inset:0, la barre d'adresse d'iOS mange le bouton du pied. */
  position: fixed; inset: 0; height: 100dvh; z-index: 100;
  --menu-pad-x: max(var(--pad-x), env(safe-area-inset-left, 0px), env(safe-area-inset-right, 0px));
  background: var(--color-text); color: var(--color-bg);
  display: flex; flex-direction: column;
  /* Sans `contain`, l'élan du doigt en bout de liste passe à la page dessous. */
  overscroll-behavior: contain;
  transform: translateY(-100%); visibility: hidden;
  transition: transform .28s ease, visibility 0s linear .28s;
}
.mobile-menu[data-open="true"] {
  transform: translateY(0); visibility: visible;
  transition: transform .28s ease, visibility 0s;
}
/* motion.css upgrades these transitions to the spring. */
.mobile-menu-top {
  display: flex; align-items: center; justify-content: space-between;
  /* Même retrait que le bandeau (6px autour du sceau) : la marque tombe
     au pixel près là où elle était, la feuille glisse dessus sans la déplacer. */
  padding: calc(6px + env(safe-area-inset-top, 0px)) var(--menu-pad-x) 6px;
  border-bottom: var(--rule-inverse); flex: none;
}
/* La marque de l'en-tête, reprise telle quelle : la feuille descend par-dessus
   le bandeau, et un sigle qui changerait de taille au passage se verrait. Le
   logo est décoratif — le texte à côté dit déjà le nom, d'où l'alt vide. */
.mobile-menu-brand {
  display: flex; align-items: center; gap: 10px;
  font-size: 11px; font-weight: var(--font-heading-weight); line-height: 1.1;
}
.mobile-menu-brand img { width: 32px; height: 32px; object-fit: contain; flex: none; }
.mobile-menu-close {
  width: 48px; height: 48px; display: flex; align-items: center; justify-content: center;
  font-size: 22px; font-weight: var(--font-heading-weight); line-height: 1;
  background: none; border: 0; color: inherit; cursor: pointer;
}
.mobile-menu nav {
  flex: 1; padding: 20px var(--menu-pad-x); display: flex; flex-direction: column;
  overflow-y: auto; overscroll-behavior: contain;
}
/* Direct children only — the language switcher lives in this nav too and must
   keep its 12px chrome size. */
.mobile-menu nav > a {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  min-height: 56px; padding: 16px 0; border-bottom: 1px solid rgba(243, 242, 242, .2);
  color: var(--color-bg); text-decoration: none;
  font-size: clamp(24px, 7vw, 28px); font-weight: var(--font-heading-weight);
  letter-spacing: -.02em; -webkit-tap-highlight-color: transparent;
}
.mobile-menu nav > a.is-accent { color: var(--color-accent-500); }
/* Un doigt n'a pas de survol : sans état pressé, le geste n'accuse rien
   pendant que la page suivante se charge. */
.mobile-menu nav > a:active { color: var(--color-accent-500); }
/* Où l'on se trouve. La pastille plutôt que la couleur : « Billets » est le
   seul mot rouge de la feuille, et il doit le rester. site.js pose
   aria-current sur la section à l'écran comme il le fait déjà pour le
   bandeau du bureau. */
.mobile-menu nav > a[aria-current="true"]::after {
  content: ""; flex: none; width: 9px; height: 9px;
  background: var(--color-accent-500);
}
/* Le panier dans le menu plein écran : il hérite du gabarit des autres entrées,
   mais porte son libellé en clair et pousse son compte au bout de la ligne. La
   pastille cesse d'être flottante — à cette taille, elle a la place de se poser.
   Et il faut lui rendre sa largeur : `.cart-link` est une cible carrée de 48px
   dans le bandeau, ici son filet s'arrêterait au bout de l'icône. */
.mobile-menu nav > a.cart-link--mobile {
  width: auto; height: auto; justify-content: flex-start; gap: 16px;
}
.cart-link--mobile .cart-link-icon { width: 26px; height: 26px; flex: none; }
.cart-link--mobile .cart-link-label { margin-right: auto; }
.cart-link--mobile .cart-link-count {
  position: static; min-width: 26px; height: 26px; padding: 0 7px; font-size: 14px;
}
.mobile-menu-foot {
  flex: none; border-top: var(--rule-inverse);
  padding: 12px var(--menu-pad-x) calc(16px + env(safe-area-inset-bottom, 0px));
}
.mobile-menu-foot .btn {
  height: 52px; width: 100%; justify-content: flex-start;
  padding: 0 22px; font-size: 15px; letter-spacing: .04em;
}

/* Téléphone couché, ou petit écran : cinq entrées à 76px ne tiennent plus et
   la liste se met à défiler alors qu'elle a cinq lignes. On resserre plutôt
   que de faire chercher « Partenaires » sous le pli. La cible reste au-dessus
   de 44px. */
@media (max-height: 620px) {
  .mobile-menu-top { padding-top: calc(10px + env(safe-area-inset-top, 0px)); padding-bottom: 10px; }
  .mobile-menu-brand img { width: 26px; height: 26px; }
  .mobile-menu nav { padding-top: 8px; padding-bottom: 8px; }
  .mobile-menu nav > a {
    min-height: 46px; padding: 8px 0; font-size: clamp(19px, 5.6vh, 24px);
  }
  /* Le sélecteur au bas du panneau : le retrait et la cible se resserrent
     comme le reste, sans descendre sous ce qu'un pouce vise. */
  .se-lang-switcher--mobile { padding-top: 10px; }
  .se-lang-switcher--mobile .se-lang-switcher__item { padding: 7px 0; }
  .mobile-menu-foot { padding-top: 8px; padding-bottom: calc(10px + env(safe-area-inset-bottom, 0px)); }
  .mobile-menu-foot .btn { height: 46px; }
}

/* ── Sticky mobile ticket bar (the design's screens 01 / 03) ──────────── */
:root {
  /* La hauteur de la barre, écrite une seule fois : 10 + les 48 du bouton +
     le filet, plus la marge du bas. Elle sert trois fois — la barre la porte,
     le corps la réserve, le hero s'en écarte — et un nombre écrit deux fois
     finit toujours par diverger : le coussin du corps valait 84px en dur et
     ignorait la zone sûre, donc la dernière ligne du pied de page passait sous
     la barre sur tout iPhone sans bouton.
     La zone sûre `max()` et non `+` : le trait tactile occupe déjà l'espace
     qu'il réserve, l'additionner à une marge donne 50px de vide sous un bouton
     qui tenait en 12. */
  --sticky-h: calc(60px + max(12px, env(safe-area-inset-bottom, 0px)));
}
.sticky-cta {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
  display: none;
  /* L'encoche en paysage repousse le bouton comme elle repousse la feuille du
     menu — même calcul que --menu-pad-x. */
  padding: 10px max(var(--pad-x), env(safe-area-inset-left, 0px), env(safe-area-inset-right, 0px))
           max(12px, env(safe-area-inset-bottom, 0px));
  background: var(--color-bg); border-top: var(--rule);
}
/* 48px et non les 52 de la maquette : elle dessinait la barre dans un cadre de
   760px, où 82px de bandeau se voyaient peu. Sur un téléphone réel, zone sûre
   comprise, la barre prenait un septième de l'écran en permanence. 48 reste
   au-dessus des 44 de la cible tactile. */
.sticky-cta .btn {
  height: 48px; width: 100%; justify-content: flex-start;
  padding: 0 22px; font-size: 15px; letter-spacing: .04em;
}

/* Par-dessus le hero, le rappel fait doublon : le même bouton y est déjà, en
   grand. Le bandeau des pages intérieures porte le sien de la même façon, donc
   il compte comme un hero — et site.js éteint aussi la barre quand la section
   qu'elle vise est à l'écran : un rappel n'a rien à rappeler par-dessus ce
   qu'il montre. Sans JavaScript rien de tout ça ne s'applique et la barre
   reste visible, comme avant. */
.js body:has(.hero, .page-hero) .sticky-cta {
  transform: translateY(100%); opacity: 0; visibility: hidden;
  transition: transform .3s ease, opacity .22s ease, visibility .3s;
}
.js body:has(.hero, .page-hero) .sticky-cta[data-out="true"] {
  transform: none; opacity: 1; visibility: visible;
}

/* ── Responsive ───────────────────────────────────────────────────────── */

/* Le bandeau sur UNE ligne — deux paliers, mesurés, pas devinés.

   Le principe n'a pas bougé : la feuille mobile — qui porte les mêmes liens,
   Billets et Contact compris — vaut mieux qu'un bandeau sur deux étages. Ce
   qui a bougé, c'est ce que le bandeau porte. Le seuil de 1180px datait d'un
   sélecteur à deux langues ; avec la pastille, la marque, les six liens, le
   panier et le bouton demandent 1382px — et 1280px sans elle. D'où deux
   paliers, du plus dispensable au moins :

     ≥ 1400px  tout ;
     1300-1399 la pastille sort du bandeau — le pied de page la porte à
               toutes les largeurs, et le bandeau de langue propose déjà
               la sienne au visiteur (inc/regions.php) ;
     < 1300px  la navigation passe au menu plein écran, qui reprend les
               trois langues en bas de son panneau.

   Ce point de rupture est celui de la navigation seule ; le reste du site
   bascule toujours à 1080px. */
@media (max-width: 1400px) {
  .header-end .se-lang-switcher { display: none; }
}

@media (max-width: 1300px) {
  .nav-main { display: none; }
  .nav-toggle { display: flex; }
}

@media (max-width: 1080px) {
  /* Trois colonnes ne tiennent plus : la description passe sous le titre et
     l'heure garde la sienne, à droite, où l'œil la cherche. */
  .day-card { grid-template-columns: 116px 1fr; }
  .day-date { padding: 22px 16px 22px 20px; }
  .day-list { padding: 0 20px 4px; }
  .day-cols, .session-main { grid-template-columns: 1fr 84px; }
  .day-cols span:nth-child(2) { display: none; }
  .session-head { grid-column: 1; grid-row: 1; }
  .session-time { grid-column: 2; grid-row: 1; }
  .session-desc { grid-column: 1 / -1; grid-row: 2; }
  .stats { grid-template-columns: repeat(2, 1fr); }
  .stat:first-child { padding-left: 24px; }
  .stat:nth-child(odd) { padding-left: 0; border-left: 0; }
  .stat:nth-child(-n+2) { border-bottom: var(--hair); }
  .packages { grid-template-columns: repeat(2, 1fr); }
  .package:first-child { padding-left: 24px; }
  .package:nth-child(odd) { padding-left: 0; border-left: 0; }
  .tiers { grid-template-columns: 1fr; }
  .tier { padding: 28px 26px 30px; }
  .partners-cta { padding: 32px 28px; }
}

@media (max-width: 760px) {
  /* The design's mobile header: 32px mark, "ABC / CANADA 2027", burger.
     nowrap keeps the burger on the brand's row instead of dropping below. */
  .site-header { min-height: 68px; flex-wrap: nowrap; gap: 12px; }
  .brand { gap: 10px; min-width: 0; }
  .brand img { width: 32px; height: 32px; }
  .brand .sceau--tete > img { width: 43px; height: 43px; }
  .sceau--tete { --sceau-nom: 8.5px; gap: 2px; }
  .brand-name { font-size: 12px; }
  .brand-name-full { display: none; }
  .brand-name-short { display: inline; }
  .brand-edition { font-size: 10px; letter-spacing: .14em; }
  .btn-ticket { display: none; }
  /* The type runs full width here, so there is no clear column to release —
     drop the horizontal layer and carry it all on the vertical one. */
  .hero-overlay {
    background: linear-gradient(to top,
      rgba(32, 30, 29, .88) 0%,
      rgba(32, 30, 29, .84) 32%,
      rgba(32, 30, 29, .74) 55%,
      rgba(32, 30, 29, .50) 72%,
      rgba(32, 30, 29, .18) 88%,
      rgba(32, 30, 29, 0) 100%);
  }
  /* The design's 48px floor still overflows a 320px screen — keep the ramp
     but let it scale below the smallest breakpoint. */
  .hero h1 { font-size: clamp(34px, min(11vw, 12.4vh), 60px); }
  /* Deux vues côte à côte sur 360px : le libellé passe sous le numéro
     plutôt que de se faire couper. */
  .hero-view { grid-template-columns: 1fr; row-gap: 2px; }
  .hero-view-n { font-size: 11px; }
  .hero-rail { gap: 14px; }
  /* Les mentions passent sous la date plutôt qu'à côté. */
  .pillar { padding: 0 0 26px; border-left: 0; border-top: var(--rule-soft); padding-top: 26px; }
  .pillars { gap: 0; }
  /* Sur un téléphone la bande se fait glisser au doigt : les flèches ne
     servent plus qu'à occuper la place du premier visage. La barre garde son
     filet et son compte, qui disent toujours ce qu'il y a à parcourir. */
  .js .amb-arrows { display: none; }
  /* ── Le programme en format compact ─────────────────────────────────── */
  .prog-head { gap: 12px; margin-bottom: 20px; }
  .prog-view { font-size: 13px; }
  /* Les deux puces d'une session dépliée : elles passent à la ligne, elles ne
     se compriment pas. */
  .prog-chip { flex: 0 0 auto; }

  /* Les onglets suivent la lecture : collés sous l'en-tête, ils se resserrent
     dès qu'ils s'y accrochent — changer de jour ne demande plus de remonter. */
  /* `.js .day-tabs { position: relative }` de motion.css tient l'indicateur
     coulissant, et motion.css est chargé après : il faut passer devant sans le
     casser. La hauteur d'en-tête est mesurée par programme.js — l'écrire en dur
     ici, c'est un décalage à chaque retouche du bandeau. */
  #programme .day-tabs {
    position: sticky; top: var(--prog-sticky-top, 70px); z-index: 20;
    background: var(--color-bg);
  }
  /* Le mois est le même pour tous les jours : sous 760px il ne mérite pas
     la seconde ligne qu'il imposait à chaque onglet. */
  .day-tab-month { display: none; }
  /* Quatre onglets par largeur d'écran : le cinquième dépasse à moitié, ce
     qui dit à lui seul que la rangée défile. */
  .day-tab {
    min-width: 0; flex: 0 0 26%; padding: 12px 20px 12px 8px;
    transition: padding .18s ease, gap .18s ease;
  }
  .day-tab-label { font-size: 16px; white-space: nowrap; }
  .day-tab-kicker {
    font-size: 10px; letter-spacing: .1em; white-space: nowrap;
    overflow: hidden; max-height: 20px;
    transition: max-height .18s ease, opacity .18s ease;
  }
  .day-tab-count { top: 8px; right: 8px; font-size: 11px; }
  .programme[data-stuck="true"] .day-tabs { border-top-color: transparent; }
  .programme[data-stuck="true"] .day-tab { gap: 0; padding-top: 9px; padding-bottom: 9px; }
  .programme[data-stuck="true"] .day-tab-kicker { max-height: 0; opacity: 0; }
  .programme[data-stuck="true"] .day-tab-count { top: 8px; }

  /* La fiche s'empile : la date devient un bandeau d'un seul rang au-dessus
     de sa liste, et les libellés de colonnes s'effacent — sur un rang par
     ligne ils n'annoncent plus rien que la ligne ne dise déjà. */
  .sessions { margin-top: 0; }
  .day-card { grid-template-columns: 1fr; }
  .day-date {
    flex-direction: row; align-items: baseline; gap: 10px;
    padding: 14px 18px; border-right: 0; border-bottom: var(--hair);
  }
  .day-date-num { font-size: 26px; line-height: 1; }
  .day-list { padding: 0 18px 4px; }
  .day-cols { display: none; }

  /* La ligne de session en lignes courtes plutôt qu'en colonnes serrées :
     l'heure en tête, le titre sur toute la largeur, puis la description, la
     salle et la piste. Le titre y gagne le double de place. */
  .session-main {
    display: flex; flex-wrap: wrap; align-items: center;
    column-gap: 12px; row-gap: 6px; padding: 16px 0;
  }
  .session-time {
    order: 1; flex: 0 1 auto; flex-direction: row; align-items: baseline; gap: 8px;
  }
  .session-head { order: 2; flex: 1 1 100%; gap: 4px; }
  .session-title { font-size: 17px; }
  .session-desc { order: 3; flex: 1 1 100%; font-size: 14px; }
  .session-detail { padding-bottom: 18px; }
  .session-meta { gap: 8px 24px; }
  .sessions-day { margin-top: 32px; }
  .stats { grid-template-columns: 1fr; }
  .stat, .stat:first-child { padding: 26px 0; border-left: 0; border-bottom: var(--hair); }
  .stat:last-child { border-bottom: 0; }
  .stat-note { max-width: none; }
  .rule-cap--spaced { margin-top: 56px; }
  .tier { padding: 26px 20px 28px; }
  .packages { grid-template-columns: 1fr; }
  .package, .package:first-child { padding: 24px 0; border-left: 0; border-bottom: var(--hair); }
  .partners-cta { margin-top: 48px; padding: 28px 22px; }
  .partners-cta .btn, .partners-actions .btn { flex: 1 1 100%; }
  .flow-step { padding: 22px 0; border-left: 0; border-bottom: var(--hair); }
  .stay-tabs { width: 100%; }
  .stay-tab { flex: 1; padding: 12px 10px; font-size: 12px; }
  .pass { padding: 28px 22px; }
  .body-has-sticky { padding-bottom: calc(var(--sticky-h) + 2px); }
  .sticky-cta { display: block; }
  /* Repli sans JavaScript : site.js mesure la barre et écrit --hero-safe-b en
     style en ligne sur <html>, qui l'emporte sur cette règle. Sans lui la
     barre reste visible — il faut donc que le hero lui garde sa place. */
  :root { --hero-safe-b: var(--sticky-h); }

  /* ── Le pied de page en une colonne ─────────────────────────────────── */
  /* Le bouton passe sous le champ : côte à côte sur 360px, il ne resterait
     ni assez de champ pour lire son adresse ni assez de bouton pour le lire. */
  .news-field .btn { flex: 1 1 100%; }
  .footer-legal-inner { justify-content: flex-start; }
  /* La langue et la signature tiennent côte à côte sur un bureau, où la barre
     du bas les cale à droite. Sur 375px la rangée s'empile et le crédit partait
     à 97px du bord, accroché à la suite du sélecteur de langue — seule ligne de
     la page à ne pas commencer sur le rail. Chacun la sienne, tous au même
     bord. */
  .footer-legal-end { flex-direction: column; align-items: flex-start; gap: 10px; }
}

/* ── Grandes vues : le bloc du hero remonte ─────────────────────────────
   Sur un grand écran le hero est bien plus haut que son contenu : ancré au
   bas, le bloc se retrouvait tassé contre le bord et le rail frôlait la
   coupure. Un coussin plus généreux sous le rail le fait remonter sans lui
   faire quitter l'ancrage bas — la respiration reste sous le contenu, pas
   au-dessus. Les vues basses gardent la marge serrée : là, chaque pixel
   sert à faire tenir le hero en une seule vue. */
@media (min-width: 1081px) and (min-height: 700px) {
  .hero-overlay {
    padding-bottom: calc(clamp(60px, 11vh, 116px) + var(--hero-safe-b));
  }
}

/* ── Vues basses : la bande des ambassadeurs tient dans la fenêtre ──────
   Le chapeau, lui, ne dépend pas de la hauteur de l'écran : sur un portable
   en 760px, ses 88px de marge haute suffisaient à renvoyer le bas de la bande
   sous la ligne de flottaison. On les reprend là plutôt que sur les visages. */
@media (max-height: 820px) {
  .amb-head { padding-top: clamp(40px, 6vh, 64px); }
  .amb-deck { margin-top: 14px; }
  .amb-bar { margin-top: 18px; }
}

/* ── Vues courtes (portable en paysage, écran 13" bas) ──────────────────
   La rampe en vh a déjà réduit le titre ; ici on reprend le reste de la place
   sur les marges plutôt que sur le contenu, pour que le hero tienne en une
   vue sans jamais rogner l'appel à l'action ni le rail. */
/* Ecrans courts. Le seuil etait a 620px, mais un telephone courant fait 667 :
   les regles ne s'appliquaient pas la ou il en fallait. Le hero aligne son
   contenu en bas ; trop haut, il debordait donc VERS LE HAUT et l'eyebrow
   passait sous l'en-tete collante. */
@media (max-height: 760px) {
  .hero-overlay { padding-top: clamp(20px, 4vh, 40px); }
  .hero-tagline { margin-top: 10px; }
  .hero-actions { margin-top: 14px; gap: 10px; }
  .js .hero-rail { margin-top: 16px; }
  .hero-view-rule { margin-bottom: 8px; }
  .hero-edition { margin-top: 6px; line-height: 1.22; letter-spacing: .2em; }
  .hero-dates { margin-top: 2px; }

  /* Filet de securite : si le contenu depasse malgre le resserrement, le hero
     grandit au lieu de rogner son propre texte. Une section un peu plus haute
     se rattrape au defilement ; un titre coupe, non. */
  .hero { height: auto; min-height: calc(100svh - var(--header-h)); }
}
/* Sous 460px de haut il ne reste plus de quoi porter une accroche : le titre,
   les billets et le rail passent avant elle. */
@media (max-height: 460px) {
  .hero-tagline { display: none; }
}

/* ── Motion & print ───────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .tier-cta-arrow { transition: none; }
  .tier-cta:hover .tier-cta-arrow { transform: none; }
  /* Le dégradé reste, son va-et-vient s'arrête. */
  .btn-cta::before { animation: none; transform: none; }
  .btn-cta::after { display: none; }
  /* Les vidéos ne sont ni chargées (site.js) ni affichées : la photographie
     de chaque vue les remplace, donc le rail garde bien ses deux vues. */
  .hero-video { display: none; }
  .mobile-menu { transition: none; }
  * { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

@media print {
  .site-header, .sticky-cta, .mobile-menu { display: none !important; }
  /* Un champ d'inscription sur papier ne sert à rien — le reste du pied de
     page, si : les coordonnées et la signature s'impriment. */
  .footer-news { display: none !important; }

  /* Un programme, ça s'imprime. Sur papier il n'y a pas d'onglet :
     les quatre jours sortent à la suite, détails dépliés. Les aplats de fond
     partent avec — une fiche sur papier, c'est un filet, pas un pavé d'encre. */
  .prog-view, .day-tabs,
  .session-detail-actions, .sessions-empty { display: none !important; }
  .programme .sessions[hidden] { display: block !important; }
  .programme .sessions-day[hidden] { display: flex !important; }
  .programme .session-detail[hidden] { display: block !important; }
  .programme, .day-card { background: none; }
  .day-card { border: var(--hair); break-inside: avoid; }
  .session { break-inside: avoid; }
  .session-toggle::after { content: none; }
}

/* ─────────────────────────────────────────────────────────────────────────
   La bannière de langue — GOAL 9.

   Elle propose une traduction, une fois, et se ferme pour de bon. En bas de
   l'écran plutôt qu'en haut : au-dessus du pli, elle pousserait le hero et
   volerait le premier regard à ce que le visiteur est venu lire. Au-dessus de
   la barre CTA collante en hauteur, jamais à sa place — les deux cohabitent.
   ───────────────────────────────────────────────────────────────────────── */
.region-langue {
  position: fixed;
  left: 16px;
  right: 16px;
  bottom: calc(var(--sticky-h, 0px) + max(12px, env(safe-area-inset-bottom)));
  z-index: 60;
  display: flex;
  align-items: center;
  gap: 16px;
  max-width: 560px;
  margin-inline: auto;
  padding: 14px 16px;
  background: var(--color-text);
  color: var(--color-bg);
  box-shadow: 0 8px 32px rgb(0 0 0 / 28%);
  animation: region-langue-entree .32s ease-out both;
}

@keyframes region-langue-entree {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .region-langue { animation: none; }
}

.region-langue-texte {
  flex: 1 1 auto;
  margin: 0;
  font-size: 14px;
  line-height: 1.35;
}

.region-langue-lien {
  flex: 0 0 auto;
  color: inherit;
  font-family: var(--font-heading);
  font-weight: var(--font-heading-weight);
  font-size: 13px;
  letter-spacing: .04em;
  text-transform: uppercase;
  text-decoration: underline;
  text-underline-offset: 3px;
}

.region-langue-fermer {
  flex: 0 0 auto;
  /* 44 px de cible, comme partout ailleurs sur ce site. */
  width: 44px;
  height: 44px;
  margin: -10px -8px -10px 0;
  border: 0;
  background: none;
  color: inherit;
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
}

.region-langue-fermer:focus-visible,
.region-langue-lien:focus-visible {
  outline: 2px solid var(--color-bg);
  outline-offset: 2px;
}

@media (max-width: 560px) {
  .region-langue { flex-wrap: wrap; gap: 8px 12px; }
  .region-langue-texte { flex-basis: calc(100% - 44px); }
}
/* ─────────────────────────────────────────────────────────────────────────
   Le sélecteur de langue — GOAL 9.

   Un drapeau, le code, un chevron : la pastille ouvre la liste des trois
   langues. C'est un `<details>` — il s'ouvre au clavier et SANS JavaScript ;
   `site.js` n'ajoute qu'Échap et le clic au-dehors.

   À angles vifs, comme tout le reste : le système pose --radius-md à 0. Le
   disque du drapeau est la seule rondeur, et elle se justifie — un rectangle
   tricolore dans un bandeau se lit comme une image, un disque se lit comme
   une pastille d'interface.

   Dans le menu plein écran, pas de menu dans un menu : les trois langues sont
   posées à plat au bas du panneau, drapeau et code.
   ───────────────────────────────────────────────────────────────────────── */
.se-lang-switcher { flex: none; }
.se-lang-switcher__menu { position: relative; }

/* `list-style` et le marqueur WebKit : le triangle natif de <summary> n'a rien
   à faire ici, le chevron est à nous. */
.se-lang-switcher__bouton {
  display: inline-flex; align-items: center; gap: 7px;
  height: 40px; padding: 0 9px;
  border: 1px solid rgba(32, 30, 29, .25);
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 12px; letter-spacing: .06em;
  color: var(--color-text); cursor: pointer;
  list-style: none; user-select: none;
  transition: border-color .18s ease;
}
.se-lang-switcher__bouton::-webkit-details-marker { display: none; }
.se-lang-switcher__bouton::marker { content: ""; }
.se-lang-switcher__bouton:hover { border-color: var(--color-text); }
.se-lang-switcher__bouton:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }

/* Le disque du drapeau : le SVG est carré, c'est le masque qui l'arrondit. Le
   liseré intérieur détache le blanc du drapeau français du fond du bandeau —
   sans lui, le tricolore n'a plus que deux bandes. */
.se-lang-switcher__drapeau {
  flex: none; display: block; width: 18px; height: 18px;
  border-radius: 50%; overflow: hidden;
  box-shadow: inset 0 0 0 1px rgba(32, 30, 29, .22);
}
.se-lang-switcher__drapeau svg { display: block; width: 100%; height: 100%; }

/* Le nom entier de la langue : lu, jamais vu. C'est la recette de `.u-sr`,
   recopiee plutot que reutilisee — le releve de classes de chaque page sert de
   test, et `u-sr` qui apparait sur vingt-cinq pages y serait un ecart de plus
   a declarer. Une classe a nous ne coute que ces quatre lignes. */
.se-lang-switcher__sr {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; white-space: nowrap; border: 0; clip-path: inset(50%);
}

.se-lang-switcher__chevron {
  flex: none; width: 13px; height: 13px;
  opacity: .5; transition: transform .18s ease;
}
.se-lang-switcher__menu[open] .se-lang-switcher__chevron { transform: rotate(180deg); }

/* La liste flotte : ouvrir le menu ne doit pas pousser le bandeau d'un cran. */
.se-lang-switcher__liste {
  position: absolute; z-index: 60; top: calc(100% + 6px); right: 0;
  min-width: 100%; margin: 0; padding: 4px; list-style: none;
  background: var(--color-bg);
  border: 1px solid rgba(32, 30, 29, .25);
  box-shadow: 0 10px 28px rgba(32, 30, 29, .16);
}
/* Dans le pied, la page s'arrête juste en dessous : la liste monte. */
.se-lang-switcher--haut .se-lang-switcher__liste { top: auto; bottom: calc(100% + 6px); }
.se-lang-switcher__liste li { margin: 0; }

.se-lang-switcher__item {
  display: flex; align-items: center; gap: 9px;
  min-height: 40px; padding: 0 12px 0 8px;
  color: var(--color-text); text-decoration: none; white-space: nowrap;
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 13px;
}
.se-lang-switcher__liste .se-lang-switcher__item:hover,
.se-lang-switcher__liste .se-lang-switcher__item:focus-visible {
  background: rgba(32, 30, 29, .07); outline: 0;
}
/* Où l'on est : la pastille, pas la seule couleur — le même signe que la
   navigation du menu plein écran. */
.se-lang-switcher__liste .se-lang-switcher__item.is-current { cursor: default; }
.se-lang-switcher__liste .se-lang-switcher__item.is-current::after {
  content: ""; flex: none; margin-left: auto; width: 7px; height: 7px;
  background: var(--canada-red);
}

/* Sur l'encre — le pied de page — la pastille s'éclaircit. La liste, elle,
   reste sur fond clair : un menu blanc sur un pied noir se lit mieux. */
.site-footer .se-lang-switcher__bouton {
  color: var(--color-bg); border-color: rgba(243, 242, 242, .35);
}
.site-footer .se-lang-switcher__bouton:hover { border-color: var(--color-bg); }
.site-footer .se-lang-switcher__drapeau,
.se-lang-switcher--mobile .se-lang-switcher__drapeau {
  box-shadow: inset 0 0 0 1px rgba(243, 242, 242, .32);
}

/* Le menu plein écran : trois langues à plat, au bas du panneau. Le nom entier
   n'y tiendrait pas à 375px — il reste pour qui écoute la page. */
.se-lang-switcher--mobile {
  display: flex; align-items: center; gap: 20px;
  margin-top: auto; padding-top: 24px;
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 14px; letter-spacing: .06em;
}
.se-lang-switcher--mobile .se-lang-switcher__item {
  gap: 8px; min-height: 44px; padding: 0;
  color: var(--color-bg);
}
/* C'est le CODE qui s'estompe, pas le drapeau : un drapeau à moitié transparent
   ne se lit pas comme « pas la langue courante », il se lit comme une image
   qui a mal chargé. */
.se-lang-switcher--mobile .se-lang-switcher__code { opacity: .5; }
.se-lang-switcher--mobile .is-current .se-lang-switcher__code { opacity: 1; }
.se-lang-switcher--mobile .se-lang-switcher__drapeau { width: 22px; height: 22px; }
