/* Polices auto-hébergées (RGPD + perf : plus d'appel à Google Fonts) */
@font-face {
  font-family: "GFS Didot";
  src: url("../fonts/GFSDidot-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Cormorant Garamond";
  src: url("../fonts/CormorantGaramond-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Cormorant Garamond";
  src: url("../fonts/CormorantGaramond-Italic.woff2") format("woff2");
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}
/* Chinois : Noto Serif SC sous-ensemblée aux caractères utilisés.
   unicode-range restreint le téléchargement aux seuls glyphes CJK
   (donc chargée uniquement quand la langue chinoise est affichée). */
@font-face {
  font-family: "Noto Serif SC";
  src: url("../fonts/NotoSerifSC-subset.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  unicode-range: U+00B7, U+2018-201F, U+2026, U+3000-303F, U+3400-4DBF, U+4E00-9FFF, U+FF00-FFEF;
}

/* Contenu réservé aux lecteurs d'écran : retiré visuellement mais gardé dans
   l'arbre d'accessibilité (donc pas de display:none, qui l'en exclurait). */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

:root {
  /* Corps de texte plus neutre/noir (quasi-noir, léger reste de chaleur) pour
     mieux se détacher du vert des titres et boutons, lui-même avivé — demande
     client, deux réglages distincts et volontairement dissociés. */
  --ink: #14160f;
  --ink-faint: rgba(20, 22, 15, 0.55);
  --ink-faintest: rgba(20, 22, 15, 0.3);
  --paper-a: #fdfcf8;
  --paper-b: #faf7f0;
  --surface: #eae6dc;
  --accent: #1c5c35;
  --shadow-rgb: 20, 22, 15;
  --edge: clamp(1.25rem, 5vw, 3rem);

  /* Encoches iOS : les éléments fixes collés aux bords doivent rester en
     dehors des zones réservées (barre d'accueil en bas, encoche en paysage). */
  --safe-b: env(safe-area-inset-bottom, 0px);
  --edge-l: max(var(--edge), calc(env(safe-area-inset-left, 0px) + 0.75rem));
  --edge-r: max(var(--edge), calc(env(safe-area-inset-right, 0px) + 0.75rem));

  /* Hauteur réservée au chrome fixe, haut et bas. C'est la clé de la mise en
     page : le contenu des pages est centré verticalement, donc rien ne l'empêche
     de remonter sous le logo / la nav ni de descendre sous la barre basse. Ces
     deux mesures deviennent le rembourrage plancher de `.page` — elles sont
     redéfinies plus bas là où le chrome change de disposition (mobile : la nav
     passe sur une seconde rangée, le sélecteur de langue au-dessus de la barre). */
  --chrome-top: 3.6rem;
  /* Il ne reste en bas que le sélecteur de langue (barre de navigation
     retirée, redondante — retour client) : même réserve à toutes les tailles. */
  --chrome-bottom: calc(2.6rem + var(--safe-b));
}

:root[data-theme="dark"] {
  --ink: #f2eee1;
  --ink-faint: rgba(242, 238, 225, 0.6);
  --ink-faintest: rgba(242, 238, 225, 0.32);
  --paper-a: #21402c;
  --paper-b: #16301f;
  --surface: #122619;
  /* Légèrement avivé, en écho au réglage du thème jour. */
  --accent: #8ec49b;
  --shadow-rgb: 0, 0, 0;
}

* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
  height: 100%;
}

body {
  background: var(--surface);
  color: var(--ink);
  font-family: "GFS Didot", "Didot", "Didot LT STD", "Noto Serif SC", Georgia, serif;
  line-height: 1.6;
  overflow: hidden;
  transition: background 0.35s ease, color 0.35s ease;
}

a {
  color: inherit;
  text-decoration: none;
}

a:hover {
  opacity: 0.55;
}

img {
  max-width: 100%;
  display: block;
}

button {
  font-family: inherit;
}

::selection {
  background: rgba(17, 53, 34, 0.12);
}

/* ---------- Header (logo + thème) ---------- */

.site-logo {
  position: fixed;
  top: 0.9rem;
  left: var(--edge-l);
  z-index: 240;
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  /* Zone tactile : le texte seul fait ~14 px de haut. Le remplissage vertical,
     compensé par la marge négative, porte la cible à 40 px sans déplacer le
     logo d'un pixel. */
  padding: 0.7rem 0.2rem;
  margin: -0.7rem -0.2rem;
}

.site-logo .mark {
  font-size: 0.85rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}

.site-logo .sub {
  font-size: 0.65rem;
  font-style: italic;
  font-family: "Cormorant Garamond", "Noto Serif SC", serif;
  color: var(--ink-faint);
}

/* Logo agrandi sur ordinateur seulement (retour client) ; mobile inchangé. */
@media (min-width: 641px) {
  .site-logo .mark {
    font-size: 1.2rem;
  }

  .site-logo .sub {
    font-size: 0.9rem;
  }
}

.theme-toggle {
  position: fixed;
  top: 0.95rem;
  right: var(--edge-r);
  z-index: 240;
  background: none;
  border: none;
  font-size: 0.65rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--accent);
  cursor: pointer;
  /* Idem logo : cible tactile de 40 px obtenue par remplissage compensé. */
  padding: 0.7rem 0.3rem;
  margin: -0.7rem -0.3rem;
  opacity: 0.75;
  transition: opacity 0.25s ease;
}

.theme-toggle:hover {
  opacity: 1;
}

.lang-switch {
  position: fixed;
  bottom: calc(clamp(12px, 2.5vh, 26px) + var(--safe-b));
  left: var(--edge-l);
  z-index: 240;
  display: flex;
  align-items: center;
  /* 0.15rem + les 0.35rem de remplissage de chaque bouton ≈ l'écart optique
     de 0.5rem d'origine. */
  gap: 0.15rem;
}

.lang-switch button {
  background: none;
  border: none;
  font-family: inherit;
  font-size: 0.62rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent);
  opacity: 0.5;
  cursor: pointer;
  /* Cible tactile ≥ 40 px : les sigles FR · EN · 中文 sont minuscules. Le
     remplissage vertical est annulé par une marge négative *verticale seule* —
     une marge négative horizontale rapprocherait les items flex et écraserait
     les séparateurs. L'écart du conteneur est réduit d'autant (voir .lang-switch). */
  padding: 0.72rem 0.35rem;
  margin-block: -0.72rem;
  transition: opacity 0.25s ease;
}

