/* ===================================================================
   publish-livres.css — Biblioteca San Juan de Miraflores
   Vitrine de prêt (Quartz v5 → livres.e-e-e.bible), espagnol.

   CE FICHIER REMPLACE UNE COPIE NON ADAPTÉE. Du 2026-08-31 au 2026-10-04,
   `publish-livres.css` était le CSS de l'atelier doctrinal `atelier.e-e-e.bible`
   recopié sous un autre nom par `sync-content.sh`. Mesuré avant remplacement :
   758 lignes, 60 349 octets chargés sur chaque page, et pour les mots du
   domaine — `libro`, `portada`, `catálogo`, `disponib`, `ficha`, `cover`,
   `biblioteca` — ZÉRO occurrence chacun. Il stylait en revanche `viz-tension`,
   `viz-weave`, un lecteur biblique et un sélecteur FR↔ES, dont rien n'existe
   ici, plus 13 sélecteurs visant des classes d'Obsidian Publish absentes du DOM
   Quartz (`.published-container`, `.markdown-preview-sizer`, `.site-body`).
   Un catalogue sans une seule règle qui le concerne n'est pas « sobre » : il est
   non habillé, et c'est l'état que `AGENTS.md` désigne comme le pire, parce
   qu'aucun contrôle ne le distingue d'un travail propre.

   D'OÙ VIENNENT LES COULEURS — palette du contrat, appliquée le 2026-10-17.
   Le « thème neutre » du 2026-08-26 a été RÉVISÉ par le contrat de page
   (coffre : « Biblioteca SJM — Contrat de page « libro » (vitrine) », § 1 et
   § 3) : un thème neutre n'est pas neutre, il est muet. Seule la PALETTE
   SYMBOLIQUE de l'atelier est reprise, par COPIE DES VALEURS (contrat § 5.5),
   jamais par dépendance ; valeurs claires et sombres relevées le 2026-10-17
   dans `publish.css` du coffre, où chaque variante sombre est déjà calibrée.
   Deux endroits, et chaque valeur n'est que dans UN :
     · `quartz.config.yaml` porte ce que Quartz sait nommer : fond `--lin`
       (#FAF7F0) → `--light` ; texte `--encre` → `--dark` ; texte courant
       `--encre-douce` → `--darkgray` ; titres et liens `--bleu-ciel` →
       `--secondary`. Tous les composants natifs suivent donc d'eux-mêmes.
     · ce fichier porte les accents que Quartz ne connaît pas, chacun à son
       rôle : `--bib-or` (action primaire « Formulario de reserva », en
       LISERÉ, jamais criard), `--bib-airain` (niveau de lecture : l'épreuve,
       et elle se gradue), `--bib-argent` et `--bib-eau` (en attente : bouton
       « Pedir un ejemplar nuevo » et bloc des citations, pas encore construits).
   Les quatre proscrits du contrat — écarlate, sang, fer, pourpre — ne sont
   DÉCLARÉS NULLE PART : un jeton absent ne peut pas être employé par mégarde.

   CONTRASTES, mesurés le 2026-10-17 sur le fond lin #FAF7F0 (WCAG 2.2
   § 1.4.3 : 4,5:1 pour le texte) : encre 15,17 · encre-douce 7,10 ·
   bleu-ciel 8,26 · or 6,18 · airain 5,43 · eau 5,09. L'argent (2,11) ne sert
   QUE de bordure ou de fond. Sur le fond sombre #161618 : encre 13,76 ·
   encre-douce 6,66 · bleu-ciel 4,60 · or 8,91 · airain 4,56 · eau 4,61.
   `--gray` passe à #6E675C (5,22:1 ; il valait 1,87:1) et `--tertiary` à
   l'encre douce (7,10:1 ; il valait 2,53:1) : Quartz s'en sert pour du
   texte (date, survol), ils ne sont donc plus interdits au texte.

   VOCABULAIRE DES CLASSES. Aucun composant de bibliothèque n'existait dans le
   coffre : il n'y avait rien à décalquer. Les noms sont donc tirés des mots que
   la sortie générée emploie DÉJÀ en espagnol — `portada`, `Disponibilidad`,
   `Autor`, `Código`, `Catálogo` — plutôt qu'inventés en anglais. Ces classes
   sont émises par `tools/airtable-to-content.py` : toute classe stylée ici doit
   y avoir sa contrepartie, et réciproquement. Un contrôle croisé le vérifie
   (voir § en fin de fichier).
   =================================================================== */

