/**
 * 27 · LA PAGE EST UN TOME
 *
 * ┌───────────────────────────────────────────────────────────────────────┐
 * │  LA VISION, ET CE QUI LA FONDE                                        │
 * │                                                                       │
 * │  Les versions précédentes étaient des sites web qui parlaient de      │
 * │  manga. Celle-ci **se lit comme un tome** : des chapitres numérotés,  │
 * │  des gouttières franches entre les cases, un compteur de page, des    │
 * │  fiches de personnage, et une dernière page « À SUIVRE ».             │
 * │                                                                       │
 * │  Ce n'est pas un habillage. Trois résultats de recherche le fondent   │
 * │  (voir recherche/MARCHE.md § 5) :                                     │
 * │                                                                       │
 * │  · **Le format interactif produit plus d'absorption que le passif.**  │
 * │    Faire défiler une page qui se comporte comme une lecture met le    │
 * │    visiteur en position de lecteur — c'est le mécanisme même de la    │
 * │    transportation narrative, pas une métaphore.                       │
 * │                                                                       │
 * │  · **La perception de réalisme la produit aussi.** Un site qui        │
 * │    respecte la grammaire du médium est cohérent avec ce qu'il vend.   │
 * │                                                                       │
 * │  · **Mettre le produit en avant la RÉDUIT.** D'où des chapitres qui   │
 * │    ne vendent rien avant le sixième.                                  │
 * │                                                                       │
 * │  Et le format vertical est celui que cette audience lit déjà tous     │
 * │  les jours : le webtoon.                                              │
 * └───────────────────────────────────────────────────────────────────────┘
 *
 * ⚠ Se charge après `25-manga.css`, dont il réutilise la trame et les cases.
 */


/* ═══════════════════════════════════════════════════════════════════════
   LA GOUTTIÈRE — ce qui sépare deux chapitres
   ═══════════════════════════════════════════════════════════════════════
   Dans un tome, deux cases ne sont pas séparées par un dégradé : elles sont
   séparées par du blanc franc. Ici c'est du noir, et un filet.

   ⚠ **C'est ce qui remplace les fonds alternés.** Faire tourner trois teintes
   de fond était la réponse générique au « tout se ressemble ». La réponse du
   médium est meilleure : ce n'est pas la couleur qui doit changer d'un
   chapitre à l'autre, c'est la COUPURE qui doit se voir.                   */

.tome__gouttiere {
  block-size: var(--e-8);
  background: var(--noir);
  border-block-start: 2px solid var(--acier);
  position: relative;
}

/* Le petit repère au milieu de la gouttière, comme la marque d'un pli. */
.tome__gouttiere::after {
  content: '';
  position: absolute;
  inset-block-start: -2px;
  inset-inline-start: 50%;
  inline-size: 3rem;
  block-size: 2px;
  translate: -50% 0;
  background: var(--rouge);
}


/* ═══════════════════════════════════════════════════════════════════════
   LA PAGE DE CHAPITRE
   ═══════════════════════════════════════════════════════════════════════
   Dans un tome, un chapitre s'ouvre par une page qui porte son numéro et son
   titre. C'est ce qui remplace le `<h2>` centré au-dessus d'un paragraphe —
   le motif le plus reconnaissable d'une page fabriquée à la chaîne.        */

/*
 * ⚠ **Sur téléphone, le numéro se pose AU-DESSUS du titre, pas à côté.**
 *
 * Mesuré : à 390 px de large, le numéro fait 67 px — le titre n'aurait plus
 * que 272 px et se briserait en quatre lignes. Une composition qui tient sur
 * grand écran et étrangle le téléphone n'est pas une composition.
 */
.chapitre {
  display: grid;
  gap: var(--e-2);
  margin-block-end: var(--e-12);
}

/* Le numéro : énorme, en contour, comme le chiffre d'un chapitre. */
.chapitre__numero {
  font-family: var(--titre);
  font-size: var(--t-enorme);
  line-height: .75;

  /*
   * ⚠ **Le repli est une couleur pleine, pas rien.**
   *
   * `color: transparent` seul, dans un moteur sans `-webkit-text-stroke`,
   * donne un numéro invisible — et la composition s'effondre sans qu'aucune
   * erreur ne le signale. La couleur pleine est donc posée d'abord ; le
   * contour ne la remplace que là où il fonctionne.
   */
  color: color-mix(in srgb, var(--rouge) 34%, transparent);
  pointer-events: none;
  user-select: none;
}

@supports (-webkit-text-stroke: 2px red) {
  .chapitre__numero {
    color: transparent;
    -webkit-text-stroke: 2px var(--rouge);
    opacity: .55;

    /*
     * ⚠ **La trame REMPLIT le chiffre, pas sa boîte.**
     *
     * Le motif de trame existait dans `25-manga.css` depuis le début et ne
     * servait nulle part. Ici il tombe juste : un chiffre en contour rempli de
     * trame, c'est le traitement que porte n'importe quelle page de titre de
     * chapitre. `background-clip: text` découpe le fond sur la forme du glyphe
     * — et il n'a d'effet QUE parce que la couleur du texte est transparente,
     * ce qui n'est vrai que dans ce bloc.
     */
    background-image: radial-gradient(
      circle at center,
      color-mix(in srgb, var(--rouge) 55%, transparent) 1px,
      transparent 1px
    );
    background-size: 6px 6px;
    -webkit-background-clip: text;
    background-clip: text;
  }
}

/*
 * La marque des pages de fin de volume. Elle occupe la place du numéro sans
 * en avoir le poids : un bonus n'est pas un chapitre, et ça doit se voir au
 * premier coup d'œil.
 */
.chapitre__marque {
  align-self: center;
  padding: var(--e-1) var(--e-3);
  border: var(--filet) solid var(--or);
  color: var(--or);
  font-family: var(--titre);
  font-size: var(--t-sm);
  letter-spacing: var(--lettrage-capital);
  text-transform: uppercase;
  justify-self: start;
}

/* ⚠ Dans un bloc de fin, tout est centré SAUF elle : posée à gauche d'un
   titre centré, l'étiquette se lit comme un reste de mise en page. Relevé sur
   « À propos », la FAQ et « Le manga » le 6 septembre 2026.
   Le centrage se pose sur le CONTENEUR : `justify-self` sur la seule
   étiquette restait sans effet, l'alignement par défaut de la grille
   reprenant le dessus. */
.suivre .chapitre {
  /* ⚠ Une seule colonne. Le chapitre à étiquette est une grille à DEUX
     colonnes — l'étiquette à gauche, le corps à droite — et c'est juste au fil
     d'un tome. Dans un bloc de fin, où tout est centré, cette première colonne
     de 84 px collait l'étiquette contre le bord gauche d'un titre centré.
     `justify-self` seul n'y pouvait rien : l'étiquette ÉTAIT centrée, dans sa
     colonne. */
  grid-template-columns: minmax(0, 1fr);
  justify-items: center;
}

.suivre .chapitre__marque { justify-self: center; }

.chapitre--bonus .chapitre__titre { font-size: var(--t-3xl); }

/* Pas de filet rouge sous un bonus : le trait de séparation appartient aux
   chapitres, et le réutiliser partout le vide de son sens. */
.chapitre--bonus .chapitre__corps::after { display: none; }

.chapitre__surtitre {
  color: var(--or);
  font-family: var(--titre);
  font-size: var(--t-sm);
  letter-spacing: var(--lettrage-capital);
  text-transform: uppercase;
}

.chapitre__titre {
  font-size: var(--t-4xl);
  margin-block: var(--e-1) 0;
}

.chapitre__chapeau {
  max-inline-size: var(--mesure);
  margin-block-start: var(--e-3);
  color: var(--gris);
  font-size: var(--t-lg);
}

/* Le filet sous le titre, qui court jusqu'au bord — le trait de séparation
   d'une planche. Il est porté par le CORPS : ainsi il commence sous le titre
   et non sous le numéro, aux deux dispositions. */
.chapitre__corps::after {
  content: '';
  display: block;
  block-size: 2px;
  margin-block-start: var(--e-4);
  background: linear-gradient(to right, var(--rouge), transparent 70%);
}

/* À partir de la tablette, le numéro reprend sa place dans la marge. */
@media (min-width: 48rem) {
  .chapitre {
    grid-template-columns: auto 1fr;
    align-items: start;
    column-gap: clamp(1rem, 3vw, 2.5rem);
  }
}


