/* ==========================================================================
   composants.css
   Le cartel, l'en-tête, le pied de page. Le reste (filtres du portfolio,
   lightbox, fiche produit) arrive aux étapes suivantes, dans ce fichier.
   ========================================================================== */


/* --------------------------------------------------------------------------
   L'en-tête
   Même balisage sur les huit pages, recopié à l'identique. C'est le coût du
   « sans étape de build » : ajouter une entrée de menu, c'est modifier huit
   fichiers. L'alternative — injecter l'en-tête en JavaScript — casserait le
   référencement et la navigation sans JS. La duplication est le bon choix
   ici, mais il faut la faire sciemment.

   PAS DE MENU HAMBURGER. Cinq entrées en mono capitales tiennent sur deux
   lignes à 390 px. Un menu repliable demanderait du JavaScript pour rien,
   et un menu qui ne s'ouvre pas est un site sans navigation.

   Sur la page courante, le lien porte aria-current="page" : c'est lui qui
   déclenche le soulignement, pas une classe. L'information est ainsi vraie
   pour les lecteurs d'écran autant que pour l'œil.
   -------------------------------------------------------------------------- */

.entete {
  padding-block: var(--espace-m);
}

.entete__interieur {
  display: flex;
  flex-direction: column;
  gap: var(--espace-s);
  padding-block-end: var(--espace-s);
  border-block-end: var(--filet-epaisseur) solid var(--filet-couleur);
}

@media (min-width: 640px) {

  .entete__interieur {
    flex-direction: row;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--espace-l);
  }
}


/* --- La marque ------------------------------------------------------------ */

.entete__marque {
  text-decoration: none;
  color: var(--texte);
}

.entete__nom {
  display: block;
  font-family: var(--police-display);
  font-size: var(--taille-display-3);
  font-weight: var(--graisse-display);
  letter-spacing: var(--interlettre-display);
  line-height: var(--interligne-titre);
}

.entete__qualite {
  display: block;
  margin-block-start: var(--espace-3xs);
}


/* --- La navigation --------------------------------------------------------- */

.nav-principale {
  display: flex;
  flex-wrap: wrap;
  gap: var(--espace-2xs) var(--espace-m);
}

.nav-principale a {
  display: inline-block;
  padding-block: var(--espace-3xs);
  color: var(--texte-secondaire);
  text-decoration: none;
  border-block-end: var(--filet-epaisseur) solid transparent;
  transition: color var(--duree-court) var(--courbe),
              border-color var(--duree-court) var(--courbe);
}

.nav-principale a:hover {
  color: var(--texte);
  border-block-end-color: var(--filet-couleur);
}

.nav-principale a[aria-current="page"] {
  color: var(--texte);
  border-block-end-color: var(--accent);
}


/* --------------------------------------------------------------------------
   Le pied de page
   Il porte ce qu'une institution cherche en dernier recours : qui, où,
   comment joindre. Et le lien vers les mentions légales, obligatoire (§8).
   -------------------------------------------------------------------------- */

.pied {
  padding-block: var(--espace-2xl) var(--espace-xl);
}

.pied__interieur {
  display: grid;
  gap: var(--espace-l);
  padding-block-start: var(--espace-l);
  border-block-start: var(--filet-epaisseur) solid var(--filet-couleur);
}

@media (min-width: 640px) {

  .pied__interieur {
    grid-template-columns: 1fr auto;
    align-items: start;
    gap: var(--espace-xl);
  }
}

.pied__bloc > * + * {
  margin-block-start: var(--espace-2xs);
}

.pied__liens {
  display: flex;
  flex-wrap: wrap;
  gap: var(--espace-2xs) var(--espace-m);
}

/* --------------------------------------------------------------------------
   L'œuvre à la une
   Ouvre la page d'accueil. L'image occupe toute la largeur de l'écran, son
   cartel revient dans la bande. Rien n'est posé SUR l'image : ni titre, ni
   voile, ni dégradé — le §6 interdit la carte flottante, et un texte sur
   une peinture ne sert ni l'un ni l'autre.
   -------------------------------------------------------------------------- */

.une__lien {
  display: block;
  color: inherit;
  text-decoration: none;
}

.une__visuel {
  display: flex;
  justify-content: center;
}

/* Deux plafonds, aucune proportion imposée : une œuvre panoramique occupe
   toute la largeur, une œuvre carrée ou en hauteur se centre à sa taille.
   max-height empêche une toile en hauteur d'occuper trois écrans.

   L'image portait avant width: 100% et object-fit: contain, avec l'ardoise
   en fond du conteneur. Sur un panoramique cela ne se voyait pas ; dès que
   Twin, qui est carré, est passé en une, la toile s'est retrouvée enfermée
   dans une boîte deux fois plus large qu'elle, entre deux aplats gris de
   344 px. L'ardoise reste, mais sur l'image seule : elle ne marque plus
   que l'attente de chargement. */
