@charset "UTF-8";
/* ==========================================================================
   charte.css — la charte graphique du site. À charger EN DERNIER.

   Ce fichier n'est pas un document : c'est la source de vérité. Il fait deux
   choses.

   1. Il NOMME les valeurs du site en variables CSS. Aujourd'hui, common-wood.css
      contient 42 fois « #241c16 » en dur ; le jour où l'on voudra bouger le brun,
      c'est ici qu'il faudra le faire, une fois. Les nouveaux styles doivent
      utiliser var(--…) et jamais un hexadécimal en dur.

   2. Il CORRIGE trois défauts de la palette héritée, mesurés et non devinés.
      Voir la section « corrections » plus bas.

   La page charte.html montre tout ça à l'écran.
   ========================================================================== */

:root {
  /* ---------------------------------------------------------------- COULEURS
     Le bois, du plus sombre au plus clair. Les noms disent la matière, pas
     l'usage — un nom d'usage (« primaire ») ne survit pas à un changement d'avis. */
  --braise:   #1a120c;   /* le plus sombre : fonds pleins, pied de page      */
  --ecorce:   #241c16;   /* LE brun du site : texte courant, fonds sombres   */
  --terre:    #3a2a1e;   /* brun moyen : survols sur sombre                  */
  --tan:      #5c3f27;   /* brun chaud                                       */
  --cuivre:   #8a5a2b;   /* les liens. Le seul accent lisible sur clair      */
  --laiton:   #c8a268;   /* l'accent DÉCORATIF. Jamais de texte sur clair    */
  --sable:    #e8cdb6;   /* clair chaud : le menu, sur fond sombre           */
  --cendre:   #796c5e;   /* texte secondaire (corrigé, voir plus bas)        */
  --trait:    #9a8c7d;   /* bordures et filets. PAS du texte                 */
  --lin:      #ded5c8;   /* filets clairs                                    */
  --parchemin:#ece5da;   /* fond alterné                                     */
  --papier:   #f5f1ea;   /* LE fond du site                                  */
  --blanc:    #ffffff;   /* les cartes posées sur le papier                  */
  --alerte:   #b2432a;   /* erreurs (corrigé, voir plus bas)                 */

  /* ------------------------------------------------------------ TYPOGRAPHIE
     Deux familles, deux rôles, aucune exception.
       — le serif porte les titres et les noms d'œuvres : il a du grain ;
       — le sans porte tout ce qui se lit vraiment : il disparaît. */
  --serif: "Noto Serif JP", "Yu Mincho", serif;
  --sans:  "Noto Sans JP", sans-serif;

  /* TROISIÈME FAMILLE — et donc une exception à la règle ci-dessus. Elle est
     assumée, mais elle est BORNÉE : elle ne sert qu'à une chose, la légende
     manuscrite au bas des tirages Polaroïd des fiches d'œuvre. Nulle part
     ailleurs. Un titre, un intertitre, un bouton écrits avec ne seraient pas
     une variante : ce serait une deuxième direction artistique.
     Caveat n'a pas de vrai italique — l'inclinaison est synthétisée par le
     navigateur, ce qui suffit pour une écriture à la main. */
  --main:  "Caveat", cursive;

  /* L'échelle est plate — 1.5 / 1.43 / 1.13 / 1 rem. Elle vient du gabarit
     d'origine et elle est VOULUE : dans une galerie, c'est l'image qui crie,
     pas le titre. Ce qui hiérarchise ici, c'est l'espace et l'interlettrage,
     pas la taille. */
  --t-h1: 1.5rem;
  --t-h2: 1.43rem;
  --t-h3: 1.13rem;
  --t-h4: 1rem;
  --t-corps: 1rem;
  --t-petit: .8571rem;
  --interligne: 1.5;

  /* L'interlettrage EST la hiérarchie. Un titre respire, un texte non. */
  --espacement-titre: 4px;
  --espacement-sur:   2.24px;   /* les sur-titres, en capitales */
  --espacement-corps: .8px;

  /* ------------------------------------------------------------------ RYTHME
     Une seule suite, partout : 8 · 16 · 24 · 40 · 56 · 88. Chaque valeur est
     la somme des deux précédentes — la marge d'une section ne se choisit plus,
     elle se prend dans la liste. */
  --e1: 8px;
  --e2: 16px;
  --e3: 24px;
  --e4: 40px;
  --e5: 56px;
  --e6: 88px;

  /* ------------------------------------------------------------------ FORMES
     Aucun arrondi. Une gouge fait des arêtes vives, pas des coins ronds.
     Seule exception : l'ascenseur, où le rond est fonctionnel. */
  --rayon: 0;
  --rayon-ascenseur: 999px;

  /* Les ombres sont chaudes, jamais grises : une ombre grise sur du bois
     ressemble à une erreur d'impression. */
  --ombre-carte:   6px 6px 24px rgba(36, 28, 22, .10);
  --ombre-flottant: 8px 8px 40px rgba(36, 28, 22, .16);

  /* --------------------------------------------------------------- MOUVEMENT
     Deux courbes, deux vitesses. Rien d'autre.
       — « vif » pour ce qui répond au doigt : survols, boutons ;
       — « ample » pour ce qui se révèle : apparitions, logo, rideau.
     Tout est neutralisé sous prefers-reduced-motion. */
  --vif:   .4s cubic-bezier(.5, .06, .11, .99);
  --ample: 1.1s cubic-bezier(.22, .61, .36, 1);

  /* ---------------------------------------------------------------- COUCHES
     Une échelle nommée. On n'écrit plus jamais « z-index: 9999 ». */
  --z-fond: 1;
  --z-carte: 10;
  --z-entete: 100;
  --z-menu: 200;
  --z-modale: 300;
  --z-rideau: 400;
}