/* ═══════════════════════════════════════════════════════════════════════
   LE COMPTEUR DE PAGE
   ═══════════════════════════════════════════════════════════════════════
   Le numéro de page d'un tome, posé dans la marge. Il dit où on en est et
   combien il reste — l'information qui manque le plus dans une page longue.

   ⚠ **Décoratif pour un lecteur d'écran** (`aria-hidden`) : la progression
   de lecture n'est pas une information de contenu, et l'annoncer à chaque
   changement serait insupportable. Le repère existe déjà dans la structure
   des titres.

   ⚠ Masqué sous 60 rem : dans la marge d'un téléphone, il n'y a pas de
   marge.                                                                    */

.compteur {
  display: none;
}

@media (min-width: 60rem) {
  .compteur {
    position: fixed;
    inset-inline-end: 0;
    inset-block-start: 50%;
    translate: 0 -50%;
    z-index: var(--plan-flottant);
    display: grid;
    gap: var(--e-2);
    justify-items: center;
    pointer-events: none;

    padding: var(--e-6) clamp(.75rem, 1.6vw, 1.5rem);
  }

  /*
   * ⚠ **Un halo, pas une plaque.**
   *
   * Le compteur flotte au-dessus de la page : sur une planche blanche, des
   * chiffres blancs disparaissent — vu à l'écran. Mais un fond opaque derrière
   * eux dessine une boîte d'interface, visible dès que la section n'est plus
   * noire — vu aussi. Un halo porté par les glyphes eux-mêmes est invisible sur
   * fond sombre et détache le chiffre sur fond clair.
   */
  .compteur__page,
  .compteur__total {
    text-shadow:
      0 0 .4rem var(--noir),
      0 0 1.2rem var(--noir);
  }

  .compteur__page {
    font-family: var(--titre);
    font-size: var(--t-xl);
    line-height: 1;
    color: var(--blanc);
    font-variant-numeric: tabular-nums;
  }

  .compteur__total {
    font-family: var(--titre);
    font-size: var(--t-sm);
    color: var(--gris);
  }

  /* Le trait de progression, vertical, comme la tranche d'un livre. */
  .compteur__tranche {
    inline-size: 2px;
    block-size: 7rem;
    background: var(--acier);
    position: relative;
    overflow: hidden;

    /* Le même halo, pour que le filet ne disparaîsse pas sur fond clair. */
    box-shadow: 0 0 .5rem .1rem var(--noir);
  }

  .compteur__tranche::after {
    content: '';
    position: absolute;
    inset-inline: 0;
    inset-block-start: 0;
    block-size: var(--avancee, 0%);
    background: var(--rouge);
    transition: block-size var(--duree-action) var(--sortie);
  }
}


/* ═══════════════════════════════════════════════════════════════════════
   LA FICHE DE PERSONNAGE
   ═══════════════════════════════════════════════════════════════════════
   Le format des pages de profil qu'on trouve à la fin d'un tome shonen :
   le portrait détouré, le nom en grand, le rôle, et une ligne de données.

   ⚠ **L'identification au personnage produit la transportation narrative.**
   Ce n'est pas de la décoration : c'est l'antécédent le mieux documenté. Une
   vignette de 120 px n'identifie personne ; une fiche pleine page, oui.    */

.fiche {
  position: relative;

  /*
   * La colonne réservée à l'étiquette verticale. Un seul nombre, lu à deux
   * endroits : la position de l'étiquette et le retrait du texte. Écrire les
   * deux séparément, c'est se garantir qu'ils divergeront un jour.
   */
  /* 3,5 rem = 56 px : mesure de l’etiquette la plus large (42 px, glyphes
     droits) plus son retrait de 12 px. Le chiffre est verifie a l’ecran, pas
     estime — une premiere valeur de 2,75 rem laissait deux noms passer
     dessous. */
  --etiquette: 3.5rem;

  /*
   * ⚠ **Une hauteur DÉFINIE, pas un `min-block-size`.**
   *
   * Une rangée de grille en `auto` avec un minimum se dimensionne sur son
   * contenu : un portrait de 900×1200 y impose 1459 px sur un écran de
   * 900. C'est exactement le défaut qui a fait exploser la hauteur de la
   * page à la version précédente. Une hauteur définie résout `100 %` à
   * l'intérieur, et la fiche fait la taille qu'on lui demande.
   */
  block-size: clamp(26rem, 62vh, 34rem);

  display: grid;
  background: var(--panneau-creux);
  border: var(--filet) solid var(--acier);
  overflow: hidden;
}

/* Portrait et identité occupent la MÊME case : l'identité se pose par-dessus
   le bas du portrait, comme le bandeau d'une fiche de fin de tome. Deux
   rangées les empileraient, et on retrouverait une carte. */
.fiche > * { grid-area: 1 / 1; }

/* La bande d'accent verticale, à gauche — le liseré d'une fiche. */
.fiche::before {
  content: '';
  position: absolute;
  inset-block: 0;
  inset-inline-start: 0;
  inline-size: 6px;
  background: var(--accent, var(--rouge));
  z-index: 3;
}

/*
 * ⚠ **Le portrait devient un contexte d'empilement, et c'est voulu.**
 *
 * Avec le projecteur du héros il y a cinq plans dans cette case : le halo, la
 * trame ou les lignes de vitesse, le nom géant, les lueurs, le personnage. Sans
 * `z-index` sur le parent, chacun se compare aux éléments de TOUTE la fiche et
 * l'ordre devient un accident — c'est exactement comme ça qu'un halo local
 * avait enterré les braises du héros de page. Ici les cinq plans se rangent
 * entre eux, et le bloc d'identité passe au-dessus de l'ensemble.
 */
.fiche__portrait {
  position: relative;
  z-index: 1;
  display: grid;
  place-items: end center;
  overflow: hidden;
}

/*
 * `contain` et pas `cover` : les portraits sont de vrais détourés sur fond
 * transparent. Les recadrer couperait un bras ou un menton.
 *
 * ⚠ **En absolu, et pour la même raison que dans le lecteur.** Sur grand écran
 * la fiche n'a plus de hauteur écrite : elle prend celle de sa rangée de grille.
 * Un `block-size: 100 %` ne s'y résout pas de façon fiable ; un élément en
 * absolu, si — il ne participe pas au dimensionnement de son parent, donc
 * aucune circularité possible.
 */
.fiche__image {
  position: absolute;
  inset: 0;
  z-index: 3;   /* devant le nom géant et les lueurs */
  inline-size: 100%;
  block-size: 100%;
  object-fit: contain;
  object-position: bottom center;
}

/*
 * La trame derrière le personnage, dans SA couleur — le screentone d'une page
 * de profil. Le motif dormait dans `25-manga.css` sans servir nulle part.
 * Le masque l'éteint vers le haut : une case entierèrement tramée devient un
 * fond, alors qu'on veut une ombre portée sous le personnage.
 */
.fiche__portrait::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: .5;
  background-image: radial-gradient(
    circle at center,
    color-mix(in srgb, var(--accent, var(--rouge)) 45%, transparent) 1px,
    transparent 1px
  );
  background-size: 7px 7px;
  mask-image: linear-gradient(to top, #000, transparent 70%);
}

/* ═══════════════════════════════════════════════════════════════════
   L'AURA — deux masses qui tournent en sens contraire
   ═══════════════════════════════════════════════════════════════════
   ⚠ **Un dégradé radial ne peut pas faire une aura vivante.** Il ne sait que
   grossir et pâlir : c'est une lampe qu'on tamise, et ça se voit. Une aura
   change de FORME.

   Ici, deux masses à la silhouette irrégulière — des `border-radius` à huit
   valeurs, jamais un cercle — tournent à des vitesses différentes et en sens
   contraire. Leur union, sous le flou, ne repasse jamais deux fois par la même
   silhouette : 17 s et 23 s sont premiers entre eux, le motif complet ne se
   répète qu'au bout de 6 min 31.

   ⚠ **Le flou est sur les MASSES, pas sur leur porteur.** Un flou posé sur le
   parent devrait être recalculé à chaque image, puisque son contenu tourne.
   Posé sur chaque masse, il est cuit une fois dans sa couche et la rotation
   n'est plus qu'une transformation — le travail de la carte graphique, pas
   celui du processeur.

   ⚠ **`prefers-reduced-motion` arrête tout ça** par la règle globale du socle :
   les masses se figent dans leur position de départ et l'aura reste une jolie
   forme immobile. Rien à redéclarer ici.                                     */

.aura {
  position: absolute;
  inset: -12%;
  z-index: 0;
  pointer-events: none;

  /* La pulsation d'ensemble. Amplitude franche — on doit la voir battre — mais
     cycle long : c'est la lenteur qui la rend douce, pas la faiblesse. */
  animation: hidaya-aura 7s var(--sortie) infinite;
  animation-delay: calc(var(--rang, 0) * -1.1s);
}