.une__image {
  max-width: 100%;
  max-height: 82vh;
  width: auto;
  height: auto;
  background-color: var(--fond-souleve);
}

.une__legende {
  display: block;
  margin-block-start: var(--espace-m);
  padding-block-start: var(--espace-2xs);
  border-block-start: var(--filet-epaisseur) solid var(--filet-couleur);
}

.une__titre {
  display: block;
  font-family: var(--police-display);
  font-size: var(--taille-display-3);
  font-weight: var(--graisse-display);
  letter-spacing: var(--interlettre-display);
  line-height: var(--interligne-titre);
}

.une__lien:hover .une__titre {
  color: var(--accent);
}

.une__donnees {
  display: block;
  margin-block-start: var(--espace-3xs);
  font-family: var(--police-mono);
  font-size: var(--taille-mono);
  letter-spacing: var(--interlettre-mono);
  font-variant-numeric: tabular-nums;
  color: var(--texte-secondaire);
}


/* --------------------------------------------------------------------------
   Les trois accès
   Le §3 fixe trois publics et trois parcours. Ce bloc leur donne une porte
   chacun, au même niveau : aucune n'est mise en avant par la couleur ou la
   taille, c'est au visiteur de savoir pourquoi il est venu.
   -------------------------------------------------------------------------- */

.acces {
  display: grid;
  gap: var(--espace-l);
}

@media (min-width: 640px) {

  .acces {
    grid-template-columns: repeat(3, 1fr);
    gap: var(--gouttiere);
  }
}

.acces__porte {
  display: block;
  padding-block-start: var(--espace-s);
  border-block-start: var(--filet-epaisseur) solid var(--filet-couleur);
  color: inherit;
  text-decoration: none;
}

.acces__porte:hover {
  border-block-start-color: var(--accent);
}

.acces__titre {
  display: block;
  font-family: var(--police-display);
  font-size: var(--taille-display-3);
  font-weight: var(--graisse-display);
  letter-spacing: var(--interlettre-display);
  line-height: var(--interligne-titre);
}

.acces__porte:hover .acces__titre {
  color: var(--accent);
}

.acces__texte {
  display: block;
  margin-block-start: var(--espace-2xs);
  max-width: 34ch;
  color: var(--texte-secondaire);
}


/* --------------------------------------------------------------------------
   Les références
   Ce que cherche le public n° 1 du §3 : la preuve que le travail a déjà été
   porté par des institutions. En mono, sans logos — un mur de logos ferait
   agence, pas atelier.
   -------------------------------------------------------------------------- */

/* Empilées, et non séparées par des barres verticales. La première version
   les alignait en ligne avec un filet à droite de chacune : dès qu'une
   référence passait à la ligne — « DRAC Hauts-de-France — résidence
   “Artiste Rencontre Territoire” » en fait deux — le filet se retrouvait
   détaché, flottant au milieu du vide. Une liste verticale ne peut pas
   produire ça, et elle se parcourt mieux. */
.references {
  margin-block-start: var(--espace-m);
}

.references li {
  padding-block: var(--espace-2xs);
  border-block-start: var(--filet-epaisseur) solid var(--filet-couleur);
  color: var(--texte-secondaire);
}


/* --------------------------------------------------------------------------
   La fiche d'une œuvre
   C'est la seule page où le titre d'une œuvre passe en Display : il y devient
   le titre de la page (§6). Display 2 et non 1 — un titre d'œuvre peut être
   long, et 104px le feraient déborder sur trois lignes.
   -------------------------------------------------------------------------- */

.fiche__retour {
  margin-block-end: var(--espace-m);
}

.fiche__titre {
  font-size: var(--taille-display-2);
}

.fiche__cartel {
  margin-block-start: var(--espace-m);
  max-width: var(--mesure);
}

.fiche__champ {
  display: grid;
  gap: var(--espace-3xs);
  padding-block: var(--espace-2xs);
  border-block-start: var(--filet-epaisseur) solid var(--filet-couleur);
}

@media (min-width: 480px) {

  .fiche__champ {
    grid-template-columns: 8rem 1fr;
    gap: var(--espace-s);
  }
}

.fiche__champ dt {
  color: var(--texte-secondaire);
}

.fiche__champ dd {
  margin: 0;
}

.fiche__texte {
  font-size: var(--taille-texte-l);
}


/* --- Les visuels ----------------------------------------------------------
   La première image occupe toute la bande, les suivantes se rangent à deux
   par ligne. Aucune proportion imposée : ce sont les attributs width et
   height qui décident, comme partout ailleurs.                              */