/* ==========================================================================
   CORRECTIONS — trois défauts de la palette héritée.

   Ils ne se voyaient pas à l'œil. Ils se sont vus au calcul du contraste, et
   c'est pour ça qu'ils étaient encore là.
   ========================================================================== */

/* 1. LE ROUGE ÉTRANGER.
      #fe4521 est un reste du gabarit japonais d'origine : ma substitution de
      palette l'avait manqué. C'est un rouge d'interface, sans rapport avec le
      bois — et il ne donne que 3,45:1 sur blanc, alors qu'il porte les MESSAGES
      D'ERREUR, l'endroit où la lisibilité compte le plus.
      Remplacé par une terre de Sienne brûlée : elle reste dans la famille du
      bois, et elle passe. Mesuré : 5,00:1 sur papier, 5,63:1 sur blanc. */
.c-form-item__error-msg,
.u-fc-red {
  color: var(--alerte) !important;
}

/* 2. LE GRIS TROP CLAIR.
      #9a8c7d donne 2,90:1 sur le papier : illisible pour du texte courant.
      Il est employé 14 fois, mais DOUZE de ces usages sont des bordures de
      tableaux — un filet n'est pas du texte, 2,9:1 y convient. Seuls les deux
      usages en `color:` sont corrigés. Même teinte, même saturation, simplement
      assombrie jusqu'à passer le seuil. Mesuré : 4,53:1 sur papier. */
.c-meta__type,
.c-form-item__field {
  color: var(--cendre);
}

/* 3. LE LAITON N'EST PAS UNE COULEUR DE TEXTE.
      #c8a268 sur le papier : 2,11:1. Sur le brun sombre : 7,04:1.
      Il est donc réservé au décor et aux fonds sombres. Cette règle ne peut pas
      être « appliquée » par du CSS — elle se tient, ou elle se viole. Elle est
      écrite ici pour qu'on ne puisse pas dire qu'on ne savait pas. */


/* ==========================================================================
   HÉROS — carrousel d'accueil.
   ========================================================================== */

/* Les points de pagination étaient alignés à droite, hérités du gabarit
   d'origine : `text-align: right` sur mobile, `justify-content: flex-end`
   au-delà de 768px. Ils sont ramenés au centre.

   Le sélecteur reprend `.swiper-container-horizontal > …` pour égaler la
   spécificité de la règle d'origine (0,2,0) — charte.css étant chargée en
   dernier, elle l'emporte. Les paddings latéraux sont symétriques (4 % puis
   48px), le centrage est donc juste sans avoir à les neutraliser. */
.swiper-container-horizontal > .c-hero-slider__pagenation {
  text-align: center;
}

@media screen and (min-width: 768px) {
  .swiper-container-horizontal > .c-hero-slider__pagenation {
    justify-content: center;
  }
}

/* Les points avaient été remontés à 64/104px pour éviter le chevron de
   défilement, qui était centré au même endroit. Le chevron a été retiré : le
   conflit n'existe plus, et les points reprennent la hauteur du gabarit
   (32px, 48px au-delà de 768px). Une règle de contournement qui survit à ce
   qu'elle contournait est une règle qu'on ne comprend plus six mois après.

   --- Les points inactifs ---
   Ils étaient en brun sombre (#3a2a1e) à 60 % d'opacité : sur une photo claire
   ils disparaissaient, et l'on ne voyait plus que le point actif — donc plus
   aucun moyen de savoir combien d'images comptait le carrousel.

   Ils restent des points PLEINS, simplement passés au blanc à demi-opacité :
   même famille que le point actif, juste en retrait. L'ombre portée fait le
   reste du travail sur les fonds clairs. (Un premier essai en anneaux vides à
   filet blanc distinguait bien mais faisait tache : deux formes différentes
   dans une même rangée, ça se remarque plus que ça ne renseigne.) */
.c-hero-slider__pagenation .swiper-pagination-bullet {
  background: #fff;
  opacity: .5;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .45);
}

.c-hero-slider__pagenation .swiper-pagination-bullet-active {
  background: #fff;
  opacity: 1;
}

/* Le halo du gabarit est un disque brun à 20 % : invisible sur une photo, et
   il double le point actif qui se distingue déjà par son remplissage. */
