/* ==========================================================================
   Full Course Yellow - feuille de style unique
   Direction artistique "1a Yellow Flag", reprise de la maquette validée.
   Aucun style inline dans le HTML : tout vit ici.

   SOMMAIRE
   01. Tokens (:root)
   02. Reset
   03. Utilitaires (visually-hidden, skip-link, wrap)
   04. Liens, focus, sélection
   05. Header sticky + navigation
   06. Hero
   07. Bio
   08. Membres
   09. Instagram
   09b. Visionneuse Instagram (lightbox)
   10. Partenaires
   11. Contact + colophon
   12. Responsive (1024 / 760 / 560 / 400)
   13. Mouvement réduit
   14. Impression
   ========================================================================== */


/* ==========================================================================
   01. TOKENS
   ========================================================================== */
:root {
  /* --- Couleurs --- */
  --c-paper:       #f4f1e6;   /* fond global, crème */
  --c-ink:         #111;      /* texte, traits */
  --c-accent:      #ffd400;   /* jaune signature : FOND uniquement sur crème */
  --c-inverse-bg:  #111;      /* fond du bloc partenaires */
  --c-inverse-ink: #f4f1e6;   /* texte sur fond noir */
  --c-muted:       #3f3f3f;   /* note technique sous la grille Instagram (9.94:1) */
  --c-placeholder: #eae6d6;   /* fond légèrement teinté des cellules vides */

  /* --- Typographie --- */
  --f-display: 'Syne', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  --f-body:    'Space Grotesk', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  --f-mono:    'Space Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

  --fw-body:      400;
  --fw-body-med:  500;
  --fw-display:   700;
  --fw-display-b: 800;

  /* --- Échelle de tailles (clamp repris de la maquette) --- */
  --fs-h2:      clamp(32px, 4vw, 52px);
  --fs-pitch:   clamp(22px, 2.6vw, 32px);
  --fs-contact: 22px;
  --fs-body:    17px;
  --fs-body-s:  15px;
  --fs-link:    14px;
  --fs-meta:    13px;
  --fs-micro:   12px;

  /* Tailles pilotées par la COLONNE (cqi), pas par la fenêtre : les mots
     longs ("COURSE", "OLIVIER", "PARTENAIRES") doivent tenir entiers dans
     leur conteneur, dont la largeur ne suit pas celle de la vue. */
  --fs-h1-cq:     clamp(34px, 14cqi, 124px);
  --fs-member-cq: clamp(20px, 15.5cqi, 40px);
  /* Borne basse calibrée sur "PARTENAIRES" (le mot le plus large) dans la
     colonne la plus étroite : au-delà, il déborde et pousse toute la page.
     La borne haute reste celle de la maquette. */
  --fs-h2-alt-cq: clamp(24px, 8.5cqi, 60px);

  /* --- Interlignes --- */
  --lh-tight:  .86;
  --lh-h2:     1;
  --lh-h2-alt: .95;
  --lh-pitch:  1.15;
  --lh-body:   1.55;
  --lh-body-s: 1.5;
  --lh-list:   1.45;
  --lh-mono:   1.5;

  /* --- Interlettrages --- */
  --ls-h1:     -.04em;
  --ls-h2:     -.03em;
  --ls-pitch:  -.02em;
  --ls-member: -.03em;
  --ls-meta:   .08em;
  --ls-cta:    .06em;

  /* --- Espacement --- */
  --gutter:      clamp(20px, 4vw, 48px);
  --maxw:        1280px;
  --sp-hero-top: clamp(40px, 6vw, 72px);
  --sp-pad-dark: clamp(32px, 4vw, 48px);
  --sp-1:  6px;
  --sp-2:  8px;
  --sp-3:  12px;
  --sp-4:  16px;
  --sp-5:  20px;
  --sp-6:  24px;
  --sp-7:  28px;
  --sp-8:  32px;
  --sp-9:  40px;
  --sp-10: 48px;
  --sp-11: 56px;
  --sp-12: 64px;
  --sp-13: 72px;

  /* --- Bordures --- */
  --bw:             2px;
  --bw-hair:        1px;
  --border:         var(--bw) solid var(--c-ink);
  --border-inverse: var(--bw-hair) solid var(--c-inverse-ink);

  /* --- Grilles --- */
  --col-member:  150px;
  /* Grille Instagram : 3 colonnes en desktop. Avec --maxw 1280px et les
     gouttières, 280px de largeur mini donne exactement 3 colonnes (des
     vignettes d'environ 380px), soit 2 rangées pour les 6 publications
     servies par le proxy. Voir le garde-fou repeat(3, ...) plus bas. */
  --col-ig:      280px;
  --col-text:    300px;
  --col-contact: 260px;
  --gap-ig:      16px;

  /* --- Divers --- */
  /* Hauteur réelle du header sticky, mesurée au navigateur et recalculée à
     chaque breakpoint : elle pilote scroll-margin-top, donc une valeur trop
     basse cache le titre de section sous le header après un clic d'ancre. */
  --header-h:   82px;
  --ratio-hero: 3 / 4;
  --dur:        160ms;
  --ease:       cubic-bezier(.2, 0, 0, 1);
}


/* ==========================================================================
   02. RESET
   ========================================================================== */