.lang-switch button.is-current {
  opacity: 1;
}

.lang-switch button:hover {
  opacity: 0.8;
}

.lang-switch .lang-sep {
  color: var(--accent);
  opacity: 0.35;
  font-size: 0.55rem;
}

/* ---------- Accès rapide (haut, centré) ---------- */

/* Navigation d'accès direct — Réserver · Menu · FAQ. Elle n'apparaît qu'une fois
   le livre ouvert (comme la barre basse) : la couverture n'offre qu'une action,
   « Ouvrir ». Centrée entre le logo (gauche) et le bouton thème (droite). Style
   livresque : petites capitales espacées, encre atténuée, séparateurs « · »
   discrets. */
.site-nav {
  position: fixed;
  top: 0.85rem;
  /* Même centrage robuste que la barre basse (voir .book-controls). */
  left: 0;
  right: 0;
  width: max-content;
  margin-inline: auto;
  z-index: 240;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  max-width: calc(100% - 2 * var(--edge));
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.4s ease;
}

body.is-open .site-nav {
  opacity: 1;
  pointer-events: auto;
}

.site-nav-link {
  background: none;
  border: none;
  font-family: inherit;
  /* Agrandie (demande client, "gros") : elle est la seule action visible en
     permanence livre ouvert, elle peut porter davantage de présence. */
  font-size: 0.95rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
  cursor: pointer;
  padding: 0.4rem 0.3rem;
  min-height: 40px;
  display: inline-flex;
  align-items: center;
  line-height: 1;
  transition: color 0.25s ease;
}

.site-nav-link:hover {
  color: var(--ink);
  opacity: 1;
}

.site-nav-sep {
  color: var(--ink-faintest);
  font-size: 0.55rem;
}

/* ---------- Couverture : la reliure reste nue ---------- */

/* Le livre fermé est un objet, pas une page : le logo (redondant avec le grand
   logo de la couverture), le bouton jour/nuit (la reliure est verte et ivoire
   dans les deux thèmes — un bouton sans effet visible y semblerait cassé) et le
   sommaire n'apparaissent qu'à l'ouverture. Le thème suit de toute façon la
   préférence système dès l'arrivée ; seul le sélecteur de langue subsiste. */
.site-logo,
.theme-toggle {
  transition: opacity 0.5s ease;
}

body:not(.is-open) .site-logo,
body:not(.is-open) .theme-toggle {
  opacity: 0;
  pointer-events: none;
}

/* Sur la reliure verte, le sélecteur de langue emprunte les teintes claires
   de la couverture — `var(--ink)` y serait illisible en thème jour. */
body:not(.is-open) .lang-switch button {
  color: rgba(207, 200, 180, 0.5);
}

body:not(.is-open) .lang-switch button.is-current,
body:not(.is-open) .lang-switch button:hover {
  color: #cfc8b4;
}

body:not(.is-open) .lang-switch .lang-sep {
  color: rgba(207, 200, 180, 0.35);
}

/* ---------- Scène (couverture + livre) ---------- */

.stage {
  position: fixed;
  inset: 0;
  overflow: hidden;
}

.book {
  position: absolute;
  inset: 0;
  perspective: 3400px;
}

/* ---------- Couverture ---------- */