/* ── Jetons dérivés (une seule place à régler) ───────────────────── */

:root {
  --bib-texte: var(--dark);
  --bib-texte-doux: var(--darkgray);        /* 7,86:1 — sûr pour du texte */
  --bib-fond: var(--light);
  --bib-fond-carte: color-mix(in srgb, var(--light) 94%, var(--dark));
  --bib-bordure: var(--lightgray);
  --bib-lien: var(--secondary);

  --bib-ok: #1b6b3a;                        /* 6,11:1 sur le lin #FAF7F0 — mesuré */
  --bib-attente: #8a5a00;                   /* 5,54:1 — mesuré */
  --bib-sorti: #7a2f1d;                     /* 8,72:1 — mesuré */
  --bib-perdu: #6b6b6b;                     /* 4,98:1 — mesuré */

  /* Palette du contrat, § 3 — accents par le sens (valeurs copiées). */
  --bib-or: #765811;                        /* action primaire, liseré — 6,18:1 */
  --bib-airain: #8C5A2B;                    /* niveau de lecture — 5,43:1 */
  --bib-argent: #A7ADB5;                    /* en attente (Pedir) — bordure seule, 2,11:1 */
  --bib-eau: #35708E;                       /* en attente (citations) — 5,09:1 */
  --bib-titre: var(--secondary);            /* bleu-ciel : en-tête et titres */

  --bib-rayon: 10px;
  --bib-gouttiere: clamp(0.75rem, 2vw, 1.25rem);
  --bib-nivel: var(--bib-airain);           /* contrat § 3 : l'airain gradue l'épreuve */
  --bib-cible: 44px;                        /* WCAG 2.2 § 2.5.8 exige 24px ; 44 est la cible confortable */
}

:root[saved-theme="dark"] {
  --bib-fond-carte: color-mix(in srgb, var(--light) 88%, #fff 12%);
  --bib-ok: #6fcf97;
  --bib-attente: #e0b354;
  --bib-sorti: #f0907a;
  --bib-perdu: #a8a8a8;
  /* Variantes sombres de l'atelier (même sens, même teinte, luminance
     recalibrée), mesurées sur #161618 : or 8,91 · airain 4,56 · eau 4,61.
     L'argent passe déjà (7,99) : inchangé. */
  --bib-or: #D8B15A;
  --bib-airain: #AD733D;
  --bib-eau: #4788A9;
}

/* ── En-tête et titres : le céleste (contrat § 3) ────────────────── */

.page-title a,
h1, h2, h3 { color: var(--bib-titre); }

/* ── Fiche livre ─────────────────────────────────────────────────── */

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

@media (min-width: 34rem) {
  .libro {
    grid-template-columns: minmax(140px, 200px) 1fr;
    align-items: start;
  }
}

.libro__portada {
  margin: 0;
  border-radius: var(--bib-rayon);
  overflow: hidden;
  border: 1px solid var(--bib-bordure);
  background: var(--bib-fond-carte);
}

/* `aspect-ratio` réserve la place AVANT le chargement : sans lui, l'arrivée
   d'une couverture tierce (covers.openlibrary.org) décale la page et dégrade
   le CLS, dont la cible est ≤ 0,1 au 75e percentile. */
.libro__portada img,
.tarjeta__portada img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 2 / 3;
  object-fit: cover;
}

.libro__sin-portada,
.tarjeta__sin-portada {
  display: grid;
  place-items: center;
  aspect-ratio: 2 / 3;
  border-radius: var(--bib-rayon);
  border: 1px dashed var(--bib-bordure);
  background: var(--bib-fond-carte);
  color: var(--bib-texte-doux);
  font-size: 0.8rem;
  text-align: center;
  padding: 0.5rem;
}

.libro__datos {
  margin: 0;
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.35rem 0.75rem;
  font-size: clamp(0.9rem, 0.86rem + 0.2vw, 1rem);
}

.libro__etiqueta {
  margin: 0;
  color: var(--bib-texte-doux);
  font-weight: 600;
}

.libro__valor {
  margin: 0;
  color: var(--bib-texte);
}

.libro__resumen {
  grid-column: 1 / -1;
  max-width: 68ch;
  line-height: 1.65;
}