*,
*::before,
*::after { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  padding: 0 0 var(--sp-12);
  background: var(--c-paper);
  color: var(--c-ink);
  font-family: var(--f-body);
  font-weight: var(--fw-body);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

h1, h2, h3, p, ul, figure { margin: 0; padding: 0; }
ul { list-style: none; }

img, svg, iframe {
  max-width: 100%;
  display: block;
}

strong { font-weight: var(--fw-display-b); }


/* ==========================================================================
   03. UTILITAIRES
   ========================================================================== */
.wrap {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Lien d'évitement : hors écran au repos, au-dessus du header sticky au focus.
   position: fixed et non absolute : en absolute, le "top: 12px" du focus se
   mesure depuis le haut du DOCUMENT. Page déjà défilée, le lien apparaissait
   donc hors écran (WCAG 2.4.11). En fixed, la référence est la fenêtre. */
.skip-link {
  position: fixed;
  top: -100px;
  left: var(--gutter);
  z-index: 100;
  background: var(--c-accent);
  color: var(--c-ink);
  border: var(--border);
  font-family: var(--f-display);
  font-weight: var(--fw-display-b);
  font-size: var(--fs-meta);
  letter-spacing: var(--ls-meta);
  text-transform: uppercase;
  text-decoration: none;
  padding: 12px 18px;
  transition: top var(--dur) var(--ease);
}

.skip-link:focus,
.skip-link:focus-visible {
  top: 12px;
}

/* Chaque cible d'ancre se dégage du header sticky */
[id] { scroll-margin-top: calc(var(--header-h) + 8px); }


/* ==========================================================================
   04. LIENS, FOCUS, SÉLECTION
   ========================================================================== */
a {
  color: var(--c-ink);
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}

/* Le survol jaune de la maquette, repris à l'identique au clavier */
a:hover,
a:focus-visible { background: var(--c-accent); }

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

:focus-visible {
  outline: 3px solid var(--c-ink);
  outline-offset: 3px;
}

/* Sur le bloc noir, l'encre est invisible : l'outline passe en jaune */
.partners :focus-visible { outline-color: var(--c-accent); }
.partners a:hover,
.partners a:focus-visible {
  background: var(--c-accent);
  color: var(--c-ink);
}

/* Au focus, le CTA passe en fond crème sur le bloc noir : un outline encre
   se fondrait dans le noir exposé par l'offset (1.00:1). L'outline doit donc
   contraster avec le FOND du bloc, pas avec le bouton (crème sur noir : 16.70:1). */
.cta:focus-visible {
  outline-color: var(--c-paper);
  outline-offset: 4px;
}


/* ==========================================================================
   05. HEADER STICKY + NAVIGATION
   Le <header> est hors du conteneur max-width : son fond couvre toute la
   largeur de la fenêtre pendant le défilement, le .wrap interne recentre.
   ========================================================================== */
.site-header {
  position: sticky;
  top: 0;
  z-index: 5;
  background: var(--c-paper);
}

.site-header__inner {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--sp-4) var(--sp-8);
  flex-wrap: wrap;
  padding-block: 18px;
  border-bottom: var(--border);
  font-size: var(--fs-meta);
  letter-spacing: var(--ls-meta);
  text-transform: uppercase;
}

.logo {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 44px;      /* cible tactile */
  font-family: var(--f-display);
  font-weight: var(--fw-display-b);
  text-decoration: none;
  padding-block: 10px;
}

/* Le monogramme du groupe remplace l'ancienne puce jaune. Il est dessine en
   clair sur fond noir : on garde donc son fond (detoure, ses contours fins
   disparaissent sur le creme). Le cercle epouse sa silhouette verticale
   mieux qu'un carre, qui laissait deux vides lateraux. */
.logo__mark {
  width: 44px;
  height: 44px;
  flex: 0 0 auto;
  border-radius: 50%;
  display: block;
}

.logo__short { display: none; }

.nav {
  display: flex;
  gap: var(--sp-6);
  flex-wrap: wrap;
}

.nav__link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;      /* cible tactile WCAG, quelle que soit la taille de police */
  text-decoration: none;
  white-space: nowrap;
  padding-block: 10px;
}

.nav__link--current { border-bottom: var(--border); }


/* ==========================================================================
   06. HERO
   ========================================================================== */
.hero {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(200px, 28%);
  gap: var(--sp-8);
  align-items: end;
  padding: var(--sp-hero-top) 0 var(--sp-9);
}

.hero__text {
  min-width: 0;
  container-type: inline-size;   /* référence des unités cqi du H1 */
}

.eyebrow {
  margin-bottom: var(--sp-5);
  font-size: var(--fs-meta);
  letter-spacing: var(--ls-meta);
  text-transform: uppercase;
}

.hero__title {
  font-family: var(--f-display);
  font-weight: var(--fw-display-b);
  /* La taille suit la COLONNE du hero (cqi), pas la fenêtre : "COURSE", le mot
     le plus large, doit tenir entier sur sa ligne. Le 9.5vw de la maquette
     supposait un titre pleine largeur, alors que la grille ne lui laisse
     que ~57% : il cassait "COURS / E" et débordait sur la photo. */
  font-size: var(--fs-h1-cq);
  line-height: var(--lh-tight);
  letter-spacing: var(--ls-h1);
  text-transform: uppercase;
  hyphens: none;
}

