/*
 * site.css — feuille unique du site public.
 *
 * Parti pris : fond clair, très peu d'éléments, aucune image en pleine page.
 * Ce qui doit rester en tête après la visite, ce sont les photographies et les
 * titres de séries — tout le reste se tient en retrait.
 *
 * Les accents gardent la logique du cadre plomb de la note d'intention : le
 * rubedo signale l'image courante et rien d'autre, l'or la pièce unique.
 */

:root {
  /* Fonds — un blanc très légèrement chaud, pas un blanc d'écran */
  --fond:      #faf9f7;
  --fond-2:    #f2f0ec;
  --filet:     #e2dfda;

  /* Encre */
  --encre:     #16161a;   /* texte principal */
  --plomb:     #6b6e75;   /* texte secondaire, cartels */
  --plomb-pale:#9a9ca1;   /* désactivé */

  /* Accents — usage strictement réglé */
  --rubedo:    #9c4a2f;   /* image courante, focus */
  --or:        #8a6a2f;   /* la pièce unique uniquement */

  /* Type */
  --display: 'Bodoni Moda', 'Didot', 'Times New Roman', serif;
  --lecture: 'Spectral', Georgia, serif;
  --cartel:  'IBM Plex Mono', ui-monospace, 'SFMono-Regular', monospace;

  --t-xs:   0.6875rem;
  --t-sm:   0.8125rem;
  --t-base: 1rem;
  --t-lg:   1.1875rem;
  --t-xl:   clamp(1.5rem, 2.6vw, 2.25rem);
  --t-2xl:  clamp(2.25rem, 5vw, 4rem);

  --gouttiere: clamp(1.25rem, 5vw, 4.5rem);
  --bande:     clamp(3.5rem, 9vh, 7rem);
  --mesure:    72rem;

  --transition: 360ms cubic-bezier(0.22, 0.61, 0.36, 1);
}

*, *::before, *::after { box-sizing: border-box; }

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

body {
  margin: 0;
  background: var(--fond);
  color: var(--encre);
  font-family: var(--lecture);
  font-size: var(--t-base);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }

:focus-visible { outline: 2px solid var(--rubedo); outline-offset: 3px; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/*
 * L'apparition — la seule animation de l'accueil.
 *
 * Un bloc monte d'un cheveu en arrivant à l'écran, lentement, une fois. La
 * classe `apparait` est posée par le script : sans JavaScript, rien n'est
 * jamais caché. La règle globale de `prefers-reduced-motion` ramène la durée à
 * zéro, et le script n'observe même pas dans ce cas.
 */
.apparait {
  opacity: 0;
  transform: translateY(1.25rem);
  transition: opacity 1100ms ease, transform 1100ms cubic-bezier(0.22, 0.61, 0.36, 1);
  transition-delay: var(--retard, 0ms);
}
.apparait.est-la { opacity: 1; transform: none; }

.evitement {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--encre);
  color: var(--fond);
  padding: 0.75rem 1rem;
  z-index: 100;
}
.evitement:focus { left: 0; }

/* ------------------------------------------------------------------ */
/* Registres typographiques                                            */
/* ------------------------------------------------------------------ */

.display {
  font-family: var(--display);
  font-weight: 400;
  font-optical-sizing: auto;
  letter-spacing: -0.012em;
  line-height: 1.08;
  text-wrap: balance;
  margin: 0;
}

/* Le registre du cartel de musée : capitales espacées, chiffres alignés. */
.cartel {
  font-family: var(--cartel);
  font-size: var(--t-xs);
  letter-spacing: 0.15em;
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
  color: var(--plomb);
}

.lecture {
  max-width: 62ch;
  font-size: var(--t-lg);
  line-height: 1.75;
  color: #3a3a40;
}
.lecture p { margin: 0 0 1.4em; }
.lecture em { color: var(--encre); font-style: italic; }

/* ------------------------------------------------------------------ */
/* En-tête                                                             */
/* ------------------------------------------------------------------ */

.entete {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1.5rem;
  flex-wrap: wrap;
  max-width: var(--mesure);
  margin: 0 auto;
  padding: 1.6rem var(--gouttiere);
}

.entete__nom {
  font-family: var(--display);
  font-size: var(--t-base);
  letter-spacing: 0.01em;
}

/* `auto` à gauche : sur l'accueil, où le nom n'est pas répété dans l'en-tête,
   la navigation reste à sa place plutôt que de glisser au bord opposé. */