/* ── Badge de disponibilité ──────────────────────────────────────── */

/* La couleur ne porte JAMAIS seule l'information : le libellé est toujours
   écrit à côté (WCAG § 1.4.1). Le point coloré n'est qu'un repère. */
.estado {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-weight: 600;
  white-space: nowrap;
}

.estado::before {
  content: "";
  width: 0.6em;
  height: 0.6em;
  border-radius: 50%;
  background: currentColor;
  flex: none;
}

.estado--disponible { color: var(--bib-ok); }
.estado--reservado  { color: var(--bib-attente); }
.estado--prestado   { color: var(--bib-sorti); }
.estado--perdido    { color: var(--bib-perdu); }

/* ── Boutons de réservation ──────────────────────────────────────── */

.acciones {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin-top: 0.25rem;
}

.boton {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  min-height: var(--bib-cible);
  min-width: var(--bib-cible);
  padding: 0.55rem 1.1rem;
  border-radius: var(--bib-rayon);
  border: 1px solid transparent;
  font-weight: 600;
  text-decoration: none;
  line-height: 1.2;
}

/* CONDITIONNELLE : émise par le générateur seulement si `whatsapp` est renseigné
   dans le panneau — vide à dessein depuis le 2026-10-10, donc 0 occurrence attendue.
   Déclarée dans CONDITIONNELLES du contrôle croisé, en fin de fichier : c'est là,
   et non dans ce commentaire, que la déclaration compte (corrigé le 2026-10-18). */
.boton--whatsapp {
  background: var(--bib-ok);
  color: var(--bib-fond);
}

/* Action PRIMAIRE (contrat § 3) : « Formulario de reserva » porte l'or, en
   liseré et jamais en aplat criard — un fond teinté à 8 %, le texte à
   l'encre (13,52:1 sur ce fond). */
.boton--formulario {
  background: color-mix(in srgb, var(--bib-or) 8%, transparent);
  color: var(--bib-texte);
  border: 2px solid var(--bib-or);
}

/* Texte complet en ligne (2026-10-17) : lien SORTANT vers la page de lecture de
   l'éditeur — action secondaire, même grammaire que le formulaire. */
.boton--lectura {
  background: transparent;
  color: var(--bib-lien);
  border-color: var(--bib-lien);
}

/* Séries de lecture et cours bibliques (2026-10-17) : même rang visuel que le
   bouton d'aide, plein. */
.boton--curso {
  background: var(--bib-lien);
  color: var(--bib-fond);
}

/* Partage (N8, 0.5.0) : action TERTIAIRE — neutre par destination, ni le
   liseré du lien ni un fond plein. Recommander n'est pas réserver. */
.boton--compartir {
  background: transparent;
  color: var(--bib-texte-doux);
  border-color: var(--bib-bordure);
}

/* Accès pratique (S1b, 0.5.0) : même rang que le bouton d'aide, à côté de lui. */
.boton--red {
  background: var(--bib-lien);
  color: var(--bib-fond);
}

.boton:hover { filter: brightness(1.08); }

.boton:focus-visible {
  outline: 3px solid var(--bib-texte);
  outline-offset: 2px;
}

/* ── Catalogue (accueil) ─────────────────────────────────────────── */

.catalogo__seccion { margin-block: 2rem; }

.catalogo__titulo {
  font-size: clamp(1.15rem, 1rem + 0.6vw, 1.5rem);
  margin-bottom: 0.75rem;
  padding-bottom: 0.3rem;
  border-bottom: 2px solid var(--bib-bordure);
}

/* Grille de couvertures : l'accueil montrait 24 liens texte alors que 12
   couvertures existaient en base et n'étaient rendues que sur la fiche. */
.rejilla {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(145px, 1fr));
  gap: var(--bib-gouttiere);
  list-style: none;
  padding: 0;
  margin: 0;
}

.tarjeta {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  position: relative;   /* ancre du lien étiré (.tarjeta__enlace::after) */
}

/* LIEN ÉTIRÉ (2026-10-17). Le lien vers la fiche ne porte plus que le titre ;
   son ::after recouvre toute la carte, couverture comprise, et les liens
   d'auteur passent au-dessus. Raison : l'auteur devient cliquable SUR la
   carte, or un <a> imbriqué dans un <a> est du HTML invalide. */