/* Surlignage jaune : le jaune est un FOND, jamais une couleur de texte */
.hl {
  background: var(--c-accent);
  padding: 0 .06em;
  display: inline-block;
  line-height: var(--lh-tight);
}

.hero__photo {
  position: relative;
  aspect-ratio: var(--ratio-hero);
  border: var(--border);
  overflow: hidden;
  min-width: 0;
}

/* Vaut pour le placeholder SVG comme pour la vraie photo à venir */
.hero__photo > svg,
.hero__photo > img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.hero__placeholder { background: var(--c-paper); }


/* ==========================================================================
   07. BIO
   ========================================================================== */
.bio {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(var(--col-text), 1fr));
  gap: var(--sp-9);
  padding: var(--sp-9) 0;
  border-top: var(--border);
}

.bio__pitch {
  font-family: var(--f-display);
  font-weight: var(--fw-display);
  font-size: var(--fs-pitch);
  line-height: var(--lh-pitch);
  letter-spacing: var(--ls-pitch);
  text-wrap: pretty;
}

.bio__para {
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  max-width: 52ch;
  text-wrap: pretty;
}

.bio__para--small {
  margin-top: var(--sp-5);
  font-size: var(--fs-body-s);
}


/* ==========================================================================
   08. MEMBRES - grille au trait 2px
   Le conteneur porte top + left, chaque cellule porte right + bottom :
   aucun trait n'est doublé, quel que soit le nombre de colonnes.
   ========================================================================== */
.members {
  display: grid;
  /* auto-fit créerait des colonnes fantômes au-delà de 4 membres de large
     (et casserait la grille au trait) : on plafonne à 4 colonnes réelles. */
  grid-template-columns: repeat(auto-fit, minmax(var(--col-member), 1fr));
  border-top: var(--border);
  border-left: var(--border);
}

@media (min-width: 761px) {
  .members { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

.member {
  padding: var(--sp-5) var(--sp-5) var(--sp-7);
  border-right: var(--border);
  border-bottom: var(--border);
  min-width: 0;
  container-type: inline-size;   /* référence des unités cqi de .member__name */
}

.member__name {
  font-family: var(--f-display);
  font-weight: var(--fw-display-b);
  /* La taille suit la largeur de la CELLULE (cqi), pas celle de la fenêtre :
     "OLIVIER", le nom le plus long, doit tenir sur une seule ligne dans une
     colonne de 4, à toute largeur. Un clamp en vw se trompait de référence
     et coupait "OLIVIE / R". */
  font-size: var(--fs-member-cq);
  line-height: 1;
  letter-spacing: var(--ls-member);
  text-transform: uppercase;
  white-space: nowrap;
}

.member__role {
  margin-top: var(--sp-2);
  font-size: var(--fs-meta);
  letter-spacing: var(--ls-meta);
  text-transform: uppercase;
}


/* ==========================================================================
   09. INSTAGRAM
   ========================================================================== */
.section--ig { padding: var(--sp-12) 0 0; }

.section__head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--sp-4);
  flex-wrap: wrap;
  margin-bottom: var(--sp-5);
}

.section__title {
  font-family: var(--f-display);
  font-weight: var(--fw-display-b);
  font-size: var(--fs-h2);
  line-height: var(--lh-h2);
  letter-spacing: var(--ls-h2);
  text-transform: uppercase;
  min-width: 0;
  overflow-wrap: break-word;   /* garde-fou : ne coupe que si le mot ne tient pas */
}

.link-underline {
  /* Même cible tactile que .nav__link : 44px de haut minimum */
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: var(--fs-link);
  letter-spacing: var(--ls-meta);
  text-transform: uppercase;
  text-decoration: none;
  border-bottom: var(--border);
  padding-block: 8px;
}

/* 4 colonnes fixes en desktop, jamais moins de 2 ensuite (voir responsive).
   On n'utilise plus auto-fill : il produisait jusqu'a 6 colonnes minuscules
   sur grand ecran, et pouvait retomber a une seule colonne en dessous de
   --col-ig, ce qui rendait la section interminable. Un nombre de colonnes
   explicite supprime les deux derives. */
.ig-grid {
  display: grid;
  /* 4 colonnes en desktop : avec 12 vignettes par page et un bouton
     "Charger plus", des vignettes de ~285px montrent encore la scene et les
     visages tout en gardant la section compacte.
     La taille reste FIXE apres chargement : reduire les vignettes au fil des
     ajouts ferait bouger sous les yeux du visiteur les images qu'il vient de
     regarder. */
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--gap-ig);
}

.ig-cell {
  position: relative;
  aspect-ratio: 1;
  min-width: 0;
  overflow: hidden;
  border: var(--border);
  background: var(--c-placeholder);
}

/* Cellules statiques du HTML : présentables sans JS, aucun texte d'erreur */
.ig-cell--placeholder {
  background-color: var(--c-placeholder);
  background-image:
    linear-gradient(135deg, rgba(17, 17, 17, .06) 25%, transparent 25%),
    linear-gradient(225deg, rgba(17, 17, 17, .06) 25%, transparent 25%);
  background-size: 18px 18px;
}