.entete__nav { display: flex; gap: clamp(1rem, 3vw, 2.25rem); margin-left: auto; }

.entete__lien {
  font-family: var(--cartel);
  font-size: var(--t-xs);
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--plomb);
  padding-bottom: 2px;
  border-bottom: 1px solid transparent;
  transition: color var(--transition), border-color var(--transition);
}
.entete__lien:hover { color: var(--encre); }
.entete__lien[aria-current='page'] {
  color: var(--encre);
  border-bottom-color: var(--rubedo);
}

/* ================================================================== */
/* ACCUEIL                                                             */
/* ================================================================== */

.accueil {
  max-width: var(--mesure);
  margin: 0 auto;
  padding: 0 var(--gouttiere) var(--bande);
}

/* --- Ouverture : le nom. Rien d'autre. ----------------------------- */

/*
 * Le nom occupe l'ouverture comme un titre de couverture, et il n'est écrit
 * qu'une fois sur la page. Ni sous-titre, ni phrase de présentation : sur le
 * site d'un photographe, ce sont les photographies qui disent le travail.
 *
 * Le bas de la réserve est calculé pour que le haut de la première
 * photographie affleure la ligne de flottaison sur un écran ordinaire : ce
 * n'est pas un hasard de valeur, c'est ce qui donne envie de descendre.
 */
.ouverture { padding: clamp(2.5rem, 11vh, 7rem) 0 clamp(3rem, 12vh, 7.5rem); }

/*
 * Le nom respire : deux mots empilés (`max-width: 8ch` force la coupure), un
 * interligne ouvert, et un crénage à peine resserré. Un nom court peut se
 * permettre d'être grand ET aéré — c'est ce qui le fait lire comme une
 * signature plutôt que comme un titre.
 */
.ouverture__titre {
  font-size: clamp(3rem, 11vw, 9.5rem);
  line-height: 1.02;
  letter-spacing: -0.02em;
  max-width: 8ch;
}

/*
 * Les deux photographies mises en avant.
 *
 * Hauteur bornée en `vh` ET en `rem` : une image ne doit jamais occuper
 * l'écran entier, même sur un très grand moniteur. C'est la demande, et c'est
 * aussi ce qui laisse les titres de séries exister sur la même page.
 */
/*
 * Douze colonnes, et une composition de double page : la première photographie
 * prend sept colonnes, la seconde quatre et descend d'un cran. Deux images de
 * même taille sur une même ligne se neutralisent — l'œil ne sait pas par où
 * commencer. Ici il entre par la grande, puis descend vers la seconde : c'est
 * la lecture d'un magazine, et c'est ce qui fait tenir la page.
 */
.avant {
  display: grid;
  gap: clamp(1.75rem, 4vw, 3rem);
  grid-template-columns: repeat(12, minmax(0, 1fr));
  margin-bottom: clamp(3.5rem, 11vh, 7rem);
}
/* Sans cette règle, une accueil sans photographie mise en avant gardait la
   section affichée et sa marge de 7 rem : un grand blanc sous le nom. Une règle
   d'auteur bat la feuille du navigateur — cf. CLAUDE.md § pièges. */
.avant[hidden] { display: none; }

.avant__piece { display: block; grid-column: 1 / -1; }

@media (min-width: 48rem) {
  .avant--deux .avant__piece--majeure { grid-column: 1 / span 7; }
  .avant--deux .avant__piece--mineure {
    grid-column: 9 / span 4;
    /* La seconde est posée plus bas : la rupture d'alignement fait la page. */
    margin-top: clamp(3rem, 12vh, 8rem);
  }
  .avant--une .avant__piece--majeure { grid-column: 1 / span 9; }
}

.avant__cadre {
  background: var(--fond-2);
  overflow: hidden;
}

.avant__cadre img,
.avant__cadre canvas {
  width: 100%;
  height: auto;
  /* Borné en `vh` ET en `rem` : une photographie ne prend jamais tout l'écran,
     même sur un très grand moniteur. C'est le parti du site. */
  max-height: min(62vh, 36rem);
  object-fit: contain;
  transition: opacity var(--transition);
}
@media (hover: hover) {
  .avant__piece:hover .avant__cadre img { opacity: 0.9; }
}

/* La seconde est la voix basse de la double page : elle ne rivalise pas. */
.avant__piece--mineure .avant__cadre img,
.avant__piece--mineure .avant__cadre canvas { max-height: min(42vh, 24rem); }