.cover {
  position: absolute;
  inset: 0;
  z-index: 220;
  transform-origin: left center;
  backface-visibility: hidden;
  cursor: pointer;
  background: linear-gradient(110deg, #23422c 0%, #16301f 100%);
  /* Pas d'ombre portée : la couverture occupe tout l'écran, l'ombre est donc
     invisible au repos et ne se voyait que pendant la rotation, où ses 80 px de
     flou débordaient en halo gris au-dessus et au-dessous. La profondeur du
     feuilletage est déjà donnée par `.page-shade` (ombre de pli animée). */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: clamp(24px, 6vw, 80px);
  transition: transform 1150ms cubic-bezier(0.45, 0.05, 0.3, 1);
}

.cover-frame {
  border: 1px solid rgba(236, 230, 216, 0.22);
  padding: clamp(34px, 7vh, 64px) clamp(34px, 7vw, 88px);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.4em;
}

.cover-eyebrow {
  font-size: 10px;
  letter-spacing: 0.5em;
  text-indent: 0.5em;
  color: #c9c2ae;
  opacity: 0.6;
}

.cover-mark {
  margin: 0;
  font-weight: 400;
  font-size: clamp(50px, 9vw, 96px);
  letter-spacing: 0.28em;
  text-indent: 0.28em;
  color: #22392b;
  text-shadow: -1px -1px 1px rgba(0, 0, 0, 0.55), 1px 1px 1px rgba(236, 230, 216, 0.14);
}

.cover-sub {
  font-style: italic;
  font-size: clamp(18px, 2.6vw, 26px);
  color: #cfc8b4;
  font-family: "Cormorant Garamond", "Noto Serif SC", serif;
}

/* Couverture au logo image : la reliure est toujours vert foncé, dans les deux
   thèmes. On y affiche donc en permanence le logo ivoire (Logo-table-Blanc) —
   la version encre serait illisible sur le vert en thème jour. Un seul <img>,
   alt="Table". */
.cover-logo {
  display: block;
  /* Le `min(…, 34vh)` évite que le bloc emblème + logo + sous-titre ne dépasse
     la reliure et n'aille chevaucher « Ouvrir » en hauteur contrainte
     (mobile paysage ~390 px, petites fenêtres desktop). */
  width: min(clamp(190px, 30vw, 240px), 34vh);
  height: auto;
}


.cover-open {
  position: absolute;
  bottom: clamp(20px, 5vh, 44px);
  left: 0;
  right: 0;
  text-align: center;
  font-size: 11px;
  letter-spacing: 0.42em;
  text-indent: 0.42em;
  color: #cfc8b4;
  opacity: 0.55;
}

/* ---------- Page générique ---------- */

.page {
  position: absolute;
  inset: 0;
  /* Grain + dégradé latéral peints directement en couches de fond sur la page.
     Comme la page est le conteneur de défilement, son background reste fixe
     pendant le scroll (background-attachment: scroll par défaut) : l'aspect
     papier est donc rigoureusement uniforme sur toute la hauteur scrollable,
     contrairement à un calque absolu inset:0 qui ne couvrait que la zone
     visible. La couche de bruit SVG est identique à l'ancien grainStyle() JS. */
  background:
    linear-gradient(to right, rgba(17, 53, 34, 0.07), rgba(17, 53, 34, 0) 4%),
    url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22180%22%20height%3D%22180%22%3E%3Cfilter%20id%3D%22n%22%3E%3CfeTurbulence%20type%3D%22fractalNoise%22%20baseFrequency%3D%220.9%22%20numOctaves%3D%222%22%20stitchTiles%3D%22stitch%22%2F%3E%3CfeColorMatrix%20values%3D%220%200%200%200%200.07%200%200%200%200%200.21%200%200%200%200%200.13%200%200%200%200.05%200%22%2F%3E%3C%2Ffilter%3E%3Crect%20width%3D%22180%22%20height%3D%22180%22%20filter%3D%22url(%23n)%22%2F%3E%3C%2Fsvg%3E"),
    linear-gradient(105deg, var(--paper-a) 0%, var(--paper-b) 100%);
  transform-origin: left center;
  backface-visibility: hidden;
  /* Idem couverture : pas d'ombre portée (halo flou pendant le flip). */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: safe center;
  text-align: center;
  /* Le contenu est centré verticalement : sans plancher, il remonte sous le
     logo / la nav d'accès rapide et descend sous la barre de navigation dès que
     la hauteur est contrainte (mobile paysage, petites fenêtres). Les deux
     `max()` garantissent que le rembourrage ne descend jamais sous la hauteur
     réservée au chrome fixe, tout en gardant les valeurs généreuses d'origine
     sur grand écran. */
  padding: max(clamp(28px, 6vw, 80px), var(--chrome-top)) clamp(28px, 6vw, 80px)
    max(clamp(70px, 10vh, 110px), var(--chrome-bottom));
  overflow: hidden auto;
  color: var(--ink);
  transition: background 0.35s ease, color 0.35s ease;
}

.page-shade {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 7;
  opacity: 0;
  background: linear-gradient(105deg, rgba(var(--shadow-rgb), 0) 45%, rgba(var(--shadow-rgb), 0.3) 100%);
}

.page-curl {
  position: absolute;
  right: 0;
  bottom: 0;
  width: 52px;
  height: 52px;
  z-index: 8;
  cursor: pointer;
  clip-path: polygon(100% 0, 100% 100%, 0 100%);
  background: linear-gradient(315deg, #e6e0d2 0%, #f4f0e6 42%, rgba(var(--shadow-rgb), 0.14) 50%, rgba(var(--shadow-rgb), 0) 58%);
}

.page-folio-badge {
  position: absolute;
  bottom: clamp(14px, 2.5vh, 24px);
  right: clamp(64px, 8vw, 96px);
  font-size: 11px;
  letter-spacing: 0.3em;
  color: var(--accent);
  opacity: 0.6;
  z-index: 6;
  pointer-events: none;
}

.page-folio-badge.is-light {
  color: #fff;
  text-shadow: 0 1px 8px rgba(0, 0, 0, 0.5);
}

/* ---------- Page 0 : couverture ouverte ---------- */

.eyebrow {
  font-size: 11px;
  letter-spacing: 0.5em;
  text-indent: 0.5em;
  opacity: 0.55;
}

.wordmark {
  margin: 0.5em 0 0;
  font-weight: 400;
  font-size: clamp(44px, 8vw, 84px);
  letter-spacing: 0.24em;
  text-indent: 0.24em;
  line-height: 1;
  /* Le grand « Table » de la première page est un titre comme les autres :
     même traitement que .chapter-title (vert en jour, encre ivoire en nuit). */
  color: var(--accent);
}

:root[data-theme="dark"] .wordmark {
  color: var(--ink);
}

.wordmark-sub {
  margin: 0.6em 0 0;
  font-style: italic;
  font-size: clamp(16px, 2.4vw, 22px);
  letter-spacing: 0.08em;
  font-family: "Cormorant Garamond", "Noto Serif SC", serif;
}

.rule {
  width: 44px;
  height: 1px;
  background: var(--accent);
  opacity: 0.55;
  /* Resserré (1.2em, contre 2.2em) : l'écart entre le titre et le texte qui
     suit était jugé trop grand, en particulier sur la page Réserver. */
  margin: 1.2em 0;
}

.quote-block {
  display: flex;
  flex-direction: column;
  gap: 0.9em;
  font-size: clamp(16px, 2.1vw, 21px);
  line-height: 1.9;
  max-width: 26em;
  font-style: italic;
  font-family: "Cormorant Garamond", "Noto Serif SC", serif;
}

.quote-block p {
  margin: 0;
}

.cta-row {
  display: flex;
  align-items: center;
  gap: 34px;
  margin-top: 2.4em;
}

.cta-link {
  background: transparent;
  border: none;
  color: var(--ink);
  letter-spacing: 0.4em;
  text-indent: 0.4em;
  font-size: 13px;
  padding: 10px 0;
  cursor: pointer;
  border-bottom: 1px solid rgba(var(--shadow-rgb), 0.5);
}

.cta-quiet {
  opacity: 0.65;
  border-bottom: 1px solid transparent;
}

.cta-link:hover {
  opacity: 1;
}

/* ---------- Pages-chapitres ---------- */

.chapter-folio {
  font-size: 12px;
  letter-spacing: 0.45em;
  text-indent: 0.45em;
  color: var(--accent);
  opacity: 0.75;
}

.chapter-title {
  margin: 0.7em 0 0;
  font-weight: 400;
  font-size: clamp(30px, 4.6vw, 44px);
  letter-spacing: 0.02em;
}

.chapter-body {
  display: flex;
  flex-direction: column;
  gap: 1em;
  font-size: clamp(18px, 2.2vw, 22px);
  line-height: 2;
  max-width: 27em;
  font-family: "Cormorant Garamond", "Noto Serif SC", serif;
}

.chapter-body p {
  margin: 0;
}

.chapter-body p.is-italic,
.chapter-body .is-italic-line {
  font-style: italic;
}

.lead {
  text-transform: uppercase;
  letter-spacing: 0.14em;
  font-size: 0.82em;
  color: var(--accent);
}

/* Retour client (2026-07-18) : la première ligne des chapitres (celle qui
   porte .lead) doit s'afficher en minuscules typographiques normales, capitale
   initiale conservée, et non en petites capitales tracées. Règle générique,
   appliquée aux trois langues (FR, EN, ZH) pour un dessin de page identique. */
.lead {
  text-transform: none;
  letter-spacing: normal;
  font-size: 1em;
  color: inherit;
}

/* ---------- Fragments ---------- */

/* Le bandeau de titre et le mur étaient tous deux positionnés en absolu, à des
   distances réglées à la main (`top: clamp(186px, 25vh, 200px)`…). Ces valeurs
   ne pouvaient pas suivre à la fois la hauteur du chrome, celle du bandeau et
   les trois langues : à 320×568 le bas des affiches passait sous le sélecteur
   de langue, en paysage le bandeau mangeait le mur. Les deux éléments repassent
   donc dans le flux : le bandeau prend sa hauteur propre, le mur occupe tout ce
   qui reste (`flex: 1` + `min-height: 0`, indispensable pour qu'un élément flex
   puisse être plus petit que son contenu). Le rembourrage de `.page` réserve
   déjà le chrome : plus aucune constante à maintenir. */
.page[data-index="7"] {
  justify-content: flex-start;
}

.frag-heading {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  pointer-events: none;
  z-index: 8;
  text-align: center;
}

.frag-folio {
  font-size: 12px;
  letter-spacing: 0.45em;
  text-indent: 0.45em;
  color: var(--ink-faint);
}

.frag-title {
  margin: 0;
  font-weight: 400;
  font-size: clamp(28px, 4.2vw, 40px);
  color: var(--ink);
}

/* ---------- Fragments : le mur ---------- */

/* Mur de fragments : les six affiches (format identique 1086×1448) alignées en
   une rangée pleine hauteur. Encastré entre les zones de clic latérales (mêmes
   bords que `.edge-zone`, dédiés au tournage de page). La rangée se centre quand
   elle tient dans la largeur, et défile horizontalement sinon — `safe center`
   retombe sur `flex-start` en cas de débordement pour ne jamais rogner la
   première affiche. */
.frag-mosaic {
  --mgap: clamp(14px, 2vw, 28px);
  /* Dans le flux : le mur prend toute la hauteur restante sous le bandeau.
     `min-height: 0` lève la taille minimale automatique des éléments flex, sans
     quoi le mur refuserait de descendre sous la hauteur de ses affiches. */
  /* `align-self: stretch` plutôt que `width: 100%` : la largeur se calcule alors
     en retranchant les marges, là où `100%` s'y ajoutait et débordait la page
     de deux fois la marge (320 px : 326 de large pour 320 disponibles). */
  align-self: stretch;
  flex: 1 1 auto;
  min-height: 0;
  margin-top: clamp(10px, 2vh, 22px);
  /* Les affiches restent en retrait des zones de clic latérales, qui leur
     passent par-dessus : sans cette marge, toucher une affiche près du bord
     tournerait la page au lieu de l'agrandir. La marge ne vaut que le
     dépassement de la zone de bord sur le rembourrage déjà appliqué à la page. */
  margin-inline: max(0px, calc(clamp(44px, 7vw, 120px) - clamp(28px, 6vw, 80px)));
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  align-items: center;
  justify-content: safe center;
  gap: var(--mgap);
  overflow-x: auto;
  overflow-y: hidden;
  overscroll-behavior-x: contain;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  z-index: 8;
}

.frag-mosaic::-webkit-scrollbar {
  display: none;
}

/* Affiche pleine hauteur ; sa largeur découle du ratio natif porté en inline
   (aspect-ratio 3/4), sans attendre le chargement de l'image. */
.frag-mosaic .tile {
  margin: 0;
  flex: 0 0 auto;
  height: 100%;
  cursor: zoom-in;
  transition: transform 0.35s ease, filter 0.35s ease;
  filter: drop-shadow(0 8px 22px rgba(var(--shadow-rgb), 0.26));
}

/* Ratio identique pour toutes les affiches ⇒ `cover` ne rogne rien. */
.frag-mosaic .tile img {
  display: block;
  height: 100%;
  width: 100%;
  object-fit: cover;
}

.frag-mosaic .tile:hover,
.frag-mosaic .tile:focus-visible {
  transform: translateY(-4px);
  filter: drop-shadow(0 14px 30px rgba(var(--shadow-rgb), 0.38));
  outline: none;
}

/* Dans le bandeau de titre : en bas de page elle heurtait la barre de navigation. */
.frag-hint {
  margin: 0;
  text-align: center;
  font-size: 0.62rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-faintest);
}

/* ---------- Planche agrandie ---------- */

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 400;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(28px, 6vh, 72px);
  background: rgba(10, 20, 14, 0.92);
  cursor: zoom-out;
}