.ig-cell__link {
  display: block;
  width: 100%;
  height: 100%;
}

.ig-cell__link:hover,
.ig-cell__link:focus-visible { background: var(--c-accent); }

.ig-cell__link img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Miniatures de Reels : Instagram y incruste des bandes noires. object-fit ne
   peut rien contre des pixels noirs présents dans l'image, on agrandit donc
   pour ne garder que la zone utile.

   Facteur mesuré, pas estimé. Les 4 vignettes vidéo servies font toutes
   1206x2144, et la bande de contenu réelle y occupe 678 à 686px de haut,
   centrée (décalage mesuré : moins d'1px, d'où transform-origin: center).
   object-fit: cover recadre d'abord au carré central 1206x1206 : la bande
   utile ne remplit donc que 682/1206 = 56,6% de la cellule, et le facteur
   nécessaire vaut 1206/682 = 1,77.

   Ce rapport ne dépend QUE du ratio interne de l'image : il est identique
   pour une cellule de 120px ou de 380px. L'agrandissement de la grille ne
   le change pas.

   L'ancienne valeur (3,05) était donc trop forte de ~72% : elle ne montrait
   que 33% de la largeur de chaque image (le chanteur seul, batteur et
   guitariste hors cadre) et imposait d'étirer une source de 395px sur une
   vignette de 380px. À 1,77 on voit 56% de la largeur, sans aucune bande
   noire. La marge de 0,03 absorbe les quelques pixels d'écart entre les
   vignettes (la plus haute bande mesurée donne 1,768). */
.ig-cell--video .ig-cell__link img {
  transform: scale(1.8);
  transform-origin: center;
}

/* Pastille vidéo, posée par le JS */
.ig-cell__badge {
  position: absolute;
  top: 6px;
  right: 6px;
  z-index: 1;
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  background: var(--c-accent);
  border: var(--bw) solid var(--c-ink);
  color: var(--c-ink);
  font-size: 11px;
  line-height: 1;
  pointer-events: none;
}

/* Badge carrousel : même pastille que la vidéo, mais elle porte un nombre
   (le nombre de vues) plutôt qu'un signe. Elle est donc un peu plus large. */
.ig-cell__badge--stack {
  width: auto;
  min-width: 24px;
  padding: 0 6px;
  font-family: var(--f-mono);
  font-size: var(--fs-micro);
}

/* États pilotés par le JS via data-state sur #ig-grid */
.ig-grid[data-state="loading"] { opacity: .6; }
.ig-grid[data-state="ready"]   { opacity: 1; }
.ig-grid[data-state="fallback"] .ig-cell--placeholder { opacity: .85; }

.ig-note {
  margin-top: var(--sp-3);
  font-family: var(--f-mono);
  font-size: var(--fs-meta);
  line-height: var(--lh-mono);
  color: var(--c-muted);
  /* Le lien vers le compte passe sous la phrase : sur la même ligne, il se
     confondait avec le texte courant et perdait son statut d'action. */
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--sp-2);
  max-width: 64ch;
}

.ig-note[hidden] { display: none; }


/* --------------------------------------------------------------------------
   Bouton « Charger plus »

   Posé par le JS sous la grille, uniquement si le proxy annonce hasMore.
   Il reprend le CTA du site (fond jaune, Syne, capitales) : c'est la même
   nature d'action, elle ne mérite pas un troisième vocabulaire visuel.

   Cible tactile : padding 14px + police 16px donnent une hauteur mesurée
   d'environ 48px, au-dessus du plancher de 44px recommandé.
   -------------------------------------------------------------------------- */
.ig-more {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-3);
  margin-top: var(--sp-5);
  text-align: center;
}

.ig-more[hidden] { display: none; }

.ig-more__btn {
  /* .cta pose déjà fond, bordure, police et capitales. On ne reprend ici que
     ce qui diffère : le CTA de la section partenaires porte une marge haute
     dont ce bouton n'a pas besoin (le conteneur la fournit déjà). */
  margin-top: 0;
  min-height: 44px;
  cursor: pointer;
}

.ig-more__btn[disabled] {
  cursor: progress;
  opacity: .7;
}

.ig-more__btn[hidden] { display: none; }

/* Annonce de chargement et message d'échec. Vide, l'élément ne doit pas
   réserver de hauteur : sans :empty, la grille serait suivie d'un blanc
   permanent sans rien pour l'expliquer. */
.ig-more__status {
  font-family: var(--f-mono);
  font-size: var(--fs-meta);
  line-height: var(--lh-mono);
  color: var(--c-muted);
  max-width: 48ch;
}

.ig-more__status:empty { display: none; }

/* Fin du flux : le bouton est retiré, cette mention prend sa place. */
.ig-more[data-done="true"]::after {
  content: "Tout est affiché";
  font-family: var(--f-mono);
  font-size: var(--fs-meta);
  letter-spacing: var(--ls-meta);
  text-transform: uppercase;
  color: var(--c-muted);
}