/* Une seule mise en avant : on la borne pour qu'elle ne domine pas la page. */
.avant--une .avant__cadre img,
.avant--une .avant__cadre canvas { max-height: min(58vh, 34rem); }

/* Le nom de la série d'abord, à la taille d'un titre : c'est ce que le lien
   ouvre. Le titre de l'œuvre suit, au registre du cartel. */
.avant__cartel {
  display: grid;
  gap: 0.4rem;
  justify-items: start;
  margin: 1rem 0 0;
}

.avant__serie {
  font-family: var(--display);
  font-size: clamp(1.15rem, 1.7vw, 1.6rem);
  line-height: 1.15;
  color: var(--encre);
  transition: color var(--transition);
}
@media (hover: hover) {
  .avant__piece:hover .avant__serie { color: var(--rubedo); }
}

.avant__oeuvre { color: var(--plomb); }

/* La seconde photographie parle plus bas : son cartel aussi. */
.avant__piece--mineure .avant__serie { font-size: clamp(1rem, 1.3vw, 1.25rem); }

/* --- Les séries : le titre d'abord, la vignette à côté ------------- */

.series { display: grid; }

.serie-ligne {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1rem;
  align-items: center;
  padding: clamp(1.5rem, 4vh, 2.5rem) 0;
  border-top: 1px solid var(--filet);
}
.serie-ligne:last-child { border-bottom: 1px solid var(--filet); }

@media (min-width: 42rem) {
  .serie-ligne {
    grid-template-columns: 1fr 12rem;
    gap: clamp(1.5rem, 4vw, 3rem);
  }
}

.serie-ligne__texte { min-width: 0; }

/* Les titres de séries portent la page autant que les photographies : à cette
   taille, la liste se lit comme un sommaire, pas comme un menu. */
.serie-ligne__titre {
  font-size: clamp(1.75rem, 3.4vw, 3rem);
  transition: color var(--transition);
}
@media (hover: hover) {
  .serie-ligne:hover .serie-ligne__titre { color: var(--rubedo); }
}

.serie-ligne__reperes { margin: 0.5rem 0 0; }

.serie-ligne__accroche {
  margin: 0.6rem 0 0;
  max-width: 52ch;
  color: var(--plomb);
  font-size: var(--t-base);
}

/* Vignette modeste : elle annonce la série, elle ne la remplace pas. */
.serie-ligne__vignette {
  order: -1;
  aspect-ratio: 4 / 3;
  background: var(--fond-2);
  overflow: hidden;
}
@media (min-width: 42rem) {
  .serie-ligne__vignette { order: 0; aspect-ratio: 3 / 2; }
}

.serie-ligne__vignette img,
.serie-ligne__vignette canvas {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 700ms cubic-bezier(0.22, 0.61, 0.36, 1);
}
.serie-ligne:hover .serie-ligne__vignette img { transform: scale(1.03); }

/* Le geste attendu, écrit. Une ligne entière est cliquable, mais rien ne le dit
   à qui ne survole pas — et le premier public de ce site regarde vite. */
.serie-ligne__entrer {
  margin: 0.9rem 0 0;
  color: var(--plomb-pale);
  transition: color var(--transition);
}
.serie-ligne__entrer::after { content: ' →'; }
.serie-ligne:hover .serie-ligne__entrer,
.serie-ligne:focus-visible .serie-ligne__entrer { color: var(--rubedo); }

.serie-ligne--vide .serie-ligne__titre { color: var(--plomb-pale); }
.serie-ligne--vide .serie-ligne__vignette { opacity: 0.4; }

/* ------------------------------------------------------------------ */
/* Pages de texte                                                      */
/* ------------------------------------------------------------------ */

.page {
  max-width: var(--mesure);
  margin: 0 auto;
  padding: clamp(2rem, 6vh, 4rem) var(--gouttiere) var(--bande);
}

.page__titre {
  font-size: var(--t-2xl);
  margin-bottom: clamp(2rem, 6vh, 3.5rem);
  max-width: 14ch;
}

.page__grille {
  display: grid;
  gap: clamp(1rem, 4vw, 3rem);
  grid-template-columns: 1fr;
}
/* Une règle d'auteur bat la feuille du navigateur : sans ceci, `hidden` sur une
   section de contact resterait sans effet. Cf. CLAUDE.md § pièges. */
.page__grille[hidden] { display: none; }
@media (min-width: 56rem) {
  .page__grille { grid-template-columns: 14rem 1fr; }
}

