/* ============================================================
   Théâtre le douze dix-huit — main.css
   Fondations CSS (chantier 1 / Foundation).
   Écrin neutre : noir + blanc + un accent par saison.
   Source : design_handoff_ledouzedixhuit/prototype/styles.css
   ============================================================ */

/* ---------- Onest (auto-hébergée, OFL) ----------
   Typo UNIQUE du site (public + admin) : remplace Hanken Grotesk +
   JetBrains Mono. UN SEUL woff2 variable (poids 100–900, ~60K) au lieu
   des 5 TTF statiques. Dupliqué à l'identique dans admin.css (qui ne
   charge PAS main.css). */
@font-face {
  font-family: 'Onest';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('../fonts/Onest/Onest-VariableFont_wght.woff2') format('woff2');
}

/* ---------- Tokens ---------- */
/* L'accent (--accent) est injecté inline dans <head> par le layout PHP
   à partir de la saison courante (saisons.accent_hex). Ne pas le redéfinir ici. */
:root {
  /* Surfaces */
  --bg:         #ffffff;   /* blanc pur — fond par défaut */
  --bg-tint:    #f6f5f2;   /* off-white — sidebars, cards partenaires */

  /* Encre */
  --ink:        #0e0e0f;   /* noir profond — texte principal */
  --ink-2:      #2a2a2c;   /* corps de texte */
  --mute:       #6a6a6e;   /* gris méta, captions, dates */
  --mute-2:     #9a9a9d;   /* gris secondaire, désactivé */

  /* Traits */
  --line:       #e6e5e1;   /* hairlines */
  --line-2:     #d8d6d0;   /* bordures légèrement plus marquées */

  /* Accent — fallback uniquement, écrasé inline par PHP */
  --accent:     #E14B1F;
  --accent-ink: #ffffff;

  /* Pills catégorie (palette désaturée, dot par catégorie via data-cat) */
  --pill-bg:    #f0eeea;
  --pill-ink:   #2a2a2c;

  /* Layout */
  --grid-gap:   clamp(20px, 2.4vw, 36px); /* aligné specimen (audit 21.07.2026) */
  --pad-x:      clamp(20px, 4vw, 64px);
  --max:        1480px;

  /* Rayons */
  --radius-sm:  4px;
  --radius:     6px;

  /* Typographie — UNE seule famille sur tout le site : Onest (400→800),
     auto-hébergée (cf. @font-face en tête). --font-display et le corps
     partagent la même pile ; les ex-eyebrows/dates/kicker (jadis en
     JetBrains Mono) sont aussi passés en Onest. */
  --font-display: 'Onest', system-ui, -apple-system, sans-serif;

  /* ---- Palette saison — arc-en-ciel du programme papier 26-27 ----
     Couleurs POSITIONNELLES (index de liste, hover d'année, filet prisme),
     jamais sémantiques. L'accent de saison reste --accent (injecté par PHP). */
  --c-orange:  #F4571F;
  --c-jaune:   #FFB400;
  --c-rouge:   #E8202A;
  --c-magenta: #E4007C;
  --c-violet:  #7B4FE0;
  --c-teal:    #00A78E;
  --c-vert:    #5BB318;
  --c-bleu:    #2E6FE0;
  --c-ciel:    #DCEBF5;
}

/* ---------- Reset & base ---------- */
*, *::before, *::after { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: 'Onest', system-ui, -apple-system, sans-serif;
  font-size: 17px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

/* Garde-fou anti-débordement horizontal.
   `overflow-x: clip` plutôt que `hidden` parce que `hidden` casse
   `position: sticky` sur les descendants (le site-header en dépend). */
html { overflow-x: clip; }
body { overflow-x: clip; }

img, svg, video { max-width: 100%; height: auto; display: block; }

a {
  color: inherit;
  text-decoration: none;
  transition: color 0.15s;
}
a:hover { color: var(--accent); }

button {
  font: inherit;
  cursor: pointer;
  border: 0;
  background: transparent;
  color: inherit;
}

::selection { background: var(--accent); color: var(--accent-ink); }

/* Focus visible accessible — outline accent, jamais default
   (le brief insiste : pas de halo, juste un outline net) */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Respect du prefers-reduced-motion */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

/* ---------- Typography scale ---------- */
/* Échelle fluide. Tout est en Onest (var --font-display = corps = ex-mono) ;
   seules la graisse, la casse et le letter-spacing distinguent les rôles. */

/* Police des titres : appliquée aux classes utilitaires de titre ET aux titres
   bespoke de composants (année archives, titres de liste, code 404) pour que
   AUCUN titre ne retombe sur la stack du corps. */
.display-xl, .display, .h1, .h2, .h3,
.seasons-row__year, .error-404__code {
  font-family: var(--font-display);
}

.display-xl {
  font-weight: 700;
  font-size: clamp(3.5rem, 12vw, 10rem);
  line-height: 0.88;
  letter-spacing: -0.035em;
  margin: 0;
  text-wrap: balance;
}

.display {
  font-weight: 700;
  font-size: clamp(2.5rem, 7.5vw, 6rem);
  line-height: 0.94;
  letter-spacing: -0.025em;
  margin: 0;
  text-wrap: balance;
}

.h1 {
  font-weight: 700;
  font-size: clamp(2rem, 4.4vw, 3.6rem);
  line-height: 1.02;
  letter-spacing: -0.022em;
  margin: 0;
  text-wrap: balance;
}

.h2 {
  font-weight: 700;
  font-size: clamp(1.5rem, 2.4vw, 2.1rem);
  line-height: 1.1;
  letter-spacing: -0.015em;
  margin: 0;
}

.h3 {
  font-weight: 600;
  font-size: 1.15rem;
  line-height: 1.25;
  letter-spacing: -0.005em;
  margin: 0;
}

.eyebrow {
  font-family: 'Onest', system-ui, sans-serif;
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--mute);
}

.meta {
  font-family: 'Onest', system-ui, sans-serif;
  font-size: 0.82rem;
  letter-spacing: 0.01em;
  color: var(--mute);
}

.body-lg {
  font-size: 1.18rem;
  line-height: 1.55;
  max-width: 62ch;
  color: var(--ink-2);
}

.body {
  font-size: 1rem;
  line-height: 1.6;
  color: var(--ink-2);
}
.body p { margin: 0 0 1em; }

/* ---------- Layout ---------- */
/* .wrap : container principal centré, gouttières fluides.
   .wrap-narrow : variante éditoriale (page contact, mentions, etc.). */

.wrap {
  max-width: var(--max);
  margin: 0 auto;
  padding-left: var(--pad-x);
  padding-right: var(--pad-x);
}

.wrap-narrow {
  max-width: 940px;
  margin: 0 auto;
  padding-left: var(--pad-x);
  padding-right: var(--pad-x);
}

.section {
  padding: clamp(56px, 7vw, 96px) 0;
}
.section + .section { border-top: 1px solid var(--line); }

/* ---------- Site header ---------- */
/* Layout chrome : header sticky + nav horizontale. Reste minimal —
   les composants (pills, cards, etc.) viendront aux chantiers suivants. */

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  border-bottom: 1px solid var(--line);
}
/* Fond translucide + blur du specimen, porté par un PSEUDO-ÉLÉMENT :
   un backdrop-filter posé sur .site-header lui-même ferait de lui le
   containing block des position:fixed descendants — le panneau mobile
   (#site-header-mobile, fixed inset:0) se calerait sur les 76px du
   header au lieu du viewport (bug mobile corrigé le 21.07.2026). */
.site-header::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: rgba(255, 255, 255, 0.94);
  backdrop-filter: saturate(140%) blur(10px);
  -webkit-backdrop-filter: saturate(140%) blur(10px);
}
.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: clamp(20px, 3vw, 48px);
  /* Hauteur FIXE 76px (specimen handoff) — plus de padding vertical. */
  height: 76px;
  /* Au-dessus du panneau mobile (z-40, enfant du même header) : la
     barre — logo + croix de fermeture — reste visible et cliquable
     panneau ouvert. */
  position: relative;
  z-index: 41;
}
.site-header__logo {
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
}
.site-header__logo svg {
  display: block;
  /* Logotype v2 (ratio 2.91) réduit à 38px — à affiner à l'œil. Le SVG
     porte désormais des width/height intrinsèques → width:auto fiable
     aussi en Safari (fin de l'écrasement vertical). */
  height: 38px;
  width: auto;
}

.site-header__nav {
  display: flex;
  align-items: center;
  gap: clamp(18px, 2.6vw, 36px);
  flex-wrap: wrap;
}
.site-header__nav-link {
  font-size: 0.97rem;
  font-weight: 500;
  color: var(--ink);
  padding: 4px 0;
  position: relative;
  letter-spacing: -0.005em;
  white-space: nowrap;
  transition: color 0.15s;
}
.site-header__nav-link:hover { color: var(--accent); }
.site-header__nav-link.is-active::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -6px;
  height: 2px;
  background: var(--accent);
}