.aura::before,
.aura::after {
  content: '';
  position: absolute;
  filter: blur(1.8rem);
  will-change: transform;
}

.aura::before {
  inset: 26% 16% 10%;
  background: color-mix(in srgb, var(--accent, var(--rouge)) 40%, transparent);
  border-radius: 62% 38% 48% 52% / 55% 44% 56% 45%;
  animation: hidaya-masse-a 17s linear infinite;
}

.aura::after {
  inset: 34% 24% 6%;
  background: color-mix(in srgb, var(--accent, var(--rouge)) 28%, transparent);
  border-radius: 38% 62% 57% 43% / 43% 58% 42% 57%;
  animation: hidaya-masse-b 23s linear infinite reverse;
}

@keyframes hidaya-masse-a {
  0%   { rotate: 0deg;   scale: 1 1; }
  33%  { rotate: 120deg; scale: 1.1 .92; }
  66%  { rotate: 240deg; scale: .92 1.12; }
  100% { rotate: 360deg; scale: 1 1; }
}

@keyframes hidaya-masse-b {
  0%   { rotate: 0deg;   scale: 1 1; }
  50%  { rotate: 180deg; scale: 1.14 .88; }
  100% { rotate: 360deg; scale: 1 1; }
}


/* ═══════════════════════════════════════════════════════════════════
   LA LUEUR QUI SUIT LE CURSEUR
   ═══════════════════════════════════════════════════════════════════
   Une petite lumière qui passe sur le personnage là où se trouve la souris. En
   `screen`, elle AJOUTE de la lumière au lieu de poser un voile : sur un fond
   sombre, c'est la différence entre éclairer et salir.

   ⚠ **Les deux coordonnées ont un repli.** Sans script — ou avant le premier
   mouvement — la déclaration reste valide et la lueur attend au centre, sans
   se voir puisqu'elle est à zéro d'opacité.

   ⚠ **Pas de survol sur un écran tactile**, et le script ne s'y branche donc
   pas : rien à masquer, la lueur n'y apparaît jamais.                        */

/* ⚠ **La lueur suit le curseur sur TOUTE carte, plus seulement les fiches.**
   C'est le geste qui dit « cet élément est vivant » ; le réserver à une seule
   section revenait à dire que le reste ne l'est pas. */
.fiche::after,
.metier::after,
.famille__grille .carte__panneau::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  opacity: 0;
  mix-blend-mode: screen;
  transition: opacity var(--duree-action) var(--sortie);
  background: radial-gradient(
    8rem 8rem at var(--souris-x, 50%) var(--souris-y, 50%),
    color-mix(in srgb, var(--accent, var(--rouge)) 34%, transparent),
    transparent 68%
  );
}

.fiche:hover::after,
.fiche:focus-within::after,
.metier:hover::after,
.metier:focus-within::after,
.famille__grille .carte:hover .carte__panneau::after,
.famille__grille .carte:focus-within .carte__panneau::after { opacity: 1; }

.fiche__identite {
  position: relative;
  z-index: 2;
  align-self: end;
  /*
   * Le haut est généreux : c'est la course du dégradé qui décolle le nom du
   * dessin. Le retrait de gauche laisse passer la bande d'accent.
   *
   * ⚠ **Et le retrait de DROITE réserve la colonne de l'étiquette.** Sans lui,
   * le nom et la description passent dessous : vu à l'écran, « …la vérité »
   * traversait « LE SAGE ». Une étiquette en absolu ne pousse rien toute
   * seule ; il faut lui faire de la place — et la même place qu'elle occupe,
   * d'où le jeton partagé.
   */
  padding: var(--e-8) var(--etiquette) var(--e-4) var(--e-6);
  background: linear-gradient(to top, var(--noir) 42%, transparent);
}

/*
 * ⚠ **Le rôle à la VERTICALE, le long du bord.**
 *
 * C'est la signature typographique du médium : une étiquette qui court le long
 * de la case. Elle coûte une déclaration, elle rend au nom toute la largeur, et
 * elle fait qu'une case ne ressemble plus à une carte de site web.
 */
/* ⚠ Un seul motif d'étiquette pour tout le site : ce qui distingue une
   fiche de personnage d'une carte de métier, ce n'est pas sa typographie. */
.fiche__role,
.metier__fonction {
  position: absolute;
  inset-block-start: var(--e-3);
  inset-inline-end: var(--e-3);
  z-index: 3;

  /*
   * ┌──────────────────────────────────────────────────────────────────┐
   * │  L'ÉTIQUETTE VERTICALE — ET LES QUATRE PIÈGES QU'ELLE M'A COÛTÉS.    │
   * │                                                                       │
   * │  1. `text-orientation: upright`, pas le pivot par défaut. Un texte    │
   * │     latin en écriture verticale est pivoté d'un quart de tour EN BLOC, │
   * │     et une apostrophe pivotée devient un trait : « L’Alliée » se       │
   * │     lisait « L - ALLIÉE ». Debout, chaque lettre s'empile.            │
   * │                                                                       │
   * │  2. `max-height`, une propriété PHYSIQUE. Les propriétés logiques      │
   * │     pivotent avec le mode d'écriture : ici `block-size` désigne la     │
   * │     LARGEUR. Un `max-block-size: 62 %` ne bornait donc rien, et        │
   * │     « La Guerrière » courait sur 77 % de la hauteur de sa case.       │
   * │                                                                       │
   * │  3. `white-space: nowrap`. Une hauteur bornée ne tronque pas en        │
   * │     vertical : elle fait revenir à la ligne, et la ligne suivante est  │
   * │     une COLONNE à côté. « LA GUERRIÈRE » se lisait « EGUERRIÈR / LA ». │
   * │                                                                       │
   * │  4. Une seule déclaration par propriété. Cette règle a porté deux       │
   * │     `font-size` et deux `letter-spacing` : la dernière gagnait, et     │
   * │     mes réglages étaient morts sans qu'aucun outil ne le dise.         │
   * └──────────────────────────────────────────────────────────────────┘
   */
  writing-mode: vertical-rl;
  text-orientation: upright;
  white-space: nowrap;
  /* 72 % : la plus longue étiquette (« L’Antagoniste », 188 px) doit tenir
     dans la plus courte case (272 px à 820 px de large). Mesuré : à 62 % elle
     était coupée à cette largeur-là et à elle seule. */
  max-height: 72%;
  overflow: hidden;

  color: var(--accent, var(--rouge));
  font-family: var(--titre);
  font-size: .68rem;
  line-height: 1;
  letter-spacing: .04em;
  text-transform: uppercase;
  text-shadow: 0 0 .6rem var(--noir), 0 0 1.4rem var(--noir);
}


.fiche__nom {
  /* Le nom s'adapte à la case : à taille fixe, « LE CORBEAU » débordait d'une
     petite fiche alors que « WIRA » flottait dans une grande. */
  font-size: clamp(1.35rem, 1rem + 1.4vw, 2rem);
  margin-block: 0 var(--e-2);
}


/* ⚠ Amplitude nettement plus franche qu'au premier essai : à .72→1 et 7 % de
   dilatation, on ne la voyait pas battre. Ici l'aura double presque
   d'intensité et respire de 20 % — le cycle long garde le geste doux. */
@keyframes hidaya-aura {
  0%, 100% { opacity: .5; scale: .94; }
  50%      { opacity: 1;  scale: 1.14; }
}


/* ════════════════════════════════════════════════════════════════════
   LE HÉROS — il n'a pas la taille d'un comparse
   ════════════════════════════════════════════════════════════════════
   ⚠ **Les lignes de vitesse sont parties, et le motif est le MÊME partout.**
   Elles ne distinguaient le héros qu'en changeant de langage : une case avec un
   fond qu'aucune autre n'a ne fait pas partie de la même planche. La trame est
   désormais identique sur les sept fiches ; ce qui distingue le héros, c'est sa
   TAILLE, son halo et son prénom — pas un décor à lui.                        */

.fiche--protagoniste .fiche__nom { font-size: var(--t-4xl); }

/*
 * Le nom en géant, derrière le personnage. Il déborde de la case et s'y fait
 * couper : c'est le propre du procédé — un nom trop grand pour son cadre.
 */
.geant {
  position: absolute;
  inset-inline: 0;
  inset-block-start: 34%;
  z-index: 1;
  translate: 0 -50%;
  pointer-events: none;
  user-select: none;
  text-align: center;
  white-space: nowrap;
  font-family: var(--titre);
  line-height: .8;
  letter-spacing: .04em;
  text-transform: uppercase;
  /* La maquette d'origine posait ce nom à 85 % de blanc — très présent. À
     16 % il devenait un fantôme : on ne le lisait plus, donc il ne servait
     plus à rien. */
  color: color-mix(in srgb, var(--blanc) 26%, transparent);

  /* Repli sans requête de conteneur : grand, mais lié à l'écran. */
  font-size: clamp(2rem, 9vw, 7rem);
}