/* ==========================================================================
   09b. VISIONNEUSE INSTAGRAM (lightbox)
   Ouverte par assets/js/main.js au clic sur une vignette. Le markup est
   construit en JS : sans JS, les vignettes restent de simples liens vers
   Instagram et rien de ce qui suit ne s'applique.

   Parti pris graphique : on reste dans la direction artistique du site.
   Le fond est l'encre du site en translucide (pas un noir neutre), les
   commandes sont les mêmes rectangles crème à filet de 2px que partout
   ailleurs, et le survol/focus passe au jaune signature.
   ========================================================================== */
.ig-viewer {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: grid;
  grid-template-rows: auto 1fr auto;
  gap: var(--sp-3);
  padding: var(--sp-4);
  /* L'encre du site, pas un noir pur : la visionneuse reste "du même monde"
     que la page qu'elle recouvre. */
  background: rgba(17, 17, 17, .93);
  /* Le fond est déjà très opaque : le flou est un bonus pour les navigateurs
     qui le supportent, jamais une condition de lisibilité. */
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  opacity: 0;
  transition: opacity var(--dur) var(--ease);
}

/* L'ouverture est pilotée par un attribut posé au frame suivant par le JS,
   pour que la transition d'opacité ait bien lieu. */
.ig-viewer[data-open="true"] { opacity: 1; }

.ig-viewer[hidden] { display: none; }

/* --- Barre haute : compteur + fermeture ------------------------------- */
.ig-viewer__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  min-height: 44px;
}

.ig-viewer__count {
  font-family: var(--f-mono);
  font-size: var(--fs-meta);
  letter-spacing: var(--ls-meta);
  color: var(--c-inverse-ink);
}

/* Sur une publication simple, le compteur n'a rien à dire : on le masque
   sans le retirer du DOM (aria-live doit rester attaché au même nœud). */
.ig-viewer__count[hidden] { visibility: hidden; display: block; }

/* --- Boutons (fermeture et flèches) ----------------------------------- */
.ig-viewer__btn {
  display: inline-grid;
  place-items: center;
  /* 44px : cible tactile minimale, cohérente avec .nav__link et .cta */
  min-width: 44px;
  min-height: 44px;
  padding: 0 var(--sp-2);
  background: var(--c-paper);
  color: var(--c-ink);
  border: var(--border);
  font-family: var(--f-display);
  font-weight: var(--fw-display-b);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  transition: background var(--dur) var(--ease);
}

.ig-viewer__btn:hover,
.ig-viewer__btn:focus-visible { background: var(--c-accent); }

/* Le fond est sombre : un outline encre (règle globale) y serait invisible.
   Tout ce qui est focusable dans la visionneuse passe donc au jaune. */
.ig-viewer :focus-visible {
  outline: 3px solid var(--c-accent);
  outline-offset: 3px;
}

/* Un bouton désactivé (première ou dernière vue, navigation non bouclée)
   reste lisible mais clairement inactif. */
.ig-viewer__btn[disabled] {
  opacity: .35;
  cursor: default;
}

/* --- Scène : l'image et les deux flèches ------------------------------ */
/* La scène occupe la rangée centrale : flèche, image, flèche, chacune dans sa
   colonne. min-height: 0 est indispensable : sans lui, une rangée `1fr` se
   laisse pousser par son contenu et la scène déborde de l'écran. */
.ig-viewer__stage {
  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--sp-3);
  min-height: 0;
}

/* align-self / justify-self : sans eux, une grid-item s'étire sur toute sa
   cellule et la flèche "suivante" barrait l'écran sur toute la largeur.
   z-index : les flèches restent au-dessus en mode téléphone, où elles
   repassent en superposition sur l'image (voir le media query 560px). */
.ig-viewer__nav {
  position: relative;
  z-index: 1;
  align-self: center;
  justify-self: center;
}

/* La figure est positionnée en absolu DANS la scène (qui est en position:
   relative). C'est le seul moyen fiable de lui donner une hauteur définie :
   en flux normal, `height: 100%` se résout contre une rangée `1fr` que
   l'image elle-même fait grandir, donc `max-height: 100%` sur l'image n'a
   aucune borne réelle et la grande image déborde vers le bas (elle passait
   sous la légende et sous le lien Instagram, qui devenaient inatteignables).
   En absolu, inset:0 fixe la hauteur avant que l'image ne soit mesurée. */
/* La figure reste dans le flux de la grille : elle occupe naturellement la
   colonne du milieu et s'arrête donc exactement où commencent les flèches
   (en absolu, elle passait dessous et l'image était barrée par la flèche
   "suivante").
   min-width / min-height à 0 : sans eux, une grid-item refuse de descendre
   sous la taille de son contenu, et l'image ressortirait de l'écran. */
/* La figure reste dans le flux : elle occupe la colonne du milieu et s'arrête
   donc exactement où commencent les flèches.
   min-width / min-height à 0 : sans eux, une grid-item refuse de descendre
   sous la taille de son contenu et l'image ressortirait de l'écran. */
.ig-viewer__figure {
  min-width: 0;
  min-height: 0;
  height: 100%;
  /* Flex, pas grid : une grid crée une rangée `auto` que l'image (très haute)
     fait grandir jusqu'à sa taille intrinsèque, et `height: 100%` sur l'image
     se résout alors contre cette rangée gonflée (1728px mesurés) au lieu des
     756px de la figure. En flex, l'enfant se dimensionne contre la hauteur
     définie de la figure. */
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  margin: 0;
}