.lightbox[hidden] {
  display: none;
}

.lightbox img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.5);
}

.lightbox-close {
  position: absolute;
  top: clamp(12px, 2.5vh, 26px);
  right: clamp(14px, 3vw, 34px);
  background: none;
  border: none;
  color: #cfc8b4;
  font-size: 30px;
  line-height: 1;
  cursor: pointer;
  padding: 4px 10px;
}

.lightbox-close:hover {
  opacity: 0.6;
}

/* ---------- Réserver ---------- */

.reserve-lede {
  display: flex;
  flex-direction: column;
  gap: 0.6em;
  font-size: clamp(15px, 1.9vw, 19px);
  line-height: 1.8;
  max-width: 32em;
  font-style: italic;
  font-family: "Cormorant Garamond", "Noto Serif SC", serif;
}

.reserve-lede p {
  margin: 0;
}

/* Le widget Zenchef est une application à part entière (calendrier, créneaux,
   formulaire) : une réserve étroite obligeait à naviguer dans une lucarne. On
   lui donne une hauteur généreuse — au moins 620 px, et jusqu'à 78 % de la
   hauteur d'écran quand elle le permet. La page défile pour l'accueillir. */
.reserve-widget {
  width: 100%;
  max-width: 720px;
  flex: 1;
  /* Modeste par défaut : c'est la taille de la simple façade (note + bouton),
     qui n'a pas besoin de grand espace. Le cadre grandit une fois la
     réservation ouverte (voir .page.is-booking ci-dessous). */
  min-height: 220px;
  margin: 1.5em 0;
  border: 1px solid rgba(var(--shadow-rgb), 0.15);
  position: relative;
  background: #fff;
  transition: min-height 0.3s ease;
}

/* Cadre Zenchef ouvert : il prend la place réellement disponible une fois le
   titre, les liens et le chrome déduits (~320 px), plafonné à 620 px pour ne
   pas devenir démesuré sur grand écran, et jamais sous 400 px. */
.page.is-booking .reserve-widget {
  min-height: clamp(400px, calc(100dvh - 320px), 620px);
}