.fiche__visuels {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--gouttiere);
}

@media (min-width: 640px) {

  .fiche__visuels {
    grid-template-columns: repeat(2, 1fr);
  }

  .fiche__visuel {
    grid-column: 1 / -1;
  }

  .fiche__visuel--secondaire {
    grid-column: span 1;
  }
}

/* Un bouton, pour que la vue agrandie soit atteignable au clavier. On lui
   retire toute apparence de bouton : c'est l'image qui est l'interface.

   width: fit-content — le cadre épouse l'image au lieu de l'encadrer. Avec
   une largeur de 100 %, une œuvre carrée ou en hauteur se retrouvait centrée
   entre deux bandes d'ardoise, alors que tout le site est calé à gauche. */
.fiche__visuel {
  display: block;
  width: fit-content;
  max-width: 100%;
  cursor: zoom-in;
  background-color: var(--fond-souleve);
}

/* La hauteur est plafonnée pour que l'œuvre tienne dans l'écran : on la
   voit entière avant de faire défiler quoi que ce soit. */
.fiche__visuel img {
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 84vh;
  transition: opacity var(--duree-court) var(--courbe);
}

.fiche__visuel--secondaire {
  width: 100%;
}

.fiche__visuel--secondaire img {
  width: 100%;
  max-height: 50vh;
  object-fit: contain;
}

.fiche__visuel:hover img {
  opacity: 0.88;
}


/* --- Les voisines ---------------------------------------------------------- */

.fiche__navigation {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--espace-m);
}

.fiche__lien {
  color: var(--texte-secondaire);
  text-decoration: none;
  border-block-end: var(--filet-epaisseur) solid transparent;
}

.fiche__lien:hover {
  color: var(--texte);
  border-block-end-color: var(--accent);
}

/* Seule sur sa ligne, la suivante se cale à droite : on garde la lecture
   « précédente à gauche, suivante à droite » même sans voisine avant. */
.fiche__lien--suivant:only-child {
  margin-inline-start: auto;
}


/* --------------------------------------------------------------------------
   La vue agrandie
   Un <dialog> natif : Échap, piège à focus, retour du focus et inertie de
   l'arrière-plan sont gérés par le navigateur (§8).

   Le display n'est posé que sur [open] : sans cela, la règle d'auteur
   écraserait le « display: none » du navigateur et la vue resterait
   affichée en permanence.
   -------------------------------------------------------------------------- */

.loupe {
  width: 100%;
  max-width: 100%;
  height: 100%;
  max-height: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  background-color: var(--encre);
  color: var(--craie);
}

.loupe[open] {
  display: grid;
  grid-template-rows: 1fr auto;
}

.loupe::backdrop {
  background-color: var(--encre);
}

.loupe__cadre {
  display: grid;
  place-items: center;
  min-height: 0;
  padding: var(--espace-m);
}

.loupe__image {
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

.loupe__barre {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--espace-m);
  padding-block: var(--espace-s);
  border-block-start: var(--filet-epaisseur) solid var(--graphite);
}

.loupe__legende {
  color: var(--os);
}

.loupe__commandes {
  display: flex;
  flex-wrap: wrap;
  gap: var(--espace-2xs);
}

.loupe__bouton {
  padding: var(--espace-2xs) var(--espace-m);
  border: var(--filet-epaisseur) solid var(--graphite);
  color: var(--craie);
  font-size: var(--taille-mono);
  letter-spacing: var(--interlettre-mono);
  text-transform: uppercase;
  transition: border-color var(--duree-court) var(--courbe),
              color var(--duree-court) var(--courbe);
}

.loupe__bouton:hover {
  border-color: var(--vert-de-gris-clair);
  color: var(--vert-de-gris-clair);
}


/* --------------------------------------------------------------------------
   Les coordonnées
   Paire terme/valeur, employée sur la page contact et dans les mentions
   légales. Même forme que les mentions d'une fiche produit : la structure
   du site ne change pas de langage d'une page à l'autre.
   -------------------------------------------------------------------------- */

.coordonnees__ligne {
  display: grid;
  gap: var(--espace-3xs);
  padding-block: var(--espace-2xs);
  border-block-start: var(--filet-epaisseur) solid var(--filet-couleur);
}

@media (min-width: 480px) {

  .coordonnees__ligne {
    grid-template-columns: 14rem 1fr;
    gap: var(--espace-s);
  }
}

.coordonnees__ligne dt {
  color: var(--texte-secondaire);
}

.coordonnees__ligne dd {
  margin: 0;
}


/* --------------------------------------------------------------------------
   Les ateliers
   Une colonne par atelier à partir de 960px. Pas de carte : le filet et le
   vide suffisent à les séparer, comme partout ailleurs.
   -------------------------------------------------------------------------- */