/* L'image ne dépasse jamais la figure, qui a une hauteur définie (inset:0).
   `contain` préserve le cadrage d'origine : une photo de concert en portrait
   ne doit pas être recadrée par la visionneuse. */
/* width/height à 100% + object-fit: contain, plutôt que max-height: 100% et
   des dimensions automatiques. Raison mesurée : en `height: auto`, une image
   très haute (ici 3072x4096) se dimensionne sur sa taille intrinsèque et
   `max-height: 100%` ne la borne pas, car `align-items: center` fait résoudre
   ce pourcentage contre la hauteur de contenu de l'élément, pas contre la
   rangée. L'image sortait donc à 1727px de haut dans une figure de 756px et
   recouvrait la légende et le lien Instagram.
   En partant du conteneur (100% des deux côtés), la taille ne dépend plus du
   fichier : `contain` inscrit l'image dedans en gardant ses proportions. */
.ig-viewer__img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  /* Ni filet ni fond sur l'image : avec `contain`, sa boîte est plus large
     que les pixels réellement affichés (bandes vides sur les côtés pour une
     photo en portrait). Une bordure posée ici encadrerait du vide, ce qui
     serait pire que pas de cadre du tout. L'image se détache déjà nettement
     du fond encre à 93% d'opacité. */
}

/* --- Légende + lien Instagram ----------------------------------------- */
.ig-viewer__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-2) var(--sp-4);
}

.ig-viewer__caption {
  margin: 0;
  max-width: 70ch;
  color: var(--c-inverse-ink);
  font-size: var(--fs-body-s);
  line-height: var(--lh-body-s);
  /* Une légende Instagram peut faire dix lignes : on en montre trois, le
     texte intégral reste accessible via le lien "Voir sur Instagram". */
  display: -webkit-box;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.ig-viewer__caption:empty { display: none; }

/* Position dans la publication d'origine (« Image 3 sur 6 de cette
   publication »). Discrète par construction : c'est un repère de contexte,
   pas une information de premier plan. */
.ig-viewer__origin {
  margin-top: var(--sp-1, 4px);
  font-family: var(--f-mono);
  font-size: var(--fs-micro);
  letter-spacing: var(--ls-meta);
  text-transform: uppercase;
  opacity: .75;
}

.ig-viewer__origin[hidden] { display: none; }

.ig-viewer__link {
  flex: none;
  color: var(--c-inverse-ink);
  font-size: var(--fs-link);
  letter-spacing: var(--ls-meta);
  text-transform: uppercase;
  text-decoration: none;
  border-bottom: var(--bw) solid var(--c-inverse-ink);
  padding-block: 4px;
  /* Cible tactile : le lien est en bas d'écran, souvent atteint au pouce. */
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}

/* La règle globale a:hover pose un fond jaune ET garde la couleur d'encre :
   ici le texte est crème, il faut donc repasser explicitement en encre. */
.ig-viewer__link:hover,
.ig-viewer__link:focus-visible {
  background: var(--c-accent);
  color: var(--c-ink);
  border-bottom-color: var(--c-ink);
}

/* --- Verrou du défilement de la page sous la visionneuse -------------- */
/* Posé sur <html> par le JS. Le padding compense la largeur de la barre de
   défilement qui disparaît, sinon toute la page saute horizontalement au
   moment de l'ouverture. */
html.is-ig-viewer-open {
  overflow: hidden;
  padding-right: var(--ig-scrollbar-w, 0px);
}

/* --- Téléphone -------------------------------------------------------- */
@media (max-width: 560px) {
  .ig-viewer { padding: var(--sp-2); }

  /* Les flèches quittent les côtés (elles y mangeraient la largeur de
     l'image) et passent en superposition en bas, à portée de pouce.
     La figure récupère donc toute la largeur. */
  .ig-viewer__stage { grid-template-columns: minmax(0, 1fr); }

  .ig-viewer__nav {
    position: absolute;
    bottom: var(--sp-2);
    z-index: 1;
  }

  .ig-viewer__nav--prev { left: var(--sp-2); }
  .ig-viewer__nav--next { right: var(--sp-2); }

  .ig-viewer__foot {
    flex-direction: column;
    align-items: flex-start;
  }

  .ig-viewer__caption { -webkit-line-clamp: 2; line-clamp: 2; }
}

/* --- Mouvement réduit ------------------------------------------------- */
/* La règle globale de la section 13 neutralise déjà les transitions, mais on
   le redit ici pour que la visionneuse reste correcte si ce fichier était
   repris isolément : aucune animation d'ouverture, apparition immédiate. */
@media (prefers-reduced-motion: reduce) {
  .ig-viewer {
    transition: none;
    opacity: 1;
  }
}


/* ==========================================================================
   10. PARTENAIRES - bloc inversé
   ========================================================================== */
.partners {
  margin-top: var(--sp-13);
  background: var(--c-inverse-bg);
  color: var(--c-inverse-ink);
  padding: var(--sp-pad-dark);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(var(--col-text), 1fr));
  gap: var(--sp-10);
}

.partners__main,
.partners__aside { min-width: 0; }

.partners__main { container-type: inline-size; }   /* référence cqi du titre */