.page__section + .page__section { margin-top: clamp(2.5rem, 7vh, 4rem); }

.page__soustitre {
  font-family: var(--cartel);
  font-size: var(--t-xs);
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--plomb);
  margin: 0;
  padding-top: 0.55rem;
  border-top: 1px solid var(--filet);
}

.liste-nue { list-style: none; margin: 0; padding: 0; }

/* minmax(0, 1fr) et non 1fr : le minimum `auto` d'une colonne vaut son contenu
   le plus long, et pousse la page hors de l'écran d'un téléphone. */
.def {
  display: grid;
  grid-template-columns: minmax(8rem, 12rem) minmax(0, 1fr);
  gap: 0.4rem 1.5rem;
  margin: 0;
}
.def dt {
  font-family: var(--cartel);
  font-size: var(--t-xs);
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--plomb);
  padding-top: 0.35em;
}
.def dd { margin: 0; color: #3a3a40; }

.lien-souligne {
  border-bottom: 1px solid var(--plomb-pale);
  transition: border-color var(--transition), color var(--transition);
}
.lien-souligne:hover { border-color: var(--rubedo); color: var(--rubedo); }

.a-faire {
  border-left: 2px solid var(--rubedo);
  padding: 0.75rem 0 0.75rem 1.25rem;
  color: var(--plomb);
  font-family: var(--cartel);
  font-size: var(--t-sm);
  letter-spacing: 0.03em;
  line-height: 1.6;
}

/* ------------------------------------------------------------------ */
/* Pied de page                                                        */
/* ------------------------------------------------------------------ */

.pied {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 2rem;
  justify-content: space-between;
  max-width: var(--mesure);
  margin: 0 auto;
  padding: 1.75rem var(--gouttiere) 2.5rem;
  border-top: 1px solid var(--filet);
}

/* ================================================================== */
/* VISIONNEUSE                                                         */
/* ================================================================== */

/*
 * Deux rangées : l'en-tête de série DANS le flux, puis la scène. L'en-tête ne
 * peut donc jamais recouvrir l'image — le voile sur le haut des œuvres était
 * un défaut constaté en production, pas une hypothèse.
 */
.visionneuse {
  height: 100svh;
  display: grid;
  grid-template-rows: auto 1fr;
  overflow: hidden;
}

.scene {
  position: relative;
  min-height: 0;
  margin: 0;
  display: grid;
  /* rangée 1 : le mur — rangée 2 : le cartel. Aucun recouvrement possible. */
  grid-template-rows: 1fr auto;
  gap: 1.25rem;
  padding: 0.75rem clamp(2rem, 7vw, 6rem) 1.5rem;
  /* Le glissement horizontal appartient au mur ; le défilement vertical de la
     page reste au navigateur. */
  touch-action: pan-y;
}

/* ------------------------------------------------------------------ */
/* La cimaise : le mur, les œuvres, les cadres plomb                    */
/* ------------------------------------------------------------------ */

/*
 * Le voile clippe le mur et porte la perspective : les inclinaisons des
 * œuvres (parallaxe, traversée) prennent leur profondeur ici.
 */
.scene__voile {
  min-height: 0;
  height: 100%;
  overflow: hidden;
  position: relative;
  perspective: 1600px;
}

.mur {
  display: flex;
  height: 100%;
  transition: transform 700ms cubic-bezier(0.22, 0.61, 0.36, 1);
}
/* Pendant que le doigt tient le mur, il suit sans inertie. */
.mur.est-tenu { transition: none; }

/*
 * La traversée : au glissement, le mur respire légèrement — rien de plus. Le
 * flou de pose longue a été retiré : l'écho était joli en principe, mais il
 * brouillait la photographie au moment précis où on la découvre, et une œuvre
 * ne doit jamais être moins nette que le tirage.
 *
 * L'animation reste, et son NOM aussi : le JS retire `est-en-mouvement`,
 * `va-droite` et `va-gauche` sur son `animationend`. Sans elle, l'inclinaison
 * resterait figée de travers pour toujours.
 */
.mur.est-en-mouvement {
  animation: traversee 700ms cubic-bezier(0.22, 0.61, 0.36, 1);
  will-change: transform;
}
@keyframes traversee {
  0%   { opacity: 1; }
  45%  { opacity: 0.92; }
  100% { opacity: 1; }
}

/* L'œuvre s'incline légèrement dans le sens du passage, comme quand on la
   dépasse en marchant. Retour à plat en fin de course. */
.mur.va-droite .oeuvre__accroche { --ry: 2.2deg; }
.mur.va-gauche .oeuvre__accroche { --ry: -2.2deg; }

/* Tout ce que porte le mur occupe un écran plein, œuvre ou texte de salle. */
.creneau {
  flex: 0 0 100%;
  min-width: 0;
}

.oeuvre {
  position: relative;
  display: grid;
  place-items: center;
  /* Conteneur de taille : le cadre se mesure en cqw/cqh, ce qui évite toute
     chaîne de pourcentages fragile (piège déjà payé). */
  container-type: size;
  padding: 0.5rem 0 1.25rem; /* place pour l'ombre portée */
}

.oeuvre__accroche {
  transform: rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg));
  transition: transform 700ms cubic-bezier(0.22, 0.61, 0.36, 1);
  transform-style: preserve-3d;
}