.c-hero-slider__pagenation .swiper-pagination-bullet-active::after {
  display: none;
}

/* --------------------------------------------------------------------------
   EN-TÊTE : LES TROIS ÉLÉMENTS SUR UNE MÊME LIGNE
   --------------------------------------------------------------------------
   Le logo et le sélecteur de langue sont ancrés en `top: 0` et prennent leur
   hauteur de leur propre marge intérieure : 56 px sur téléphone, 106 px
   au-delà de 768 px. Leur milieu tombe donc à 28 puis 53 px du haut.

   Le bouton de menu, lui, était posé autrement : `top: 22px` et une boîte de
   46 px, soit un milieu à 45 px. Il descendait de 17 px sous les deux autres
   sur téléphone, et remontait de 8 px au-dessus sur grand écran.

   Il adopte ici la même construction : ancré en haut, dimensionné comme le
   logo, et son icône centrée dedans. Les trois milieux se rejoignent.

   L'icône elle-même n'est pas agrandie sur grand écran : ses trois traits sont
   positionnés au pixel (0, 6 et 12 px) et l'animation en croix déplace de 6 px
   exactement. La redimensionner casserait la croix. Seule la zone cliquable
   grandit, ce qui est de toute façon la partie qui compte pour le doigt.
   -------------------------------------------------------------------------- */
.c-burger {
  top: 0;
  left: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
}

@media screen and (min-width: 768px) {
  .c-burger {
    width: 106px;
    height: 106px;
  }
}

/* Le sélecteur de langue tirait sa hauteur de sa marge intérieure (16 px sur
   téléphone, 48 au-delà) plus la hauteur du texte : 54 px puis 115 px, donc un
   milieu 5 px sous celui du logo sur grand écran. L'écart était petit mais il
   se voyait, les trois éléments étant sur la même ligne.

   Il reçoit donc la hauteur du logo, et ses deux liens s'y centrent en
   occupant toute la hauteur : la zone cliquable ne rétrécit pas, elle est même
   plus régulière qu'avec la marge d'origine. */
.c-global-nav-trigger-lang {
  height: 56px;
  align-items: center;
}

.c-global-nav-trigger-lang .c-global-nav-trigger-lang__target {
  display: flex;
  align-items: center;
  height: 100%;
  min-height: 0;
  padding-top: 0;
  padding-bottom: 0;
}

@media screen and (min-width: 768px) {
  .c-global-nav-trigger-lang {
    height: 106px;
  }
}

/* --------------------------------------------------------------------------
   BULLE DE CONTACT — raccourci permanent vers le formulaire
   --------------------------------------------------------------------------
   Un rond fixe en bas à droite, présent sur toutes les pages sauf celle du
   contact, où il n'aurait rien à ouvrir.

   Sa place dans l'empilement est choisie pour qu'il s'efface tout seul quand
   autre chose s'ouvre : au-dessus du contenu, mais SOUS le voile du menu (290),
   le tiroir (300), le logo (350), les fiches (500) et la visionneuse (600). On
   n'a donc rien à masquer à la main — ni au clic sur le menu, ni à l'ouverture
   d'une œuvre.

   L'infobulle est écrite en CSS plutôt qu'avec l'attribut `title` : celui-ci
   n'apparaît qu'après une seconde d'attente, et jamais au clavier.
   -------------------------------------------------------------------------- */
/* LE LAITON, et non le brun de l'encre. La bulle traverse deux fonds très
   différents au fil du défilement : le hero, sombre, et le papier crème des
   sections. Un rond brun se fondait dans le premier ; un rond crème aurait
   disparu dans le second.

   Le laiton est le seul ton de la charte qui tranche sur les deux — il est
   plus clair que le hero et plus soutenu que le papier — et c'est déjà
   l'accent du site (curseur, filet de champ actif, méta des fiches). L'icône
   passe donc en brun foncé, à l'inverse. */
.c-bulle-contact {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 260;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 54px;
  height: 54px;
  color: #241c16;
  background: #c8a268;
  border-radius: 50%;
  box-shadow: 0 10px 28px rgba(21, 14, 8, .45);
  text-decoration: none;
  transition: transform .35s cubic-bezier(.22, .61, .36, 1),
              background .35s ease, box-shadow .35s ease;
}

@media screen and (min-width: 768px) {
  .c-bulle-contact {
    right: 32px;
    bottom: 32px;
    width: 62px;
    height: 62px;
  }
}

.c-bulle-contact::before {
  font-size: 1.25rem;             /* la pastille @ de la police d'icônes */
  line-height: 1;
}

.c-bulle-contact:hover,
.c-bulle-contact:focus-visible {
  background: #d8b47c;            /* le laiton s'éclaire, il ne s'assombrit pas */
  transform: translateY(-3px);
  box-shadow: 0 16px 34px rgba(21, 14, 8, .52);
}

/* Le libellé sort du rond au survol. `visibility` en plus de l'opacité : sans
   elle, l'étiquette resterait cliquable et déclencherait l'infobulle en
   passant à côté du bouton. */