.tarjeta__enlace {
  display: block;
  text-decoration: none;
  border-radius: var(--bib-rayon);
}

.tarjeta__enlace::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: var(--bib-rayon);
}

.tarjeta__enlace:focus-visible { outline: none; }

.tarjeta__enlace:focus-visible::after {
  outline: 3px solid var(--bib-texte);
  outline-offset: 3px;
}

.tarjeta__autor .dato__enlace {
  position: relative;
  z-index: 1;
}

.tarjeta__portada {
  margin: 0;
  border-radius: var(--bib-rayon);
  overflow: hidden;
  border: 1px solid var(--bib-bordure);
}

.tarjeta__cuerpo {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}

.tarjeta__titulo {
  font-weight: 600;
  line-height: 1.3;
  color: var(--bib-texte);
  font-size: 0.95rem;
}

.tarjeta__autor {
  color: var(--bib-texte-doux);
  font-size: 0.85rem;
}

.tarjeta--no-disponible .tarjeta__portada { opacity: 0.55; }

/* ── Niveau de lecture : pastille à REMPLISSAGE ──────────────────── */
/*
   Vide = fácil, à moitié = medio, plein = difícil. Arbitré par l'utilisateur le
   2026-10-08, et le même dessin vit dans le greffon « EEE · Bibliothèque » côté
   gestion (`bib-puck`) — deux surfaces, un seul vocabulaire visuel.

   LE SIGNAL EST LA SURFACE, PAS LA COULEUR. Une échelle rendue par trois
   opacités du même ton ne s'ordonne pas à l'œil, disparaît en nuances de gris et
   devient illisible pour un lecteur daltonien. Une moitié pleine se voit partout.
   Le libellé textuel reste à côté de la pastille : WCAG 2.2 § 1.4.1 interdit de
   confier une information à la seule couleur, et ici même la forme ne porte
   jamais seule.

   `currentColor` À DESSEIN sur le dégradé : la pastille suit la couleur du texte
   qui l'accompagne, donc elle reste contrastée sur la fiche comme sur la carte,
   en thème clair comme en thème sombre, sans seconde déclaration à maintenir.
*/
.nivel {
  display: inline-block;
  flex: 0 0 auto;
  width: 0.72em;
  height: 0.72em;
  margin-right: 0.4em;
  vertical-align: -0.05em;
  border: 2px solid currentColor;
  border-radius: 50%;
  background: transparent;
  color: var(--bib-nivel);
}

.nivel--vacio  { background: transparent; }
.nivel--mitad  {
  background: linear-gradient(to right,
    currentColor 0 50%, transparent 50% 100%);
}
.nivel--lleno  { background: currentColor; }

/* Non évalué : contour pointillé et vide. Sans cela « vide » dirait à la fois
   « facile » et « personne n'a tranché » — deux choses opposées. */
.nivel--sin-evaluar { border-style: dashed; background: transparent; }

/* Sur la carte du catalogue, le niveau est une ligne discrète sous l'auteur. */
.tarjeta__nivel {
  display: flex;
  align-items: center;
  color: var(--bib-texte-doux);
  font-size: 0.8rem;
}

/* ═══════════════════════════════════════════════════════════════════
   AJOUTS DU 2026-10-08 — lot des six demandes SJM.
   Quatre familles : les DONNÉES CLIQUABLES de la fiche (.dato__enlace,
   .libro__biblia), les FILTRES de l'accueil (.filtros*), les PAGES DÉRIVÉES
   auteur / éditeur / année (.autor*, .lista-libros*, .grupo__resumen), et la
   PAGE D'AIDE (.ayuda*).

   RIEN N'EST ÉMIS SANS RÈGLE, ET AUCUNE RÈGLE NE VISE DU VIDE. C'est la règle 4
   du contrat UI d'AGENTS.md, et la raison en est mesurée : deux modales livrées
   le 2026-09-28 respectaient tout le contrat existant, passaient le contrôle au
   vert, et étaient NUES à l'écran — parce qu'un contrôle qui compte les classes
   sans règle ne voit pas l'absence totale de classes. Le contrôle croisé en fin
   de fichier a donc été étendu aux quatre familles ci-dessous : il échouerait
   si l'une d'elles était émise sans style, ou stylée sans être émise.

   LES DEUX JETONS INTERDITS AU TEXTE le restent ici : `--gray` et `--tertiary`
   ne servent qu'en bordure ou en fond. Tout texte secondaire prend
   `--bib-texte-doux` (7,86:1).
   ═══════════════════════════════════════════════════════════════════ */