.ateliers {
  display: grid;
  gap: var(--espace-xl);
}

@media (min-width: 960px) {

  .ateliers {
    grid-template-columns: repeat(2, 1fr);
    gap: var(--espace-xl) var(--gouttiere);
    align-items: start;
  }
}

/* Les visuels d'un atelier, posés au-dessus du titre. Même discipline que
   la fiche produit : la proportion vient du fichier, les deux plafonds
   bornent sans déformer ni recadrer.

   Le plafond de hauteur n'est pas décoratif. Un gros plan de marionnette
   fait ici plus de deux fois sa largeur en hauteur ; sans lui, il occupe
   la fiche entière et écrase tout le reste. */

.atelier__visuels {
  display: grid;
  justify-items: start;
  gap: var(--espace-2xs);
  margin-block-end: var(--espace-s);
}

/* Hauteur fixe. C'est elle qui permet la permutation au clic : une photo
   verticale remplacée par une horizontale ne déplace plus la fiche, et les
   vignettes ne fuient pas sous le curseur. */
.atelier__scene {
  display: flex;
  align-items: flex-start;
  width: 100%;
  height: 24rem;
}

.atelier__image {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  background-color: var(--fond-souleve);
}

/* Toutes à la même hauteur, largeur libre : la rangée s'aligne et aucune
   vue n'est recadrée. En colonnes de largeur égale, chacune gardait sa
   propre hauteur et la rangée partait en escalier. */
.atelier__secondaires {
  display: flex;
  flex-wrap: wrap;
  gap: var(--espace-2xs);
}

/* Le lecteur occupe la même place que la grande image et se range sous les
   mêmes plafonds : la scène ne change pas de hauteur quand on passe de
   l'une à l'autre. */
.atelier__video {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  background-color: var(--fond-souleve);
}

.atelier__vignette {
  position: relative;
  display: block;
  padding: 0;
  border: var(--filet-epaisseur) solid transparent;
  background: none;
  cursor: pointer;
  transition: border-color var(--duree-court) var(--courbe),
              opacity var(--duree-court) var(--courbe);
}

.atelier__vignette:hover {
  opacity: 0.75;
}

/* La vue affichée en grand se signale par un filet, pas par un voile :
   l'information doit rester lisible sur l'encre comme sur la craie. */
.atelier__vignette[aria-current="true"] {
  border-color: var(--accent);
}

.atelier__image--secondaire {
  display: block;
  width: auto;
  height: 5.5rem;
  background-color: var(--fond-souleve);
}

/* Un triangle, rien de plus : c'est le seul pictogramme du site, et il ne
   sert qu'à distinguer une vidéo d'une photo dans la rangée. Dessiné en
   bordures plutôt qu'importé, pour ne pas ajouter de fichier. */
.atelier__lecture {
  position: absolute;
  inset-block-end: var(--espace-3xs);
  inset-inline-start: var(--espace-3xs);
  width: 0;
  height: 0;
  border-block: 0.5rem solid transparent;
  border-inline-start: 0.8rem solid var(--craie);
  border-inline-end: 0;
  filter: drop-shadow(0 0 2px rgb(0 0 0 / 0.6));
}

.atelier__titre {
  padding-block-end: var(--espace-2xs);
  border-block-end: var(--filet-epaisseur) solid var(--filet-couleur);
}

.atelier__detail {
  display: grid;
  grid-template-columns: 7rem 1fr;
  gap: var(--espace-s);
  padding-block: var(--espace-3xs);
}

.atelier__detail dt {
  color: var(--texte-secondaire);
}

.atelier__detail dd {
  margin: 0;
}

.atelier__details {
  margin-block-start: var(--espace-2xs);
}

.atelier__texte {
  margin-block-start: var(--espace-s);
}


/* --------------------------------------------------------------------------
   La presse
   Le scan à gauche, la référence à droite. Même forme que le cartel : une
   image, puis des données alignées à gauche. Le scan est volontairement
   petit — c'est une preuve qu'on peut ouvrir, pas une lecture.
   -------------------------------------------------------------------------- */

.coupure + .coupure {
  margin-block-start: var(--espace-l);
  padding-block-start: var(--espace-l);
  border-block-start: var(--filet-epaisseur) solid var(--filet-couleur);
}

.coupure {
  display: grid;
  gap: var(--espace-m);
}

@media (min-width: 640px) {

  .coupure {
    grid-template-columns: 10rem 1fr;
    gap: var(--espace-l);
    align-items: start;
  }

  /* Une référence en ligne, sans coupure scannée, reprend toute la largeur
     plutôt que de laisser une colonne vide à sa gauche. */
  .coupure--sans-visuel {
    grid-template-columns: 1fr;
  }
}