.c-bulle-contact__texte {
  position: absolute;
  right: calc(100% + 12px);
  padding: 7px 13px;
  font-size: .82rem;
  letter-spacing: 1px;
  text-transform: uppercase;
  white-space: nowrap;
  color: #f5f1ea;
  background: #241c16;
  border-radius: 4px;
  opacity: 0;
  visibility: hidden;
  transform: translateX(6px);
  transition: opacity .3s ease, transform .3s ease, visibility .3s;
}

.c-bulle-contact:hover .c-bulle-contact__texte,
.c-bulle-contact:focus-visible .c-bulle-contact__texte {
  opacity: 1;
  visibility: visible;
  transform: translateX(0);
}

@media (prefers-reduced-motion: reduce) {
  .c-bulle-contact,
  .c-bulle-contact__texte {
    transition: none;
  }

  .c-bulle-contact:hover,
  .c-bulle-contact:focus-visible {
    transform: none;
  }
}

/* --------------------------------------------------------------------------
   ANCRES — le titre visé ne doit pas passer sous les éléments fixes
   --------------------------------------------------------------------------
   Un lien d'ancre amène le BORD HAUT de la section au sommet de la fenêtre. Or
   le sommet est occupé en permanence par le logo, le bouton de menu, le
   sélecteur de langue et la bande de flou : le titre de la section arrivait
   dessous, donc caché.

   La grande marge haute de `.c-section` (96 px, 232 px au-delà de 768 px) n'y
   changeait rien : une marge est à l'EXTÉRIEUR de la boîte, le défilement la
   laisse au-dessus de l'écran.

   `scroll-margin-top` est fait pour ça — il ne déplace pas l'élément, il
   décale seulement l'endroit où le défilement s'arrête. Il vaut aussi bien
   pour `scrollIntoView` (les clics dans la page, via initSmoothScroll) que
   pour une arrivée directe sur une adresse avec ancre, du genre
   index.html#expos depuis une autre page.

   Les valeurs partent de la hauteur réellement occupée — ~106 px pour le logo
   au-delà de 768 px, 110 px pour la bande de flou — puis ajoutent de l'air :
   dégager le titre ne suffit pas, il doit RESPIRER sous le bord de l'écran,
   sans quoi la section a l'air d'avoir été coupée.

   C'est le seul réglage à toucher si l'arrivée paraît trop haute ou trop
   basse. Deux valeurs, une par palier de largeur.
   -------------------------------------------------------------------------- */
section[id],
header[id],
main[id] {
  scroll-margin-top: 124px;
}

@media screen and (min-width: 768px) {
  section[id],
  header[id],
  main[id] {
    scroll-margin-top: 184px;
  }
}

/* --------------------------------------------------------------------------
   L'ICÔNE DE CONTACT : UNE ENVELOPPE, PLUS UN ARROBASE
   --------------------------------------------------------------------------
   Les icônes du site ne viennent pas d'une police mais de silhouettes SVG
   posées en masque (voir icon.css). Il suffit donc de redéfinir le dessin de
   `myfont-atmark` pour que TOUS ses emplois changent d'un coup : la bulle en
   bas de page, le bouton d'envoi, les liens Contact des menus et des pieds de
   page. Aucun HTML à modifier, et rien à oublier.

   Le nom de la classe reste `atmark`, qui ne veut plus dire grand-chose. Le
   renommer aurait obligé à retoucher les quatre pages pour un gain nul.

   Le tracé reprend les conventions des autres icônes : cadre de 24, contour
   seul, épaisseur 1,6, angles arrondis.
   -------------------------------------------------------------------------- */
.myfont-atmark::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='2.8' y='5.4' width='18.4' height='13.2' rx='1.8'/%3E%3Cpath d='m3.7 7 8.3 6.1L20.3 7'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='2.8' y='5.4' width='18.4' height='13.2' rx='1.8'/%3E%3Cpath d='m3.7 7 8.3 6.1L20.3 7'/%3E%3C/svg%3E");
}

/* --------------------------------------------------------------------------
   PAGE CONTACT — texte d'accueil et formulaire
   --------------------------------------------------------------------------
   Le gabarit d'origine n'avait aucun formulaire : tout est écrit ici, en
   reprenant les valeurs déjà nommées plus haut plutôt que de réinventer une
   palette pour trois champs.

   Deux colonnes au-delà de 900 px — quelques phrases à gauche, les champs à
   droite — et un simple empilement en dessous. Le texte passe en premier dans
   les deux cas : on explique ce qu'on attend avant de demander de le taper.
   -------------------------------------------------------------------------- */

/* Trois blocs : le texte, le formulaire, la photo.

   Sur téléphone, ils s'empilent dans cet ordre : on lit pourquoi écrire, on
   écrit, et la photo vient après. Placée avant le formulaire, elle aurait
   repoussé les champs sous l'écran.

   Sur grand écran, deux colonnes : le texte puis la photo à gauche, le
   formulaire à droite sur toute la hauteur. */