/* Le jaune en TEXTE est autorisé ici : fond noir, ratio 12.05:1 */
.partners__title {
  font-family: var(--f-display);
  font-weight: var(--fw-display-b);
  line-height: var(--lh-h2-alt);
  letter-spacing: var(--ls-h2);
  text-transform: uppercase;
  color: var(--c-accent);
  text-wrap: balance;
  min-width: 0;
  /* Comme le H1 : la taille suit la colonne, pour que "PARTENAIRES" tienne
     entier au lieu d'être coupé en "PARTENAI / RES". */
  font-size: var(--fs-h2-alt-cq);
}

.partners__para {
  margin-top: var(--sp-6);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  text-wrap: pretty;
}

.partners__para--small {
  margin-top: var(--sp-4);
  font-size: var(--fs-body-s);
  line-height: var(--lh-body-s);
}

.cta {
  display: inline-block;
  margin-top: var(--sp-7);
  background: var(--c-accent);
  color: var(--c-ink);
  border: var(--bw) solid var(--c-accent);
  font-family: var(--f-display);
  font-weight: var(--fw-display-b);
  font-size: var(--fs-body-s);
  letter-spacing: var(--ls-cta);
  text-transform: uppercase;
  text-decoration: none;
  padding: 14px 22px;
}

.partners .cta:hover,
.partners .cta:focus-visible {
  background: var(--c-paper);
  border-color: var(--c-paper);
  color: var(--c-ink);
}

.partners__intro {
  margin-bottom: var(--sp-2);
  font-size: var(--fs-meta);
  letter-spacing: var(--ls-meta);
  text-transform: uppercase;
}

.partners__list {
  display: flex;
  flex-direction: column;
}

.partners__item {
  padding: var(--sp-4) 0;
  border-top: var(--border-inverse);
  font-size: var(--fs-body);
  line-height: var(--lh-list);
  text-wrap: pretty;
}

.partners__item strong {
  font-family: var(--f-display);
  font-weight: var(--fw-display-b);
  text-transform: uppercase;
}

/* Filet de clôture de la liste */
.partners__rule { border-top: var(--border-inverse); }


/* ==========================================================================
   11. CONTACT + COLOPHON
   ========================================================================== */
.site-footer { padding-top: var(--sp-10); }

.site-footer .section__title { margin-bottom: var(--sp-6); }

.contact {
  display: grid;
  /* auto-fit repartissait les 3 blocs a parts egales : l'email, bien plus long
     que le telephone et le pseudo, se coupait en "gmail. / com" alors que ses
     voisins avaient de la place de reste. Chaque piste prend donc la largeur de
     son contenu (auto), l'email recoit le reste, et min() garde le plancher
     sous la place disponible pour ne jamais pousser la page. */
  grid-template-columns: auto minmax(min(20ch, 100%), auto) auto;
  gap: var(--sp-6) var(--sp-8);
}

.contact__block {
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.contact__label {
  margin-bottom: var(--sp-1);
  font-size: var(--fs-micro);
  letter-spacing: var(--ls-meta);
  text-transform: uppercase;
}

.contact__value {
  font-family: var(--f-display);
  font-weight: var(--fw-display);
  font-size: var(--fs-contact);
  line-height: 1.25;
  text-decoration: none;
  /* anywhere (et non break-word) : seul anywhere est pris en compte dans le
     calcul de la largeur minimale intrinsèque de la cellule de grille. Avec
     break-word, l'adresse gonflait la colonne et poussait la page à 768px.
     Le confort de lecture est préservé par --fs-contact, réduit plus bas
     tant que la colonne est étroite, pour éviter la coupure inutile. */
  overflow-wrap: anywhere;
  align-self: flex-start;
  /* Cible tactile : ce sont les actions principales de la page */
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}

.contact__note {
  font-family: var(--f-body);
  font-weight: var(--fw-body);
  font-size: var(--fs-body-s);
}

.colophon {
  margin-top: var(--sp-11);
  padding-top: var(--sp-4);
  border-top: var(--border);
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--sp-3) var(--sp-6);
  flex-wrap: wrap;
  font-size: var(--fs-micro);
  letter-spacing: var(--ls-meta);
  text-transform: uppercase;
}

/* Le credit d'auteur ferme la ligne a droite : "Luxembourg" reste donc au
   centre, et space-between garde les trois blocs a distance egale. */
.colophon__credit {
  margin-left: auto;
  color: var(--c-muted);
}

.colophon__credit a {
  color: inherit;
  text-decoration: none;
  border-bottom: var(--bw-hair) solid currentColor;
  padding-bottom: 1px;
}

.colophon__credit a:hover,
.colophon__credit a:focus-visible {
  color: var(--c-ink);
  background: var(--c-accent);
}


/* ==========================================================================
   12. RESPONSIVE
   Desktop-first : les clamp() et les grilles auto-fit font l'essentiel.
   Les media queries ci-dessous ne règlent que ce que les grilles ne savent
   pas faire seules. Jamais de burger : 4 liens courts ne le justifient pas.
   ========================================================================== */