/* Le filet apparaît au survol : il signale que la coupure s'ouvre, sans
   poser d'encadrement permanent autour d'une image de journal. */
.coupure__visuel {
  display: block;
  border: var(--filet-epaisseur) solid transparent;
  transition: border-color var(--duree-court) var(--courbe);
}

.coupure__visuel:hover,
.coupure__visuel:focus-visible {
  border-color: var(--accent);
}

.coupure__visuel img {
  width: 100%;
  height: auto;
  background-color: var(--fond-souleve);
}

.coupure__source {
  color: var(--texte-secondaire);
}

.coupure__titre {
  margin-block-start: var(--espace-3xs);
  font-size: var(--taille-display-3);
}

/* La citation revient à la mesure de lecture. Laissée à la largeur de la
   bande, elle faisait une ligne de plus de cent caractères : l'œil perd le
   début de la ligne suivante. */
.coupure__citation {
  max-width: var(--mesure);
  margin-block-start: var(--espace-s);
  padding-inline-start: var(--espace-s);
  border-inline-start: var(--filet-epaisseur) solid var(--filet-couleur);
}

.coupure__signature {
  margin-block-start: var(--espace-2xs);
  color: var(--texte-secondaire);
}


/* Le poids et la date d'un fichier à télécharger : des données, pas de la
   prose. En retrait du lien, en texte secondaire, pour renseigner sans lui
   disputer l'attention. On ne fait pas cliquer quelqu'un sur un fichier
   sans lui dire ce qu'il reçoit. */
.lien-fichier {
  margin-inline-start: var(--espace-s);
  color: var(--texte-secondaire);
}


/* --------------------------------------------------------------------------
   Le parcours
   La période à gauche en mono, l'intitulé à droite. C'est la forme d'un CV
   d'artiste, et c'est ce que cherche le premier public du §3.
   -------------------------------------------------------------------------- */

.parcours__groupe + .parcours__groupe {
  margin-block-start: var(--espace-xl);
}

.parcours__titre {
  padding-block-end: var(--espace-2xs);
  border-block-end: var(--filet-epaisseur) solid var(--filet-couleur);
}

.parcours__entree {
  display: grid;
  gap: var(--espace-3xs);
  padding-block: var(--espace-xs);
  border-block-end: var(--filet-epaisseur) solid var(--filet-couleur);
}

@media (min-width: 480px) {

  .parcours__entree {
    grid-template-columns: 9rem 1fr;
    gap: var(--espace-s);
  }
}

.parcours__periode {
  color: var(--texte-secondaire);
  font-variant-numeric: tabular-nums;
}

.parcours__intitule {
  display: block;
}

.parcours__complement {
  display: block;
  margin-block-start: var(--espace-3xs);
  color: var(--texte-secondaire);
}

/* En prose, et à la mesure de lecture : c'est la seule ligne du parcours
   qui se lit comme une phrase et non comme une donnée. */
.parcours__description {
  display: block;
  max-width: var(--mesure);
  margin-block-start: var(--espace-2xs);
  color: var(--texte-secondaire);
}


/* --------------------------------------------------------------------------
   Le bouton
   Le seul aplat de couleur du site. Réservé à l'action qui engage : passer
   commande. Partout ailleurs, un lien souligné suffit.
   -------------------------------------------------------------------------- */

.bouton {
  display: inline-block;
  padding: var(--espace-2xs) var(--espace-m);
  background-color: var(--accent);
  color: var(--fond);
  font-family: var(--police-mono);
  font-size: var(--taille-mono);
  letter-spacing: var(--interlettre-mono);
  text-transform: uppercase;
  text-decoration: none;
  border: var(--filet-epaisseur) solid var(--accent);
  transition: background-color var(--duree-court) var(--courbe),
              color var(--duree-court) var(--courbe);
}

.bouton:hover {
  background-color: transparent;
  color: var(--accent);
}


/* --------------------------------------------------------------------------
   La fiche produit
   Pas de carte, pas d'ombre : les mêmes règles que le cartel. Les visuels à
   gauche, les mentions obligatoires du §10 à droite, et l'achat en bas.
   -------------------------------------------------------------------------- */

.produit {
  display: grid;
  gap: var(--espace-l);
}

@media (min-width: 960px) {

  .produit {
    grid-template-columns: 3fr 2fr;
    gap: var(--espace-xl);
    align-items: start;
  }
}

/* Deux pièces qui se suivent sont séparées par un filet et du vide, jamais
   par un encadrement. */
.produit + .produit {
  margin-block-start: var(--espace-2xl);
  padding-block-start: var(--espace-2xl);
  border-block-start: var(--filet-epaisseur) solid var(--filet-couleur);
}