/*
 * L'emplacement de l'œuvre.
 *
 * PAS DE CADRE : ni bande, ni fond, ni ombre portée. Le tirage est posé nu sur
 * le mur, et c'est l'échelle et le blanc autour qui font l'accrochage. Le site
 * d'origine dessinait un encadrement en plomb ; il n'a rien à voir avec ce
 * travail-ci, et tout cadre inventé se serait mis entre le visiteur et l'image.
 *
 * L'élément reste : il porte le rapport (--ratio), posé par serie.js au
 * chargement, qui réserve la place exacte du tirage avant qu'il n'arrive.
 */
.oeuvre__cadre {
  --ratio: 1.5;
  aspect-ratio: var(--ratio);
  width: min(90cqw, calc(86cqh * var(--ratio)));
  box-sizing: border-box;
  position: relative;
}

.oeuvre__image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  opacity: 0;
  transition: opacity 480ms ease;
}
.oeuvre__image.est-visible { opacity: 1; }

/* L'entrée en scène : la salle s'allume sur l'œuvre d'arrivée. Sans flou, là
   encore — l'image arrive nette, elle se lève seulement. */
.oeuvre--nait .oeuvre__accroche {
  animation: lever-de-salle 650ms cubic-bezier(0.22, 0.61, 0.36, 1) both;
}
@keyframes lever-de-salle {
  from { opacity: 0; transform: translateY(10px); }
}

.mur__vide {
  align-self: center;
  margin: 0 auto;
  text-align: center;
  line-height: 2;
}

/* --- Le seuil et la fin : les deux textes de salle ------------------ */

/*
 * Une exposition a une entrée et une sortie. Le seuil dit en cinq lignes ce
 * qu'est la série et propose d'y entrer ; la fin dit ce qu'on vient de voir et
 * ce qu'on peut en faire. Aucun des deux ne barre le passage : une flèche suffit
 * à les dépasser, et un lien profond ne les rencontre jamais.
 *
 * `safe center` n'est pas un raffinement : sur un écran court, un centrage
 * ordinaire ferait sortir le haut du texte de la boîte, sans moyen d'y revenir.
 */
.panneau {
  display: flex;
  flex-direction: column;
  justify-content: center;
  justify-content: safe center;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 0.5rem 0 1rem;
}

.panneau__corps { width: 100%; max-width: 46rem; }

.panneau__sur { margin: 0; }

.panneau__titre {
  font-size: clamp(1.9rem, 4.4vw, 3.1rem);
  max-width: 20ch;
  margin: 0.7rem 0 0;
}

.panneau__effectif { margin: 0.9rem 0 0; }

.panneau__phrase {
  margin: 1.1rem 0 0;
  max-width: 48ch;
  font-size: var(--t-lg);
  line-height: 1.7;
  color: #3a3a40;
}

.panneau__actions {
  margin-top: clamp(1.5rem, 4.5vh, 2.75rem);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem 1.5rem;
}

/* La fin ne repart pas d'elle-même : c'est la différence entre une exposition
   qu'on quitte et un carrousel qui recommence. */
.panneau--fin .panneau__titre { font-size: clamp(1.6rem, 3.4vw, 2.4rem); }

/* --- Les commandes de texte : un verbe, rien de plus ---------------- */

.action {
  font-family: var(--cartel);
  font-size: var(--t-xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--plomb);
  background: none;
  border: 0;
  border-bottom: 1px solid var(--filet);
  padding: 0.45rem 0 0.35rem;
  cursor: pointer;
  transition: color var(--transition), border-color var(--transition),
              background-color var(--transition);
}
.action:hover { color: var(--encre); border-bottom-color: var(--plomb-pale); }