/* --- 1024px : respiration légèrement resserrée ------------------------- */
@media (max-width: 1024px) {
  .hero { gap: var(--sp-7); }
  .bio  { gap: var(--sp-8); }
  .partners { gap: var(--sp-9); }

  /* Sous 1024px les 3 colonnes ne laissent plus assez de place à l'email, qui
     se couperait en "gmail. / com". Deux colonnes, l'email occupant la sienne
     entière sur la première ligne. */
  .contact {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .contact__block--email { grid-column: 1 / -1; }

  /* Palier tablette : a 4 colonnes les vignettes tomberaient sous 200px et
     les photos de scene deviendraient illisibles. On passe a 3. */
  .ig-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }

  /* La grille Instagram est deja a 3 colonnes en desktop : rien a corriger
     a ce palier, le passage a 2 colonnes se fait a 760px. */
}

/* --- 800px : la nav ne tient plus sur la ligne du logo, le header
       passe à deux lignes (142px mesurés). ------------------------------ */
@media (max-width: 800px) {
  :root { --header-h: 142px; }
}

/* --- 760px : passage en une colonne ----------------------------------- */
@media (max-width: 760px) {
  :root {
    --header-h: 128px;   /* deux lignes, padding réduit (mesuré au navigateur) */
  }

  .site-header__inner {
    padding-block: 12px;
    gap: 14px 18px;
    font-size: var(--fs-micro);
  }

  .nav {
    width: 100%;               /* force le retour à la ligne de la nav */
    gap: 14px 18px;
  }

  /* Hero en 1 colonne : le H1 reste le premier contenu perçu */
  .hero {
    grid-template-columns: 1fr;
    gap: var(--sp-6);
    padding-top: var(--sp-8);
  }

  .hero__photo {
    aspect-ratio: 4 / 3;
    max-height: 60vh;
  }

  /* Bio en 1 colonne */
  .bio {
    grid-template-columns: 1fr;
    gap: var(--sp-7);
  }

  .bio__para { max-width: none; }

  /* Partenaires en 1 colonne, padding réduit */
  .partners {
    grid-template-columns: 1fr;
    gap: var(--sp-8);
    padding: 28px 22px;
    margin-top: var(--sp-10);
  }

  /* Instagram : 2 colonnes. On ne descend JAMAIS à une seule colonne, qui
     étirerait la section sur 6 écrans de haut. */
  .ig-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* --- 560px : téléphone ------------------------------------------------- */
@media (max-width: 560px) {
  :root {
    --fs-contact: 18px;
    /* --col-ig n'est plus utilisé : le nombre de colonnes est explicite.
       Seule la gouttière se resserre pour laisser de la place aux images. */
    --gap-ig: 10px;
    /* Les planchers des clamp desktop (32px / 36px) rendent les mots longs
       ("INSTAGRAM", "PARTENAIRES") plus larges que leur colonne sous ~400px.
       On repasse sur des bornes relatives à la vue pour garder chaque mot
       entier, sans césure, et sans scroll horizontal. */
    --fs-h2:     clamp(24px, 7.6vw, 52px);
  }

  /* Logo réduit à FCY, la puce jaune reste */
  .logo__full  { display: none; }
  .logo__short { display: inline; }

  /* Nav sur une seule ligne, défilement horizontal sans barre visible */
  .nav {
    width: 100%;
    flex-wrap: nowrap;
    justify-content: space-between;
    gap: var(--sp-3);
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    font-size: 11px;
  }

  .nav::-webkit-scrollbar { display: none; }

  /* Membres : exactement 2 colonnes, plus lisible que 3 étroites */
  .members { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .member  { padding: var(--sp-4) var(--sp-4) var(--sp-5); }

  .section--ig { padding-top: var(--sp-10); }

  /* CTA en cible tactile pleine largeur, au moins 44px de haut */
  .cta {
    display: block;
    width: 100%;
    text-align: center;
    padding: 16px 20px;
  }

  .partners__item { padding: 14px 0; }

  /* Contact en 1 colonne, chaque bloc séparé par un filet */
  .contact {
    grid-template-columns: 1fr;
    gap: var(--sp-5);
  }

  .contact__block + .contact__block {
    border-top: var(--bw-hair) solid var(--c-ink);
    padding-top: var(--sp-4);
  }

  .colophon { margin-top: var(--sp-9); }
}

/* --- 400px : petits téléphones ---------------------------------------- */
@media (max-width: 400px) {
  /* Membres en 1 colonne : le motif left-conteneur / right-cellule
     reste correct, aucun trait n'est doublé. */
  .members { grid-template-columns: 1fr; }

  /* 2 colonnes maintenues même sur les plus petits téléphones (plancher). */
  .ig-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 8px;
  }

  .partners { padding: 24px 18px; }
}


/* ==========================================================================
   13. MOUVEMENT RÉDUIT
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  *,
  *::before,
  *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}


/* ==========================================================================
   14. IMPRESSION
   ========================================================================== */
@media print {
  .site-header,
  .skip-link,
  .ig-grid,
  .ig-note { display: none; }

  body { padding-bottom: 0; }

  .partners {
    background: #fff;
    color: #111;
    border: var(--border);
  }

  .partners__title { color: #111; }

  .cta {
    border: var(--border);
    background: #fff;
  }

  .hero,
  .bio,
  .partners,
  .site-footer { break-inside: avoid; }
}