/* --- Les visuels ----------------------------------------------------------
   La première image occupe toute la largeur, les suivantes se rangent en
   dessous. Aucune proportion imposée, comme pour les œuvres : ce sont les
   attributs width et height qui décident.                                   */

.produit__visuels {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--espace-2xs);
  align-items: start;
}

/* La proportion vient du fichier, jamais du CSS. Les deux plafonds bornent
   l'image sans la déformer ni la recadrer : le navigateur la réduit jusqu'à
   ce qu'elle tienne dans les deux, et la boîte prend exactement sa taille.

   Le plafond de hauteur existe parce que la pièce en kit est photographiée
   en très haut format et occupait deux écrans à elle seule.

   La version précédente combinait width: 100% et object-fit: contain. Sur
   une photo carrée on ne voyait rien ; dès que la Basilique est passée en
   cadrage vertical, l'image s'est retrouvée enfermée dans une boîte plus
   large qu'elle, avec deux bandes d'ardoise sur les côtés. Ne pas y revenir :
   object-fit ne sert que si la boîte impose une proportion, et ici elle n'en
   impose aucune. */
.produit__image {
  grid-column: 1 / -1;
  max-width: 100%;
  max-height: 72vh;
  width: auto;
  height: auto;
  justify-self: start;
  background-color: var(--fond-souleve);
}

/* Les vues secondaires occupent un tiers de la largeur chacune : assez
   grandes pour être lisibles, assez petites pour rester secondaires. Elles
   remplissent leur colonne, d'où le retour à width: 100%. */
.produit__image--secondaire {
  grid-column: span 1;
  width: 100%;
  max-height: none;
  justify-self: stretch;
}


/* --- Le texte -------------------------------------------------------------- */

.produit__titre {
  font-size: var(--taille-display-3);
}

.produit__sous-titre {
  margin-block-start: var(--espace-3xs);
  color: var(--texte-secondaire);
}

.produit__mentions {
  margin-block-start: var(--espace-m);
}

.produit__mention {
  display: grid;
  gap: var(--espace-3xs);
  padding-block: var(--espace-2xs);
  border-block-start: var(--filet-epaisseur) solid var(--filet-couleur);
}

@media (min-width: 480px) {

  .produit__mention {
    grid-template-columns: 9rem 1fr;
    gap: var(--espace-s);
  }
}

.produit__mention dt {
  color: var(--texte-secondaire);
}

.produit__mention dd {
  margin: 0;
}


/* --- L'achat --------------------------------------------------------------- */

.produit__achat {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--espace-m);
  margin-block-start: var(--espace-l);
}

.produit__prix {
  font-size: var(--taille-texte-l);
  font-weight: var(--graisse-accent);
  font-variant-numeric: tabular-nums;
  color: var(--texte);
}

/* Une commande suspendue, une série épuisée : ce sont des états, pas des
   prix. Ils occupent la même place et doivent donc se distinguer du
   montant — en retrait, à la taille du texte courant. Pas de rouge : rien
   n'est en panne, et le site n'a qu'un accent (§6). */
.produit__prix--pause,
.produit__prix--epuise {
  font-size: var(--taille-texte);
  font-weight: var(--graisse-texte);
  color: var(--texte-secondaire);
}


/* --- Les séries de pièces uniques -----------------------------------------
   Sept veilleuses différentes sous un même intitulé. La grille est posée
   sous les deux colonnes de la fiche, sinon les vignettes se tasseraient
   dans la colonne de texte.

   Même discipline que la grille des œuvres : colonnes régulières, pas de
   carte, pas d'ombre. Ce qui distingue une pièce d'une autre est sa photo,
   pas un encadrement.                                                      */

.produit__serie {
  grid-column: 1 / -1;
  margin-block-start: var(--espace-l);
  padding-block-start: var(--espace-l);
  border-block-start: var(--filet-epaisseur) solid var(--filet-couleur);
}

.produit__serie-titre {
  margin-block-end: var(--espace-m);
  color: var(--texte-secondaire);
}

.serie {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: var(--espace-m);
  list-style: none;
  align-items: start;
}

.variante__image {
  width: 100%;
  height: auto;
  background-color: var(--fond-souleve);
}

/* Même emplacement en attente que dans le portfolio : une zone d'ardoise à
   la bonne proportion, pour que la grille ne saute pas quand les photos
   arriveront. */
.variante__attente {
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 1 / 1;
  padding: var(--espace-2xs);
  background-color: var(--fond-souleve);
  border: var(--filet-epaisseur) solid var(--filet-couleur);
  color: var(--texte-secondaire);
  text-align: center;
}

.variante__numero {
  margin-block-start: var(--espace-2xs);
  color: var(--texte);
}

.variante__etat {
  margin-block-start: var(--espace-2xs);
  color: var(--texte-secondaire);
}