/* Une seule action forte par panneau : celle qu'on attend du visiteur. */
.action--fort {
  color: var(--encre);
  border: 1px solid var(--encre);
  padding: 0.7rem 1.15rem;
}
.action--fort:hover { color: var(--fond); background: var(--encre); }

/*
 * L'effacement : après quelques secondes sans geste, tout fond sauf l'œuvre.
 * En opacité seule — la mise en page ne bouge pas, l'image ne saute pas.
 * Sur <body> parce que l'en-tête de série est hors de la visionneuse.
 */
body.est-calme .entete-serie,
body.est-calme .scene__pied {
  opacity: 0;
  transition: opacity 900ms ease;
}

.scene__pied {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 2rem;
  min-height: 3.5rem;
}

/*
 * Au seuil, le titre est déjà écrit en grand sur le mur : l'en-tête ne le répète
 * pas. Il s'efface en opacité seule — la rangée garde sa hauteur, donc l'image
 * de la première œuvre ne saute pas quand on entre.
 */
body.est-au-seuil .entete-serie__identite {
  opacity: 0;
  transition: opacity var(--transition);
}

/* --- Le pavé de flèches : les touches du clavier, cliquables -------- */

.pave {
  display: grid;
  grid-template-columns: repeat(3, auto);
  gap: 0.35rem;
  justify-items: center;
  flex: 0 0 auto;
  /* Le pavé reste à droite même quand le cartel disparaît (seuil, fin) : une
     commande qui change de place à chaque écran ne se retient pas. */
  margin-left: auto;
}
/* Une règle d'auteur bat la feuille du navigateur : sans cette ligne, `hidden`
   ne masque rien et une série vide gardait ses flèches (piège déjà payé sur
   .portail et .console, retrouvé ici au banc d'essai). */
.pave[hidden] { display: none; }
/* T inversé, comme sur le clavier : ↑ au centre de la rangée haute. */
.pave__touche--haut { grid-column: 2; }

/* 2,9 rem, soit 46 px : au-dessus de la cible tactile de 44 px, et assez grande
   pour se voir sans se faire remarquer — c'est la seule commande de la salle. */
.pave__touche {
  font-family: var(--cartel);
  font-size: var(--t-base);
  line-height: 1;
  width: 2.9rem;
  height: 2.9rem;
  display: grid;
  place-items: center;
  background: var(--fond);
  border: 1px solid var(--filet);
  border-bottom-width: 2px;   /* l'épaisseur d'une touche */
  border-radius: 4px;
  color: var(--plomb);
  cursor: pointer;
  transition: color var(--transition), border-color var(--transition),
              transform 120ms ease;
}
.pave__touche:hover:not(:disabled) { color: var(--encre); border-color: var(--plomb-pale); }
.pave__touche:active:not(:disabled) { transform: translateY(1px); border-bottom-width: 1px; }
.pave__touche:disabled { opacity: 0.3; cursor: default; }

/* --- Cartel -------------------------------------------------------- */

.cartel-oeuvre {
  max-width: 38rem;
  margin: 0;
  display: grid;
  gap: 0.35rem;
  transition: opacity var(--transition);
}
.cartel-oeuvre[hidden] { display: none; }

.compteur { font-variant-numeric: tabular-nums; }
.compteur b { font-weight: 400; color: var(--encre); }

.cartel-oeuvre__titre {
  font-family: var(--display);
  font-size: var(--t-lg);
  line-height: 1.2;
  margin: 0;
}
.cartel-oeuvre__titre:empty { display: none; }

.cartel-oeuvre__ligne { display: flex; flex-wrap: wrap; gap: 0.35rem 1.1rem; }

.cartel-oeuvre__note {
  font-size: var(--t-sm);
  color: var(--plomb);
  margin: 0;
  max-width: 46ch;
}

/* Le procédé, en toutes lettres. La pastille de couleur qui l'accompagnait
   désignait la matière du cadre : sans cadre, elle ne disait plus rien. */
.etat { display: inline-flex; align-items: center; }

.unique { color: var(--or); }

/* --- Boutons utilitaires (partagés avec le back office) ------------ */