@media (prefers-reduced-motion: reduce) {
  .reserve-widget {
    transition: none;
  }
}

.reserve-widget iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}

/* Façade sobre affichée avant l'ouverture du widget Zenchef : aucun script
   ni cookie tiers n'est chargé tant que le convive n'a pas cliqué. */
.reserve-facade {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1.1em;
  padding: 24px;
  text-align: center;
  background: linear-gradient(105deg, var(--paper-a) 0%, var(--paper-b) 100%);
}

.reserve-facade-note {
  margin: 0;
  max-width: 26em;
  font-family: "Cormorant Garamond", "Noto Serif SC", serif;
  font-style: italic;
  font-size: clamp(14px, 1.7vw, 17px);
  line-height: 1.7;
  color: var(--ink-faint);
}

.reserve-facade-btn {
  background: none;
  border: 1px solid rgba(var(--shadow-rgb), 0.4);
  color: var(--ink);
  font-size: 12px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  cursor: pointer;
  padding: 12px 26px;
  transition: color 0.2s ease, border-color 0.2s ease;
}

.reserve-facade-btn:hover {
  color: var(--accent);
  border-color: var(--accent);
}

.reserve-links {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 12px 36px;
  font-size: 12px;
  letter-spacing: 0.2em;
  padding-bottom: 24px;
  text-transform: uppercase;
}

.reserve-link {
  background: none;
  border: none;
  color: var(--ink);
  font-size: 12px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  cursor: pointer;
  padding: 0 0 3px;
  border-bottom: 1px solid rgba(var(--shadow-rgb), 0.35);
}

/* ---------- Colophon ---------- */

.colophon-mark {
  margin: 0;
  font-weight: 400;
  font-size: clamp(18px, 2.4vw, 24px);
  letter-spacing: 0.4em;
  text-indent: 0.4em;
}

.colophon-body {
  display: flex;
  flex-direction: column;
  gap: 0.8em;
  font-size: clamp(14px, 1.8vw, 18px);
  line-height: 1.9;
  font-family: "Cormorant Garamond", "Noto Serif SC", serif;
}

.colophon-body p {
  margin: 0;
}

.colophon-body .closing {
  margin-top: 1.6em;
  font-style: italic;
  opacity: 0.75;
}

.imprint {
  margin: 2.5em 0 0;
  font-size: 10px;
  letter-spacing: 0.25em;
  text-transform: uppercase;
  color: var(--ink-faintest);
}

/* ---------- Navigation basse ---------- */

/* Retirée (retour client) : redondante avec la nav du haut, les zones de
   bord, le clavier/la molette/le swipe, et le folio affiché sur la page. Les
   boutons #prevPage/#nextPage restent dans le DOM (utilisés par le clavier et
   d'autres déclencheurs) mais ne s'affichent plus. */
.book-controls {
  display: none;
}

/* ---------- Préférence « animations réduites » ---------- */
/* Le feuilletage 3D et les mouvements décoratifs sont neutralisés : la
   couverture et les pages basculent sans transition (book.js force déjà la
   bascule instantanée côté JS), les survols et l'indice de navigation ne
   bougent plus. Le livre demeure entièrement navigable. */
@media (prefers-reduced-motion: reduce) {
  .cover {
    transition: none;
  }
  .page {
    transition: none !important;
  }
  .site-logo,
  .theme-toggle {
    transition: none;
  }
  .frag-mosaic .tile {
    transition: none;
  }
  /* Les fondus de défilement apparaissent d'un coup, sans fondu enchaîné. */
  body.is-open::before,
  body.is-open::after {
    transition: none;
  }
}

.chapter-label {
  letter-spacing: 0.28em;
  text-indent: 0.28em;
  /* Texte informatif, pas un bouton ni un lien : reste en encre, comme le
     reste de la prose. Le vert accent est réservé aux titres, boutons et
     liens cliquables (demande client). */
  color: var(--ink-faint);
  opacity: 0.75;
  min-width: 9em;
  text-align: center;
  text-transform: uppercase;
}

/* ---------- Zones de clic sur les bords ---------- */

.edge-zone {
  position: absolute;
  top: 0;
  bottom: 0;
  width: clamp(44px, 7vw, 120px);
  z-index: 150;
  cursor: pointer;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding-bottom: 22dvh;
}

.edge-prev {
  left: 0;
}

.edge-next {
  right: 0;
}

.edge-zone span {
  font-size: 28px;
  opacity: 0;
  transition: opacity 0.3s;
  user-select: none;
}

.edge-zone.is-active:hover {
  background: linear-gradient(to right, rgba(var(--shadow-rgb), 0.05), rgba(var(--shadow-rgb), 0));
}

.edge-next.is-active:hover {
  background: linear-gradient(to left, rgba(var(--shadow-rgb), 0.05), rgba(var(--shadow-rgb), 0));
}

.edge-zone.is-active span {
  opacity: 0.3;
}

/* ---------- FAQ ---------- */

.faq-list {
  width: 100%;
  max-width: 34em;
  text-align: left;
  font-family: "Cormorant Garamond", "Noto Serif SC", serif;
}

.faq-item {
  border-bottom: 1px solid rgba(var(--shadow-rgb), 0.18);
}

.faq-item > summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1em;
  padding: 0.75em 0;
  font-size: clamp(15px, 1.9vw, 19px);
  letter-spacing: 0.01em;
  color: var(--ink);
}

.faq-item > summary::-webkit-details-marker {
  display: none;
}

.faq-item > summary::after {
  content: "+";
  color: var(--accent);
  font-size: 1.1em;
  line-height: 1;
  opacity: 0.5;
}

.faq-item[open] > summary::after {
  content: "–";
}

.faq-answer {
  margin: 0 0 0.9em;
  font-size: clamp(14px, 1.7vw, 17px);
  line-height: 1.8;
  color: var(--ink-faint);
}

.faq-answer p {
  margin: 0;
}

/* ---------- Galerie photos ---------- */

.gallery-overlay {
  position: fixed;
  inset: 0;
  z-index: 300;
  background: var(--surface);
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: clamp(20px, 4vw, 48px);
  overflow: hidden;
}

.gallery-overlay[hidden] {
  display: none;
}

/* La croix de fermeture doit rester joignable même quand on défile la
   grille : seule .gallery-grid scrolle, l'en-tête reste fixe en haut. */
.gallery-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  max-width: 1080px;
  margin-bottom: 26px;
  flex-shrink: 0;
}