.site-header__cta {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 18px;
  background: var(--ink);
  color: #fff;
  border-radius: 999px;
  font-weight: 600;
  font-size: 0.92rem;
  white-space: nowrap;
  transition: background 0.18s, color 0.18s;
}
.site-header__cta:hover { background: var(--accent); color: var(--accent-ink, #fff); }

/* Burger mobile : caché par défaut, montré sous 880px (cf. media query plus bas). */
.site-header__burger {
  display: none;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border: 0;
  background: transparent;
  cursor: pointer;
  padding: 0;
  color: var(--ink);
}
.site-header__burger-lines,
.site-header__burger-lines::before,
.site-header__burger-lines::after {
  display: block;
  width: 22px;
  height: 2px;
  background: currentColor;
  transition: transform 0.2s ease, opacity 0.2s ease;
}
.site-header__burger-lines {
  position: relative;
}
.site-header__burger-lines::before,
.site-header__burger-lines::after {
  content: "";
  position: absolute;
  left: 0;
}
.site-header__burger-lines::before { top: -7px; }
.site-header__burger-lines::after  { top:  7px; }

/* Panneau mobile : caché par défaut, affiché si [aria-expanded="true"]. */
.site-header__mobile {
  display: none;
  position: fixed;
  inset: 0;
  /* AU-DESSUS de tout, sans dépendre de l'empilement du header (fragile
     cross-browser : Safari iOS peignait la diagonale par-dessus le
     panneau avec l'approche z-40 sous la barre). La fermeture est
     assurée par une croix DANS le panneau (.site-header__mobile-close). */
  z-index: 100;
  background: var(--bg);
  padding: 96px var(--pad-x) 32px;
  flex-direction: column;
  gap: 32px;
  overflow-y: auto;
}

/* Croix de fermeture interne — calée sur la position du burger de la
   barre (même zone tactile 44px, même coin) pour une continuité totale. */
.site-header__mobile-close {
  position: absolute;
  top: 16px;
  right: var(--pad-x);
  width: 44px;
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 2rem;
  line-height: 1;
  color: var(--ink);
  cursor: pointer;
}
.site-header__mobile-close:hover { color: var(--accent); }
.site-header__mobile-nav {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.site-header__mobile-nav a {
  font-size: 1.6rem;
  font-weight: 600;
  letter-spacing: -0.015em;
  padding: 14px 0;
  border-bottom: 1px solid var(--line);
  color: var(--ink);
}
.site-header__mobile-nav a:hover { color: var(--accent); }
.site-header__mobile-nav a.is-active { color: var(--accent); }
.site-header__mobile-cta {
  display: inline-flex;
  align-self: flex-start;
  align-items: center;
  gap: 8px;
  padding: 14px 22px;
  background: var(--ink);
  color: #fff;
  border-radius: 999px;
  font-weight: 600;
  font-size: 1rem;
  margin-top: 12px;
}
.site-header__mobile-cta:hover { background: var(--accent); }

@media (max-width: 880px) {
  .site-header__nav { display: none; }
  .site-header__burger { display: inline-flex; }
}

/* Quand le panneau est ouvert, on bascule l'affichage et on barre le scroll de fond. */
body.has-mobile-nav-open { overflow: hidden; }
body.has-mobile-nav-open .site-header__mobile { display: flex; }

/* État ouvert du burger : croix */
.site-header__burger[aria-expanded="true"] .site-header__burger-lines {
  background: transparent;
}
.site-header__burger[aria-expanded="true"] .site-header__burger-lines::before {
  top: 0;
  transform: rotate(45deg);
}
.site-header__burger[aria-expanded="true"] .site-header__burger-lines::after {
  top: 0;
  transform: rotate(-45deg);
}

/* ---------- Site footer ---------- */

.site-footer {
  background: var(--ink);
  color: #fff;
  padding-top: clamp(48px, 6vw, 80px);
  padding-bottom: 32px;
  margin-top: clamp(56px, 6vw, 96px);
}
.site-footer__grid {
  display: grid;
  grid-template-columns: 1.5fr 1fr 1fr 1fr;
  gap: clamp(28px, 3.5vw, 56px);
  padding-bottom: 48px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.12);
}
@media (max-width: 720px) {
  .site-footer__grid { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 480px) {
  .site-footer__grid { grid-template-columns: 1fr; gap: 32px; }
}
.site-footer__col h4 {
  font-family: 'Onest', system-ui, sans-serif;
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.45);
  margin: 0 0 14px;
}
.site-footer__col ul {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
  font-size: 0.95rem;
}
.site-footer__col a {
  color: rgba(255, 255, 255, 0.7);
  transition: color 0.15s;
}
.site-footer__col a:hover { color: #fff; }

.site-footer__col--brand {
  display: flex;
  flex-direction: column;
  gap: 18px;
}
.site-footer__logo svg {
  display: block;
  /* Réduit (logotype v2, cf. header) — à affiner à l'œil. */
  height: clamp(42px, 4.4vw, 58px);
  width: auto;
}
.site-footer__addr {
  font-style: normal;
  font-size: 0.95rem;
  color: rgba(255, 255, 255, 0.7);
  line-height: 1.5;
}

.site-footer__legal {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-top: 28px;
  font-family: 'Onest', system-ui, sans-serif;
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  color: rgba(255, 255, 255, 0.45);
  flex-wrap: wrap;
  gap: 16px;
}

/* ---------- Home ---------- */
/* Section ajoutée au chantier 2. Tout ce qui suit ne sert qu'à la home,
   peut éventuellement migrer ailleurs si réutilisé par d'autres pages.
   Ordre : hero affiche → grille spectacles → hors-saison teaser. */

/* (purge design-v2 phase I : home-hero legacy supprimé — obj-hero) */

/* Section head (utilisé par /partials/section-head.php) */
.section-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 32px;
  margin-bottom: clamp(28px, 4vw, 48px);
  flex-wrap: wrap;
}
.section-head__lhs { max-width: 720px; }
.section-head__eyebrow { display: block; margin-bottom: 14px; }
.section-head__title { margin: 0; }
.section-head__sub { margin-top: 14px; }
.section-head__cta {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 12px 20px;
  background: transparent;
  color: var(--ink);
  border: 1px solid var(--line-2);
  border-radius: 999px;
  font-weight: 600;
  font-size: 0.95rem;
  transition: border-color 0.18s, color 0.18s;
  white-space: nowrap;
}
.section-head__cta:hover { border-color: var(--ink); color: var(--ink); }

/* (purge design-v2 phase I : shows-grid/show-card + affiche-card legacy supprimés — obj-list) */
/* Pills catégorie — palette désaturée du handoff. data-cat = slug DB.
   Cas spécial 'jeune-public' (slug DB plus long que le 'jeune' du proto). */
.pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 11px;
  border-radius: 999px;
  background: var(--pill-bg);
  color: var(--pill-ink);
  font-size: 0.78rem;
  font-weight: 500;
  border: 1px solid transparent;
  white-space: nowrap;
}
.pill::before {
  content: "";
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--pill-dot, #c4c1b8);
}
.pill[data-cat="theatre"]      { --pill-dot: #5b6f8f; }
.pill[data-cat="cinema"]       { --pill-dot: #7a6a8a; }
.pill[data-cat="humour"]       { --pill-dot: #b08850; }
.pill[data-cat="impro"]        { --pill-dot: #6f8a6a; }
.pill[data-cat="jeune"],
.pill[data-cat="jeune-public"] { --pill-dot: #c08a7a; }
.pill[data-cat="musique"]      { --pill-dot: #8c7a90; }
.pill[data-cat="seul"]         { --pill-dot: #8a7a5a; }
.pill[data-cat="danse"]        { --pill-dot: #a08a8a; }
.pill[data-cat="hors-saison"]  { --pill-dot: #9a9a9d; }

/* (purge design-v2 phase I : section--tint + hors-saison-teaser legacy supprimés — hs-teaser) */

/* ---------- Components — Buttons primitives ---------- */
/* Primitives génériques pill, déclinées en 3 variantes. Adoptées au
   chantier 3 (Fiche spectacle). La home utilise encore `.home-hero__cta`
   (équivalent à `.btn-primary` à l'identique) — on les fusionnera quand
   un chantier le justifiera. */
.btn-primary,
.btn-ghost,
.btn-ink {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 14px 22px;
  border-radius: 999px;
  font-weight: 600;
  font-size: 0.98rem;
  font-family: inherit;
  line-height: 1.1;
  border: 1px solid transparent;
  text-decoration: none;
  cursor: pointer;
  transition: background 0.18s, color 0.18s, border-color 0.18s;
  white-space: nowrap;
}
.btn-primary { background: var(--accent); color: var(--accent-ink, #fff); }
.btn-primary:hover { background: var(--ink); color: #fff; }
.btn-ghost   { background: transparent; border-color: var(--line-2); color: var(--ink); }
.btn-ghost:hover { border-color: var(--ink); }
.btn-ink     { background: var(--ink); color: #fff; }
.btn-ink:hover { background: var(--accent); }

/* État désactivé : gris doux + cursor not-allowed + suppression du hover.
   Appliqué quand un CTA Réserver est rendu en <span aria-disabled>. */
.btn-primary.is-disabled,
.btn-ghost.is-disabled,
.btn-ink.is-disabled {
  background: var(--line-2);
  color: var(--mute);
  border-color: var(--line-2);
  cursor: not-allowed;
  pointer-events: none;
}

/* ---------- Fiche spectacle ---------- */
/* Page /spectacle/{slug} — split sticky (affiche / contenu) puis
   galerie + related en pleine largeur sous le split.
   Référence : design_handoff/screenshots/04-fiche-spectacle.png +
   prototype/pages.jsx → ShowPage(). */

.fiche {
  padding-top:    clamp(32px, 4vw, 56px);
  padding-bottom: clamp(80px, 8vw, 120px);
}

/* Back-link discret en haut de page (vrai href, pas history.back). */
.fiche-back {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-bottom: clamp(28px, 3vw, 44px);
  color: var(--mute);
  font-size: 0.92rem;
  transition: color 0.15s;
}
.fiche-back:hover { color: var(--ink); }

.fiche-grid {
  display: grid;
  /* 1fr (affiche) | 1.05fr (contenu) — la colonne droite est légèrement
     plus large, c'est le contenu qui domine. align-items: start est
     essentiel pour que `position: sticky` fonctionne sur l'affiche. */
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
  gap: clamp(36px, 5vw, 88px);
  align-items: start;
}
/* Breakpoint stack à 1100px — aligné sur le hero de la home pour
   une cohérence inter-pages, et parce que le split à 1024 était trop
   serré pour le contenu droit (dl + prose + 3 CTAs). */
@media (max-width: 1100px) {
  /* Stack : l'affiche passe au-dessus du texte. Pas de sticky en stack
     (le sticky devient inutile et perturbe le scroll). */
  .fiche-grid { grid-template-columns: minmax(0, 1fr); gap: 36px; }
}

/* Colonne gauche : affiche sticky.
   `top: 100px` = hauteur header sticky (~76px) + 24px de respiration.
   `max-height: calc(100vh - 120px)` borne en hauteur sur les écrans courts
   — sans ça, sur un viewport 720px, l'affiche dépasse en bas du viewport
   pendant le scroll et le `sticky` perd son intérêt. */
.fiche-poster {
  position: sticky;
  top: 100px;
  max-height: calc(100vh - 120px);
  display: flex;
  align-items: flex-start;
  justify-content: center;
}
@media (max-width: 1100px) {
  .fiche-poster {
    position: static;
    max-height: none;
    max-width: 480px;
    margin: 0 auto;
  }
}
/* Image : sizing par max-width/max-height (PAS de boîte forcée), donc l'affiche
   garde TOUJOURS son ratio réel — aucun letterbox, aucune bande, aucun rognage,
   quel que soit le ratio du fichier. width:auto + max-width:100% → remplit la
   colonne ; max-height borne la hauteur sur écran court (l'image rétrécit et se
   centre via le cadre, l'espace latéral est blanc, pas gris). Reflow évité par
   les attributs width/height HTML (dimensions réelles, cf. spectacle.php). */
.fiche-poster__img {
  /* Carré forcé, crop centré (décision Tony). aspect-ratio:1/1 réserve
     aussi la boîte → anti-reflow sans getimagesize. Plus de max-height
     (il briserait le carré) : le conteneur .fiche-poster borne encore
     via son max-height + overflow:hidden. */
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  height: auto;
  display: block;
}

/* Fallback "Affiche à venir" : aspect 5/7 cohérent avec ShowCard,
   teinté off-white, caption mono en bas. */
.fiche-poster__placeholder {
  width: 100%;
  aspect-ratio: 1 / 1; /* carré, cohérent avec le poster image (décision Tony) */
  background: var(--bg-tint);
  background-image: repeating-linear-gradient(
    135deg,
    transparent 0 14px,
    rgba(0,0,0,0.025) 14px 15px
  );
  display: flex;
  align-items: flex-end;
  padding: clamp(16px, 1.8vw, 24px);
  border-radius: 2px;
}
.fiche-poster__placeholder-caption {
  font-family: 'Onest', system-ui, sans-serif;
  font-size: 10.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--mute);
}

/* Colonne droite : contenu vertical */
.fiche-body {
  min-width: 0; /* permet au contenu prose de respecter la grille */
}
/* Genre / catégories : ligne texte mono (plus de pastilles sur la fiche,
   cohérent avec la révision A3 de la home). */
/* (.meta-genre retiré au nettoyage post-fusion : plus rendu nulle part
   — la fiche est passée aux pills, la carte home à l'obj-list.) */
/* Titre : gabarit de taille repris de la maquette. margin-top 18px se
   collapse quand le genre est absent → titre affleurant en haut de colonne. */
.fiche-title {
  font-family: var(--font-display);
  font-size: clamp(2rem, 4vw, 3.2rem);
  line-height: 1.02;
  letter-spacing: -0.025em;
  margin: 18px 0 0;
}
/* Ligne 3 — sous-titre (subtitle) : qualificatif de forme sous le titre. */
.fiche-soustitre {
  font-size: 1.25rem;
  line-height: 1.3;
  color: var(--ink-2);
  max-width: 36ch;
  margin: 8px 0 0; /* le sous-titre se lit comme 2e ligne du titre (écart réduit) */
}
/* (.meta-accroche retiré au nettoyage post-fusion : le champ accroche
   (migration 029) n'est plus rendu côté public depuis la refonte.) */
/* Prose (description) APRÈS les CTA. Rythme SCOPÉ à l'enfant direct de
   .fiche-body → ne touche PAS les proses de Distribution/Soutiens (imbriquées
   dans .fiche-section). Rupture ~40px, plus marquée que le rythme d'en-tête. */
.fiche-body > .fiche-prose { margin: 40px 0 0; }
/* Ligne méta sous le titre : Date · Compagnie · Durée · Public.
   Quatre segments depuis le lot 037 — au-delà de deux, le retour à la ligne
   devient la règle et non l'exception sur mobile.

   Traitement MIXTE assumé : la date porte l'information principale (0.92rem,
   --ink), le reste passe au registre de référence (0.85rem, --mute). L'écart
   est volontairement court — un cran de taille, un cran de couleur — pour que
   la hiérarchie se voie sans que la ligne se lise en deux morceaux. */
.meta-summary {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 14px;
  margin-top: 26px;
}
/* ⚠️ Chaque segment EMBARQUE le point qui le suit, au lieu de le laisser flotter
   en item frère. Sans ce groupe, `flex-wrap` casse indifféremment entre un texte
   et son point : à 390px le point partait ouvrir seul la ligne suivante. Ici il
   ne peut plus se détacher du mot qu'il suit. Le gap interne vaut celui du
   conteneur : à plat, l'espacement reste exactement celui d'avant. */
.meta-summary__item {
  display: inline-flex;
  align-items: center;
  gap: 14px;
}
.meta-summary__date {
  font-family: 'Onest', system-ui, sans-serif;
  font-size: 0.92rem;
  color: var(--ink);
}
.meta-summary__dot {
  width: 4px; height: 4px;
  border-radius: 50%;
  background: #b4b2a9;
  flex: none;
}
/* .meta-summary__prod et .meta-summary__info sont mis en forme plus haut, avec
   .fiche-prose--small : ils partagent le registre « information de référence ».
   Seule la date garde un traitement propre, juste au-dessus. */
/* Flags = conditions commerciales (badges), APRÈS la méta, distincts des
   catégories. Traitement visuel .badge-flag inchangé. */
.fiche-flags {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 14px;
}

/* Liste de définition : 2 colonnes (label mono | valeur), hairlines
   top/bottom, padding vertical confortable.
   La colonne dt est en largeur fixe pour aligner les valeurs ;
   sur mobile on stack en single column pour ne pas écraser le label. */
.fiche-meta {
  display: grid;
  grid-template-columns: 130px 1fr;
  gap: 14px 24px;
  padding: 24px 0;
  border-top:    1px solid var(--line);
  border-bottom: 1px solid var(--line);
  margin: 32px 0 32px 0;
  scroll-margin-top: 100px; /* cible de l'ancre « Voir les dates » sous le header sticky */
}
@media (max-width: 480px) {
  .fiche-meta { grid-template-columns: 1fr; gap: 4px 0; }
  .fiche-meta dt:not(:first-child) { margin-top: 14px; }
}
.fiche-meta dt {
  font-family: 'Onest', system-ui, sans-serif;
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--mute);
  padding-top: 2px;
}
.fiche-meta dd {
  margin: 0;
  font-weight: 500;
  color: var(--ink);
}
.fiche-meta__strong { font-weight: 700; }

/* Prose : styles éditoriaux pour le HTML WYSIWYG (description, distrib,
   soutiens). Restitution conservative : pas d'effets clinquants. */
.fiche-prose {
  font-size: 1.06rem;
  line-height: 1.65;
  color: var(--ink-2);
  margin: 0 0 32px 0;
  max-width: 62ch;
}
.fiche-prose > *:first-child { margin-top: 0; }
.fiche-prose > *:last-child  { margin-bottom: 0; }
.fiche-prose p { margin: 0 0 1em 0; }
.fiche-prose a {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-color: var(--line-2);
  text-underline-offset: 3px;
  transition: text-decoration-color 0.15s, color 0.15s;
}
.fiche-prose a:hover {
  color: var(--accent);
  text-decoration-color: var(--accent);
}
.fiche-prose em, .fiche-prose i { font-style: italic; }
.fiche-prose strong, .fiche-prose b { font-weight: 700; color: var(--ink); }
.fiche-prose ul, .fiche-prose ol { padding-left: 1.2em; margin: 0 0 1em 0; }
.fiche-prose li { margin-bottom: 0.4em; }
.fiche-prose h2, .fiche-prose h3 { margin: 1.6em 0 0.6em; line-height: 1.2; }
.fiche-prose h2 { font-size: 1.4rem; font-weight: 700; }
.fiche-prose h3 { font-size: 1.15rem; font-weight: 600; }
.fiche-prose blockquote {
  margin: 1em 0;
  padding-left: 1.2em;
  border-left: 2px solid var(--line);
  color: var(--mute);
  font-style: italic;
}
/* ─── Registre « information de référence » ──────────────────────────────────
   Un cran sous le corps de texte en TAILLE et en COULEUR : ce qu'on consulte,
   par opposition à ce qu'on lit d'un trait. Trois usages le partagent :

     .fiche-prose--small   Distribution et Soutiens d'une fiche
     .meta-summary__prod   compagnie, en tête de fiche
     .meta-summary__info   durée et âge conseillé, en tête de fiche

   Ils sont RÉUNIS ICI plutôt que recopiés : la même valeur à trois endroits
   dérive au premier ajustement. La date (.meta-summary__date) en est exclue —
   elle reste l'information principale de sa ligne, le reste est du contexte.

   ⚠️ .volet__texte--second (la distribution d'un volet) porte les mêmes
   déclarations mais reste une règle SÉPARÉE : elle vit dans le bloc des cartes
   de volets, avec le reste de leur mise en forme. Les deux se citent
   mutuellement — toute retouche ici doit y être reportée.

   Plancher : --mute mesure 5.39:1 sur fond blanc, au-dessus du 4.5:1 exigé d'un
   texte. --mute-2 (2.81:1) est exclu, il est réservé au désactivé. */
.fiche-prose--small,
.meta-summary__prod,
.meta-summary__info {
  font-size: 0.85rem;
  line-height: 1.55;
  color: var(--mute);
}

/* ---- Utilitaires de prose, posés à la main en back-office (TinyMCE, mode
   « code »). Ils n'apparaissent nulle part dans les vues : c'est voulu. ----

   .prose-note  : mention secondaire à mettre en retrait du corps de texte
                  (ex. « Billets subventionnés par la République et Canton de
                  Genève. » dans l'onglet Tarifs).
   .prose-logo  : logo inséré dans la prose (ex. 20 ans / 20 francs, JPEG 538px
                  de large). Le max-width l'emporte sur les attributs width/
                  height que TinyMCE pose sur l'<img> (spécificité nulle), d'où
                  le height:auto qui préserve le ratio. */
.fiche-prose .prose-note {
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--mute);
}
.fiche-prose img.prose-logo {
  display: block;
  max-width: 180px;
  height: auto;
  margin: 1.2em 0;
}

/* Actions de fiche : « Réserver » seul en pill primary. Wrap sur mobile. */
.fiche-actions {
  margin: 32px 0 0; /* la rupture avant la prose est portée par .fiche-body > .fiche-prose (40px) */
}
.fiche-actions__buttons {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}
/* Boutons 1 (Réserver) et 2 (Voir les dates) : gabarit maquette (pill hérité
   de .btn-*, padding 13px 26px). */
.fiche-cta { font-size: 1rem; padding: 13px 26px; }

/* Sections éditoriales (Distribution, Soutiens & coproductions) :
   marquées par un titre h3 et un bloc prose en dessous. */
.fiche-section {
  margin-top: 40px;
}
.fiche-section__title {
  margin: 0 0 14px 0;
  letter-spacing: -0.005em;
}

/* Galerie photos — pleine largeur sous le split.
   3 colonnes desktop → 2 cols < 720 → 1 col < 480. */
.fiche-gallery {
  margin-top: clamp(60px, 6vw, 80px);
  padding-top: 32px;
  border-top: 1px solid var(--line);
}
.fiche-gallery__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
  margin-top: 18px;
}
@media (max-width: 720px) {
  .fiche-gallery__grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 480px) {
  .fiche-gallery__grid { grid-template-columns: 1fr; }
}
/* Chaque item : <button> reset, ratio 4/3, photo en cover, hover discret. */
.fiche-gallery__item {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  background: var(--bg-tint);
  border: 0;
  padding: 0;
  margin: 0;
  cursor: zoom-in;
  overflow: hidden;
  border-radius: 2px;
  transition: transform 0.25s;
}
.fiche-gallery__item:hover { transform: translateY(-2px); }
.fiche-gallery__item:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.fiche-gallery__item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Lightbox : overlay plein écran ouvert par JS. Hors-affichage par
   défaut (display:none) ; basculé en flex via .is-open par le JS. */
.fiche-lightbox {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 200;
  background: rgba(8, 8, 12, 0.92);
  padding: 4vw;
  align-items: center;
  justify-content: center;
}
.fiche-lightbox.is-open { display: flex; }
.fiche-lightbox__img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  box-shadow: 0 24px 60px -10px rgba(0,0,0,0.5);
}
.fiche-lightbox__close {
  position: absolute;
  top: 16px;
  right: 16px;
  width: 48px;
  height: 48px;
  border: 0;
  background: rgba(255,255,255,0.08);
  color: #fff;
  font-size: 28px;
  line-height: 1;
  cursor: pointer;
  border-radius: 50%;
  transition: background 0.15s;
}
.fiche-lightbox__close:hover  { background: rgba(255,255,255,0.16); }
.fiche-lightbox__close:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

/* Aussi cette saison — section pleine largeur sous le split.
   Réutilise .shows-grid déjà défini pour la home. */
.fiche-related {
  margin-top: clamp(80px, 8vw, 120px);
  padding-top: 56px;
  border-top: 1px solid var(--line);
}
.fiche-related__head {
  margin-bottom: clamp(32px, 4vw, 48px);
}
.fiche-related__head .eyebrow {
  display: block;
  margin-bottom: 12px;
}
.fiche-related__title {
  margin: 0;
}

/* ---------- Programmation ---------- */
/* Page /programmation — liste des spectacles d'une saison, filtres
   catégorie + toggle grille/liste.
   Référence : design_handoff/screenshots/03-programmation.png +
   prototype/pages.jsx → ProgramPage(). */

/* En-tête de page (réutilisable : aussi pour Hors-saison plus tard).
/* (purge design-v2 phase I : page-head legacy supprimé — partial page-head.php) */

.section--program {
  padding-top:    24px;
  padding-bottom: clamp(80px, 8vw, 120px);
}

/* Barre de filtres : hairline bottom seule (le filet top — la « ligne grise
   sous le hero » — est retiré, révision Tony 29.07.2026), chips alignées,
   count à droite. flex-wrap pour mobile (les chips passent à la ligne). */
.filterbar {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  padding: 18px 0;
  border-bottom: 1px solid var(--line);
}
.filterbar__label {
  font-family: 'Onest', system-ui, sans-serif;
  font-size: 11px;
  color: var(--mute);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin-right: 6px;
}
.filterbar__spacer { flex: 1 1 auto; }
.filterbar__count {
  font-family: 'Onest', system-ui, sans-serif;
  font-size: 0.82rem;
  color: var(--mute);
  margin-left: auto; /* sur mobile, repousse à droite même quand wrap */
}

/* Chip filtre : pill ghost par défaut, ink-solid en .is-on (sélectionné). */
.filter-chip {
  display: inline-block;
  padding: 8px 14px;
  border-radius: 999px;
  font-size: 0.92rem;
  font-weight: 500;
  color: var(--ink);
  background: transparent;
  border: 1px solid var(--line-2);
  text-decoration: none;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
  white-space: nowrap;
}
.filter-chip:hover { border-color: var(--ink); }
.filter-chip.is-on {
  background: var(--ink);
  color: #fff;
  border-color: var(--ink);
}
.filter-chip:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Badge flag (Hors abonnement / Hors saison / Proposé par le Grand-Saconnex).
   Cumulable, volontairement DISTINCT des .pill de catégorie : rectangle
   hairline mono uppercase, sans pastille colorée — un marqueur, pas une
   taxonomie. */
.badge-flag {
  display: inline-flex;
  align-items: center;
  padding: 4px 9px;
  border: 1px solid var(--line-2);
  border-radius: 4px;
  background: transparent;
  font-family: 'Onest', system-ui, sans-serif;
  font-size: 0.66rem;
  font-weight: 500;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--mute);
  white-space: nowrap;
}

/* (purge design-v2 phase I : program-list legacy supprimé — obj-list) */
/* Empty state : sobre, centré, avec lien de retour si filtré. */
.program-empty {
  text-align: center;
  padding: clamp(60px, 8vw, 100px) 0;
  color: var(--mute);
}
.program-empty__eyebrow {
  display: block;
  margin-bottom: 10px;
}
.program-empty__text {
  margin: 0 0 24px 0;
  font-size: 1.08rem;
  color: var(--ink-2);
}
.program-empty__text strong { color: var(--ink); }
.program-empty__back {
  /* Hérite .btn-ghost — pas d'override ici. */
}

/* ---------- Archives ---------- */
/* /archives — index liste des saisons (par saison) + détail d'une saison.
   Réutilise .page-head, .shows-grid, .fiche-back, .program-empty. Stats =
   compte réel uniquement (pas de représentations/spectateurs : absents en base).
   Référence : design_handoff/screenshots/07-archives.png + proto ArchivesPage. */
.section--archives {
  padding-top:    8px;
  padding-bottom: clamp(80px, 8vw, 120px);
}

/* Index : une ligne par saison, séparées par un filet. */
.seasons-list {
  list-style: none;
  padding: 0;
  margin: 0;
  border-bottom: 1px solid var(--line);
}
.seasons-row { border-top: 1px solid var(--line); }
.seasons-row__link {
  display: grid;
  grid-template-columns: minmax(110px, 200px) minmax(0, 1fr) auto auto;
  gap: clamp(16px, 2.5vw, 36px);
  align-items: center;
  padding: clamp(24px, 3.5vw, 40px) 0;
  text-decoration: none;
  color: inherit;
  transition: padding-left 0.18s ease;
}
.seasons-row__link:hover { padding-left: 8px; }
.seasons-row__link:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 2px;
}
.seasons-row__year {
  font-weight: 700;
  font-size: clamp(2rem, 4vw, 3rem);
  line-height: 1;
  letter-spacing: -0.025em;
  color: var(--ink);
}
.seasons-row__period { color: var(--mute); }
.seasons-row__stats  { color: var(--mute); white-space: nowrap; }
.seasons-row__arrow {
  color: var(--mute);
  font-size: 1.3rem;
  transition: color 0.15s, transform 0.18s;
}
.seasons-row__link:hover .seasons-row__arrow { color: var(--accent); transform: translateX(4px); }

/* (purge design-v2 phase I : archive-year/stats legacy supprimés — PHead) */
.archive-shows-eyebrow { display: block; margin-bottom: clamp(20px, 3vw, 32px); }
.archive-note {
  margin-top: clamp(28px, 4vw, 44px);
  text-align: center;
}

/* Mobile : la liste de saisons s'empile (année et période sur leur ligne). */
@media (max-width: 620px) {
  .seasons-row__link {
    grid-template-columns: minmax(0, 1fr) auto;
    column-gap: 16px;
    row-gap: 6px;
  }
  .seasons-row__year   { grid-column: 1 / -1; }
  .seasons-row__period { grid-column: 1 / -1; }
}

/* ---------- Contact ---------- */
/* /contact — page-head + grille 2 colonnes (formulaire + aside infos).
   Les classes form (.form-field/.form-alert/.hp-field) sont génériques et
   réutilisables. Réutilise .page-head et .btn-primary. */
.section--contact {
  padding-top:    8px;
  padding-bottom: clamp(80px, 8vw, 120px);
}
.contact-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
  gap: clamp(32px, 5vw, 72px);
  align-items: start;
}

/* --- Formulaire --- */
.contact-form { display: flex; flex-direction: column; gap: 20px; }
.form-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20px;
}
.form-field { display: flex; flex-direction: column; gap: 8px; }
.form-field__label {
  font-family: 'Onest', system-ui, sans-serif;
  font-size: 0.74rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--mute);
}
.form-input {
  width: 100%;
  padding: 13px 16px;
  font: inherit;
  font-size: 1rem;
  color: var(--ink);
  background: #fff;
  border: 1px solid var(--line-2);
  border-radius: 4px;
  transition: border-color 0.15s;
}
.form-input:focus {
  outline: none;
  border-color: var(--ink); /* pas de halo, cf. handoff */
}
textarea.form-input { resize: vertical; min-height: 140px; line-height: 1.55; }
.form-field.is-error .form-input { border-color: var(--accent); }
.form-field__error {
  margin: 0;
  font-size: 0.82rem;
  color: var(--accent);
}
.contact-form__submit { align-self: flex-start; margin-top: 4px; }

/* Honeypot : hors écran, jamais visible ni focusable au clavier. */
.hp-field {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* Alertes succès / erreur — sobres, pas de couleurs criardes. */
.form-alert {
  padding: 16px 20px;
  border-radius: 4px;
  margin-bottom: 24px;
  font-size: 0.96rem;
  border: 1px solid var(--line-2);
}
.form-alert--success {
  border-color: var(--ink);
  background: var(--bg-tint);
  color: var(--ink);
}
.form-alert--error {
  border-color: var(--accent);
  color: var(--ink);
}

/* --- Aside infos pratiques --- */
.contact-aside {
  display: flex;
  flex-direction: column;
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: 4px;
  overflow: hidden;
  position: sticky;
  top: 100px;
}
.contact-info {
  background: var(--bg-tint);
  padding: 20px 22px;
}
.contact-info__label { display: block; margin-bottom: 10px; }
.contact-info__value {
  margin: 0;
  font-size: 1rem;
  line-height: 1.6;
  color: var(--ink);
}
.contact-info__value--link { transition: color 0.15s; }
.contact-info__value--link:hover { color: var(--accent); }
/* Note sous une valeur (horaires du téléphone) : discrète, sous le lien. */
.contact-info__note {
  margin: 6px 0 0;
  font-size: 0.9rem;
  line-height: 1.5;
  color: var(--mute);
}
.contact-info__link {
  display: inline-block;
  margin-top: 10px;
  font-size: 0.9rem;
  color: var(--mute);
  transition: color 0.15s;
}
.contact-info__link:hover { color: var(--accent); }

/* Responsive : une seule colonne, aside sous le formulaire (non sticky). */
@media (max-width: 880px) {
  .contact-grid { grid-template-columns: minmax(0, 1fr); }
  .contact-aside { position: static; }
}
@media (max-width: 520px) {
  .form-row { grid-template-columns: 1fr; }
}

/* ---------- Pages éditoriales (abonnements, tarifs, CGV) ---------- */
/* Gabarit commun : page-head + corps prose (largeur de lecture limitée).
   Contenu tiré de pages.content (admin). Réutilise .page-head. */
.section--editorial {
  padding-top:    8px;
  padding-bottom: clamp(80px, 8vw, 120px);
}
.page-prose {
  max-width: 70ch;
  color: var(--ink-2);
}
.page-prose > :first-child { margin-top: 0; }
.page-prose h2 {
  font-size: clamp(1.4rem, 2.4vw, 1.9rem);
  font-weight: 700;
  letter-spacing: -0.015em;
  color: var(--ink);
  margin: clamp(32px, 4vw, 48px) 0 12px;
}
.page-prose h3 {
  font-size: 1.15rem;
  font-weight: 600;
  color: var(--ink);
  margin: 28px 0 10px;
}
.page-prose p  { margin: 0 0 16px; line-height: 1.6; }
.page-prose ul,
.page-prose ol { margin: 0 0 16px; padding-left: 22px; line-height: 1.7; }
.page-prose li { margin-bottom: 6px; }
.page-prose a  { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; }
.page-prose a:hover { color: var(--ink); }

/* Variante « Infos et tarifs » : titres de section en --font-display (Poppins).
   SCOPÉ à cette page — le .page-prose global (cgv/mentions/confidentialité) garde
   ses H2 en font body. */
.page-prose--tarifs h2 { font-family: var(--font-display); }

.editorial-banner {
  max-width: 70ch;
  margin: 0 0 clamp(28px, 4vw, 40px);
  padding: 12px 16px;
  font-size: 0.9rem;
  color: var(--ink);
  background: var(--bg-tint);
  border-left: 3px solid var(--accent);
  border-radius: 4px;
}
.editorial-placeholder {
  font-family: 'Onest', system-ui, sans-serif;
  font-size: 0.85rem;
  letter-spacing: 0.04em;
  color: var(--mute);
}

/* ---------- 404 ---------- */
.section--404 {
  max-width: 640px;
  padding-top:    clamp(48px, 7vw, 96px);
  padding-bottom: clamp(80px, 9vw, 140px);
}
.error-404__eyebrow { display: block; margin-bottom: 16px; }
.error-404__code {
  margin: 0;
  font-weight: 700;
  font-size: clamp(5rem, 16vw, 11rem);
  line-height: 0.9;
  letter-spacing: -0.04em;
  color: var(--line-2);
}
.error-404__title { margin: 8px 0 0; }
.error-404__lead  { margin: 18px 0 0; color: var(--ink-2); }
.error-404__links {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: clamp(28px, 4vw, 40px);
}

/* ---------- Le lieu ---------- */
/* Page /le-lieu — éditoriale à 6 onglets (lieu, acces, equipe, technique,
   location, partenaires). Layout : .editorial 2 colonnes (mark sticky +
   contenu max 62ch) cohérent avec le proto.
   Référence : design_handoff/screenshots/06-le-lieu.png +
   prototype/pages.jsx → LieuPage(). */

.section--lieu {
  padding-top:    8px;
  padding-bottom: clamp(80px, 8vw, 120px);
}

/* Nav onglets : réutilise visuellement .filter-chip mais sémantique
   différente (c'est une nav, pas un filtre). Hairline bottom seule,
   comme la filterbar (filet top retiré, révision Tony 29.07.2026). */
.lieu-tabs {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  padding: 18px 0;
  border-bottom: 1px solid var(--line);
  margin-bottom: clamp(40px, 5vw, 64px);
}
.lieu-tabs__label {
  font-family: 'Onest', system-ui, sans-serif;
  font-size: 11px;
  color: var(--mute);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin-right: 6px;
}

/* Layout éditorial 3 colonnes : mark mono sticky à gauche, prose bornée au
   milieu, gouttière blanche à droite (04.08.2026 — remplace l'encart pratique
   qui occupait cette place). Colonne du mark fixée à 180px : largeur stable
   d'un onglet à l'autre (le fit-content rendait 120px et faisait respirer la
   grille différemment selon le libellé) ; la prose est bornée à ~68ch pour
   garder une mesure lisible maintenant que rien ne la contraint plus à
   droite. Stack sous 880px (mark passe au-dessus, perd le sticky). */
.editorial {
  display: grid;
  grid-template-columns: 180px minmax(0, 68ch) 1fr;
  gap: clamp(40px, 5vw, 80px);
  align-items: start;
}
@media (max-width: 880px) {
  .editorial { grid-template-columns: minmax(0, 1fr); gap: 24px; }
}

/* Mark de section : mono, sticky à top:100px (cohérent fiche spectacle).
   Pas de border ni de fond — un repère discret, c'est tout. */
.editorial__mark {
  position: sticky;
  top: 100px;
  font-family: 'Onest', system-ui, sans-serif;
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--mute);
}
@media (max-width: 880px) {
  .editorial__mark {
    position: static;
    border-bottom: 1px solid var(--line);
    padding-bottom: 16px;
    margin-bottom: 8px;
  }
}

/* Contenu éditorial — réutilise les styles prose de la fiche spectacle
   (.fiche-prose) pour cohérence ; cf section "Fiche spectacle" plus haut.
   Min-width pour ne pas casser la colonne grid. */
.editorial__content { min-width: 0; }

/* Placeholder "Contenu à venir" — sobre, mute. */
.editorial__placeholder {
  padding: 40px 0;
  color: var(--mute);
}
.editorial__placeholder .eyebrow {
  display: block;
  margin-bottom: 10px;
}
.editorial__placeholder p {
  margin: 0 0 8px 0;
}

/* Grille Partenaires — cartes tintées, 3 cols desktop, 2 tablet, 1 mobile.
   Les vrais logos remplaceront le texte centré (chantier futur). */
.partner-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 14px;
  margin-top: 28px;
}
@media (max-width: 880px) { .partner-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 480px) { .partner-grid { grid-template-columns: 1fr; } }
.partner-card {
  padding: 28px 18px;
  background: var(--bg-tint);
  border-radius: 4px;
  min-height: 88px;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  font-weight: 600;
  font-size: 0.96rem;
  color: var(--ink-2);
}
/* Carte-lien (partenaire avec url) : même rendu que la carte statique. */
a.partner-card {
  text-decoration: none;
  color: var(--ink-2);
  transition: background 0.15s ease, opacity 0.15s ease;
}
a.partner-card:hover { background: var(--bg-tint-2, #efede8); }
/* Carte à logo : le logo porte l'identité visuelle → fond tinté retiré,
   padding réduit pour laisser le logo respirer en grand. */
.partner-card--logo { background: none; padding: 12px; }
a.partner-card--logo:hover { background: none; opacity: 0.8; }
/* Logo : contenu dans la carte, jamais recadré ni étiré. */
.partner-card__logo {
  max-width: 100%;
  max-height: 120px;
  width: auto;
  height: auto;
  object-fit: contain;
}
.partner-grid__note {
  margin-top: 18px;
  font-size: 0.88rem;
  color: var(--mute);
}

/* ============================================================
   DIRECTION « OBJETS & GRANDS TITRES » — socle P3 (design-v2)
   Source : design-handoff/ (styles.css + bloc .p3 de joy.css).
   Placé en FIN de fichier : la cascade fait gagner ces règles sur
   les sections legacy ci-dessus, remplacées phase par phase.
   Adaptations : préfixe .p3 supprimé, <image-slot> → <img>,
   orange fixe du prototype → var(--accent) quand le rôle est
   « accent de saison » ; la palette --c-* reste positionnelle.
   ============================================================ */

/* ---------- Accent de la direction (révision Tony 21.07.2026) ----------
   La maquette est hi-fi : l'accent EST l'orange du programme papier
   #F4571F (= --c-orange), pas l'accent_hex de la saison en base
   (#E14B1F, hérité de l'ancienne direction). On l'écrase ici en CSS —
   AUCUNE écriture en base. :root:root bat le <style> inline injecté
   par le layout (spécificité 0-2-0 > 0-1-0). Pour rendre la main au
   mécanisme par-saison : supprimer cette règle. */
:root:root {
  --accent: #F4571F;
  --accent-ink: #ffffff;
  /* Gabarit de hauteur COMMUN à tous les heros (PHead + home) —
     révision Tony 21.07.2026. */
  --hero-h: clamp(380px, 30.5vw, 500px);
}

/* ---------- Slash signature (repris du logo) ---------- */
.slash {
  color: var(--accent);
  font-style: normal;
  transform: skewX(-9deg);
  display: inline-block;
}

/* ---------- Diagonale prisme (motif signature) ----------
   Image assets/img/streak-affiche.png — faisceau glossy extrait de
   l'affiche de saison, fond transparent, sens montant vers la droite.
   Présente sur toutes les pages SAUF la home. Le conteneur (.phead,
   .obj-top) est en overflow:hidden.
   Fondu blanc RETIRÉ (révision Tony 29.07.2026) : le faisceau s'affiche
   à pleine intensité sur toute sa longueur, la coupe basse du PNG
   (diagonale nette) est assumée. */
.prism {
  position: absolute;
  overflow: visible;
  filter: saturate(1.05);
  opacity: 0.97;
  pointer-events: none;
}
.prism img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.prism-ray { transform: none; }

/* ---------- En-tête de page éditorial (PHead) ----------
   Grand titre à la coupe (l1 encre / l2 accent) + kicker + lead,
   diagonale en haut-droite. Ligne grise retirée (révision Tony
   21.07.2026) : la diagonale ne s'appuie plus dessus, l'ancrage
   visuel est le coin haut-droite. */
.phead {
  position: relative;
  overflow: hidden;
  padding: clamp(48px, 6vw, 96px) 0 clamp(30px, 3vw, 46px);
  /* Hauteur COMMANDÉE PAR LE CONTENU, plus par un plancher.
     Jusqu'ici : min-height: var(--hero-h) et contenu ancré en bas, pour que le
     titre tombe au même endroit d'une page à l'autre. Le prix en était le vide
     — une page sans lead ne remontait pas son texte, elle réservait la place
     de celui qui manquait : 53 % de la boîte en desktop, 71 % en mobile sur
     /le-lieu, et jusqu'à 58 % sur les pages légales, dont le lead tient sur
     une ligne. Sur un portable, il fallait défiler avant d'atteindre la
     première information.

     Les paddings suffisent à tenir le bandeau (77px en haut à 1280, 48px à
     390) : son caractère vient de la diagonale, du kicker et d'un titre à
     83px, pas d'une réserve d'espace. La stabilité du titre de page en page
     est le compromis abandonné, en connaissance de cause.

     `display: flex` + `align-items: flex-end` sont CONSERVÉS : sans plancher
     ils n'ont plus d'effet, mais ils redeviennent actifs si un plancher
     revient un jour — et les retirer changerait le comportement de .wrap. */
  display: flex;
  align-items: flex-end;
  box-sizing: border-box;
}
.phead > .wrap { width: 100%; }
.phead .prism-ray {
  top: -8%;
  right: -6%;
  width: min(50%, 580px);
  height: 170%;
}
.phead .wrap { position: relative; z-index: 1; }

.kick {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-family: 'Onest', system-ui, sans-serif;
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--mute);
  margin-bottom: 18px;
}
.kick b {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent);
}

.ptitle {
  font-family: var(--font-display);
  /* Taille canonique des titres de tête (= .obj-hero .big-title du hero
     home) — uniformité PHead ↔ home (décision Tony). */
  font-size: clamp(2.4rem, 6.5vw, 5.6rem);
  font-weight: 800;
  line-height: 0.86;
  letter-spacing: -0.045em;
  margin: 0;
}
.ptitle .l1 { color: var(--ink); }
.ptitle .l2 { color: var(--accent); }

.plead {
  font-size: 1.18rem;
  line-height: 1.5;
  max-width: 52ch;
  color: var(--ink-2);
  margin-top: 22px;
  margin-bottom: 0;
}

/* ---------- Hero objets (home uniquement — PAS de diagonale) ---------- */
/* Home : hero à affiche, HORS gabarit --hero-h de hauteur (le hero est
   plus haut) mais avec la MÊME diagonale que les PHead. */
.obj-hero {
  position: relative;
}
.obj-top {
  position: relative;
  overflow: hidden;
  /* Padding haut ICI (pas sur .obj-hero) : le conteneur — donc la
     diagonale qu'il coupe — commence au ras du header. */
  padding-top: clamp(40px, 5vw, 72px);
  padding-bottom: clamp(24px, 3vw, 44px);
  /* Ligne grise sous le hero retirée (révision Tony 29.07.2026) —
     cohérent avec les PHead (filet des filterbar/lieu-tabs retiré aussi). */
}
/* Diagonale de la home : DERRIÈRE l'affiche (z-index 1 de .obj-grid),
   aux dimensions ABSOLUES du rayon des PHead — calées sur --hero-h et
   non sur la hauteur du hero (plus haut : un % le rendrait géant et
   object-fit:cover l'épaissirait). Au pixel identique aux autres pages. */
.obj-top .prism-ray {
  top: calc(var(--hero-h) * -0.08);
  right: -6%;
  width: min(50%, 580px);
  /* MÊME hauteur que les PHead : réduire la boîte recadrerait l'image
     (object-fit cover) et le faisceau quitterait l'angle haut-droite
     (régression relevée par Tony, 29.07.2026). */
  height: calc(var(--hero-h) * 1.7);
}
/* Home uniquement : le rayon n'est visible qu'EN HAUT et plonge derrière
   l'affiche — COUPE FRANCHE dans l'axe du faisceau (stops binaires : ce
   n'est PAS le fondu blanc supprimé le même jour), à 40 % de sa longueur.
   Validé desktop 1440 + mobile 375. */
.obj-top .prism {
  -webkit-mask: linear-gradient(20deg, transparent 40%, #000 40%);
          mask: linear-gradient(20deg, transparent 40%, #000 40%);
}
.obj-grid {
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  gap: clamp(24px, 4vw, 64px);
  align-items: center;
  position: relative;
  z-index: 1;
}
@media (max-width: 860px) {
  .obj-grid { grid-template-columns: 1fr; }
}

.big-title {
  font-family: var(--font-display);
  font-size: clamp(3rem, 8vw, 7rem);
  font-weight: 800;
  line-height: 0.86;
  letter-spacing: -0.04em;
  margin: 0 0 24px;
}
.obj-hero .big-title {
  /* Corps réduit vs .ptitle : Onest est plus large que Hanken → à
     7.5vw/6.4rem « douze dix-huit » débordait la colonne intro (wrap sur
     3 lignes). 6.5vw/5.6rem + letter-spacing resserré ramène la 2e ligne
     sur UNE ligne (2 lignes au total), du mobile au desktop. Portée hero
     uniquement (pas .h1/.display/.ptitle). */
  font-size: clamp(2.4rem, 6.5vw, 5.6rem);
  line-height: 0.86;
  letter-spacing: -0.045em;
}
.big-title .l1 { color: var(--ink); }
.big-title .l2 { color: var(--accent); }

/* Titres de spectacle en minuscules — parti pris typographique (décision
   Tony 22.07.2026). PUREMENT VISUEL : la casse réelle est préservée pour
   <title>, JSON-LD, alt/aria-label et lecteurs d'écran. Aucune exception
   (IMPROOO, XPM, FORMA… s'affichent en minuscules). Surfaces : hero home
   (.big-title — le fallback « bienvenue au / douze dix-huit » est déjà
   minuscule, donc inchangé), rangées obj-list (.ot), h1 fiche
   (.fiche-title), teaser hors-saison (.hs-teaser__title-line). */
.big-title,
.ot,
.fiche-title,
.hs-teaser__title-line {
  text-transform: lowercase;
}

.obj-hero .lead {
  font-size: 1.15rem;
  max-width: 44ch;
  color: var(--ink-2);
  margin: 0 0 28px;
}
.obj-intro .kick { margin-bottom: 22px; }

/* Zone affiche du hero — portrait, ratio de l'affiche réelle */
.obj-photo {
  position: relative;
  /* Plafond de hauteur repris de l'ancienne home : on borne la LARGEUR
     à celle qu'aurait l'affiche à min(70vh, 720px) de haut —
     l'aspect-ratio dicte la hauteur, le ratio reste intact, l'affiche
     entière tient dans ~800px de viewport utile header compris. */
  width: min(100%, calc(min(70vh, 720px) * (1683 / 2381)));
  aspect-ratio: 1683 / 2381;
  margin: 0 auto;
  border-radius: 16px;
  overflow: hidden;
  background: var(--c-ciel);
}
@media (max-width: 860px) {
  /* En pile : l'affiche ne mange pas tout l'écran mobile, et passe
     AU-DESSUS du texte (inversion visuelle seule — DOM intact, décalage
     de tabulation en featured assumé : le lien-affiche et le CTA
     « Découvrir → » pointent vers la même fiche). */
  .obj-photo {
    max-width: 480px;
    order: -1;
  }
}
.obj-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
/* Visuel de saison (fallback) : cadre raccourci ancré en haut — coupe la
   traîne de la diagonale INTERNE de saison-hero.webp qui filait sous le
   « 26/27 » (révision Tony 29.07.2026). 2381 → 2143 ≈ bas du « 26/27 ».
   Ne s'applique PAS au hero featured (affiches de spectacles entières). */
.obj-photo--saison { aspect-ratio: 1683 / 2143; }
.obj-photo--saison img { object-position: top; }

/* Actions du hero (2 CTA côte à côte) */
.obj-actions {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
}

/* Ruban d'état sur l'affiche du hero (mécanique featured conservée) */
/* Kicker-statut du hero featured : le « En ce moment / Bientôt » qui
   vivait sur l'affiche (.obj-ribbon, supprimé) est désormais un chip
   accent dans la colonne texte. */
.kick--status {
  color: var(--accent);
  font-weight: 700;
}
.kick--status b { background: var(--accent); }
/* En cours : le point pulse (« live »). */
.kick--live b {
  animation: kick-pulse 2.4s ease-in-out infinite;
}
@keyframes kick-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%      { opacity: 0.55; transform: scale(0.8); }
}

/* Affiche cliquable (état featured) : hover discret */
a.obj-photo {
  display: block;
  transition: transform 0.18s ease, box-shadow 0.18s ease;
}
a.obj-photo:hover {
  transform: translateY(-3px);
  box-shadow: 0 30px 70px -20px rgba(20, 30, 50, 0.30);
}

/* ---------- ObjList — liste à grands titres + vignette objet ----------
   LE motif récurrent de la direction (home, programmation, related,
   archives détail, hors saison). Couleur d'index POSITIONNELLE. */
.olist {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0;
  margin-top: clamp(30px, 4vw, 56px);
}
.orow {
  display: grid;
  grid-template-columns: 64px 64px 1fr auto;
  gap: 22px;
  align-items: center;
  padding: 26px 0;
  border-top: 2px solid var(--ink);
  color: var(--ink);
  transition: padding-left 0.18s;
}
.orow:last-child { border-bottom: 2px solid var(--ink); }
a.orow:hover { padding-left: 14px; color: var(--ink); }

.orow .idx {
  font-family: 'Onest', system-ui, sans-serif;
  font-size: 1rem;
  font-weight: 500;
}
.orow:nth-child(6n + 1) .idx { color: var(--c-orange); }
.orow:nth-child(6n + 2) .idx { color: var(--c-teal); }
.orow:nth-child(6n + 3) .idx { color: var(--c-magenta); }
.orow:nth-child(6n + 4) .idx { color: var(--c-violet); }
.orow:nth-child(6n + 5) .idx { color: var(--c-vert); }
.orow:nth-child(6n + 6) .idx { color: var(--c-bleu); }

.orow .othumb {
  width: 64px;
  height: 64px;
  border-radius: 10px;
  overflow: hidden;
  background: var(--c-ciel);
}
.orow .othumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.orow .omain { min-width: 0; }
.orow .oend {
  display: flex;
  align-items: center;
  gap: 18px;
}

.orow .ot {
  display: block;
  font-family: var(--font-display);
  font-size: clamp(1.6rem, 3vw, 2.6rem);
  font-weight: 800;
  letter-spacing: -0.025em;
  line-height: 1;
}
.orow .oa {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  color: var(--mute);
  font-size: 0.95rem;
  margin-top: 6px;
}
.orow .od {
  font-family: 'Onest', system-ui, sans-serif;
  font-size: 0.9rem;
  color: var(--ink);
  text-align: right;
}
.orow .go {
  font-size: 1.6rem;
  transition: transform 0.18s;
}
a.orow:hover .go { transform: translateX(6px); }

@media (max-width: 720px) {
  .orow {
    grid-template-columns: 40px 52px 1fr auto;
    gap: 14px;
    padding: 20px 0;
  }
  .orow .othumb { width: 52px; height: 52px; }
  .orow .od { display: none; }
}

/* Spectacle passé : grisé, index neutralisé (les dates seules décident) */
.orow--past .ot,
.orow--past .oa,
.orow--past .od { color: var(--mute-2); }
.orow--past .othumb { opacity: 0.55; filter: grayscale(0.4); }
.orow--past.orow:nth-child(n) .idx { color: var(--mute-2); }
.orow--past .od-past {
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-size: 0.78rem;
}

/* ---------- Filet prisme (séparateur gai) ---------- */
.rainbow-rule {
  height: 7px;
  border-radius: 7px;
  width: 200px;
  margin-top: 20px;
  background: linear-gradient(90deg,
    #E8202A, #F4571F, #FF7A00, #FFB400, #F2D21A, #B9CE14, #5FA81E);
}

/* ---------- Teaser hors saison (home) — carte fond ciel ---------- */
.hs-teaser {
  margin-top: clamp(40px, 5vw, 72px);
  background: var(--c-ciel);
  border-radius: 16px;
  padding: clamp(28px, 4vw, 52px);
}
.hs-teaser h2 {
  font-family: var(--font-display);
  font-size: clamp(1.8rem, 3.4vw, 2.8rem);
  font-weight: 800;
  letter-spacing: -0.02em;
  /* Interlignage serré des grands titres de la direction. */
  line-height: 0.95;
  margin: 0 0 10px;
  color: var(--ink);
}
.hs-teaser__l2 { color: var(--accent); }
.hs-teaser .eyebrow { display: block; margin-bottom: 12px; }
.hs-teaser .btn-ghost { background: #fff; }

/* Split intro | liste des 3 prochains événements (révision Tony
   21.07.2026 — reprise du fonctionnement de l'ancienne home). */
.hs-teaser__grid {
  display: grid;
  grid-template-columns: 1fr 1.2fr;
  gap: clamp(28px, 4vw, 64px);
  align-items: start;
}
@media (max-width: 820px) {
  .hs-teaser__grid { grid-template-columns: 1fr; }
}
.hs-teaser__intro { display: flex; flex-direction: column; align-items: flex-start; }
.hs-teaser__intro h2 { margin-bottom: 22px; }

.hs-teaser__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
}
.hs-teaser__item { border-top: 1px solid rgba(14, 14, 15, 0.15); }
.hs-teaser__item:last-child { border-bottom: 1px solid rgba(14, 14, 15, 0.15); }
.hs-teaser__link {
  display: grid;
  grid-template-columns: 130px 1fr auto;
  gap: 18px;
  align-items: baseline;
  padding: 16px 0;
  color: var(--ink);
  transition: padding-left 0.15s;
}
.hs-teaser__link:hover {
  padding-left: 8px;
  color: var(--ink);
}
.hs-teaser__link:hover .hs-teaser__arrow {
  color: var(--accent);
  transform: translateX(4px);
}
.hs-teaser__when { color: var(--ink); letter-spacing: 0.04em; }
.hs-teaser__what { display: flex; flex-direction: column; gap: 2px; }
.hs-teaser__title-line { font-weight: 600; font-size: 1.05rem; line-height: 1.3; }
.hs-teaser__who { color: var(--mute); font-size: 0.92rem; }
.hs-teaser__arrow {
  color: var(--mute);
  transition: color 0.15s, transform 0.15s;
}
@media (max-width: 620px) {
  .hs-teaser__link { grid-template-columns: 1fr auto; }
  .hs-teaser__when { grid-column: 1 / -1; }
}

/* ---------- Overrides direction sur composants partagés ---------- */
/* Chip de filtre actif : accent (au lieu d'encre) */
.filter-chip.is-on {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

/* Bouton primaire : encre, hover accent (inversé par rapport au legacy) */
.btn-primary { background: var(--ink); color: #fff; }
.btn-primary:hover { background: var(--accent); color: var(--accent-ink, #fff); }

/* Archives : année en graisse 800 (grands titres de la direction) */
.seasons-row__year {
  font-weight: 800;
  letter-spacing: -0.025em;
}

/* Archives : année colorée au hover, par rang (positionnel) */
.seasons-row:nth-child(6n + 1):hover .seasons-row__year { color: var(--c-orange); }
.seasons-row:nth-child(6n + 2):hover .seasons-row__year { color: var(--c-teal); }
.seasons-row:nth-child(6n + 3):hover .seasons-row__year { color: var(--c-magenta); }
.seasons-row:nth-child(6n + 4):hover .seasons-row__year { color: var(--c-violet); }
.seasons-row:nth-child(6n + 5):hover .seasons-row__year { color: var(--c-vert); }
.seasons-row:nth-child(6n + 6):hover .seasons-row__year { color: var(--c-bleu); }

/* Marque de section éditoriale (§) : accent + gras */
.editorial__mark { color: var(--accent); font-weight: 700; }

/* 404 : code en très grand, graisse 800, accent (grands titres P3) */
.error-404__code {
  font-weight: 800;
  color: var(--accent);
  line-height: 0.86;
  letter-spacing: -0.04em;
}

/* ---------- Compléments audit maquette (21.07.2026) ---------- */
/* Filterbar P3 : pas de filet haut (joy.css .p3 .filterbar) */
.filterbar { border-top-color: transparent; }

/* Liens de contenu : accent, hover magenta (joy.css .p3 a) — scopé aux
   zones de prose pour ne pas toucher nav/listes qui ont leurs règles. */
.fiche-prose a,
.page-prose a {
  color: var(--accent);
  text-decoration-color: var(--accent);
}
.fiche-prose a:hover,
.page-prose a:hover {
  color: var(--c-magenta);
  text-decoration-color: var(--c-magenta);
}

/* Transition d'arrivée de page (pageFade du prototype) — neutralisée
   par le bloc prefers-reduced-motion global. */
.site-main {
  animation: pageFade 0.32s cubic-bezier(0.2, 0.7, 0.2, 1);
}
@keyframes pageFade {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ---------- Grille pratique + sidebar (lieu / info-tarifs) ---------- */
.pratique {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) 320px;
  gap: clamp(28px, 4vw, 56px);
  align-items: start;
}
@media (max-width: 920px) {
  .pratique { grid-template-columns: 1fr; }
}

.sidebar {
  background: var(--bg-tint);
  padding: 28px;
  border-radius: 4px;
  display: flex;
  flex-direction: column;
  gap: 22px;
  position: sticky;
  top: 100px;
  align-self: start;
}
.sidebar h4 {
  font-family: 'Onest', system-ui, sans-serif;
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--mute);
  margin: 0 0 6px;
  font-weight: 500;
}
.sidebar__block {
  padding-bottom: 18px;
  border-bottom: 1px solid var(--line-2);
}
.sidebar__block:last-child { border: 0; padding-bottom: 0; }
.sidebar__block p { margin: 0; }
.sidebar__addr { font-weight: 600; line-height: 1.4; }
.sidebar__tel {
  font-family: 'Onest', system-ui, sans-serif;
  font-size: 0.95rem;
}
.sidebar__socials { display: flex; gap: 14px; }
.sidebar__socials a,
.sidebar__block a {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-color: var(--line-2);
  text-underline-offset: 3px;
}
.sidebar__socials a:hover,
.sidebar__block a:hover {
  color: var(--accent);
  text-decoration-color: var(--accent);
}

/* ---------- Fiche spectacle — direction P3 ---------- */
/* Affiche sticky : coins arrondis, fond ciel (zone objet de la maquette) */
.fiche-poster {
  border-radius: 14px;
  overflow: hidden;
  /* Fond bleu retiré (décision Tony) : l'affiche remplit une boîte carrée
     (crop centré), plus rien derrière. */
}

/* Titre : graisse 800, interlignage serré (grands titres de la direction) */
.fiche-title {
  font-family: var(--font-display);
  font-size: clamp(2.4rem, 5.5vw, 4.4rem);
  font-weight: 800;
  line-height: 0.9;
  letter-spacing: -0.03em;
}

/* Pastille(s) catégorie : fond blanc, contour + texte à l'accent de saison
   (révision Tony 29.07.2026 — remplace le plein bleu/texte blanc de la
   maquette P3). */
.fiche-cat {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 18px;
}
.fiche-cat .pill {
  background: #fff;
  color: var(--accent);
  border-color: var(--accent);
}
.fiche-cat .pill::before { display: none; }

/* Valeur forte du dl (dates) : accent */
.fiche-meta__strong { color: var(--accent); font-weight: 700; }

/* Retour : hover accent */
.fiche-back:hover { color: var(--accent); }

/* ---------- Liste des séances (fiche spectacle, LOT 1) ----------
   Remplace le bloc CTA quand la billetterie a été synchronisée : une ligne
   par représentation, jour + heure. Lignes PUREMENT INFORMATIVES — pas de
   bouton par ligne : le widget Infomaniak n'honore pas la route par date
   (cf. commentaire de la vue). Un bouton unique suit sous la liste.

   Règles PROPRES, volontairement pas .orow--past : les sélecteurs de la
   programmation ciblent .ot/.oa/.od/.othumb/.idx, et adopter .orow
   importerait tout son layout (grille 64px 64px 1fr auto, bordures 2px,
   padding au survol). Seule la LOGIQUE est reprise : passé = comparaison
   de date, jamais le statut. */
.seance-list {
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--line);
}
.seance {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 10px;
  padding: 12px 0;
  border-bottom: 1px solid var(--line);
}
.seance__date {
  font-weight: 600;
  color: var(--ink);
  line-height: 1.3;
}
.seance__time {
  font-family: 'Onest', system-ui, sans-serif;
  font-size: 0.92rem;
  color: var(--mute);
  white-space: nowrap;
}

/* Fin de ligne : le badge (information) ou la mention « Passée ». Les deux sont
   exclusifs d'une même ligne et prennent la position stable à droite. */
.seance > .badge-dispo,
.seance__past {
  margin-left: auto;
  flex-shrink: 0;
}
.seance__past {
  font-family: 'Onest', system-ui, sans-serif;
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--mute-2);
}

/* Séance passée : grisée. Même intention visuelle que .orow--past sur la
   programmation, sélecteurs indépendants. */
.seance--past .seance__date,
.seance--past .seance__time { color: var(--mute-2); }

/* Bouton unique sous la liste. La mention qui l'accompagnait a été absorbée par
   son libellé (« Réserver sur la billetterie »). */
.seance-cta {
  margin-top: 22px;
}

@media (max-width: 520px) {
  .seance { align-items: flex-start; }
  .seance > .badge-dispo,
  .seance__past { margin-left: 0; }
}

/* Billetterie pas encore ouverte : mention sobre à la place du bouton mort.
   État NORMAL (9 spectacles sur 10), pas un état dégradé — d'où le ton neutre
   plutôt qu'un avertissement. */
.fiche-billetterie-soon {
  margin: 0;
  font-size: 0.95rem;
  color: var(--mute);
}

/* ---------- Badge de disponibilité (LOT 2) ----------
   Deux états seulement, tous deux dérivés de `free` et `warning_low` — les
   seuls champs dont la sémantique soit démontrée (sonde du 04.08.2026).
   Informatif : il ne désactive rien, le bouton de réservation reste actif.

   Sur la fiche : en fin de ligne de séance, ou en tête de carte de volet.
   Sur obj-list : en tête de la colonne de droite, avant les dates.
   Jamais affiché sur une séance ou un spectacle passé — .seance--past et
   .orow--past portent déjà cette information. */
.badge-dispo {
  display: inline-block;
  padding: 2px 9px;
  border-radius: 999px;
  border: 1px solid currentColor;
  font-family: 'Onest', system-ui, sans-serif;
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  white-space: nowrap;
  line-height: 1.5;
}
/* Complet : neutre. C'est une information, pas une alerte — le spectacle a
   marché, le ton reste factuel. */
.badge-dispo[data-dispo="complet"] {
  color: var(--mute);
  background: var(--bg-tint);
}
/* Bientôt complet : à l'accent de saison, c'est l'état qui appelle une action. */
.badge-dispo[data-dispo="bientot"] {
  color: var(--accent);
  background: transparent;
}
/* Dans obj-list, la colonne de droite est alignée à droite et empilée. */
.oend .badge-dispo { margin-bottom: 4px; }

/* ---------- Volets de festival (chantier festival, morceau 3) ----------
   Une CARTE par soirée, là où une séance tient sur une ligne : un volet porte
   un titre — son information principale — et jusqu'à deux textes libres.
   Trois volets sur cinq n'ayant aucun texte, la carte doit s'affaisser sans
   laisser de blanc résiduel : d'où des marges portées par les enfants et non
   par le conteneur. */
.volet-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.volet {
  padding: 18px 20px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--bg);
}

/* Date en tête : un festival se lit chronologiquement. Le badge la rejoint à
   droite, il qualifie la soirée. */
.volet__when {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 10px;
  margin: 0 0 6px;
}
.volet__date {
  font-family: 'Onest', system-ui, sans-serif;
  font-size: 0.82rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--mute);
}
.volet__time {
  font-family: 'Onest', system-ui, sans-serif;
  font-size: 0.82rem;
  color: var(--mute);
  white-space: nowrap;
}
.volet__when .badge-dispo,
.volet__past { margin-left: auto; flex-shrink: 0; }
.volet__past {
  font-family: 'Onest', system-ui, sans-serif;
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--mute-2);
}

/* Titre : l'accroche de la soirée, pas un sous-titre de la fiche. */
.volet__titre {
  margin: 0;
  font-size: 1.25rem;
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: -0.01em;
  color: var(--ink);
}

/* Durée et âge conseillé (037) : mention de service, sous le titre. Même
   traitement que la date en tête — Onest, 0.82rem, --mute — parce que c'est la
   même nature d'information : du factuel, pas de l'éditorial. Elle ne doit pas
   peser autant que la description qui la suit. */
.volet__infos {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px;
  margin: 6px 0 0;
  font-family: 'Onest', system-ui, sans-serif;
  font-size: 0.82rem;
  color: var(--mute);
}
/* Point de séparation, posé UNIQUEMENT entre deux mentions par la vue. */
.volet__infos-dot {
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: var(--mute-2);
  flex-shrink: 0;
}
.volet__texte {
  margin: 10px 0 0;
  font-size: 0.98rem;
  line-height: 1.55;
  color: var(--ink-2);
}
/* Second texte = la DISTRIBUTION de la soirée (colonne `texte_2`, libellée
   « Distribution » en back-office ; `texte` est la description).

   ⚠️ Traitement STRICTEMENT ALIGNÉ sur .fiche-prose--small, qui porte la
   Distribution et les Soutiens d'une fiche ordinaire : même taille, même
   couleur, même interlignage. C'est la même information, elle ne doit pas
   changer d'aspect selon qu'elle est sur une carte de volet ou sur une fiche.
   Les deux règles se citent mutuellement — ne pas en bouger une seule. */
.volet__texte--second {
  margin-top: 8px;
  font-size: 0.85rem;
  line-height: 1.55;
  color: var(--mute);
}
.volet__cta { margin: 14px 0 0; }
.volet__cta .btn-primary { font-size: 0.92rem; padding: 9px 20px; }

/* Soirée passée : grisée, jamais masquée — les dates seules décident, jamais
   le statut. Même intention que .seance--past et .orow--past, sélecteurs
   indépendants. */
.volet--past { background: var(--bg-tint); border-color: var(--line-2); }
.volet--past .volet__titre { color: var(--mute); }
.volet--past .volet__texte,
.volet--past .volet__date,
.volet--past .volet__infos,
.volet--past .volet__time { color: var(--mute-2); }

@media (max-width: 520px) {
  .volet { padding: 16px; }
  .volet__when .badge-dispo,
  .volet__past { margin-left: 0; }
}

/* ==========================================================================
   Masquage accessible + bloc newsletter (footer)
   ========================================================================== */

/* Retiré du flux visuel, mais lu par les lecteurs d'écran (aucun utilitaire
   sr-only n'existait). Sert au <label> du champ email de la newsletter. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Bloc newsletter — ligne de service centrée dans le footer, au-dessus des
   colonnes. Discret (fond --ink, même filet que .site-footer__grid). */
.newsletter {
  padding-bottom: 26px;
  margin-bottom: 26px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.12);
}

/* UNE seule ligne : le <h4> vit dans .inf-main_… (HORS .inf-content), c'est
   donc CE conteneur qu'on passe en flex pour que titre + champ + bouton
   partagent la ligne. Ciblé par préfixe (le hash suit le webform), scopé
   .newsletter — aucune classe renommée. Centré horizontalement, éléments
   centrés verticalement entre eux. */
.newsletter [class*="inf-main_"] {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 8px 16px;
}

/* Titre au MÊME corps que les intitulés de colonnes (LE THÉÂTRE…), pas au-dessus. */
.newsletter__title {
  font-family: 'Onest', system-ui, sans-serif;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  margin: 0;
}
.newsletter__intro { color: rgba(255, 255, 255, 0.7); font-size: 0.82rem; margin: 0; }
.newsletter__intro:empty { display: none; } /* tant que Tony ne l'a pas rempli */

/* Champ + bouton côte à côte, centrés verticalement. nowrap : le bouton reste
   à côté du champ (le nesting flex le ferait sinon passer dessous) ; on ne
   repasse en wrap qu'en dessous de 480px. */
.newsletter__form .inf-content {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: 8px;
  margin: 0;
}
.newsletter__field {
  flex: 0 0 240px;
  max-width: 240px;
  min-width: 0;
  margin: 0;
}
/* altcha vide (scripts injectés au focus) : hors flux jusqu'à son upgrade. */
.newsletter__form altcha-widget:not(:defined) { display: none; }

/* Champ discret : ~240 × 36. Surcharge SCOPÉE — .form-input global non modifié. */
.newsletter .form-input {
  width: 100%;
  height: 36px;
  padding: 0 12px;
  font-size: 0.88rem;
}

.newsletter__submit { flex: 0 0 auto; margin: 0; }
/* Bouton à l'avenant, fond accent lisible sur le footer sombre (réasserté). */
.newsletter__submit .btn-primary {
  height: 36px;
  padding: 0 16px;
  font-size: 0.82rem;
  background: var(--accent);
  color: var(--accent-ink, #fff);
  border-color: transparent;
  cursor: pointer;
}
/* Hover : le --ink global le ferait disparaître sur le footer → on garde
   l'accent et on nuance par la luminosité (sans couleur en dur). */
.newsletter__submit .btn-primary:hover {
  background: var(--accent);
  color: var(--accent-ink, #fff);
  filter: brightness(1.08);
}

/* < 700px : le titre passe au-dessus ; champ + bouton restent côte à côte. */
@media (max-width: 700px) {
  .newsletter [class*="inf-main_"] { flex-direction: column; gap: 12px; }
}
/* < 480px : champ et bouton pleine largeur, empilés. */
@media (max-width: 480px) {
  .newsletter__form .inf-content { flex-wrap: wrap; }
  .newsletter__field { flex-basis: 100%; max-width: none; }
  .newsletter__submit { width: 100%; }
  .newsletter__submit .btn-primary { width: 100%; }
}

/* Message de succès. webform_index.js bascule son display:none inline → block ;
   on ne touche pas à cette mécanique, on s'y adapte. Quand il est visible, il
   occupe la ligne seul, en pleine largeur, centré. */
.newsletter .inf-success {
  flex-basis: 100%;
  text-align: center;
}
/* Son <h4> prend la typo du bloc (pas le gros gras par défaut) : même corps,
   graisse et couleur (blanche héritée du footer) que le titre newsletter. */
.newsletter .inf-success h4 {
  font-family: 'Onest', system-ui, sans-serif;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  margin: 0;
}
/* Le <p> ne contient que le lien de retour « « » : orphelin inutile une fois
   l'inscription faite → masqué (couvre aussi .inf-btn). */
.newsletter .inf-success p { display: none; }

/* Quand le succès est affiché (son style inline ne porte plus « none »), on
   masque le titre du bloc pour qu'il ne reste pas à côté du message : le
   message de confirmation se suffit à lui-même. */
.newsletter [class*="inf-main_"]:has(.inf-success:not([style*="none"])) .newsletter__title {
  display: none;
}