.bouton {
  font-family: var(--cartel);
  font-size: var(--t-xs);
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--plomb);
  background: transparent;
  border: 1px solid var(--filet);
  padding: 0.45rem 0.8rem;
  cursor: pointer;
  transition: color var(--transition), border-color var(--transition);
}
.bouton:hover { color: var(--encre); border-color: var(--plomb-pale); }
.bouton[aria-pressed='true'] { color: var(--encre); border-color: var(--rubedo); }

kbd {
  font-family: var(--cartel);
  font-size: var(--t-xs);
  border: 1px solid var(--filet);
  padding: 0.15rem 0.4rem;
  color: var(--plomb);
}

/* --- Bandeau de tête de série -------------------------------------- */

/* Dans le flux de la grille, jamais par-dessus l'image. */
.entete-serie {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.4rem 1.5rem;
  padding: 1.4rem var(--gouttiere) 0.9rem;
  transition: opacity var(--transition);
}

.entete-serie__identite { min-width: 0; }
.entete-serie__titre { font-family: var(--display); font-size: var(--t-base); margin: 0; }
.entete-serie__reperes { margin: 0.3rem 0 0; }

.entete-serie__liens {
  display: flex;
  align-items: baseline;
  gap: clamp(0.9rem, 2.5vw, 2rem);
}

/* Le même registre que les liens de navigation, sur un bouton. */
button.entete__lien {
  background: none;
  border: 0;
  border-bottom: 1px solid transparent;
  cursor: pointer;
}

/* --- L'étage : la page de détail de l'œuvre ------------------------ */

/*
 * Panneau plein écran qui se lève au-dessus de tout (↑ pour l'ouvrir,
 * ↓, Échap ou la croix pour en revenir). L'image y est seule et centrée,
 * bornée par le viewport : elle ne peut être rognée par rien.
 */
.etage {
  position: fixed;
  inset: 0;
  z-index: 80;
  background: var(--fond);
  transform: translateY(100%);
  transition: transform 520ms cubic-bezier(0.22, 0.61, 0.36, 1);
}
.etage[hidden] { display: none; }
.etage.est-leve { transform: translateY(0); }

.etage__scene {
  height: 100%;
  margin: 0;
  display: grid;
  grid-template-rows: 1fr auto;
  gap: 1rem;
  padding: clamp(2.5rem, 6vh, 4rem) var(--gouttiere) 1.5rem;
}

.etage__image {
  min-height: 0;
  position: relative;
}
/* `inset: 0` + `contain` : le motif prouvé — un max-height en pourcentage
   dans une rangée 1fr retombe en `auto` et laisse déborder (piège payé). */
.etage__image img,
.etage__image canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.etage__cartel { max-width: 48rem; }

.etage__croix {
  position: absolute;
  top: 1rem;
  right: var(--gouttiere);
  z-index: 1;
  width: 2.4rem;
  height: 2.4rem;
  display: grid;
  place-items: center;
  font-family: var(--cartel);
  font-size: var(--t-base);
  background: var(--fond);
  border: 1px solid var(--filet);
  border-radius: 50%;
  color: var(--plomb);
  cursor: pointer;
  transition: color var(--transition), border-color var(--transition);
}
.etage__croix:hover { color: var(--encre); border-color: var(--plomb-pale); }

/* --- La vue professionnelle ---------------------------------------- */

/*
 * Elle ne remplace pas la galerie, elle répond à une autre question : un
 * galeriste veut embrasser la série d'un regard et lire les données de chaque
 * pièce. D'où la planche-contact — le geste du métier — et pas une grille de
 * produits : pas de prix, pas de panier, pas de vignettes rognées.
 */
.dossier {
  position: fixed;
  inset: 0;
  z-index: 90;
  background: var(--fond);
  overflow-y: auto;
  overscroll-behavior: contain;
  transform: translateY(100%);
  transition: transform 520ms cubic-bezier(0.22, 0.61, 0.36, 1);
}
.dossier[hidden] { display: none; }
.dossier.est-leve { transform: translateY(0); }

/* La croix reste sous la main tout le long d'un dossier qui défile. Fixe DANS
   le panneau : c'est lui qui porte la transformation, donc le bloc conteneur. */
.dossier__croix { position: fixed; }

.dossier__corps {
  max-width: var(--mesure);
  margin: 0 auto;
  padding: clamp(2.5rem, 6vh, 4rem) var(--gouttiere) var(--bande);
}