/*
 * ⚠ **`cqw` : le nom se mesure sur SA CASE, pas sur l'écran.**
 *
 * La case du héros fait 42 % de la largeur au-delà de 64 rem, 100 % en dessous.
 * Une taille en `vw` serait donc juste à une seule largeur et fausse partout
 * ailleurs. En unités de conteneur, le nom occupe toujours la même part de sa
 * case. La déclaration en `vw` juste au-dessus reste comme repli.
 */
@supports (container-type: inline-size) {
  .fiche,
  .metier { container-type: inline-size; }

  /*
   * ⚠ **La taille se déduit de la LONGUEUR du prénom.**
   *
   * « Wira » fait quatre lettres, « Le Corbeau » en fait dix : à taille égale
   * dans une case de même largeur, le second sort du cadre des deux côtés et
   * on n'en lit plus que le milieu. `238cqw / lettres` le ramène à la largeur
   * de sa case ; le plafond de 34 cqw évite qu'un prénom court ne devienne
   * énorme. Le 238 vient de la chasse de Bebas Neue — environ 0,42 em par
   * signe — vérifié à l'écran, pas estimé.
   */
  .geant {
    /* ⚠ 220 et non 238 : à 238, « Rashmad » et « Pong Po » remplissaient
       exactement 100 % de leur case et se faisaient rogner d'une lettre. La
       marge de 8 % les fait tenir. */
    font-size: min(31cqw, calc(220cqw / var(--lettres, 7)));
  }
}

/*
 * ┌──────────────────────────────────────────────────────────────────┐
 * │  SUR TÉLÉPHONE, TOUTES LES FICHES ONT LA MÊME HAUTEUR.                  │
 * │                                                                       │
 * │  Ismail, capture à l'appui : « faut pas une différence de hauteur sur   │
 * │  mobile ». Il a raison, et c'est une faute que j'avais commise en       │
 * │  connaissance de cause : j'avais donné 74 vh aux protagonistes pour     │
 * │  créer une hiérarchie là où le carrousel impose une largeur commune.     │
 * │                                                                       │
 * │  Mesuré à 390 px : 625 px contre 523. Dans une piste horizontale, deux   │
 * │  hauteurs différentes ne font pas une hiérarchie — elles font une       │
 * │  rangée cassée : la fiche voisine flotte avec un vide sous elle.        │
 * │                                                                       │
 * │  ⚠ **La hiérarchie ne disparaît pas, elle change de moyen.** Sur        │
 * │  téléphone on ne compare pas deux fiches côte à côte, on en fait        │
 * │  défiler une à la fois : ce qui distingue un protagoniste, ce sont ses  │
 * │  lueurs, son aura plus forte et son résumé — pas sa taille.            │
 * │                                                                       │
 * │  La composition en deux rangées (portrait au-dessus, identité dessous,  │
 * │  ligne de sol entre les deux) reste donc un traitement de GRAND ÉCRAN,  │
 * │  où la case est assez haute pour la porter.                            │
 * └──────────────────────────────────────────────────────────────────┘
 */
@media (min-width: 48rem) {
  /*
   * ⚠ **Chez le héros, le portrait et l'identité ne se superposent PLUS.**
   *
   * Sur une petite fiche, l'identité posée en bas du portrait économise la place.
   * Sur la grande, elle mange les jambes du personnage — et surtout elle empêche
   * la ligne de sol, qui n'a de sens qu'entre les pieds et le texte. Deux rangées
   * rendent exactement la composition du carrousel d'origine.
   */
  .fiche--protagoniste { grid-template-rows: 1fr auto; }
  .fiche--protagoniste > * { grid-area: auto; }
  .fiche--protagoniste .fiche__portrait { grid-row: 1; min-block-size: 0; }

  .fiche--protagoniste .fiche__identite {
    position: relative;
    grid-row: 2;
    align-self: auto;
    padding-block-start: var(--e-4);
    background: none;
  }

  /* La ligne de sol : le personnage se tient sur quelque chose. Reprise telle
     quelle de la maquette d'origine — c'est ce qui l'empêche de flotter. */
  .fiche--protagoniste .fiche__identite::before {
    content: '';
    position: absolute;
    inset-inline: 0;
    inset-block-start: 0;
    block-size: 2px;
    background: linear-gradient(
      90deg,
      transparent,
      var(--accent, var(--rouge)) 28%,
      var(--or) 50%,
      var(--accent, var(--rouge)) 72%,
      transparent
    );
  }
}

/* L'aura du héros porte plus loin : c'est un projecteur, plus une ombre. */
.fiche--protagoniste .aura::before {
  background: color-mix(in srgb, var(--accent, var(--rouge)) 55%, transparent);
  filter: blur(2.6rem);
}

.fiche--protagoniste .aura::after {
  background: color-mix(in srgb, var(--accent, var(--rouge)) 38%, transparent);
  filter: blur(2.6rem);
}

/* Les lueurs, entre le nom et le personnage. */
.fiche--protagoniste .braises {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
}

/*
 * ⚠ **AUCUNE hauteur propre aux protagonistes.**
 *
 * Elle valait 74 vh, soit 625 px à 390 contre 523 pour les autres, et ce n'était
 * pas un détail : dans une piste horizontale, une fiche plus haute que sa
 * voisine laisse un vide sous cette dernière. Toutes les fiches partagent
 * désormais le `clamp` de `.fiche`, et la rangée est droite.
 */
.fiche--protagoniste .fiche__texte { -webkit-line-clamp: 4; }


/* ════════════════════════════════════════════════════════════════════
   L'ANTAGONISTE — la case elle-même est de travers
   ════════════════════════════════════════════════════════════════════
   Une case oblique, c'est le signal de tension du médium : le lecteur le
   comprend sans savoir le nommer. Un coin coupé coûte un `clip-path`.        */

.fiche--antagoniste {
  clip-path: polygon(
    0 0,
    100% 0,
    100% calc(100% - 2.5rem),
    calc(100% - 2.5rem) 100%,
    0 100%
  );
}

/* Le portrait s'assombrit : l'antagoniste ne se présente pas sous la même
   lumière que le héros. */
.fiche--antagoniste .fiche__image { filter: brightness(.84) contrast(1.06); }

/*
 * ⚠ **Sur une case LARGE, le portrait se range à droite.**
 *
 * Un détouré centré dans une case deux fois plus large que haute laisse deux
 * grands vides et le nom flotte dans l'un d'eux. Le portrait à droite, le nom à
 * gauche : la case se lit, et c'est la mise en page d'une bande.
 */
@media (min-width: 64rem) {
  .fiche--antagoniste .fiche__image { object-position: bottom right; }
  .fiche--antagoniste .fiche__portrait::before {
    background: radial-gradient(
      42% 62% at 76% 74%,
      color-mix(in srgb, var(--accent, var(--rouge)) 30%, transparent),
      transparent 72%
    );
  }
}

/* ⚠ Plus de trame plus dense pour l'antagoniste non plus : même motif partout.
   Ce qui le distingue reste la coupe oblique de sa case et son portrait
   assombri — deux choses qui parlent de LUI, pas de son fond. */