/* Une pièce vendue reste visible : la série garde son sens une fois
   épuisée. Elle est seulement mise en retrait, jamais barrée — ce n'est
   pas une erreur, c'est une vente. */
.variante__etat--vendue {
  color: var(--accent);
  text-transform: uppercase;
  letter-spacing: var(--interlettre-mono);
}


/* --------------------------------------------------------------------------
   Les filtres du portfolio
   Même traitement que la navigation principale : ce sont des liens, pas des
   boutons, parce que « ?discipline=bas-relief » doit pouvoir se copier et
   se partager. Le clic est intercepté en JavaScript pour éviter un
   rechargement, mais l'URL reste juste dans tous les cas.
   -------------------------------------------------------------------------- */

.filtres {
  display: flex;
  flex-wrap: wrap;
  gap: var(--espace-2xs) var(--espace-m);
}

.filtres__lien {
  display: inline-block;
  padding-block: var(--espace-3xs);
  color: var(--texte-secondaire);
  text-decoration: none;
  border-block-end: var(--filet-epaisseur) solid transparent;
  transition: color var(--duree-court) var(--courbe),
              border-color var(--duree-court) var(--courbe);
}

.filtres__lien:hover {
  color: var(--texte);
  border-block-end-color: var(--filet-couleur);
}

.filtres__lien[aria-current="true"] {
  color: var(--texte);
  border-block-end-color: var(--accent);
}


/* --------------------------------------------------------------------------
   L'emplacement réservé
   Une œuvre peut être décrite dans oeuvres.json avant d'être photographiée.
   On réserve sa place au lieu d'afficher une image cassée. C'est le seul
   usage de --ardoise, et la seule proportion imposée du site.
   -------------------------------------------------------------------------- */

.cartel__attente {
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: var(--proportion-attente);
  padding: var(--espace-s);
  background-color: var(--fond-souleve);
  border: var(--filet-epaisseur) solid var(--filet-couleur);
  color: var(--texte-secondaire);
  text-align: center;
}


/* --------------------------------------------------------------------------
   Les messages
   Un chargement qui échoue doit dire quoi faire, jamais laisser un écran
   vide (§7). Ce bloc sert aussi à l'état « aucun résultat ».
   -------------------------------------------------------------------------- */

.message {
  grid-column: 1 / -1;
  max-width: var(--mesure);
  padding: var(--espace-m);
  border-inline-start: var(--epaisseur-focus) solid var(--accent);
  background-color: var(--fond-souleve);
  color: var(--texte-secondaire);
}

.message strong {
  color: var(--texte);
}


/* --------------------------------------------------------------------------
   Révélation au défilement
   La classe .reveler n'est posée par JavaScript qu'au moment d'observer
   l'élément. Elle n'existe jamais dans le HTML livré : si le script ne
   tournait pas, rien ne resterait invisible.
   -------------------------------------------------------------------------- */

.reveler {
  opacity: 0;
  transform: translateY(var(--translation-revelation));
  transition: opacity var(--duree-revelation) var(--courbe),
              transform var(--duree-revelation) var(--courbe);

  /* Le rang dans la cascade est posé par utils.js au moment où l'élément
     entre à l'écran, et retiré dès que l'apparition est finie. Sans valeur,
     la variable vaut 0 : un élément révélé sans JavaScript de cascade
     apparaît simplement sans retard. */
  transition-delay: min(
    calc(var(--rang-cascade, 0) * var(--pas-cascade)),
    var(--cascade-plafond)
  );
}

.reveler--visible {
  opacity: 1;
  transform: none;
}

/* Filet de sécurité. base.css neutralise déjà les transitions, mais sans
   ceci un élément resterait à opacity: 0 pour toujours. */
@media (prefers-reduced-motion: reduce) {

  .reveler {
    opacity: 1;
    transform: none;
    transition-delay: 0s;
  }
}


.pied__mention {
  /* Toute la largeur, sous les deux colonnes. */
  grid-column: 1 / -1;
  margin-block-start: var(--espace-l);
  color: var(--texte-secondaire);
}

/* Les trois mentions du bas de page tiennent chacune leur ligne. Mises bout
   à bout et séparées par des points, elles se cassaient n'importe où selon
   la largeur de l'écran — au milieu de « Artiste-auteur », au milieu du
   SIRET — et le point de séparation restait seul en fin de ligne. Trois
   lignes courtes, aucune ponctuation à faire tenir. Les espaces du numéro
   de SIRET sont insécables dans le HTML : il ne se coupe jamais. */
.pied__ligne {
  display: block;
}