.dossier__titre { font-size: var(--t-2xl); margin: 0.6rem 0 clamp(1.5rem, 4vh, 2.5rem); max-width: 16ch; }
.dossier__reperes { max-width: 52rem; }

.planche {
  list-style: none;
  margin: clamp(2rem, 5vh, 3.25rem) 0 0;
  padding: 0;
  display: grid;
  gap: clamp(1.25rem, 3vw, 2.25rem);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 13.5rem), 1fr));
}

.planche__lien { display: grid; gap: 0.65rem; }

.planche__vue {
  display: block;
  aspect-ratio: 3 / 2;
  background: var(--fond-2);
}
/* `contain` et non `cover` : sur une planche-contact, le cadrage de l'œuvre est
   précisément ce qu'on vient juger. Mieux vaut une planche irrégulière qu'un
   tirage rogné. */
.planche__vue img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  transition: opacity var(--transition);
}
.planche__lien:hover .planche__vue img { opacity: 0.85; }

.planche__cartel { display: grid; gap: 0.3rem; }
.planche__rang { color: var(--plomb-pale); }
.planche__titre { font-family: var(--display); font-size: var(--t-base); line-height: 1.25; }
/* Le rubedo désigne le point actif : au doigt, où le survol reste collé après
   le tap, il désignerait n'importe quoi. */
@media (hover: hover) {
  .planche__lien:hover .planche__titre { color: var(--rubedo); }
}
.planche__bribes { display: flex; flex-wrap: wrap; gap: 0.2rem 0.9rem; }

.dossier__reserve,
.dossier__demande { margin: clamp(2rem, 5vh, 3rem) 0 0; max-width: 52ch; }

.dossier__reserve { color: var(--plomb); }

.dossier__note { margin-top: clamp(2.5rem, 7vh, 4rem); }
.dossier__note .lecture { margin-top: 1.5rem; }

/* --- Note d'intention ---------------------------------------------- */

.intention {
  max-width: var(--mesure);
  margin: 0 auto;
  padding: var(--bande) var(--gouttiere);
  border-top: 1px solid var(--filet);
}

.intention__titre { margin-bottom: 1.75rem; max-width: 14rem; }

@media (max-width: 48rem) {
  .scene { padding-left: 1rem; padding-right: 1rem; }
  .cartel-oeuvre__note,
  .cartel-oeuvre .sur-large { display: none; }
  .etage__scene { padding: 3.25rem 1rem 1rem; }
  .entete-serie { padding-top: 1rem; padding-bottom: 0.6rem; }

  /* Les actions passent en colonne : à cette largeur, trois verbes côte à côte
     se lisent comme une seule ligne illisible. */
  .panneau__actions { flex-direction: column; align-items: flex-start; gap: 0.9rem; }
  .action--fort { width: 100%; text-align: center; }
}

/*
 * Écran court (390 × 480 et compagnie). La galerie tient dans la hauteur
 * disponible, donc chaque rangée doit rendre ce qu'elle peut : le texte de salle
 * se resserre, le cartel abandonne ce qui n'est pas l'œuvre.
 */
@media (max-height: 34rem) {
  .panneau__titre { font-size: clamp(1.3rem, 5.4vw, 1.7rem); margin-top: 0.3rem; }
  .panneau__effectif { margin-top: 0.4rem; }
  .panneau__phrase { font-size: 0.95rem; line-height: 1.4; margin-top: 0.5rem; }
  .panneau__actions { margin-top: 0.65rem; gap: 0.45rem; }
  .action { padding: 0.25rem 0 0.2rem; }
  .action--fort { padding: 0.45rem 0.9rem; }
  .scene { gap: 0.45rem; padding-top: 0.4rem; padding-bottom: 0.7rem; }

  /* Sur un écran court, l'en-tête rend le peu qu'il peut : les repères sont
     déjà écrits sur le seuil et dans le cartel de chaque œuvre. */
  .entete-serie { padding-top: 0.55rem; padding-bottom: 0.2rem; }
  .entete-serie__reperes { display: none; }
  .scene__pied { min-height: 0; }
  .pave__touche { width: 2.4rem; height: 2.4rem; font-size: var(--t-sm); }
  .panneau { padding: 0.25rem 0 0.5rem; }

  /* On revient à des actions qui s'enroulent : en colonne, la fin de parcours
     et ses quatre verbes dépassaient le bas de l'écran. */
  .panneau__actions { flex-direction: row; align-items: center; gap: 0.5rem 1.1rem; }
  .action--fort { width: auto; }
}