.fiche__texte {
  color: var(--gris);
  font-size: var(--t-sm);
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Le numéro de fiche, dans le coin — comme une référence de personnage. */
.fiche__reference {
  position: absolute;
  inset-block-start: var(--e-3);
  inset-inline-end: var(--e-3);
  z-index: 3;
  font-family: var(--titre);
  font-size: var(--t-sm);
  letter-spacing: var(--lettrage-capital);
  color: var(--gris);
  font-variant-numeric: tabular-nums;
}


/* ═══════════════════════════════════════════════════════════════════════
   LE SENS DE LECTURE
   ═══════════════════════════════════════════════════════════════════════
   Un manga se lit de droite à gauche, et tous les tomes portent ce repère.
   C'est le détail que personne ne met sur un site — et il est vrai.        */

.sens-lecture {
  display: inline-flex;
  align-items: center;
  gap: var(--e-2);
  padding: var(--e-1) var(--e-3);
  border: var(--filet) solid var(--acier);
  color: var(--gris);
  font-family: var(--titre);
  font-size: var(--t-xs);
  letter-spacing: var(--lettrage-capital);
  text-transform: uppercase;
}

.sens-lecture::before { content: '\2190'; color: var(--rouge); font-size: 1.2em; }


/* ═══════════════════════════════════════════════════════════════════════
   LA DERNIÈRE PAGE — « À SUIVRE »
   ═══════════════════════════════════════════════════════════════════════
   Un tome ne se termine pas par un formulaire : il se termine par une
   promesse. C'est exactement là qu'un manga place son appel au tome
   suivant — et c'est donc là que la demande est le moins ressentie comme
   une demande.                                                             */

.suivre {
  position: relative;
  text-align: center;
  padding-block: var(--e-24);
}

.suivre__mention {
  font-family: var(--titre);
  font-size: clamp(3rem, 1.5rem + 6vw, 7rem);
  line-height: .9;
  letter-spacing: .06em;
  text-transform: uppercase;

  /* Même repli que le numéro de chapitre, pour la même raison. */
  color: color-mix(in srgb, var(--rouge) 62%, transparent);
}

@supports (-webkit-text-stroke: 2px red) {
  .suivre__mention {
    color: transparent;
    -webkit-text-stroke: 2px var(--rouge);
  }
}

.suivre__titre {
  font-size: var(--t-3xl);
  margin-block: var(--e-6) var(--e-3);
}

.suivre__texte {
  max-inline-size: var(--mesure);
  margin: 0 auto var(--e-8);
  color: var(--gris);
  font-size: var(--t-lg);
}

/* ═══════════════════════════════════════════════════════════════════
   LE TOME OUVERT — l'objet qu'on clique
   ═══════════════════════════════════════════════════════════════════
   Une piste de quatre vignettes se REGARDE. Un volume posé sur la page, avec sa
   tranche et son pli, s'OUVRE — et c'est le geste qu'on cherche : le format
   interactif produit plus d'absorption que le format passif.

   ⚠ **`direction: rtl`.** Un manga se lit de droite à gauche : la planche 21
   est à DROITE, la 22 à gauche. L'ordre du HTML reste 21, 22 — c'est le CSS
   qui place, donc un lecteur d'écran annonce toujours le bon ordre.           */

.tome-ouvert {
  position: relative;
  isolation: isolate;
  display: grid;
  justify-items: center;
  max-inline-size: 58rem;
  margin-inline: auto;
  color: inherit;
  text-decoration: none;
  transition: translate var(--duree-action) var(--sortie);
}

/* La double page. C'est ELLE qui est en écriture de droite à gauche, pas tout
   le bloc : le volume et l'invite restent en lecture normale. */
.tome-ouvert__pages {
  /* Le pli est un ``::before`` en absolu : sans ce ``relative``, il se
     positionnerait sur tout le bloc et le trait descendrait derriere le
     volume au lieu de s arreter au bas des pages. */
  position: relative;
  display: grid;
  grid-template-columns: 1fr;   /* une seule page sur téléphone */
  direction: rtl;
  inline-size: 100%;
  filter: drop-shadow(0 1.6rem 2.4rem rgba(0, 0, 0, .75));
}

/* À partir de la tablette, la double page — le tome est vraiment ouvert. */
@media (min-width: 48rem) {
  .tome-ouvert__pages { grid-template-columns: 1fr 1fr; }
}

/*
 * Le volume, DEVANT ses pages.
 *
 * ⚠ **La remontée est en pourcentage, donc stable.** Un pourcentage de marge
 * se résout toujours sur la LARGEUR du bloc conteneur — jamais sur la hauteur,
 * qui varie ici avec la forme des planches. Le chevauchement garde donc la même
 * proportion à toutes les tailles d'écran, ce qu'une valeur en pixels ne fait
 * pas.
 */
.tome-ouvert__volume {
  position: relative;
  z-index: 4;
  inline-size: min(76%, 28rem);
  block-size: auto;
  margin-block-start: -15%;
  filter: drop-shadow(0 1rem 1.8rem rgba(0, 0, 0, .9));
  transition: translate var(--duree-action) var(--sortie),
              transform var(--duree-action) var(--sortie);
}

/*
 * L'inclinaison, posée par le script au passage du pointeur.
 *
 * ⚠ **Les deux angles ont un repli à zéro.** Sans script — ou avant le premier
 * mouvement — la déclaration reste valide et le livre est simplement droit. Un
 * `var()` nu sur une variable jamais posée annulerait TOUTE la déclaration, et
 * `transform` avec elle.
 */
.tome-ouvert__volume {
  transform: perspective(60rem)
             rotateX(var(--incline-x, 0deg))
             rotateY(var(--incline-y, 0deg));
}

.tome-ouvert__page {
  position: relative;
  display: block;
  overflow: hidden;
  background: var(--blanc);

  /* La forme réelle du fichier, mesurée par `hidaya_dimensions()`. */
  aspect-ratio: var(--forme, 3 / 4);

  /* La tranche : l'épaisseur du volume, sur le bord extérieur. */
  box-shadow:
    .4rem 0 0 -.15rem color-mix(in srgb, var(--blanc) 16%, transparent),
    .8rem 0 0 -.35rem color-mix(in srgb, var(--blanc) 9%, transparent);
}

.tome-ouvert__page--gauche {
  display: none;   /* la seconde page n'apparaît qu'à partir de 48 rem */
  box-shadow:
    -.4rem 0 0 -.15rem color-mix(in srgb, var(--blanc) 16%, transparent),
    -.8rem 0 0 -.35rem color-mix(in srgb, var(--blanc) 9%, transparent);
}

@media (min-width: 48rem) {
  .tome-ouvert__page--gauche { display: block; }

  /* Le pli, au centre : c'est lui qui fait lire « un livre » et non
     « deux images côte à côte ». */
  .tome-ouvert__pages::before {
    content: '';
    position: absolute;
    inset-block: 0;

    /*
     * ┌──────────────────────────────────────────────────────────┐
     * │  `left`, PAS `inset-inline-start` — ET C'EST MESURÉ.               │
     * │                                                                   │
     * │  `.tome-ouvert__pages` est en `direction: rtl`, parce que les pages │
     * │  d'un manga se suivent de droite à gauche. Dans ce conteneur,       │
     * │  **`inset-inline-start` ne veut pas dire « gauche », il veut dire   │
     * │  « droite »** : le bord DROIT du dégradé se posait sur le milieu,   │
     * │  puis `translate: -50%` le décalait encore d'une demi-largeur.     │
     * │                                                                   │
     * │  Relevé à 1505 px : pli centré sur **392 au lieu de 464**, soit     │
     * │  72 px trop à gauche — exactement sa propre largeur. Il tombait    │
     * │  donc en entier DANS la page de gauche au lieu d'être la reliure.  │
     * │                                                                   │
     * │  Une reliure est au milieu géométrique. Ce n'est pas une notion de │
     * │  sens de lecture : la propriété physique est la bonne, et elle ne  │
     * │  peut pas se retourner le jour où quelqu'un touche à `direction`.  │
     * └──────────────────────────────────────────────────────────┘
     */
    left: 50%;
    inline-size: 4.5rem;
    translate: -50% 0;
    z-index: 2;
    pointer-events: none;
    background: linear-gradient(
      to right,
      transparent,
      rgba(0, 0, 0, .30) 44%,
      rgba(0, 0, 0, .55) 50%,
      rgba(0, 0, 0, .30) 56%,
      transparent
    );
  }
}

.tome-ouvert__image {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  transition: scale var(--duree-entree) var(--sortie);
}

/*
 * L'invite : TOUJOURS visible, jamais seulement au survol — sur un écran
 * tactile il n'y a pas de survol, et l'invite y est encore plus nécessaire.
 *
 * ⚠ **Plus aucun voile sur le dessin.** Tant que l'invite était posée SUR les
 * planches, il fallait un dégradé noir derrière elle pour qu'elle reste lisible
 * — et ce dégradé mangeait les cases du bas, c'est-à-dire exactement ce qu'on
 * était venu montrer. Sous le volume, sur le fond de la section, elle n'a plus
 * besoin de rien.
 */
.tome-ouvert__invite {
  display: grid;
  justify-items: center;
  gap: var(--e-1);
  margin-block-start: var(--e-4);
  pointer-events: none;
}

.tome-ouvert__mot {
  display: inline-flex;
  align-items: center;
  gap: var(--e-2);
  color: var(--blanc);
  font-family: var(--titre);
  font-size: var(--t-xl);
  letter-spacing: var(--lettrage-capital);
  text-transform: uppercase;
  transition: color var(--duree-action) var(--sortie);
}

/* Un livre qui s'ouvre, dessiné en masque : aucun fichier à charger, et la
   couleur suit le survol. */
.tome-ouvert__mot::before {
  content: '';
  inline-size: 1.1em;
  block-size: 1.1em;
  background: currentColor;
  mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M12 7v14'/><path d='M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z'/></svg>") center / contain no-repeat;
}

.tome-ouvert__compte {
  color: var(--gris);
  font-family: var(--titre);
  font-size: var(--t-xs);
  letter-spacing: var(--lettrage-capital);
  text-transform: uppercase;
}

.tome-ouvert:hover .tome-ouvert__volume,
.tome-ouvert:focus-visible .tome-ouvert__volume { translate: 0 -.6rem; }
.tome-ouvert:hover .tome-ouvert__image { scale: 1.02; }
.tome-ouvert:hover .tome-ouvert__mot,
.tome-ouvert:focus-visible .tome-ouvert__mot { color: var(--rouge); }


/* ═══════════════════════════════════════════════════════════════════
   LE LECTEUR — le tome ouvert en plein écran
   ═══════════════════════════════════════════════════════════════════
   ⚠ **`.lecteur[open]`, PAS `.lecteur`.** La feuille du navigateur pose
   `dialog:not([open]) { display: none }`, qui pèse (0,1,1). Une règle
   `.lecteur { display: grid }` ne pèse que (0,1,0) : le lecteur serait visible
   en permanence, en haut de la page, ouvert ou pas. En qualifiant par `[open]`
   la règle pèse (0,2,0) et ne s'applique QUE quand le dialogue est ouvert.    */

.lecteur {
  inline-size: 100%;
  max-inline-size: 100%;
  block-size: 100%;
  max-block-size: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  overflow: hidden;
  background: var(--noir);
  color: var(--blanc);
}

/*
 * ⚠ **Plus de rangées : la planche occupe TOUT.**
 *
 * La barre et les commandes ne prennent plus de place dans la mise en page ;
 * elles flottent en dégradé par-dessus, et s'effacent au bout de quelques
 * secondes sans geste. C'est ce que fait n'importe quelle liseuse, et c'est ce
 * qui transforme « une fenêtre qui montre une image » en « une planche qu'on
 * lit » : sur un téléphone, la barre et les commandes coûtaient 138 px de
 * hauteur, soit un cinquième de la planche.
 */
.lecteur[open] { display: block; }

.lecteur::backdrop { background: rgba(0, 0, 0, .94); }

/* ────────────────────────────────────────────────────────────
   La barre du haut */

.lecteur__barre {
  position: absolute;
  inset-inline: 0;
  inset-block-start: 0;
  z-index: 5;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: var(--e-3);
  padding: var(--e-3) var(--gouttiere) var(--e-8);

  /* Un dégradé, pas un bandeau : l'interface ne doit pas dessiner de boîte
     par-dessus le dessin. */
  background: linear-gradient(to bottom, rgba(0, 0, 0, .88), transparent);
  transition: opacity var(--duree-action) var(--sortie),
              translate var(--duree-action) var(--sortie);
}

.lecteur__outils {
  justify-self: end;
  display: flex;
  align-items: center;
  gap: var(--e-2);
}

.lecteur__mode {
  padding: var(--e-2) var(--e-3);
  border: var(--filet) solid var(--acier);
  background: transparent;
  color: var(--blanc);
  font-family: var(--titre);
  font-size: var(--t-xs);
  letter-spacing: var(--lettrage-capital);
  text-transform: uppercase;
  cursor: pointer;
  transition: border-color var(--duree-action) var(--sortie), color var(--duree-action) var(--sortie);
}

.lecteur__mode:hover,
.lecteur__mode:focus-visible { border-color: var(--or); color: var(--or); }

/*
 * ┌───────────────────────────────────────────────────────────┐
 * │  PAS D'AGRANDISSEMENT SUR TÉLÉPHONE — ET C'EST UNE CONTRAINTE DE      │
 * │  GÉOMÉTRIE, PAS UN RÉGLAGE.                                          │
 * │                                                                     │
 * │  Agrandir une planche sur 390 px de large la fait forcément déborder,  │
 * │  donc forcément couper en largeur. Une case qui prend toute la        │
 * │  largeur de la planche — et il y en a une dès la première — se        │
 * │  retrouve alors coupée en deux, quel que soit l'endroit de la coupe.   │
 * │                                                                     │
 * │  Il n'y a pas de réglage qui échappe à ça : seul un découpage sur les  │
 * │  VRAIES cases le ferait, et il n'est pas trouvable automatiquement    │
 * │  sur ces planches (cherché par les gouttières et par les cadres, les  │
 * │  deux négatifs).                                                     │
 * │                                                                     │
 * │  ⚠ La planche tient donc dans la largeur, à 0,25 de sa taille réelle.  │
 * │  Le pincement du navigateur reste disponible — la balise `viewport`   │
 * │  ne le bloque pas, et c'est volontaire.                              │
 * └───────────────────────────────────────────────────────────┘
 */
@media (max-width: 47.99rem) {
  .lecteur__mode { display: none; }
}

/* ⚠ Sous 30 rem, « HIDAYA — Tome 2 » et « Planche 21 » se disputent la même
   ligne et le numéro cesse d'être centré. Le numéro est l'information utile ;
   la marque est déjà partout ailleurs. */
.lecteur__marque {
  display: none;
  color: var(--gris);
  font-family: var(--titre);
  font-size: var(--t-sm);
  letter-spacing: var(--lettrage-capital);
}

@media (min-width: 30rem) {
  .lecteur__marque { display: block; }
}

.lecteur__compte {
  color: var(--blanc);
  font-family: var(--titre);
  font-size: var(--t-base);
  letter-spacing: var(--lettrage-capital);
  text-transform: uppercase;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

.lecteur__fermer {
  inline-size: 2.75rem;
  block-size: 2.75rem;
  border: var(--filet) solid var(--acier);
  background: transparent;
  color: var(--blanc);
  font-size: var(--t-xl);
  line-height: 1;
  cursor: pointer;
  transition: border-color var(--duree-action) var(--sortie), color var(--duree-action) var(--sortie);
}

.lecteur__fermer:hover,
.lecteur__fermer:focus-visible { border-color: var(--rouge); color: var(--rouge); }

/* ────────────────────────────────────────────────────────────
   Les planches */

.lecteur__piste {
  position: absolute;
  inset: 0;
  direction: rtl;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 100%;

  /*
   * ⚠ **`grid-template-rows: 100%`, et c'est TOUT L'ENJEU.**
   *
   * Sans lui, la rangée implicite vaut `auto` : elle se dimensionne sur son
   * contenu, donc `max-block-size: 100 %` sur la planche ne se résout PAS
   * (100 % de quoi ?) et l'image garde sa hauteur naturelle. Observé à
   * l'écran : 981 px de planche dans 800 px de piste, le bas de la page coupé.
   *
   * La piste est la rangée `1fr` du dialogue — hauteur définie. Un pourcentage
   * posé dessus l'est donc aussi, et la chaîne se résout jusqu'à l'image.
   *
   * C'est la troisième fois que ce même mécanisme coûte une passe sur ce
   * thème : une hauteur indéfinie ne se voit nulle part, elle se déduit.
   */
  grid-template-rows: 100%;

  overflow: auto;
  overscroll-behavior: contain;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
}

.lecteur__piste::-webkit-scrollbar { display: none; }

/*
 * ┌───────────────────────────────────────────────────────────┐
 * │  ON TOURNE UN FEUILLET, PAS UNE PAGE — ET ÇA CHANGE TOUT LE RESTE.  │
 * │                                                                    │
 * │  L'ancien commentaire disait « on avance d'une page à la fois,       │
 * │  exactement comme dans un volume ». C'était faux : dans un volume on │
 * │  tourne un FEUILLET, et deux pages neuves apparaissent ensemble.     │
 * │  Une planche ne passe jamais de la gauche à la droite de la reliure. │
 * │                                                                    │
 * │  Et cette erreur en cachait une visible. Chaque planche était        │
 * │  centrée DANS SA MOITIÉ d'écran : mesuré à 2000 px, la planche de     │
 * │  droite peinte à 1214..1786 et celle de gauche à 214..786 — **428 px │
 * │  de noir entre les deux**, avec le pli qui flottait au milieu de     │
 * │  rien.                                                             │
 * │                                                                    │
 * │  Les pousser contre la reliure demande de savoir laquelle est à      │
 * │  droite — donc un appariement STABLE. D'où l'aimantation par         │
 * │  feuillet : les cases impaires (rangs 0, 2, 4…) sont les pages de    │
 * │  droite et portent seules le point d'arrêt.                         │
 * │                                                                    │
 * │  ⚠ Le script doit suivre : il avance de DEUX en double page. Sans    │
 * │  ça, un appui sur deux ne bougerait rien.                           │
 * └───────────────────────────────────────────────────────────┘
 */
@media (min-width: 64rem) {
  .lecteur[data-mode="page"] .lecteur__piste { grid-auto-columns: 50%; }

  /* Le feuillet s'arrête sur sa page de droite ; sa voisine de gauche
     l'accompagne sans point d'arrêt propre. */
  .lecteur[data-mode="page"] .lecteur__page:nth-child(even) {
    scroll-snap-align: none;
  }

  /*
   * `object-position` est PHYSIQUE : `left` reste à gauche même si la piste
   * est en `rtl`. C'est exactement ce qu'on veut ici — la reliure est au
   * milieu de l'écran, pas au début du sens de lecture.
   *
   * Le `padding` de l'image reste : les deux planches ne se collent pas, il
   * demeure une gouttière de 2 × var(--e-3) de part et d'autre du pli.
   */
  .lecteur[data-mode="page"] .lecteur__page:nth-child(odd) .lecteur__image {
    object-position: left center;
  }

  .lecteur[data-mode="page"] .lecteur__page:nth-child(even) .lecteur__image {
    object-position: right center;
  }

  /*
   * ┌───────────────────────────────────────────────────────────┐
   * │  « À SUIVRE » PREND LE FEUILLET ENTIER, ET ÇA RÉPARE LE COMPTE.      │
   * │                                                                    │
   * │  Avec cinq cases à 50 %, la piste mesure 250 % et ne peut défiler que  │
   * │  de 150. Le dernier feuillet visait 200 : le navigateur le ramenait  │
   * │  à 150, et **réappariait les planches** — on revoyait la 24 à droite,  │
   * │  du mauvais côté de la reliure, puisque la parité ne correspondait     │
   * │  plus. Observé à l'écran, pas déduit.                                │
   * │                                                                    │
   * │  En donnant la largeur entière à la clôture, la piste passe à 300 %   │
   * │  pour 200 de défilement, et les trois arrêts tombent PILE sur 0, 100  │
   * │  et 200. Plus de calage, plus de réappariement.                      │
   * │                                                                    │
   * │  Et c'est meilleur en soi : une carte de fin n'est pas la moitié     │
   * │  d'un feuillet, c'est ce qu'on voit quand on referme.                │
   * └───────────────────────────────────────────────────────────┘
   */
  .lecteur[data-mode="page"] .lecteur__page--fin {
    grid-column: span 2;
    scroll-snap-align: start;
  }
}


/* ────────────────────────────────────────────────────────────
   LE MODE « PLEINE LARGEUR » — celui où l'on LIT

   ⚠ **Le défaut dépend de l'écran, et c'est le script qui le choisit.**

   « Page entière » montre la planche en entier : parfait sur un grand écran, où
   elle reste lisible. Sur un téléphone, la même planche tient dans 390 px de
   large — les bulles deviennent illisibles. On la VOIT, on ne la LIT pas.

   ⚠ **« Pleine largeur » ne suffisait PAS, et c'est une mesure qui l'a dit.**
   À 390 px, une planche à 100 % de la largeur fait 390×549 — exactement ce que
   donnait déjà « planche entière », puisque c'est la largeur de l'écran qui
   contraint dans les deux cas. Le mode ne changeait donc rien là où il servait
   le plus. Il faut DÉPASSER la largeur de l'écran, et laisser déplacer.

   ⚠ **Le zoom est borné par la largeur du FICHIER** (`--largeur`, mesurée par
   `hidaya_dimensions()`). Au-delà, on n'agrandit plus le dessin : on agrandit
   ses pixels.

   ⚠ **Vertical contenu, horizontal chaîné.** En bloquant les deux axes, on
   s'enfermerait dans la planche : le glissement ne tournerait plus la page et
   il ne resterait que les boutons — lesquels s'effacent au bout de quelques
   secondes. En laissant l'axe horizontal se chaîner, on parcourt la planche
   puis, arrivé au bord, on passe à la suivante. C'est le geste continu.       */

.lecteur[data-mode="zoom"] .lecteur__page {
  overflow: auto;
  overscroll-behavior-y: contain;
  overscroll-behavior-x: auto;
  scrollbar-width: none;
}

.lecteur[data-mode="zoom"] .lecteur__page::-webkit-scrollbar { display: none; }

.lecteur[data-mode="zoom"] .lecteur__image {
  position: static;
  /*
   * ┌────────────────────────────────────────────────────────┐
   * │  DEUX LARGEURS D'ÉCRAN, ET C'EST LA GÉOMÉTRIE QUI DONNE LE NOMBRE.  │
   * │                                                                   │
   * │  `155vw` était un chiffre de confort, pas une mesure. À 390 px il    │
   * │  donnait 605 px de planche sur 1559 natifs, soit **0,39** — c'est-à- │
   * │  dire, à un cheveu près, l'ajustement en HAUTEUR (844/2197 = 0,384). │
   * │  Le mode « lire en grand » rognait donc un tiers de la planche sans  │
   * │  rien agrandir du tout. Il ne servait à rien.                       │
   * │                                                                   │
   * │  La planche a un rapport de 1,41 ; un téléphone, 2,16. Elle est bien │
   * │  plus carrée que lui, donc **aucune échelle lisible ne tient dans    │
   * │  l'écran** : l'ajuster en largeur laisse un tiers de vide, en        │
   * │  hauteur coupe un tiers du dessin. Il faut déborder, et choisir de   │
   * │  combien.                                                          │
   * │                                                                   │
   * │  `200%` est le seul nombre qui se justifie : la planche fait        │
   * │  exactement DEUX largeurs d'écran. On lit la moitié droite, on       │
   * │  glisse une fois, on lit la moitié gauche, on glisse encore et la    │
   * │  page tourne. Le geste est régulier, jamais à tâtons.               │
   * │                                                                   │
   * │    390 px  →  780 de planche  →  **0,50**  (contre 0,39)            │
   * │   1440 px  →  1559, borné par le fichier  →  1,00  (inchangé)        │
   * │                                                                   │
   * │  ⚠ `--largeur` reste la borne dure : au-delà de la largeur du        │
   * │  FICHIER on n'agrandit plus le dessin, on agrandit ses pixels.      │
   * └────────────────────────────────────────────────────────┘
   */
  inline-size: max(100%, min(200%, var(--largeur, 1400px)));
  max-inline-size: none;
  block-size: auto;
  padding: 0;
}

/* La dernière page reste centrée : elle n'a rien à faire défiler. */
.lecteur[data-mode="zoom"] .lecteur__page--fin { overflow: hidden; }

/* En zoom, une planche à la fois : deux planches à moitié déplacées chacune,
   personne ne s'y retrouve. */
@media (min-width: 64rem) {
  .lecteur[data-mode="zoom"] .lecteur__piste { grid-auto-columns: 100%; }
}

/*
 * ┌──────────────────────────────────────────────────────────────────┐
 * │  LA PLANCHE SE POSE EN ABSOLU, ET C'EST LE SEUL MOYEN SÛR.            │
 * │                                                                       │
 * │  Diagnostic fait à l'écran, pas deviné : sur la même image,            │
 * │  `height: 400px !important` s'appliquait, `height: 100 % !important`   │
 * │  était ignoré. Ce n'était donc pas une question de cascade mais de     │
 * │  RÉSOLUTION : la case était une grille dont la rangée implicite vaut   │
 * │  `auto`, donc dimensionnée par son contenu — l'image. Une image qui    │
 * │  demande « 100 % de la hauteur que je détermine » est circulaire :     │
 * │  le navigateur abandonne et garde la hauteur naturelle. Résultat :     │
 * │  981 px de planche dans 762 px de case, le bas de la page coupé.       │
 * │                                                                       │
 * │  Un élément positionné en absolu ne participe PAS au dimensionnement   │
 * │  de son parent. La circularité disparaît, le bloc conteneur est la     │
 * │  boîte de remplissage de la case, et le pourcentage se résout          │
 * │  toujours. `object-fit: contain` fait le reste : la planche s'inscrit  │
 * │  dedans sans jamais être déformée ni rognée, quelle que soit sa forme. │
 * └──────────────────────────────────────────────────────────────────┘
 */
.lecteur__page {
  position: relative;
  scroll-snap-align: start;
  min-inline-size: 0;
}

.lecteur__image {
  position: absolute;
  inset: 0;

  /*
   * Sur une image, `auto` reprend la taille du FICHIER et ignore les `inset` :
   * une planche de 1559 x 2197 sortait telle quelle. Les pourcentages, eux, se
   * resolvent ici sans circularite possible.
   *
   * La marge autour de la planche est un PADDING de l’image, pas de la case :
   * un element en absolu se dimensionne sur la boite de remplissage de son
   * ancetre, donc le padding de la case ne l’ecarterait pas. `object-fit`
   * inscrit le dessin dans la boite de CONTENU — le padding est donc respecte.
   */
  inline-size: 100%;
  block-size: 100%;
  max-inline-size: none;
  padding: var(--e-3);
  object-fit: contain;
}

/* ────────────────────────────────────────────────────────────
   La dernière page de l'extrait */

/* ⚠ **Cette case-là EST une grille.** Les cases de planche n'en sont plus
   une — une image en absolu s'y place seule. Celle-ci contient du texte, qui
   doit être centré : sans ça il se colle en haut et l'accent de « À » passe
   sous la barre du lecteur. Vu à l'écran. */
.lecteur__page--fin {
  display: grid;
  place-items: center;
}

.lecteur__fin {
  display: grid;
  justify-items: center;
  gap: var(--e-4);
  max-inline-size: 26rem;
  padding: var(--e-4);
  direction: ltr;
  text-align: center;
}

.lecteur__fin-mention {
  font-family: var(--titre);
  font-size: clamp(2.5rem, 1.5rem + 4vw, 4.5rem);

  /* ⚠ Pas de `line-height` sous 1 sur une capitale accentuée : la boîte de
     ligne devient plus courte que le glyphe et l'accent de « À » se fait
     rogner. C'est exactement ce qui se voyait sur « À SUIVRE ». */
  line-height: 1.05;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--rouge) 62%, transparent);
}

