/* =====================================================================
   FAZZINO IN LYON — feuille de style
   ---------------------------------------------------------------------
   Conçue mobile d'abord : les règles de base visent un téléphone, les
   media queries n'élargissent que ce qui doit l'être. La palette est
   relevée directement sur les visuels fournis (bleu du logo, rouge et
   bleu des étoiles du fond).

   Sommaire
     1. Variables et bases
     2. Utilitaires (conteneur, boutons, accessibilité)
     3. Pop-up d'ouverture
     4. Contrôle audio
     5. Étoiles décoratives
     6. Section invitation (drapeau, vidéo, texte, calendrier)
     7. Section œuvres (images et vidéos)
     8. Pied de page
     9. Mouvement réduit
   ===================================================================== */


/* ------------------------------------------------------------------ *
   1. Variables et bases
 * ------------------------------------------------------------------ */

:root {
  /* Couleurs relevées sur logo-fazzino.png et background.jpg */
  --bleu:          #1B3080;
  --bleu-clair:    #3E63D8;
  --rouge:         #D02A2A;
  --rouge-clair:   #E1474A;
  --encre:         #12131A;
  --encre-douce:   #4B4D5E;   /* 7,3:1 sur blanc — conforme AA */
  --blanc:         #FFFFFF;
  --trait:         #E7E8EF;

  /* Gouttière latérale réservée aux étoiles : le contenu ne l'atteint
     jamais, les étoiles ne mordent jamais sur le texte. */
  --gouttiere:     clamp(30px, 8vw, 140px);
  --taille-etoile: clamp(8px, 2.2vw, 15px);

  --rayon:         6px;
  --souple:        cubic-bezier(.22, .61, .36, 1);
}

/* Les @font-face et les bases de body/html sont dans le CSS critique
   inliné dans index.html : ne pas les redéclarer ici. */

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

/* L'attribut hidden doit l'emporter sur les display: de cette feuille.
   Sans cette règle, le lecteur vidéo, le menu du calendrier et le bouton
   audio resteraient visibles alors qu'ils sont marqués hidden. */
[hidden] { display: none !important; }

a { color: var(--bleu); text-underline-offset: .18em; }
a:focus-visible,
button:focus-visible {
  outline: 3px solid var(--bleu-clair);
  outline-offset: 3px;
  border-radius: 4px;
}


/* ------------------------------------------------------------------ *
   2. Utilitaires
 * ------------------------------------------------------------------ */

.conteneur {
  width: 100%;
  max-width: 720px;
  margin-inline: auto;
}
/* La grille des œuvres peut respirer davantage que le texte. */
.conteneur--large { max-width: 1100px; }