.gallery-head h2 {
  font-size: clamp(15px, 1.9vw, 19px);
  letter-spacing: 0.4em;
  text-indent: 0.4em;
  font-weight: 400;
  margin: 0;
}

.gallery-close {
  background: none;
  border: none;
  color: var(--ink);
  font-size: 30px;
  cursor: pointer;
  line-height: 1;
  padding: 4px 10px;
}

.gallery-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  /* Sans ce grid-auto-rows, la hauteur des rangées se calcule à tort sur un
     contenu quasi nul (conflit d'intrinsic sizing entre grid, flex:1 et
     overflow-y:auto) : les figures (aspect-ratio 4/3) débordent alors de leur
     rangée et se chevauchent en une seule colonne (mobile). */
  grid-auto-rows: min-content;
  align-content: start;
  gap: 18px;
  width: 100%;
  max-width: 1080px;
  overflow-y: auto;
  flex: 1;
  -webkit-overflow-scrolling: touch;
}

.gallery-grid figure {
  margin: 0;
  aspect-ratio: 4 / 3;
  overflow: hidden;
}

.gallery-grid img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* ---------- Écrans étroits ---------- */

/* Césures additionnelles, réservées aux écrans étroits : certains <br> posés
   pour le rythme desktop tombent après un retour à la ligne naturel sur
   mobile, isolant un mot seul sur sa ligne (ex. « transformer », « Cornue »).
   Ce <br> supplémentaire, invisible sur desktop, coupe plus tôt pour l'éviter. */
.br-mobile {
  display: none;
}

@media (max-width: 640px) {
  .br-mobile {
    display: inline;
  }
}

/* Sur mobile, la barre de navigation basse (centrée) occupe presque toute la
   largeur : on remonte le sélecteur de langue au-dessus pour éviter la collision. */