@supports (-webkit-text-stroke: 2px red) {
  .lecteur__fin-mention {
    color: transparent;
    -webkit-text-stroke: 2px var(--rouge);
  }
}

.lecteur__fin-texte { color: var(--gris); font-size: var(--t-lg); }

/* Le volume, sur la dernière page : l'objet qui répond à « et le reste ? ». */
.lecteur__fin-volume {
  inline-size: min(100%, 18rem);
  block-size: auto;
  filter: drop-shadow(0 .8rem 1.4rem rgba(0, 0, 0, .9));
}

/* ────────────────────────────────────────────────────────────
   Les commandes */

.lecteur__commandes {
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  z-index: 5;
  display: flex;
  justify-content: space-between;
  gap: var(--e-3);
  padding: var(--e-8) var(--gouttiere) var(--e-3);
  background: linear-gradient(to top, rgba(0, 0, 0, .88), transparent);
  transition: opacity var(--duree-action) var(--sortie),
              translate var(--duree-action) var(--sortie);
}


/* ────────────────────────────────────────────────────────────
   L'INTERFACE S'EFFACE

   ⚠ **Elle revient au moindre geste, et dès qu'une commande reçoit le focus.**
   Personne ne doit se retrouver à naviguer au clavier dans une barre invisible :
   c'est la faute classique des lecteurs « immersifs ».                        */