/* --------------------------------------------------------------------------
   Le cartel
   L'élément signature du site (§6). Un accrochage, pas une carte de site
   marchand : image, filet de 1px, puis les données en mono sur des lignes
   serrées alignées à gauche. Pas d'ombre, pas d'arrondi, pas de fond.

   Balisage attendu :

     <figure class="cartel">
       <span class="cartel__visuel">
         <img class="cartel__image"  src="…" alt="…" width="…" height="…">
         <img class="cartel__detail" src="…" alt=""  width="…" height="…">
       </span>
       <figcaption class="cartel__legende">
         <a class="cartel__lien" href="oeuvre.html?id=…">Soleil Boulonnais III</a>
         <dl class="cartel__donnees">
           <div class="cartel__champ">
             <dt class="visuellement-cache">Année</dt>
             <dd>2021</dd>
           </div>
           …
         </dl>
       </figcaption>
     </figure>

   Deux partis pris à connaître avant de modifier ce composant :

   1. Un seul lien, posé sur le titre, puis étendu à toute la vignette par
      un ::after. Le clic marche partout, mais le clavier ne s'arrête qu'une
      fois par œuvre et le lecteur d'écran annonce le titre, pas « lien ».
      Ne pas ajouter de second lien sur l'image : la carte en aurait deux.

   2. Les <dt> sont masqués à l'œil : un cartel de musée n'écrit pas
      « Matériaux : ». Les lecteurs d'écran, eux, les annoncent.

   3. Le titre est en mono ICI, dans la vignette, parce qu'il fait partie du
      bloc de données. Il ne passe en Display que sur la fiche de l'œuvre,
      où il devient le titre de la page. C'est l'arbitrage entre les deux
      règles du §6 qui se contredisaient.
   -------------------------------------------------------------------------- */

.cartel {
  position: relative;
}


/* --- Le visuel ------------------------------------------------------------
   AUCUN FORMAT IMPOSÉ. Chaque œuvre garde sa proportion réelle : un Soleil
   Boulonnais est carré, une toile est en hauteur, un bas-relief en situ est
   souvent en largeur. Rien n'est recadré, rien n'est aligné sur une hauteur
   commune — c'est exactement le désalignement que demande le §6.

   Conséquence directe, à ne pas contourner : chaque <img> DOIT porter ses
   attributs width et height (§8). Ce sont eux, et eux seuls, qui réservent
   la bonne hauteur avant le chargement. Sans eux, la grille sautera à
   chaque image reçue. Ces dimensions viennent de oeuvres.json.

   Le fond --fond-souleve n'est visible que pendant ce laps de temps : il
   marque l'emplacement réservé. C'est le seul rôle de --ardoise.          */

.cartel__visuel {
  position: relative;
  display: block;
  overflow: hidden;
  background-color: var(--fond-souleve);
}

/* La hauteur vient de l'image elle-même, via son ratio width/height. */
.cartel__image {
  width: 100%;
  height: auto;
}

/* Le détail, lui, se cale sur le cadre défini par l'image principale : il
   est recadré par nature, object-fit: cover est ici volontaire. */
.cartel__detail {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Au survol : passage à un détail recadré de l'œuvre. Jamais un zoom,
   jamais un filtre (§6).

   Par convention, le détail est images[1] dans oeuvres.json — pas de champ
   dédié. Une œuvre qui n'a qu'une image ne fait simplement rien au survol :
   c'est un comportement prévu, pas une panne.

   L'image de détail est décorative : elle montre la même œuvre que
   l'image principale, qui porte déjà l'alt. Son alt reste donc vide. */
.cartel__detail {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity var(--duree-court) var(--courbe);
}

.cartel:hover .cartel__detail,
.cartel:focus-within .cartel__detail {
  opacity: 1;
}


/* --- La légende ----------------------------------------------------------- */

.cartel__legende {
  /* Le filet : l'unique ornement du site. */
  border-block-start: var(--filet-epaisseur) solid var(--filet-couleur);
  padding-block-start: var(--espace-2xs);
  margin-block-start: var(--espace-xs);
}

.cartel__lien {
  display: block;
  font-family: var(--police-mono);
  font-size: var(--taille-mono);
  font-weight: var(--graisse-accent);
  letter-spacing: var(--interlettre-mono);
  line-height: var(--interligne-cartel);
  color: var(--texte);
  text-decoration: none;
}

/* Étend la zone cliquable à toute la vignette sans ajouter de lien. */
.cartel__lien::after {
  content: "";
  position: absolute;
  inset: 0;
}

.cartel__lien:hover {
  color: var(--accent);
}

.cartel__donnees {
  margin-block-start: var(--espace-3xs);
  font-family: var(--police-mono);
  font-size: var(--taille-mono);
  line-height: var(--interligne-cartel);
  letter-spacing: var(--interlettre-mono);
  font-variant-numeric: tabular-nums;
  color: var(--texte-secondaire);
}

.cartel__champ > dd {
  margin: 0;
}