/* ── Données cliquables de la fiche ──────────────────────────────── */

.dato__enlace {
  color: var(--bib-lien);
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
}

.dato__enlace:hover { text-decoration-thickness: 2px; }

/* Cible tactile : WCAG 2.2 § 2.5.8 demande 24 px. Un lien en ligne dans une
   liste de données ne peut pas faire 44 px de haut sans disloquer la ligne ;
   on élargit donc la zone cliquable par le padding vertical, sans changer la
   hauteur de ligne. */
.libro__datos .dato__enlace {
  display: inline-block;
  padding-block: 0.15rem;
  min-height: 24px;
}

.libro__biblia .dato__enlace { white-space: nowrap; }

/* ── Filtres de l'accueil ────────────────────────────────────────── */

.filtros {
  margin-block: 1.5rem 2rem;
  padding: var(--bib-gouttiere);
  background: var(--bib-fond-carte);
  border: 1px solid var(--bib-bordure);
  border-radius: var(--bib-rayon);
}

.filtros__titulo {
  margin: 0 0 0.75rem;
  font-size: 1.05rem;
}

.filtros__campos {
  display: grid;
  gap: 0.75rem;
  grid-template-columns: 1fr;
}

@media (min-width: 34rem) {
  .filtros__campos { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .filtros__campo--ancho { grid-column: 1 / -1; }
}

@media (min-width: 60rem) {
  .filtros__campos { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

.filtros__campo {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  min-width: 0;
}

.filtros__etiqueta {
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--bib-texte-doux);
}

.filtros__select,
.filtros__busqueda {
  width: 100%;
  min-height: var(--bib-cible);
  padding: 0.4rem 0.6rem;
  border: 1px solid var(--bib-bordure);
  border-radius: calc(var(--bib-rayon) - 4px);
  background: var(--bib-fond);
  color: var(--bib-texte);
  font: inherit;
  font-size: 0.95rem;
}

.filtros__select:focus-visible,
.filtros__busqueda:focus-visible,
.filtros__boton:focus-visible {
  outline: 3px solid var(--bib-texte);
  outline-offset: 2px;
}

.filtros__acciones {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  margin-top: 0.9rem;
}

.filtros__contador {
  margin: 0;
  font-size: 0.9rem;
  color: var(--bib-texte-doux);
}

.filtros__boton {
  min-height: var(--bib-cible);
  padding: 0.45rem 1rem;
  border: 1px solid var(--bib-lien);
  border-radius: var(--bib-rayon);
  background: transparent;
  color: var(--bib-lien);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}

.filtros__vacio {
  margin: 0.9rem 0 0;
  padding: 0.7rem 0.9rem;
  border-left: 4px solid var(--bib-attente);
  background: var(--bib-fond);
  color: var(--bib-texte);
  font-size: 0.95rem;
}

/* Masquage par les filtres. `display: none` et non l'opacité : une carte
   seulement transparente reste dans l'ordre de tabulation, et le lecteur au
   clavier traverse des livres invisibles. */
.tarjeta--oculta,
.catalogo__seccion--oculta { display: none; }

/* ── Pages dérivées : auteur, éditeur, année ─────────────────────── */

.autor {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: var(--bib-gouttiere);
  margin-block: 1rem 1.5rem;
}

.autor__retrato {
  flex: 0 0 auto;
  width: min(180px, 40vw);
  margin: 0;
}

.autor__retrato img {
  width: 100%;
  height: auto;
  border-radius: var(--bib-rayon);
  border: 1px solid var(--bib-bordure);
  object-fit: cover;
}

/* Absence RENDUE, jamais muette : un simple trou dans la mise en page se
   confond avec une image qui n'a pas chargé, et personne ne le signale. */
.autor__sin-retrato {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  width: min(180px, 40vw);
  aspect-ratio: 3 / 4;
  border: 1px dashed var(--bib-bordure);
  border-radius: var(--bib-rayon);
  background: var(--bib-fond-carte);
  color: var(--bib-texte-doux);
  font-size: 0.85rem;
  text-align: center;
}

.autor__cuerpo {
  flex: 1 1 14rem;
  min-width: 0;
}

.autor__fechas,
.autor__cuenta,
.autor__enlaces,
.grupo__resumen {
  margin: 0 0 0.4rem;
  color: var(--bib-texte-doux);
  font-size: 0.95rem;
}

.autor__enlaces a { color: var(--bib-lien); }

.lista-libros {
  list-style: none;
  margin: 1rem 0 0;
  padding: 0;
  display: grid;
  gap: 0.5rem;
}

.lista-libros__item {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  padding: 0.6rem 0.8rem;
  background: var(--bib-fond-carte);
  border: 1px solid var(--bib-bordure);
  border-radius: calc(var(--bib-rayon) - 2px);
}

.lista-libros__enlace {
  min-height: 24px;
  color: var(--bib-lien);
  font-weight: 600;
  text-decoration: none;
}

.lista-libros__enlace:hover { text-decoration: underline; }

/* Titre « en stock » : pas de fiche, donc pas de lien — même poids que le
   titre cliquable, couleur du texte (2026-10-17). */
.lista-libros__titulo {
  color: var(--bib-texte);
  font-weight: 600;
}

.lista-libros__detalle {
  color: var(--bib-texte-doux);
  font-size: 0.85rem;
}

/* ── « Para seguir leyendo » (F4, audit « Donner envie de lire ») ───────
   Bas de fiche, après les boutons, posé par tools/seguir-leyendo.py. Trois
   règles de DONNÉES, jamais un avis : même série, même auteur, même livre
   biblique — au plus trois livres chacune. Les listes réemploient
   .lista-libros* ; seuls le cadre et les titres de groupe sont propres. */
.seguir {
  margin-top: 2rem;
  padding-top: 1rem;
  border-top: 1px solid var(--bib-bordure);
}

.seguir__titulo {
  margin: 0;
  font-size: 1.25rem;
}

/* Étiquette d'une règle : texte secondaire (contrat § 3), pas un titre. */
.seguir__regla {
  margin: 1rem 0 0;
  color: var(--bib-texte-doux);
  font-size: 0.95rem;
  font-weight: 600;
}

.seguir .lista-libros { margin-top: 0.4rem; }

/* ── Page d'aide et FAQ ──────────────────────────────────────────── */

.ayuda__enlace {
  margin-block: 1rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
}

.boton--ayuda {
  background: var(--bib-lien);
  color: var(--bib-fond);
}

.ayuda__intro {
  padding: 0.8rem 1rem;
  background: var(--bib-fond-carte);
  border-left: 4px solid var(--bib-lien);
  border-radius: calc(var(--bib-rayon) - 4px);
}

.ayuda__pasos {
  margin: 0.8rem 0 1.4rem;
  padding-left: 1.4rem;
  display: grid;
  gap: 0.5rem;
}

.ayuda__paso { line-height: 1.55; }

/* Pictogramme SVG d'un pas de la page d'aide (54 × 54, décoratif). */
.ayuda__figura {
  display: block;
  flex: none;
  margin-block-end: 0.5rem;
  color: var(--bleu-ciel, currentColor);
}

.ayuda__faq { margin-block: 1rem 2rem; }

.ayuda__pregunta {
  margin-top: 1.1rem;
  font-weight: 700;
  color: var(--bib-texte);
}

.ayuda__respuesta {
  margin: 0.3rem 0 0;
  padding-left: 0.9rem;
  border-left: 2px solid var(--bib-bordure);
  color: var(--bib-texte);
  line-height: 1.55;
}

/* ── Pied de page : lieu et horaire (S1b, 0.5.0) ─────────────────── */
/* Posé par quartz/static/biblio-pie.js (le greffon footer n'accepte que des
   liens). Texte secondaire sûr : --bib-texte-doux = 7,86:1. */
.biblio-pie {
  margin: 0 0 0.6rem;
  color: var(--bib-texte-doux);
  font-size: 0.9rem;
  line-height: 1.5;
}

.biblio-pie__horario { font-weight: 600; }

/* ── Mouvement réduit ────────────────────────────────────────────── */

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

/* ===================================================================
   CONTRÔLE CROISÉ — à relancer après toute modification de ce fichier
   OU de `tools/airtable-to-content.py`. Il vérifie les DEUX sens :
   aucune classe émise sans règle, aucune classe stylée sans être émise.
   C'est la leçon de la règle 8 de `check:ui` : un garde qui ne compte que
   les classes orphelines ne voit pas l'absence totale de classes.

   IL LIT LA SORTIE GÉNÉRÉE, PAS LE GÉNÉRATEUR — corrigé le 2026-10-08.
   La version précédente cherchait `class="…"` dans le code Python, donc elle
   ne voyait aucune classe construite par variable (`class="{cls}"`) : elle
   déclarait 15 classes « stylées sans être émises » dont 9 l'étaient en fait.
   Un contrôle qui crie à tort finit ignoré, et c'est alors un contrôle en
   moins. La vérité est le markdown produit dans `content/`.

   ÉTATS CONDITIONNELS ATTENDUS. Huit classes sont stylées sans apparaître :
   trois états de circulation (prestado, reservado, perdido), deux absences de
   couverture, le niveau non évalué, le livre sorti, et le bouton WhatsApp
   (aucun numéro publié, décision du 2026-10-10). Elles ne sont pas mortes —
   elles attendent un livre dans cet état, ou un numéro. Elles sont listées pour que le contrôle
   reste VERT sur un catalogue sain, au lieu de hurler six fois pour rien.

     cd ~/quartz-livres-sjm && python3 - <<'EOF'
     import re, glob
     css = open('quartz/static/publish-livres.css', encoding='utf-8').read()
     out = "".join(open(p, encoding='utf-8').read()
                   for p in glob.glob('content/**/*.md', recursive=True))
     fam = (r'\.(libro__[\w-]+|tarjeta__[\w-]+|catalogo__[\w-]+|estado--[\w-]+'
            r'|boton--[\w-]+|nivel--[\w-]+|filtros__[\w-]+|autor__[\w-]+'
            r'|lista-libros__[\w-]+|ayuda__[\w-]+|dato__[\w-]+|grupo__[\w-]+|seguir__[\w-]+'
            r'|tarjeta--[\w-]+|libro|tarjeta|rejilla|estado|boton'
            r'|acciones|nivel|filtros|autor|lista-libros|seguir)\b')
     # Classes posées PAR LE SCRIPT DE FILTRE, jamais présentes dans le markdown :
     # elles naissent dans le navigateur. Les compter comme « stylées jamais
     # émises » ferait crier le contrôle à chaque passage — et un contrôle qui
     # crie à tort finit ignoré, c'est-à-dire un contrôle en moins (leçon du
     # 2026-10-08 sur la version qui lisait le générateur).
     CLIENT = {'filtros', 'filtros__titulo', 'filtros__campos', 'filtros__campo',
               'filtros__campo--ancho', 'filtros__etiqueta', 'filtros__select',
               'filtros__busqueda', 'filtros__acciones', 'filtros__contador',
               'filtros__boton', 'filtros__vacio', 'tarjeta--oculta',
               'catalogo__seccion--oculta'}
     # `tarjeta--no-disponible` a rejoint cette liste le 2026-10-08, et c'est
     # l'élargissement de `fam` aux classes `tarjeta--*` qui l'a révélée : elle
     # était stylée depuis le 2026-10-04 et jamais contrôlée. Elle n'est pas
     # morte — elle attend un livre sorti, et les 32 sont disponibles.
     # `boton--whatsapp` (2026-10-18) : le générateur ne l'émet que si le
     # panneau porte un numéro — vide à dessein depuis le 2026-10-10.
     CONDITIONNELLES = {'estado--prestado', 'estado--reservado', 'estado--perdido',
                        'libro__sin-portada', 'tarjeta__sin-portada',
                        'nivel--sin-evaluar', 'tarjeta--no-disponible',
                        'boton--whatsapp'} | CLIENT
     stylees = set(re.findall(fam, css))
     emises  = {c for v in re.findall(r'class="([^"]+)"', out) for c in v.split()}
     orphelines = sorted(stylees - emises - CONDITIONNELLES)
     sans_regle = sorted(emises - stylees)
     print('émises sans règle        :', sans_regle or 'aucune')
     print('stylées jamais émises    :', orphelines or 'aucune')
     print('classes émises           :', len(emises), '(0 serait le PIRE état)')
     raise SystemExit(1 if (orphelines or sans_regle or not emises) else 0)
     EOF
   =================================================================== */