.lecteur.est-nu .lecteur__barre {
  opacity: 0;
  translate: 0 -100%;
  pointer-events: none;
}

.lecteur.est-nu .lecteur__commandes {
  opacity: 0;
  translate: 0 100%;
  pointer-events: none;
}


/* ────────────────────────────────────────────────────────────
   LE PLI, en mode double page */

.lecteur__pli { display: none; }

@media (min-width: 64rem) {
  .lecteur[data-mode="page"] .lecteur__pli {
    display: block;
    position: absolute;
    inset-block: 0;

    /* ⚠ Le même piège qu'à l'aperçu, ici sans dommage : `.lecteur` est en
       LTR, donc `inset-inline-start` valait bien `left`. Mesuré à 960..1040
       pour un milieu à 1000, c'était juste — par chance. La propriété
       physique enlève la chance de l'équation. */
    left: 50%;
    inline-size: 5rem;
    translate: -50% 0;
    z-index: 3;
    pointer-events: none;
    background: linear-gradient(
      to right,
      transparent,
      rgba(0, 0, 0, .26) 44%,
      rgba(0, 0, 0, .52) 50%,
      rgba(0, 0, 0, .26) 56%,
      transparent
    );
  }
}


/* ────────────────────────────────────────────────────────────
   LE REPÈRE DE SENS — une seule fois dans la vie du visiteur */