.m-contact {
  display: flex;
  flex-direction: column;
  gap: 40px;
}

.m-contact__aside { order: 1; }
.m-form           { order: 2; }
.m-contact__photo { order: 3; }

@media screen and (min-width: 900px) {
  .m-contact {
    display: grid;
    grid-template-columns: minmax(0, 4fr) minmax(0, 6fr);
    column-gap: 64px;
    row-gap: 32px;
    align-items: start;
  }

  .m-contact__aside { grid-column: 1; grid-row: 1; }
  .m-contact__photo { grid-column: 1; grid-row: 2; }
  .m-form           { grid-column: 2; grid-row: 1 / span 2; }
}

.m-contact__lead {
  font-size: 1.05rem;
  line-height: 1.9;
  color: var(--encre, #241c16);
}

.m-contact__note {
  margin-top: 20px;
  font-size: .93rem;
  color: rgba(36, 28, 22, .62);
}

/* La photo de Florence, sous le texte d'accueil. Même ombre portée que les
   vignettes de la grille, pour qu'elle appartienne à la même famille d'images
   que le reste du site. */
.m-contact__photo {
  margin: 32px 0 0;
}

.m-contact__photo img {
  display: block;
  width: 100%;
  height: auto;
  box-shadow: 6px 6px 32px rgba(21, 30, 66, .16);
}


/* --- Les champs ----------------------------------------------------------- */

.m-form__champ + .m-form__champ {
  margin-top: 26px;
}

.m-form__label {
  display: block;
  margin-bottom: 8px;
  font-size: .84rem;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: rgba(36, 28, 22, .72);
}

/* Un filet sous le champ plutôt qu'une boîte fermée : la page est faite de
   papier et de traits, pas de composants d'interface. Le fond reste celui du
   papier — `transparent` hériterait du blanc des navigateurs sur certains
   remplissages automatiques. */
.m-form__saisie {
  display: block;
  width: 100%;
  padding: 10px 2px;
  font-family: inherit;
  font-size: 1rem;
  color: #241c16;
  background: rgba(255, 255, 255, .35);
  border: 0;
  border-bottom: 1px solid rgba(36, 28, 22, .28);
  border-radius: 0;              /* iOS arrondit les champs par défaut */
  transition: border-color .3s ease, background .3s ease;
}

.m-form__saisie:focus {
  outline: none;
  border-bottom-color: #c8a268;  /* le laiton, comme le reste des accents */
  background: rgba(255, 255, 255, .6);
}

/* Le focus visible au clavier doit rester perceptible même là où le filet
   change à peine : on double d'un liseré. */
.m-form__saisie:focus-visible {
  box-shadow: 0 2px 0 0 #c8a268;
}

.m-form__zone {
  resize: vertical;
  min-height: 150px;
  line-height: 1.7;
}

/* --- Erreurs et issue ----------------------------------------------------- */

/* Le rouge est celui de la charte, corrigé plus haut pour le contraste : pas
   un rouge d'alerte système. */
.m-form__erreur {
  margin-top: 8px;
  font-size: .88rem;
  color: #a8321f;
}

.m-form__saisie[aria-invalid="true"] {
  border-bottom-color: #a8321f;
}

/* Le piège à robots. Il doit être invisible SANS être `display: none` ni
   `hidden` : les automates un peu sérieux ignorent les champs ainsi masqués,
   et le piège ne prendrait plus rien. On le sort donc de l'écran. */
.m-form__piege {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.m-form__envoi {
  margin-top: 32px;
  justify-content: flex-start;
}

/* Pendant l'envoi : le bouton ne répond plus, et ça se voit. */
.m-form.is-envoi .c-button {
  opacity: .55;
  pointer-events: none;
}

.m-form__issue {
  margin-top: 18px;
  font-size: .93rem;
  line-height: 1.7;
  color: rgba(36, 28, 22, .78);
}

.m-form__issue:empty {
  margin-top: 0;
}

.m-form__issue.is-erreur {
  color: #a8321f;
}

/* --------------------------------------------------------------------------
   FLOU PROGRESSIF EN HAUT DE PAGE
   --------------------------------------------------------------------------
   Une bande fixe en haut de l'écran, sous laquelle le contenu défile et se
   trouble. Elle décolle le logo, le sélecteur de langue et le bouton de menu
   de ce qui passe derrière, sans poser de barre opaque : le fond reste lisible,
   simplement estompé.

   POURQUOI DEUX COUCHES. Une seule bande floutée puis effacée en dégradé donne
   un résultat trouble : on voit l'image nette ET son double flou l'un sur
   l'autre là où le masque est à demi transparent. En empilant deux couches de
   rayons différents, chacune éteinte plus tôt que la précédente, le flou
   s'atténue par paliers assez rapprochés pour se lire comme un continu.

   Le conteneur ne porte ni filtre ni masque : il ne fait que placer les deux
   couches. Un `backdrop-filter` sur un parent masqué se comporte mal, les
   couches doivent donc être sœurs.

   La couche du dessus voit le résultat de celle du dessous : les rayons
   s'additionnent vers le haut de la bande, ce qui accentue encore la
   progression sans avoir à monter les valeurs.

   `pointer-events: none` : la bande couvre le haut de la page, il ne faut pas
   qu'elle intercepte les clics du menu ou du logo qui sont dessous.
   -------------------------------------------------------------------------- */
.c-flou-haut {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 80px;
  /* Sous le logo (350), le sélecteur de langue (351) et le menu (320),
     au-dessus du contenu de la page. */
  z-index: 280;
  pointer-events: none;
}

@media screen and (min-width: 768px) {
  .c-flou-haut {
    height: 110px;
  }
}

.c-flou-haut::before,
.c-flou-haut::after {
  content: "";
  position: absolute;
  inset: 0;
}

/* Couche basse : flou très léger, éteint dès le départ et sur toute la bande.
   C'est elle qui fait la longueur du dégradé. */
.c-flou-haut::before {
  -webkit-backdrop-filter: blur(1.5px);
  backdrop-filter: blur(1.5px);
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 18%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 0%, #000 18%, transparent 100%);
}

/* Couche haute : à peine plus marquée, et éteinte tôt. Elle ne se voit que dans
   le bandeau où se trouvent le logo et les menus. */
.c-flou-haut::after {
  -webkit-backdrop-filter: blur(5px);
  backdrop-filter: blur(5px);
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, transparent 48%);
  mask-image: linear-gradient(to bottom, #000 0%, transparent 48%);
}

/* Là où `backdrop-filter` manque, la bande ne fait rien du tout — pas de
   rectangle gris à la place. Mieux vaut l'absence de l'effet que son fantôme. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .c-flou-haut {
    display: none;
  }
}

/* --------------------------------------------------------------------------
   LOGO PENDANT LE CHARGEMENT — pas de survol sur le rideau
   --------------------------------------------------------------------------
   Le logo affiché sur l'écran de chargement n'est pas un second logo : c'est
   celui du header, que main.js agrandit et déplace au centre du rideau le temps
   de l'animation d'entrée (classe `.is-entering`, transformation posée en
   `style` inline).

   Ses deux effets de survol continuaient de s'appliquer là-dessus :
     - `.c-site-logo:hover` posait le disque brun, qui apparaissait en grand
       derrière la marque ;
     - `.c-site-logo:hover .c-site-logo__img` déclenchait la rotation de 180°,
       qui écrasait la rotation d'entrée écrite en inline par le JS — la marque
       sautait sous le curseur.

   Pendant l'entrée, le logo n'est donc plus une cible : ni survol, ni clic. Il
   redevient interactif dès que main.js retire `.is-entering`, à la fin de
   l'animation.
   -------------------------------------------------------------------------- */
.c-site-logo.is-entering {
  pointer-events: none;
}

.c-site-logo.is-entering:hover {
  background-color: transparent;
}

.c-site-logo.is-entering:hover .c-site-logo__img {
  transform: none;
}

/* --------------------------------------------------------------------------
   FICHES D'EXPOSITION — image à gauche, texte à droite
   --------------------------------------------------------------------------
   Les fiches d'exposition adoptent la mise en page à deux colonnes des fiches
   d'œuvre, mais en miroir : une œuvre se lit d'abord par son cartel, une
   exposition d'abord par son lieu.

   Le gabarit met le texte en première colonne ; `order` renvoie donc l'image
   à gauche, sans toucher à l'ordre du HTML — où le texte reste après l'image
   pour les lecteurs d'écran comme pour l'affichage empilé sur téléphone.

   Les proportions sont aussi inversées : l'image prend la colonne large. Une
   présentation d'exposition est plus courte qu'un cartel d'œuvre, et ce sont
   les vues de l'accrochage qui portent la fiche.
   -------------------------------------------------------------------------- */
@media screen and (min-width: 900px) {
  .m-modal__layout.is-expo {
    grid-template-columns: minmax(0, 6fr) minmax(0, 5fr);
  }

  .m-modal__layout.is-expo .m-modal__col-media { order: -1; }
  .m-modal__layout.is-expo .m-modal__col-text  { order: 0; }
}

/* --------------------------------------------------------------------------
   TIRAGES DES FICHES — le cadre suit la photo, plus de bandes de remplissage
   --------------------------------------------------------------------------
   Le gabarit imposait un format au cadre de l'image : 3/4 pour une pièce en
   hauteur, 4/3 pour une pièce en largeur, avec `object-fit: contain` et un fond
   braise pour combler. Tant que toutes les photos d'une même fiche partageaient
   ce format, ça ne se voyait pas.

   Les photos réelles ne le partagent pas. Une fiche mêle une vue d'ensemble
   verticale et un détail horizontal (la lampe), ou deux vues en largeur de
   proportions différentes (le brasier) : la photo qui ne tombait pas juste
   flottait entre deux bandes marron, dans la marge blanche du tirage.

   Le format imposé est donc retiré. Chaque photo garde ses proportions et le
   tirage se dimensionne sur elle : aucun remplissage, donc aucune bande. Le
   carrousel ne s'effondre pas pour autant — ses slides sont empilées en grille
   (voir swiper-lite.css), et une grille prend la taille de son plus grand
   enfant. Les tirages de la pile ont simplement des hauteurs différentes, ce
   qui est le propre d'un paquet de photos de formats différents.

   Conséquence utile : le champ `format` de js/photos.js n'a plus d'effet sur
   les fiches. Il est conservé pour mémoire, il ne nuit pas.
   -------------------------------------------------------------------------- */
.m-modal__col-media .m-modal-gallery .swiper-slide img,
.m-modal__col-media .m-modal-gallery.is-landscape .swiper-slide img,
.m-modal-gallery.is-expo .swiper-slide img {
  aspect-ratio: auto;
  width: 100%;
  height: auto;
  object-fit: fill;               /* sans objet : le cadre épouse déjà la photo */
  background: none;
}

/* Même principe pour la vue unique. `width: auto` est indispensable : avec
   `width: 100%` et une hauteur plafonnée par `max-height`, une photo très
   verticale se retrouvait écrasée — d'où le `contain` d'origine, et ses bandes.
   En laissant les deux dimensions libres sous leurs plafonds, le navigateur
   conserve les proportions tout seul. */
.m-modal__pic img {
  width: auto;
  height: auto;
  max-width: 100%;
  margin: 0 auto;
  object-fit: fill;
  background: none;
}

/* Et le cadre se serre sur la photo au lieu de tenir toute la colonne. Sans
   ça, une pièce très verticale — dont la hauteur bute sur `max-height` — était
   posée au milieu d'un tirage bien plus large qu'elle : deux marges crème sur
   les côtés, en plus de la marge basse du Polaroïd. */
.m-modal__pic {
  width: fit-content;
  max-width: 100%;
  margin-left: auto;
  margin-right: auto;
}

/* Les slides du carrousel sont des éléments de grille empilés dans une seule
   cellule (voir swiper-lite.css). Deux choses les faisaient prendre la hauteur
   de la plus grande photo du paquet, au lieu de la leur :

     - une cellule de grille ÉTIRE ses enfants par défaut ;
     - et surtout `.swiper-slide { height: 100% }`, hérité du gabarit du
       carrousel, où toutes les images ont le même format. Dans une grille, ce
       100 % se calcule sur la hauteur de la cellule — donc sur la plus grande
       carte. Une hauteur explicite l'emporte sur l'alignement : sans la
       remettre à `auto`, `align-items` ne pouvait rien.

   Les deux ensemble rendent à chaque tirage la hauteur de sa propre photo. La
   règle ne touche que l'effet « cartes » : le carrousel du hero, où le 100 %
   est nécessaire, garde son comportement.

   `center` et non `start` : les tirages n'ont plus la même hauteur, et calés
   en haut de la pile, les plus courts laissaient un vide sous eux — le paquet
   penchait. Centrés, ils tournent autour d'un même axe, comme des photos
   posées les unes sur les autres. */
.swiper-effect-cards .swiper-wrapper {
  align-items: center;
}

.swiper-effect-cards .swiper-slide {
  height: auto;
}

/* --------------------------------------------------------------------------
   RIEN NE SORT DU TIRAGE, ET LE TIRAGE TIENT DANS LA FENÊTRE
   --------------------------------------------------------------------------
   Deux garanties, parce que le plafond de hauteur du gabarit ne portait que sur
   la PHOTO :

   1. `max-height` était posé sur l'image seule, sans compter les 16 px de blanc
      du haut ni les 68 px de marge basse du Polaroïd. Une pièce très verticale
      remplissait donc 82 % de la fenêtre, puis le cadre ajoutait ses 84 px
      par-dessus : le bas du tirage — le nom écrit à la main — passait sous le
      bord de l'écran. Le plafond porte maintenant sur le tirage entier.

   2. `overflow: hidden` sur le cadre : quoi qu'il arrive, une photo ne peut pas
      sortir de son tirage. C'est une ceinture en plus des bretelles — utile là
      où `fit-content` n'est pas connu (Safari ancien), cas où le cadre
      reprendrait toute la colonne.

   Les cartes du carrousel reçoivent le même traitement, et se serrent elles
   aussi sur leur photo. Elles n'ont plus la largeur de la cellule, donc
   `justify-self` les recentre.
   -------------------------------------------------------------------------- */

.m-modal__pic,
.swiper-effect-cards .swiper-slide {
  overflow: hidden;
}

.swiper-effect-cards .swiper-slide {
  width: fit-content;
  max-width: 100%;
  justify-self: center;
}

/* 84 px = 16 de blanc en haut + 68 de marge basse, le cadre au-delà de 768 px.
   En dessous, le cadre est plus fin (12 + 52 = 64) mais on garde la même marge
   de sécurité : mieux vaut un tirage un peu plus petit que tronqué. */
.m-modal__pic img,
.m-modal-gallery .swiper-slide img {
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: calc(56vh - 84px);
}

/* NOTE — un fondu des bords de la photo a été essayé ici pour adoucir la
   jonction avec le cadre : masque en dégradé, 26 px éteints sur les quatre
   côtés. À écarter. Sur ces clichés, le fond studio occupe une large part de
   l'image ; le dissoudre sur une bande aussi épaisse délave la photo entière
   et la fait passer pour floue. La jonction se traite du côté du CADRE, pas de
   la photo. */

@media screen and (min-width: 900px) {
  .m-modal__col-media .m-modal__pic img,
  .m-modal__col-media .m-modal-gallery .swiper-slide img {
    max-height: calc(82vh - 84px);
  }
}

/* --------------------------------------------------------------------------
   VOIR UNE PHOTO EN GRAND — visionneuse plein écran
   --------------------------------------------------------------------------
   Portée par js/zoom.js. Un clic sur une photo de fiche l'ouvre ici, seule sur
   fond noir : ni cadre, ni cartel, ni marge. C'est le seul endroit du site où
   une pièce se regarde sans mise en scène autour.

   Le z-index passe au-dessus de la modale des fiches (500) : la visionneuse
   s'ouvre PAR-DESSUS la fiche, qui reste en place derrière. La fermer y
   ramène, sans avoir perdu la lecture en cours.
   -------------------------------------------------------------------------- */

/* L'icône, posée dans le coin haut droit du tirage par js/zoom.js. En haut et
   non en bas : la marge basse du Polaroïd porte déjà le nom de la pièce, écrit
   à la main, et les puces du carrousel. Le coin haut est le seul angle libre.

   Discrète au repos — un rond sombre translucide sur la photo — et franche au
   survol. Elle ne s'efface jamais complètement : une commande qui n'apparaît
   qu'au survol n'existe pas sur un écran tactile. */
.m-zoom-trigger {
  position: absolute;
  top: 22px;
  right: 22px;
  z-index: 3;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  color: #f5f1ea;
  background: rgba(20, 14, 9, .45);
  cursor: pointer;
  transition: background .3s ease, transform .3s ease;
}

.m-zoom-trigger:hover,
.m-zoom-trigger:focus-visible {
  background: rgba(20, 14, 9, .85);
  transform: scale(1.08);
}

@media screen and (min-width: 768px) {
  .m-zoom-trigger {
    top: 26px;
    right: 26px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .m-zoom-trigger {
    transition: none;
  }
}

.m-zoom {
  position: fixed;
  inset: 0;
  z-index: 600;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2vmin;
  background: #0b0806;
  cursor: zoom-out;
  opacity: 0;
  /* Tant qu'elle n'est pas ouverte, elle ne prend aucun clic. C'est ce qui
     couvre les 260 ms du fondu de sortie : `hidden` n'est reposé qu'à la fin de
     la transition, et sans ça l'écran resterait un obstacle transparent pendant
     tout ce temps. */
  pointer-events: none;
  transition: opacity .26s ease;
}

/* INDISPENSABLE, et facile à oublier : l'attribut `hidden` ne pose qu'un
   `display: none` de feuille utilisateur, que le `display: flex` ci-dessus
   écrase. Sans cette règle, fermer la visionneuse la rend transparente mais la
   laisse en place par-dessus toute la page — elle continue d'avaler les clics,
   et le site paraît figé. La modale des fiches a la même règle, pour la même
   raison (voir `.m-modal[hidden]` dans components.css). */
.m-zoom[hidden] {
  display: none;
}

.m-zoom.is-open {
  opacity: 1;
  pointer-events: auto;
}

/* `contain` et non `cover` : on vient là pour voir la pièce entière. Le curseur
   par défaut sur la photo, puisque cliquer dessus ne ferme pas. */
.m-zoom__img {
  display: block;
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
  cursor: default;
}

/* Croix reprise du modèle de celle des fiches, en plus discret : ici il n'y a
   rien d'autre à l'écran, elle n'a pas besoin d'insister. */
.m-zoom__close {
  position: absolute;
  top: 16px;
  right: 16px;
  width: 44px;
  height: 44px;
  border: 0;
  border-radius: 50%;
  background: rgba(245, 241, 234, .1);
  cursor: pointer;
  transition: background .3s ease;
}

.m-zoom__close:hover {
  background: rgba(245, 241, 234, .22);
}

.m-zoom__close::before,
.m-zoom__close::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 18px;
  height: 1px;
  background: #f5f1ea;
}

.m-zoom__close::before { transform: translate(-50%, -50%) rotate(45deg); }
.m-zoom__close::after  { transform: translate(-50%, -50%) rotate(-45deg); }

@media screen and (min-width: 768px) {
  .m-zoom__close {
    top: 28px;
    right: 28px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .m-zoom {
    transition: none;
  }
}