/* Masqué visuellement, restitué par les lecteurs d'écran. */
.sr-uniquement {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.bouton {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 52px;
  padding: .95rem 2rem;
  border: 2px solid var(--bleu);
  border-radius: 999px;
  background: var(--blanc);
  color: var(--bleu);
  font: inherit;
  font-size: .875rem;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  transition: background-color .25s var(--souple), color .25s var(--souple);
}
.bouton:hover { background: var(--bleu); color: var(--blanc); }

.bouton--sombre { background: var(--bleu); color: var(--blanc); }
.bouton--sombre:hover { background: #16276A; color: var(--blanc); }


/* ------------------------------------------------------------------ *
   3. Pop-up d'ouverture
   Les règles de mise en page sont dans le CSS critique ; on ne trouve
   ici que l'état de sortie et la transition.
 * ------------------------------------------------------------------ */

.popup {
  transition:
    opacity   .72s var(--souple),
    transform .72s var(--souple),
    visibility 0s linear .72s;
}

/* État appliqué au clic : fondu + très légère montée et mise à l'échelle. */
.popup.est-fermee {
  opacity: 0;
  transform: scale(1.05) translateY(-2%);
  visibility: hidden;
  pointer-events: none;
}

.popup__bouton:hover { background: #16276A; }
.popup__bouton:active { transform: translateY(1px); }


/* ------------------------------------------------------------------ *
   4. Contrôle audio persistant
 * ------------------------------------------------------------------ */

.audio-bouton {
  position: fixed;
  top: max(14px, env(safe-area-inset-top));
  right: max(14px, env(safe-area-inset-right));
  z-index: 90;
  display: grid;
  place-items: center;
  width: 46px;                 /* zone tactile : 46 × 46 px */
  height: 46px;
  padding: 0;
  border: 1px solid var(--trait);
  border-radius: 50%;
  background: rgba(255, 255, 255, .92);
  color: var(--bleu);
  cursor: pointer;
  box-shadow: 0 3px 14px rgba(18, 19, 26, .14);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
}

.audio-bouton__icone {
  width: 23px; height: 23px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.9;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.audio-bouton__haut-parleur { fill: currentColor; stroke-width: 1.4; }

/* Par défaut le son est actif : ondes visibles, croix masquée.
   aria-pressed="true" signale l'état « coupé ». */
.audio-bouton__croix { opacity: 0; }
.audio-bouton[aria-pressed="true"] .audio-bouton__ondes { opacity: 0; }
.audio-bouton[aria-pressed="true"] .audio-bouton__croix { opacity: 1; }


/* ------------------------------------------------------------------ *
   5. Pluie d'étoiles
   Deux bandes fixes, larges comme la gouttière, dans lesquelles les
   étoiles tombent en boucle. Le décor ne passe jamais derrière le
   texte : aucun contraste n'est entamé, et rien n'est cliquable.

   Tout est en CSS : pas de boucle JavaScript, pas de canvas qui tourne
   en fond, donc pas de batterie consommée pour un décor.
 * ------------------------------------------------------------------ */

.pluie {
  position: fixed;
  inset: 0;
  /* Au-dessus du fond blanc des sections (2), mais sous le bouton audio
     (90), la pop-up (100) et la lightbox (200). Les bandes n'occupent
     que les gouttières : elles ne recouvrent jamais un contenu. */
  z-index: 3;
  pointer-events: none;
  overflow: hidden;
}

.pluie__bande {
  position: absolute;
  top: 0;
  bottom: 0;
  width: var(--gouttiere);
  overflow: hidden;
}
.pluie__bande--gauche { left: 0; }
.pluie__bande--droite { right: 0; }

.flocon {
  position: absolute;
  top: 0;
  /* Bornées pour rester dans la bande sur les petits écrans. */
  left: min(var(--x), calc(100% - var(--taille) - 2px));
  width: min(var(--taille), calc(var(--gouttiere) * .34));
  height: auto;
  opacity: 0;
  animation: chute var(--duree) linear var(--retard) infinite;
  will-change: transform, opacity;
}

@keyframes chute {
  0%   { transform: translate3d(0, -14vh, 0) rotate(0deg);                    opacity: 0; }
  12%  { opacity: .9; }
  88%  { opacity: .9; }
  100% { transform: translate3d(var(--derive), 114vh, 0) rotate(var(--tour)); opacity: 0; }
}

/* Le contenu passe devant la pluie. */
.section, .pied, .popup { position: relative; z-index: 2; }

/* Réserve la gouttière où tombent les étoiles, et empêche tout
   débordement horizontal. */
.section {
  padding-inline: var(--gouttiere);
  overflow: hidden;
  background: var(--blanc);
}


/* ------------------------------------------------------------------ *
   5 bis. Étincelles
   Gerbe d'étoiles projetée à la fermeture de la pop-up et à chaque
   œuvre révélée. Les éléments sont créés puis retirés par le script :
   rien ne subsiste dans le DOM.
 * ------------------------------------------------------------------ */

.etincelle {
  position: fixed;
  z-index: 150;
  pointer-events: none;
  animation: eclat var(--duree) cubic-bezier(.15, .75, .3, 1) forwards;
}

@keyframes eclat {
  0%   { transform: translate3d(0, 0, 0) scale(.25) rotate(0deg);                     opacity: 1; }
  70%  { opacity: 1; }
  100% { transform: translate3d(var(--dx), var(--dy), 0) scale(1) rotate(var(--tour)); opacity: 0; }
}


/* ------------------------------------------------------------------ *
   5 ter. Apparition au défilement
 * ------------------------------------------------------------------ */

.apparait {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity .75s var(--souple), transform .75s var(--souple);
}
.apparait.est-apparu { opacity: 1; transform: none; }

/* Les cartes de la grille portent déjà un décalage de composition : on
   n'anime donc que leur opacité, sinon l'un écraserait l'autre. */
.oeuvre.apparait { transform: none; transition: opacity .75s var(--souple); }

/* Décalage en cascade pour les éléments d'un même bloc. */
.apparait--2 { transition-delay: .1s; }
.apparait--3 { transition-delay: .2s; }
.apparait--4 { transition-delay: .3s; }


/* ------------------------------------------------------------------ *
   6. Section invitation
 * ------------------------------------------------------------------ */

.section--invitation { padding-block: clamp(1.5rem, 5vw, 2.75rem) clamp(2.5rem, 8vw, 4rem); }

.drapeau { display: block; }
.drapeau img {
  display: block;
  width: 100%;
  height: auto;
  /* Remonte le bandeau pour rogner le blanc situé au-dessus du drapeau.
     Valeur fixe : la part rognée varie donc avec la largeur d'écran
     (70 % à 320 px, 59 % à 375 px, 27 % à 1440 px). Pour un rognage
     identique partout, remplacer par un pourcentage — margin-top: -28%
     se réfère à la largeur du conteneur et reste proportionnel. */
  margin-top: -92px;
  border-radius: var(--rayon);
}

/* --- Bloc vidéo ---
   Miniature et vidéo superposées dans un cadre au format de la vidéo.
   La vidéo est transparente tant qu'elle n'affiche pas d'image, et le
   redevient une fois terminée : la miniature est ce que l'on voit avant
   et après, sans jamais de rectangle noir. */
.video {
  position: relative;
  aspect-ratio: 1006 / 561;
  margin-top: clamp(1.5rem, 5vw, 2.5rem);
  border-radius: var(--rayon);
  overflow: hidden;
  background: var(--blanc);
}

.video picture,
.video__miniature,
.video__lecteur {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
}
.video__miniature,
.video__lecteur { object-fit: cover; }

.video__lecteur {
  opacity: 0;
  transition: opacity .5s var(--souple);
  pointer-events: none;        /* rien à cliquer : ni pause, ni relance */
}
.video__lecteur.est-rendue { opacity: 1; }
.video__lecteur.est-terminee { opacity: 0; }


/* --- Texte de l'invitation --- */
.invitation {
  margin-top: clamp(2rem, 7vw, 3.25rem);
  text-align: center;
}

.invitation__titre {
  margin: 0;
  font-size: clamp(.9375rem, 3.9vw, 1.125rem);
  font-weight: 400;
  line-height: 1.65;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--encre);
  text-wrap: balance;
}

/* La date domine nettement le reste du bloc. */
.invitation__date {
  margin: clamp(1.5rem, 5vw, 2.25rem) 0 clamp(1.25rem, 4vw, 1.75rem);
  color: var(--bleu);
  font-weight: 700;
  line-height: 1.15;
}
.invitation__jour {
  display: block;
  font-size: clamp(1.5rem, 7.2vw, 2.5rem);
  letter-spacing: .015em;
  text-transform: uppercase;
}
.invitation__heures {
  display: block;
  margin-top: .35em;
  font-size: clamp(1.125rem, 5.2vw, 1.75rem);
  letter-spacing: .06em;
}

.invitation__details {
  margin: .35rem 0;
  font-size: clamp(.8125rem, 3.5vw, .9375rem);
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--encre-douce);
}

/* --- Ajout au calendrier --- */
.calendrier { position: relative; margin-top: clamp(2rem, 6vw, 2.75rem); }

.calendrier__menu {
  display: flex;
  flex-direction: column;
  gap: .5rem;
  width: min(100%, 320px);
  margin: .85rem auto 0;
  padding: .5rem;
  border: 1px solid var(--trait);
  border-radius: 12px;
  background: var(--blanc);
  box-shadow: 0 12px 34px rgba(18, 19, 26, .1);
}

.calendrier__option {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 46px;
  padding: .6rem 1rem;
  border-radius: 8px;
  color: var(--encre);
  font-size: .875rem;
  font-weight: 700;
  letter-spacing: .04em;
  text-decoration: none;
}
.calendrier__option:hover { background: #F3F4F9; }


/* ------------------------------------------------------------------ *
   7. Section œuvres
   Carte au format 4/5 avec l'œuvre en « contain » : la grille reste
   régulière alors que les formats vont du tondo au 41 × 71, et aucune
   sérigraphie n'est rognée.
 * ------------------------------------------------------------------ */

.section--oeuvres { padding-block: clamp(1rem, 3vw, 2rem) clamp(2.5rem, 8vw, 4.5rem); }

.grille {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(1.25rem, 4vw, 2rem);
  margin: 0;
  padding: 0;
  list-style: none;
}

@media (min-width: 480px) {
  .grille { grid-template-columns: repeat(2, 1fr); }
  /* Décalage vertical d'une carte sur deux : la grille cesse de
     s'aligner au cordeau et prend un rythme d'accrochage. */
  .grille .oeuvre:nth-child(even) { transform: translateY(clamp(14px, 4vw, 40px)); }
}
@media (min-width: 900px) {
  .grille { grid-template-columns: repeat(3, 1fr); }
  .grille .oeuvre:nth-child(even) { transform: none; }
  .grille .oeuvre:nth-child(3n + 2) { transform: translateY(clamp(20px, 3vw, 46px)); }
}

.oeuvre { margin: 0; }

.oeuvre__vignette {
  position: relative;      /* repère du voile à gratter */
  display: block;
  width: 100%;
  aspect-ratio: 4 / 5;
  padding: clamp(10px, 3%, 20px);
  border: 1px solid var(--trait);
  border-radius: var(--rayon);
  background: var(--blanc);
}
.oeuvre__vignette picture { display: block; width: 100%; height: 100%; }
.oeuvre__vignette img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

/* --- Cartes vidéo ---------------------------------------------------
   Un travelling sur l'œuvre remplace l'image fixe. La vidéo est en
   9/16 alors que la carte est en 4/5 : « cover » recadre en hauteur
   plutôt que de laisser deux bandes blanches. Comme le plan descend le
   long de la pièce, tout finit de toute façon par passer à l'écran.

   L'affiche et la vidéo sont superposées dans le cadre. L'affiche est
   toujours peinte la première ; la vidéo, transparente au départ, ne se
   révèle qu'une fois qu'elle produit réellement des images. C'est ce
   qui supprime l'écran noir : il n'existe plus aucun instant où l'on
   regarde autre chose qu'une image de l'œuvre.

   Le fond de la carte est blanc, jamais sombre : si quoi que ce soit
   transparaissait une fraction de seconde, ce serait le blanc de la
   page, pas un rectangle noir. */
.oeuvre__vignette--video {
  padding: 0;
  overflow: hidden;
  background: var(--blanc);
}

.oeuvre__affiche,
.oeuvre__video {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.oeuvre__video {
  opacity: 0;
  transition: opacity .5s var(--souple);
}
/* Posée par le script au premier rendu d'image, et jamais retirée : au
   retour en arrière, la carte montre l'arrêt sur image, sans clignoter. */
.oeuvre__video.est-rendue { opacity: 1; }

.oeuvre__titre {
  margin: .9rem 0 .25rem;
  font-size: .9375rem;
  font-weight: 700;
  line-height: 1.4;
  color: var(--encre);
  text-wrap: balance;
}
.oeuvre__legende {
  margin: 0;
  font-size: .8125rem;
  color: var(--encre-douce);
}


/* ------------------------------------------------------------------ *
   7 bis. Œuvres à gratter
   Deux œuvres — les images — arrivent sous un voile que l'on efface du
   doigt. Le voile est un <canvas> posé par le script : sans JavaScript,
   aucune de ces règles ne s'applique et l'œuvre est visible d'emblée.
   Les vidéos ne sont pas concernées.
 * ------------------------------------------------------------------ */

/* Tant que le canvas n'est pas posé, un aplat couvre l'œuvre : on ne
   doit jamais l'entrevoir avant le voile. Actif seulement quand le
   script a confirmé qu'il prenait la main (body.a-voiles). */
body.a-voiles [data-gratter]:not([data-revele])::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  border-radius: var(--rayon);
  background: #1B3080;
}

[data-gratter]:not([data-revele]) { cursor: crosshair; }
[data-gratter]:focus-visible { outline: 3px solid var(--bleu-clair); outline-offset: 3px; }

.oeuvre__voile {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: block;
  width: 100%;
  height: 100%;
  border-radius: var(--rayon);
  touch-action: none;          /* le geste est capté, pas interprété en défilement */
  transition: opacity .55s var(--souple), transform .55s var(--souple);
}
.oeuvre__voile.est-dissipe {
  opacity: 0;
  transform: scale(1.04);
}

/* Balayage lumineux montrant le geste attendu, sur la première carte
   seulement, et jusqu'au premier grattage. */
.oeuvre__indice {
  position: absolute;
  inset: 0;
  z-index: 3;
  overflow: hidden;
  border-radius: var(--rayon);
  pointer-events: none;
}
.oeuvre__indice::after {
  content: "";
  position: absolute;
  top: 50%;
  left: -34%;
  width: 44%;
  height: 74px;
  transform: translateY(-50%);
  border-radius: 999px;
  background: radial-gradient(closest-side, rgba(255, 255, 255, .6), transparent);
  animation: balayage 2.8s ease-in-out infinite;
}
@keyframes balayage {
  0%   { left: -34%; opacity: 0; }
  18%  { opacity: 1; }
  82%  { opacity: 1; }
  100% { left: 90%;  opacity: 0; }
}


/* ------------------------------------------------------------------ *
   8. Pied de page
 * ------------------------------------------------------------------ */

.pied {
  padding: clamp(2.5rem, 8vw, 4rem) var(--gouttiere) calc(clamp(2.5rem, 8vw, 4rem) + env(safe-area-inset-bottom));
  border-top: 1px solid var(--trait);
  background: var(--blanc);
  text-align: center;
}

.pied__logo { width: 240px; height: auto; margin-bottom: 1.5rem; }

.pied__adresse,
.pied__horaires {
  margin: 0 auto .85rem;
  max-width: 46ch;
  font-size: .875rem;
  font-style: normal;
  /* Interligne généreux : les liens tel:/mailto: portent une zone
     tactile de 44 px, il faut la place pour qu'ils ne se chevauchent pas. */
  line-height: 2.3;
  color: var(--encre-douce);
}

/* Zone tactile confortable sur les liens tel: et mailto:, sans casser
   le flux du texte. Le :not(.bouton) est indispensable : sans lui, cette
   règle repeindrait le bouton « Itinéraire » en bleu sur bleu. */
.pied a:not(.bouton) {
  display: inline-block;
  padding: .6rem .25rem;      /* porte la hauteur tactile à 44 px */
  color: var(--bleu);
  font-weight: 700;
  text-decoration: none;
  border-bottom: 1px solid rgba(27, 48, 128, .3);
}
.pied a:not(.bouton):hover { border-bottom-color: var(--bleu); }

.pied .bouton { margin-top: 1.25rem; }


/* ------------------------------------------------------------------ *
   9. Mouvement réduit
   Toutes les animations se réduisent à un fondu, conformément au
   réglage système de l'utilisateur.
 * ------------------------------------------------------------------ */

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

  /* La pluie et les étincelles sont purement décoratives : on les
     retire plutôt que de les figer dans une position arbitraire. */
  .pluie, .etincelle, .oeuvre__indice { display: none !important; }

  /* Les apparitions au défilement se contentent d'être là. */
  .apparait { opacity: 1; transform: none; transition: none; }

  .popup {
    transition: opacity .3s linear, visibility 0s linear .3s;
  }
  .popup.est-fermee { transform: none; }
  .bouton, .video__lecteur, .oeuvre__video { transition: none; }
}