@media (max-width: 640px) {
  /* Le sélecteur de langue est le seul élément restant en bas sur téléphone
     (barre de navigation et folios masqués) : on le centre pour équilibrer la
     page. Centrage par `inset` + marges automatiques, comme la barre basse —
     `left: 50%` plafonnerait sa largeur à la moitié de l'écran. Sur ordinateur
     il reste à gauche, la barre de navigation occupant le centre. */
  .lang-switch {
    bottom: calc(clamp(8px, 1.8vh, 18px) + var(--safe-b));
    left: 0;
    right: 0;
    width: max-content;
    margin-inline: auto;
  }

  /* L'accès rapide ne tient pas sur la même ligne que le logo et le bouton
     thème à cette largeur : on le descend sur sa propre rangée, sous l'en-tête,
     toute la largeur disponible lui étant alors offerte. */
  .site-nav {
    top: 2.9rem;
  }

  /* Le chrome occupe deux rangées en haut (logo/thème puis nav). La barre de
     navigation basse est déjà masquée à toutes les tailles (voir .book-controls
     en base) ; sur téléphone, les folios en chiffres romains et le coin corné
     le sont aussi. */
  :root {
    --chrome-top: 6.2rem;
  }

  .page-folio-badge,
  .page-curl {
    display: none;
  }

  /* Les bords cliquables mordent sur la largeur utile d'un petit écran ; on les
     resserre pour rendre les lignes de texte au contenu. */
  .edge-zone {
    width: 34px;
  }

  /* Les zones de bord étant réduites à 34 px, le retrait du mur l'est aussi :
     sur 320 px de large, chaque pixel rendu aux affiches compte. */
  .frag-mosaic {
    margin-inline: 6px;
  }

  /* Première page : c'est l'écran d'accueil du livre ouvert, ses deux boutons
     doivent être visibles sans défiler. Sur 320 px de large, le texte anglais
     (plus long que le français) faisait déborder la page et poussait
     « Reserve » / « Read » sous la barre de navigation. On resserre les
     respirations — filet, interligne de la citation, écart des boutons — sans
     réduire le corps du texte, qui reste à 16 px. */
  .rule {
    margin: 1.4em 0;
  }

  .quote-block {
    line-height: 1.75;
    gap: 0.7em;
  }

  .cta-row {
    margin-top: 1.6em;
    gap: 24px;
  }

  .wordmark {
    font-size: clamp(38px, 11vw, 58px);
  }

  /* Le libellé de chapitre ne doit jamais faire grandir la barre en hauteur :
     une seule ligne, tronquée si la place manque (les flèches priment). */
  .chapter-label {
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
}

/* ---------- Hauteurs contraintes ---------- */

/* Mobile paysage et petites fenêtres desktop. Le chrome fixe est de hauteur
   quasi constante alors que la place disponible fond : sans ce palier, le titre
   de chapitre passait sous la nav du haut et « Ouvrir » chevauchait
   « Bruno Verjus » sur la couverture. On comprime les respirations verticales
   (filets, interlignes, bandeaux) plutôt que le corps du texte, qui doit rester
   lisible. */
@media (max-height: 560px) {
  /* La reliure : cadre resserré et logo borné pour dégager « Ouvrir ». */
  .cover-frame {
    padding: clamp(16px, 4vh, 34px) clamp(24px, 5vw, 60px);
    gap: 0.7em;
  }

  .cover-sub {
    font-size: clamp(14px, 2vw, 18px);
  }

  .cover {
    /* Réserve la bande basse où « Ouvrir » est ancré : le cadre ne peut plus
       venir la recouvrir, quel que soit le rapport hauteur/largeur. */
    padding-bottom: clamp(46px, 12vh, 72px);
  }

  .cover-open {
    bottom: clamp(12px, 3.5vh, 24px);
  }

  /* Respirations des pages intérieures. */
  .rule {
    margin: 1em 0;
  }

  .chapter-title {
    font-size: clamp(24px, 3.4vw, 32px);
  }

  .chapter-body {
    line-height: 1.65;
    gap: 0.7em;
  }

  .quote-block {
    line-height: 1.6;
    gap: 0.6em;
  }

  .cta-row {
    margin-top: 1.2em;
  }

  .colophon-body {
    line-height: 1.6;
    gap: 0.5em;
  }

  .imprint {
    margin-top: 1.4em;
  }

  /* Fragments : le bandeau de titre est ancré en `vh` mais garde une hauteur
     propre presque constante. En paysage, il mangeait toute la place du mur —
     on le compacte et on remonte le mur juste sous lui. */
  /* Le mur étant dans le flux, il récupère automatiquement ce que le bandeau
     libère : il suffit de compacter le bandeau. */
  .frag-heading {
    gap: 4px;
  }

  .frag-title {
    font-size: clamp(20px, 3vw, 26px);
  }

  .frag-mosaic {
    margin-top: 8px;
  }

  /* Le widget de réservation ne peut pas exiger 220 px de haut quand il en
     reste 200 en tout : il rétrécit, la page défile pour le reste. */
  .reserve-widget {
    min-height: 150px;
    margin: 0.8em 0;
  }

  .reserve-links {
    padding-bottom: 12px;
    gap: 8px 24px;
  }

  /* Le filigrane de la première page suit la hauteur disponible. */
  .page[data-index="0"] {
    --emblem-size: min(62dvh, 46vw);
  }
}

/* Très petites hauteurs (≈390 px et moins : iPhone en paysage). Le chrome se
   réduit encore, sans quoi il ne resterait plus rien pour le texte. */
@media (max-height: 430px) {
  :root {
    /* `--chrome-top` n'est pas réduit : la nav d'accès rapide garde ses 40 px de
       cible tactile et son ancrage à 0.85rem, donc son bas reste à ~54 px. Le
       raccourcir faisait repasser le folio de chapitre (« III », « IX ») sous la
       nav. (`--chrome-bottom` n'a plus besoin d'être touché ici : la barre de
       navigation qu'il compensait a disparu à toutes les tailles.) */
  }

  .site-logo .sub {
    display: none;
  }

  .wordmark {
    font-size: clamp(34px, 6vw, 52px);
  }

  .quote-block {
    font-size: clamp(14px, 1.8vw, 17px);
  }

  .chapter-body {
    font-size: clamp(15px, 1.9vw, 18px);
  }
}

/* Mobile paysage : le chrome bas repasse sur une seule rangée (la largeur ne
   manque plus), ce qui rend une rangée entière au contenu. On annule donc le
   décalage vertical du sélecteur de langue posé par la requête « écran
   étroit », qui ne s'applique de toute façon plus au-delà de 640 px de large. */
@media (max-height: 430px) and (min-width: 641px) {
  .lang-switch {
    bottom: calc(clamp(8px, 1.8vh, 18px) + var(--safe-b));
  }
}



/* ---------- Interactifs en vert accent (repérables) ---------- */

/* Tous les liens et boutons de contenu prennent le vert accent pour se
   distinguer du texte en encre ; le chrome discret (flèches, langues, thème)
   reste atténué. Les :hover existants (plus spécifiques) gardent la main. */
.cta-link,
.reserve-link,
.reserve-facade-btn,
.site-nav-link,
.chapter-body a,
.colophon-body a,
.faq-answer a {
  color: var(--accent);
}

/* ---------- Titres en vert accent (thème jour) ---------- */

/* Les titres de chapitres adoptent le vert des interactifs (celui du CTA de la
   première page) — demande client. En nuit, ils restent en encre ivoire. */
.chapter-title,
.frag-title,
.colophon-mark {
  color: var(--accent);
}

:root[data-theme="dark"] .chapter-title,
:root[data-theme="dark"] .frag-title,
:root[data-theme="dark"] .colophon-mark {
  color: var(--ink);
}

/* ---------- Boutons de contenu agrandis (+20 %, demande client) ---------- */

.cta-link {
  font-size: 16px;
}

.reserve-link,
.reserve-facade-btn {
  font-size: 14px;
}

/* ---------- Fondus sous le chrome fixe ---------- */

/* Les pages longues — Réserver, FAQ, et la plupart des chapitres en paysage —
   défilent sous un chrome fixe qui n'a pas de fond. Le rembourrage de `.page`
   protège le premier et le dernier écran, mais dès que le convive fait défiler,
   le texte passe littéralement à travers la nav du haut et la barre du bas.
   Deux fondus vers la couleur du papier protègent la lisibilité du chrome.

   Ils sont **invisibles au repos** (demande client : au premier regard, le texte
   doit ressortir sans voile) et n'apparaissent que lorsque la page défile
   réellement — book.js pose `is-scrolled-top` / `is-scrolled-bottom` sur `body`.
   Le dégradé part du papier plein pour s'éteindre au bout de la bande, sans
   plateau opaque : il masque juste assez pour que le chrome reste lisible.
   z-index 210 : au-dessus des pages (200 au maximum, cf. syncPage) et sous la
   couverture (220), qui doit rester verte de bord à bord pendant le feuilletage. */
body.is-open::before,
body.is-open::after {
  content: "";
  position: fixed;
  left: 0;
  right: 0;
  z-index: 210;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.3s ease;
}

/* La bande est opaque sur exactement la hauteur réservée au chrome, puis
   s'éteint sur 28 px au-delà. Un dégradé qui commençait à s'éclaircir dès le
   bord ne protégeait rien là où le chrome se trouve réellement — la nav du haut
   est ancrée tout en bas de sa bande, le sélecteur de langue tout en haut de la
   sienne — et le texte continuait de traverser les libellés. */
body.is-open::before {
  top: 0;
  height: calc(var(--chrome-top) + 28px);
  background: linear-gradient(
    to bottom,
    var(--paper-b) 0,
    var(--paper-b) var(--chrome-top),
    rgba(0, 0, 0, 0) calc(var(--chrome-top) + 28px)
  );
}

body.is-open::after {
  bottom: 0;
  height: calc(var(--chrome-bottom) + 28px);
  background: linear-gradient(
    to top,
    var(--paper-b) 0,
    var(--paper-b) var(--chrome-bottom),
    rgba(0, 0, 0, 0) calc(var(--chrome-bottom) + 28px)
  );
}

body.is-open.is-scrolled-top::before,
body.is-open.is-scrolled-bottom::after {
  opacity: 1;
}

/* ---------- Cibles tactiles ---------- */

/* Tout interactif doit offrir au moins 40 px de haut au doigt. Les libellés
   sont volontairement petits et espacés (parti pris typographique) : on gagne
   la surface par le remplissage, sans toucher au dessin. `inline-flex` +
   `align-items: center` garde le trait de soulignement collé au texte. */
.cta-link,
.reserve-link {
  min-height: 40px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.reserve-link {
  padding: 0 0 3px;
}

/* Les croix de fermeture (galerie, planche agrandie) sont les seules sorties
   de ces calques : elles doivent être confortables au pouce. */
.gallery-close,
.lightbox-close {
  min-width: 44px;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
}

/* Les accordéons de la FAQ : la ligne de résumé fait déjà ~47 px avec son
   remplissage, on garantit le plancher pour les libellés courts (« Le dress
   code ») et pour le chinois, plus compact. */
.faq-item > summary {
  min-height: 44px;
  align-items: center;
}

/* ---------- Filigrane hippocampe — page « Table » (index 0) ---------- */

/* Peint en COUCHE DE FOND de la page, comme le grain : la page étant le
   conteneur de défilement, son background ne défile pas et couvre donc toute la
   hauteur, y compris la partie atteinte au scroll. Un pseudo-élément absolu
   inset:0 ne couvrait, lui, que la zone visible (même piège que l'ancien
   .page-grain). L'opacité est « cuite » dans le PNG (50 % jour / 40 % nuit),
   une couche de background n'ayant pas d'opacité propre.
   Le dessin est carré : une taille identique sur les deux axes conserve ses
   proportions ; `min()` le borne en hauteur ET en largeur pour qu'il ne déborde
   pas sur écran étroit. `dvh` pour ne pas sauter au repli de la barre d'URL. */
.page[data-index="0"] {
  /* Taille et opacité du filigrane en variables : reprises par l'élément
     animé `.emblem-fly-in` ci-dessous (SEULE représentation visuelle du
     hippocampe sur cette page — le fond ne porte plus le filigrane, pour ne
     jamais superposer deux hippocampes) et par les redéfinitions responsive. */
  --emblem-size: min(76dvh, 78vw);
  --emblem-opacity: 0.5;
  background-image:
    linear-gradient(to right, rgba(17, 53, 34, 0.07), rgba(17, 53, 34, 0) 4%),
    url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22180%22%20height%3D%22180%22%3E%3Cfilter%20id%3D%22n%22%3E%3CfeTurbulence%20type%3D%22fractalNoise%22%20baseFrequency%3D%220.9%22%20numOctaves%3D%222%22%20stitchTiles%3D%22stitch%22%2F%3E%3CfeColorMatrix%20values%3D%220%200%200%200%200.07%200%200%200%200%200.21%200%200%200%200%200.13%200%200%200%200.05%200%22%2F%3E%3C%2Ffilter%3E%3Crect%20width%3D%22180%22%20height%3D%22180%22%20filter%3D%22url(%23n)%22%2F%3E%3C%2Fsvg%3E"),
    linear-gradient(105deg, var(--paper-a) 0%, var(--paper-b) 100%);
  background-repeat: no-repeat, repeat, no-repeat;
}

:root[data-theme="dark"] .page[data-index="0"] {
  --emblem-opacity: 0.4;
}

/* ---------- Arrivée animée de l'hippocampe (demande client) ---------- */

/* Le filigrane de fond ci-dessus reste STATIQUE en permanence (filet de
   sécurité robuste au scroll, cf. commentaire plus haut). Par-dessus, à
   l'ouverture du livre, un vrai hippocampe (élément <img>, même dessin)
   arrive en grand, nage en plusieurs mouvements (échelle, rotation,
   trajectoire), puis s'estompe pile à la place et à l'opacité du filigrane —
   à cet instant les deux se confondent et l'élément animé disparaît,
   invisible. `z-index:-1` : derrière le texte, comme le fond. Décoratif
   (`alt=""`), jamais présent dans le pré-rendu qu'en tant que balise inerte
   avant le premier script. */
.emblem-fly-in {
  position: absolute;
  top: 46%;
  left: 50%;
  width: var(--emblem-size);
  height: auto;
  /* État de repos = déjà le filigrane final (opacité, taille, position) : ce
     même élément EST le filigrane en permanence, il n'existe pas de calque de
     fond séparé qui le doublerait. L'arrivée animée (.emblem-intro) part d'un
     état extrême et REVIENT précisément à cet état de repos ; qu'elle se
     termine proprement ou non ne change donc jamais le rendu. */
  transform: translate(-50%, -50%);
  opacity: var(--emblem-opacity);
  pointer-events: none;
  z-index: -1;
}

.emblem-fly-in-night {
  display: none;
}

:root[data-theme="dark"] .emblem-fly-in-day {
  display: none;
}

:root[data-theme="dark"] .emblem-fly-in-night {
  display: block;
}

.page[data-index="0"].emblem-intro .emblem-fly-in-day,
.page[data-index="0"].emblem-intro .emblem-fly-in-night {
  animation: emblem-fly-in 3.4s cubic-bezier(0.22, 0.68, 0.2, 1) both;
}

@keyframes emblem-fly-in {
  0% {
    opacity: 0;
    transform: translate(-32%, -72%) scale(1.85) rotate(-16deg);
  }
  14% {
    opacity: 0.85;
  }
  32% {
    opacity: 0.85;
    transform: translate(-66%, -38%) scale(1.5) rotate(11deg);
  }
  50% {
    transform: translate(-38%, -60%) scale(1.28) rotate(-8deg);
  }
  68% {
    opacity: 0.7;
    transform: translate(-56%, -44%) scale(1.1) rotate(4deg);
  }
  84% {
    transform: translate(-48%, -52%) scale(1.02) rotate(-1deg);
  }
  100% {
    opacity: var(--emblem-opacity);
    transform: translate(-50%, -50%) scale(1) rotate(0deg);
  }
}

@media (prefers-reduced-motion: reduce) {
  .page[data-index="0"].emblem-intro .emblem-fly-in-day,
  .page[data-index="0"].emblem-intro .emblem-fly-in-night {
    animation: none;
  }
}

/* ---------- Réservation ouverte : la page cède la place au widget ---------- */

/* Quand le convive ouvre la réservation, le texte d'accueil s'efface : le cadre
   Zenchef récupère sa hauteur et la page cesse de déborder. Le titre et les
   liens vers les cartes restent en place. */
.page.is-booking .reserve-lede {
  display: none;
}

@media (prefers-reduced-motion: no-preference) {
  .reserve-lede {
    transition: opacity 0.3s ease;
  }
}

/* ---------- Fond du document sous les barres du navigateur ---------- */

/* Sur iOS, la bande sous la barre d'accueil et les zones d'encoche laissent voir
   le fond du document : il doit se confondre avec ce qui est affiché, sinon une
   lisière d'une autre couleur casse l'immersion. Reliure verte livre fermé,
   couleur du papier livre ouvert. */
html,
body {
  background: #1b3623;
}

/* La bascule vers la couleur du papier est posée par `updateThemeColor()` dans
   book.js, en même temps que la balise theme-color : un pilotage unique évite de
   dépendre de `:has()` et garantit que les deux restent cohérents. */