/* ────────────────────────────────────────────────
   LA PAGE DE GARDE — le sens de lecture, montré et non dit

   Elle couvre la planche le temps de trois respirations, puis s'efface. Un
   appui l'écarte tout de suite : personne n'attend une animation qu'il a
   déjà comprise.                                                            */

.lecteur__sens {
  position: absolute;
  inset: 0;
  z-index: 7;
  display: grid;
  place-items: center;
  padding: var(--gouttiere);
  background: rgba(10, 10, 12, .90);
  cursor: pointer;
  animation: hidaya-sens-parait var(--duree-entree) var(--sortie);
}

.lecteur__sens[hidden] { display: none; }

.lecteur__sens.s-efface {
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--duree-action) var(--sortie);
}

.lecteur__sens-carte {
  display: grid;
  justify-items: center;
  gap: var(--e-4);
  max-inline-size: 22rem;
  text-align: center;
}

.lecteur__sens-titre {
  color: var(--blanc);
  font-family: var(--titre);
  font-size: clamp(1.4rem, 1.05rem + 1.7vw, 2.1rem);
  line-height: 1.15;
  letter-spacing: var(--lettrage-capital);
  text-transform: uppercase;
}

.lecteur__sens-schema {
  display: grid;
  justify-items: center;
  gap: var(--e-2);
  inline-size: min(100%, 14rem);
}

.lecteur__sens-fleche {
  color: var(--rouge);
  font-size: var(--t-2xl);
  line-height: 1;
  animation: hidaya-sens-glisse 1.8s var(--sortie) infinite;
}

/*
 * ⚠ **La page 1 est à DROITE, et c'est tout le propos du schéma.**
 * En écriture normale, le premier élément du balisage se pose à gauche : on
 * écrit donc la 2 avant la 1. Inverser le balisage « pour que ça se lise mieux
 * dans le code » retournerait le dessin et enseignerait le contraire.
 */
.lecteur__sens-pages {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--e-2);
  inline-size: 100%;
}

.lecteur__sens-page {
  display: grid;
  place-items: center;
  aspect-ratio: 1559 / 2197;
  border: var(--filet) solid var(--acier);

  /* ⚠ **Opaques, sinon le schéma est illisible.** La carte laisse volontairement
     transparaître la planche — c'est ce qui dit « tu es dedans ». Mais deux
     rectangles vides posés sur un dessin laissent leurs chiffres se noyer
     dedans : le « 2 » disparaît dans le feuillage. Vu à l'écran. */
  background: var(--noir);
  color: var(--gris);
  font-family: var(--titre);
  font-size: var(--t-lg);
}

.lecteur__sens-page--debut {
  border-color: var(--rouge);
  background: color-mix(in srgb, var(--rouge) 16%, var(--noir));
  color: var(--rouge);
}

.lecteur__sens-texte {
  color: var(--gris);
  font-size: var(--t-base);
  line-height: 1.5;
}

/* Le geste ne vaut que là où il existe : sur grand écran on a les boutons et
   les flèches du clavier. */
.lecteur__sens-geste { display: none; }

@media (max-width: 47.99rem) {
  .lecteur__sens-geste {
    display: block;
    color: var(--blanc);
    font-family: var(--titre);
    font-size: var(--t-sm);
    letter-spacing: var(--lettrage-capital);
    text-transform: uppercase;
  }
}

@keyframes hidaya-sens-parait {
  from { opacity: 0; }
}

@keyframes hidaya-sens-glisse {
  0%, 100% { translate: .5rem 0; opacity: .5; }
  50%      { translate: -.5rem 0; opacity: 1; }
}

.lecteur__aller {
  display: inline-flex;
  align-items: center;
  gap: var(--e-2);
  padding: var(--e-2) var(--e-4);
  border: var(--filet) solid var(--acier);
  background: transparent;
  color: var(--blanc);
  font-family: var(--titre);
  font-size: var(--t-sm);
  letter-spacing: var(--lettrage-capital);
  text-transform: uppercase;
  cursor: pointer;
  transition: border-color var(--duree-action) var(--sortie), color var(--duree-action) var(--sortie);
}

.lecteur__aller:hover:not(:disabled),
.lecteur__aller:focus-visible { border-color: var(--rouge); color: var(--rouge); }

/* ⚠ **Désactivé se VOIT.** Un bouton qui ne fait rien et qui a l'air actif est
   pire qu'un bouton absent : on clique, rien ne bouge, on conclut que c'est
   cassé. */
.lecteur__aller:disabled { opacity: .3; cursor: default; }

.lecteur__fleche { color: var(--rouge); font-size: 1.2em; line-height: 1; }
