/* =========================================================================
   SITE-THEME.CSS — Base visuelle partagée « Encre & lumière 2026 »
   =========================================================================
   PROPOSITION — pas encore chargé par index.html (voir analyse SEO du
   2026-08-25 pour le plan complet). Contient les règles extraites du
   <style> d'index.html qui définissent : tokens (couleurs/rayons/ombres),
   décor de page (parchemin, lanternes, cerisier, montagnes), .panel et son
   glassmorphism, .panelTitle, .hubPanel, .seal, .title/.subtitle,
   .footerNote, mode sombre. Numéros de ligne = position dans index.html
   au moment de l'extraction (2026-08-25) ; peuvent bouger si le fichier
   est réédité, mais les règles elles-mêmes sont copiées mot pour mot.

   CE QUI N'EST PAS ICI (reste propre à index.html, spécifique au jeu) :
   barre de profils, zoom flottant, bouton de soutien/don, cartes de mode
   / type de partie / dashboard / mot / écriture, chips (niveau, thème,
   ton, filtre), champs de saisie, sélecteur de langue, icônes sociales.

   ORDRE : à l'intérieur d'un même sélecteur (ex. tous les blocs qui
   touchent .panel), l'ordre d'origine du fichier source est conservé —
   c'est ce qui fait gagner la bonne règle dans la cascade. L'ordre ENTRE
   sélecteurs différents n'a pas d'importance et a été réorganisé par
   thème pour la lisibilité.
   ========================================================================= */

/* --- Tokens clairs (source : index.html L.140-202) --------------------- */
.page {
  /* Fonds & surfaces (du plus profond au plus élevé) */
  --paper:        #E0D2B4;
  --paper-2:      #F6EEDA;
  --paper-3:      #EADEC4;
  --surface-0:    var(--paper-3);
  --surface-1:    var(--paper-2);
  --surface-2:    #FDF7E7;
  --surface-sunken: #D9C9A9;
  --surface-veil: rgba(255,250,240,0.55);

  /* Texte : encre brune, jamais de gris froid */
  --ink:          #2A1E15;
  --ink-2:        #5C4733;
  --ink-3:        #8C7457;
  --ink-4:        #A8916F;

  /* Bordures : brun chaud très discret */
  --line:         rgba(92,64,36,0.13);
  --line-strong:  rgba(92,64,36,0.21);
  --line-contrast: rgba(92,64,36,0.32);

  /* Couleur officielle du mot étudié */
  --word:         #D9563A;
  --word-soft:    rgba(217,86,58,0.12);
  --word-softer:  rgba(217,86,58,0.06);
  --word-ring:    rgba(217,86,58,0.30);
  --word-strong:  #B8402A;

  /* Accents (interface, jamais le mot étudié) */
  --cinabre:      var(--word);
  --cinabre-soft: var(--word-soft);
  --jade:         #4C7C60;
  --jade-soft:    rgba(76,124,96,0.12);
  --gold:         #9A7B45;
  --blossom:      #D98FA0;
  --wood:         #4A2F26;

  --hanzi-outline: #DCCFB6;
  --hanzi-draw:    #2F231D;

  /* Rayons harmonisés sur tout le site */
  --r-sm: 12px; --r-md: 16px; --r-lg: 22px; --r-xl: 28px; --r-pill: 999px;

  /* Élévations : ombres très douces, jamais dures */
  --sh-1: 0 1px 2px rgba(122,74,32,0.10), 0 3px 10px -5px rgba(122,74,32,0.14);
  --sh-2: 0 2px 6px -2px rgba(122,74,32,0.13), 0 16px 36px -20px rgba(107,62,26,0.40);
  --sh-3: 0 4px 14px -5px rgba(122,74,32,0.16), 0 34px 64px -32px rgba(107,62,26,0.50);
  --sh-inset: inset 0 1px 0 rgba(255,251,242,0.7);
  --glow-word: 0 10px 30px -18px rgba(217,86,58,0.65);

  /* Mouvement : court et fluide (150-250 ms) */
  --dur-1: 150ms; --dur-2: 200ms; --dur-3: 250ms;
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);

  --ui: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  --serif: "Instrument Serif", "Songti SC", "Noto Serif SC", Georgia, serif;
  --han: "Noto Serif SC", "Songti SC", "SimSun", serif;

  /* Échelle typographique (Lot 2, PROMPT 4, 30/08/2026) : terrain vierge
     avant ce prompt (aucun token --fs-* n'existait, voir ARCHITECTURE_LOT2.md
     §F) -- introduite ici pour la refonte spatiale du Parcours guidé,
     destinée à devenir la référence pour tout le site par la suite.
     clamp(MIN, MIN-fixe + pente-vw, MAX) respire entre 360px et 1920px
     sans multiplier les media queries, comme demandé. Même valeur en clair
     et en sombre (la taille de police ne dépend pas du thème) : un seul
     bloc ici, jamais dupliqué dans .page.dark.
     Repères du kit : corps de texte >= 16px (idéalement 17-18px sur grand
     écran) -> --fs-base ; titres de carte nettement au-dessus du corps,
     pas +2px -> --fs-xl/--fs-2xl ; chiffres clés traités comme un élément
     d'affichage -> --fs-2xl/--fs-3xl. */
  --fs-xs:   clamp(11px, 10.77px + 0.064vw, 12px);
  --fs-sm:   clamp(12.5px, 12.15px + 0.096vw, 14px);
  --fs-base: clamp(16px, 15.54px + 0.128vw, 18px);
  --fs-md:   clamp(17px, 16.31px + 0.192vw, 20px);
  --fs-lg:   clamp(20px, 19.08px + 0.256vw, 24px);
  --fs-xl:   clamp(24px, 22.62px + 0.385vw, 30px);
  --fs-2xl:  clamp(30px, 27.69px + 0.641vw, 40px);
  --fs-3xl:  clamp(38px, 34.77px + 0.897vw, 52px);
  /* Ajouté au Lot 2, PROMPT 7 (30/08/2026) : le caractère chinois affiché
     en grand sur les écrans de jeu (.wordCard) est le SEUL élément de
     toute l'application dont la taille dépasse --fs-3xl (déjà 72px avant
     même ce lot) -- étend la même échelle plutôt que d'en créer une
     seconde ("une seule échelle pour toute l'application", kit de prompts). */
  --fs-4xl:  clamp(56px, 51.38px + 1.28vw, 76px);
}

/* --- Tokens sombres (source : L.1115-1171) ------------------------------ */
.page.dark {
  --paper:        #2A1C12;
  --paper-2:      #3A2718;
  --paper-3:      #332215;
  --surface-0:    var(--paper-3);
  --surface-1:    var(--paper-2);
  --surface-2:    #47301E;
  --surface-sunken: #241709;
  --surface-veil: rgba(232,197,148,0.06);

  --ink:          #F2E6D2;
  --ink-2:        #D3BE9F;
  --ink-3:        #A38C6E;
  --ink-4:        #806A50;

  --line:         rgba(226,184,124,0.11);
  --line-strong:  rgba(226,184,124,0.19);
  --line-contrast: rgba(226,184,124,0.30);

  --word:         #D9563A;
  --word-soft:    rgba(217,86,58,0.16);
  --word-softer:  rgba(217,86,58,0.08);
  --word-ring:    rgba(217,86,58,0.38);
  --word-strong:  #E2724F;

  --cinabre:      var(--word);
  --cinabre-soft: var(--word-soft);
  --jade:         #82AA8B;
  --jade-soft:    rgba(130,170,139,0.14);
  --gold:         #C9A669;
  --blossom:      #C98E9B;
  --wood:         #2A1B11;

  --hanzi-outline: #3A2B1E;
  --hanzi-draw:    #F2E6D2;

  --sh-1: 0 1px 2px rgba(46,25,8,0.45), 0 3px 10px -5px rgba(46,25,8,0.5);
  --sh-2: 0 2px 6px -2px rgba(46,25,8,0.5), 0 18px 40px -22px rgba(38,20,6,0.72);
  --sh-3: 0 4px 14px -6px rgba(46,25,8,0.55), 0 36px 70px -34px rgba(38,20,6,0.8);
  --sh-inset: inset 0 1px 0 rgba(232,197,148,0.07);
  --glow-word: 0 10px 30px -18px rgba(217,86,58,0.55);

  color: var(--ink);
  background-color: var(--paper);
  background-attachment: fixed;
  background-image:
    radial-gradient(1150px 700px at 12% -6%, rgba(226,178,112,0.16), transparent 68%),
    radial-gradient(1200px 560px at 55% -240px, rgba(217,86,58,0.13), transparent 70%),
    radial-gradient(980px 560px at 104% 12%, rgba(201,166,105,0.10), transparent 70%),
    linear-gradient(168deg, #332215 0%, #2A1C12 52%, #221609 100%);
}

/* --- Reset & accessibilité (source : L.204-211, 1363-1364) -------------- */
html, body { margin: 0; padding: 0; }
#root { min-height: 100vh; }
* { box-sizing: border-box; }
input:focus { outline: none; }
::selection { background: rgba(180,57,47,0.18); }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-thumb { background: var(--line-strong, #C8C1B2); border-radius: 20px; border: 3px solid transparent; background-clip: content-box; }
.page.dark ::-webkit-scrollbar-thumb { background: var(--line-strong); }
.page.dark ::selection { background: rgba(201,97,76,0.30); }
@media (prefers-reduced-motion: reduce) {
  * { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}

/* --- Animation d'apparition (source : L.219-222, 1361) ------------------ */
@keyframes fadeUp {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}
.fade-up { animation: fadeUp var(--dur-3) var(--ease-out); }

/* =========================================================================
   STRUCTURE & DÉCOR DE PAGE (source : L.371-467, dégradés de fond
   ré-écrits 2 fois plus loin dans le fichier — L.1264-1276 puis
   L.1793-1826, versions finales incluses ci-dessous à la suite)
   ========================================================================= */
.page {
  position: relative;
  z-index: 0;
  min-height: 100vh;
  background-color: var(--paper);
  background-attachment: fixed;
  background-image:
    radial-gradient(1200px 720px at 12% -8%, rgba(255,246,226,0.85), transparent 68%),
    radial-gradient(1000px 620px at 104% 6%, rgba(206,152,110,0.22), transparent 70%),
    radial-gradient(1100px 700px at 50% 118%, rgba(120,78,40,0.16), transparent 72%),
    linear-gradient(168deg, #E6D9BD 0%, #E0D2B4 46%, #D8C8A6 100%);
  color: var(--ink);
  font-family: var(--ui);
  -webkit-font-smoothing: antialiased;
  padding: 64px 22px 88px;
  /* Bug iPhone résolu le 01/09/2026 (dérive horizontale, signalé par
     Jules sur la Chaîne du jour). `overflow-x: hidden` ne se contente
     pas de rogner : il fait de .page un CONTENEUR DE DÉFILEMENT —
     défilable par script, mais sans barre de défilement ni geste
     tactile pour revenir. À chaque nouveau mot, le focus de
     #answerInput (index.html, useEffect [screen, currentWord,
     reviewIndex]) demandait à être « révélé » : Safari remontait
     jusqu'à .page et décalait scrollLeft définitivement. Le
     dépassement à révéler était fourni par .parchmentDecor (480px en
     absolu, plus large que l'écran d'un iPhone — voir sa règle plus
     bas, également corrigée).
     `overflow: clip` rogne à l'identique et n'est PAS un conteneur de
     défilement : le décalage devient structurellement impossible.
     NE PAS revenir à `hidden` ici. */
  overflow: clip;
}
/* Repli Safari < 16 : comportement d'avant le correctif. */
@supports not (overflow: clip) {
  .page { overflow-x: hidden; }
}
/* Branche de cerisier en filigrane */
.page::before {
  content: "";
  position: absolute; top: -70px; right: -150px;
  width: min(600px, 68vw); height: 430px;
  background: url("images/blossom.png") right top / contain no-repeat;
  opacity: 0.7; pointer-events: none; z-index: 1;
}
/* Paysage à l'encre en bas de page */
.page::after {
  content: "";
  position: fixed; left: 0; right: 0; bottom: 0; height: 320px;
  background: url("images/mountains.jpg") center bottom / cover no-repeat;
  opacity: 1; pointer-events: none; z-index: 1;
  -webkit-mask-image: linear-gradient(180deg, transparent, #000 75%);
  mask-image: linear-gradient(180deg, transparent, #000 75%);
  mix-blend-mode: multiply;
  /* `will-change: transform` testé ici le 01/09/2026 (hypothèse : ce
     calque `position: fixed` + `mix-blend-mode` se repeindrait mal quand
     l'audio charge les voix sur le fil principal) -- déployé et testé
     par Jules, AUDIO ACTIVÉ : AUCUN EFFET sur le flash. Retiré. Cause
     réelle trouvée ailleurs (texture de `.wordCard`/`.summaryCard`, voir
     CONTEXTE_PROJET.md §6). Ne pas retenter cette piste sans nouvel
     élément. */
}
/* Lanternes en filigrane, coin haut-gauche */
.page .lanternDecor {
  position: absolute; top: -70px; left: -150px;
  width: min(900px, 102vw); height: 780px;
  background: url("images/Lanternes.png") left top / contain no-repeat;
  opacity: 0.8; pointer-events: none; z-index: 0;
}
.page > * { position: relative; z-index: 1; }
/* Parchemin : bande verticale collée au bord gauche */
.page .parchmentDecor {
  position: absolute; top: 0; left: 0;
  width: min(240px, 20vw);
  height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  overflow: hidden;
  pointer-events: none; z-index: 0;
}
.parchmentDecor .parchmentCapTop,
.parchmentDecor .parchmentCapBottom {
  flex: 0 0 auto;
  width: 100%;
  line-height: 0;
}
.parchmentDecor .parchmentCapTop img,
.parchmentDecor .parchmentCapBottom img {
  display: block;
  width: 100%;
  height: auto;
}
.parchmentDecor .parchmentCapBottom img {
  transform: scaleY(-1);
}
.parchmentDecor {
  /* 01/09/2026 (signalé par Jules) : 480px FIXES en position absolue
     dépassaient de ~90px à droite sur un iPhone (~390px de large), ce qui
     donnait au conteneur de défilement .page exactement de quoi dériver
     (voir la règle .page plus haut). Et sur toute fenêtre < 960px, les
     deux bandes de 480px se rejoignaient au milieu, alors que
     l'intention est « une bande collée au bord ». Plafond en unités
     relatives : plus aucun dépassement possible, à aucune largeur. */
  width: min(480px, 26vw);
}
.parchmentDecorRight {
  left: auto !important;
  right: 0;
  /* images/Parchemin.png (477×330) porte une bordure à motif de grecque
     de CHAQUE côté. Sans miroir, la bordure GAUCHE de la bande de droite
     atterrissait à 480px du bord droit de la fenêtre — soit en plein
     milieu de la page : une colonne de motifs carrés rattachée
     visuellement à rien, dont la hauteur bouge au défilement (elle est
     animée en JS, voir ParchmentDecor dans index.html). C'est la source
     des « barres et gros carrés à des endroits random ». Le miroir
     ramène la bordure décorée contre le bord droit, symétrique de celle
     de gauche. */
  transform: scaleX(-1);
}
.parchmentDecor .parchmentBody {
  flex: 1 1 auto;
  min-height: 0;
  background: url("images/Parchemin.png") left top repeat-y;
  background-size: 100% auto;
}
.container { max-width: 760px; margin: 0 auto; position: relative; z-index: 0; }
.container-wide { max-width: 1120px; }

/* Lot 2, PROMPT 7 (30/08/2026) : conteneur des écrans de mini-jeu
   (GameScreen, ToneDrillScreen, ToneConfusionScreen,
   ComponentWorkshopScreen, WritingPracticeScreen, CheckpointReviewScreen)
   -- composé AVEC .container (`className="container gameContainer"`),
   jamais à sa place : hérite du centrage/z-index existant, ajoute
   uniquement la largeur et le centrage vertical demandés. `min-height`
   volontairement MODÉRÉ (pas 100vh — .page a déjà 56-64px de padding
   haut/bas ET ProfileBar au-dessus, hors de .page) : sous 700px de
   hauteur de fenêtre, un min-height trop grand forcerait un centrage qui
   pousse le haut de la carte hors champ. `justify-content: center` seul
   ne PRODUIT de vide qu'à l'intérieur de ce budget -- jamais un
   débordement forcé, le contenu reste toujours visible en premier. */
.gameContainer {
  /* .container pose déjà max-width: 760px -- doit être explicitement
     redéfini ici, sinon il plafonnerait `width` ci-dessous quoi qu'il
     arrive (max-width agit indépendamment de width, il ne suffit pas de
     redéfinir width seul). */
  max-width: 920px;
  width: min(920px, calc(100% - 32px));
  min-height: min(60vh, 560px);
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* --- Décor en mode sombre (source : L.1174-1185) ------------------------ */
.page.dark::before { opacity: 0.30; filter: brightness(0.75) saturate(0.7); }
.page.dark::after {
  mix-blend-mode: screen;
  opacity: 0.22;
  filter: grayscale(0.6) brightness(0.7) contrast(1.1);
}
.page.dark .lanternDecor { opacity: 0.32; filter: brightness(0.7) saturate(0.75); }
.page.dark .parchmentDecor .parchmentBody,
.page.dark .parchmentDecor .parchmentCapTop img,
.page.dark .parchmentDecor .parchmentCapBottom img {
  filter: brightness(0.42) saturate(0.6) contrast(1.05);
}

/* --- Fond de page, itération « Premium 2026 » (source : L.1256, 1264-1276) */
.page { letter-spacing: -0.006em; line-height: 1.55; padding: 56px 22px 96px; }
.page {
  background-image:
    radial-gradient(1100px 520px at 50% -260px, rgba(217,86,58,0.10), transparent 70%),
    radial-gradient(900px 480px at 100% 0%, rgba(154,123,69,0.09), transparent 70%),
    radial-gradient(820px 520px at 0% 34%, rgba(76,124,96,0.07), transparent 70%),
    linear-gradient(180deg, rgba(46,32,25,0.05), transparent 420px);
}
.page::before { opacity: 0.42; }
.page::after { opacity: 0.55; }
.page .lanternDecor { opacity: 0.45; }
.page .parchmentDecor { opacity: 0.5; }
.page.dark .parchmentDecor { opacity: 0.75; }

/* --- Fond de page, itération finale « lavis d'encre » (source : L.1793-1826) */
.page {
  --ink-blob-1: rgba(52, 70, 112, 0.20);
  --ink-blob-2: rgba(196, 76, 50, 0.15);
}
.page.dark {
  --ink-blob-1: rgba(46, 68, 112, 0.24);
  --ink-blob-2: rgba(206, 92, 62, 0.18);
}
.page {
  background-image:
    radial-gradient(1100px 520px at 50% -260px, rgba(217,86,58,0.10), transparent 70%),
    radial-gradient(900px 480px at 100% 0%, rgba(154,123,69,0.09), transparent 70%),
    radial-gradient(820px 520px at 0% 34%, rgba(76,124,96,0.07), transparent 70%),
    linear-gradient(180deg, rgba(46,32,25,0.05), transparent 420px),
    radial-gradient(1600px 1200px at -8% -12%, var(--ink-blob-1), transparent 62%),
    radial-gradient(1300px 1050px at 108% 112%, var(--ink-blob-2), transparent 60%),
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='220' height='220'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix type='matrix' values='0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 0.22 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
  background-repeat: no-repeat, no-repeat, no-repeat, no-repeat, no-repeat, no-repeat, repeat;
  background-size: auto, auto, auto, auto, auto, auto, 220px 220px;
  background-attachment: scroll;
}
.page.dark {
  background-image:
    radial-gradient(1150px 700px at 12% -6%, rgba(226,178,112,0.16), transparent 68%),
    radial-gradient(1200px 560px at 55% -240px, rgba(217,86,58,0.13), transparent 70%),
    radial-gradient(980px 560px at 104% 12%, rgba(201,166,105,0.10), transparent 70%),
    linear-gradient(168deg, #332215 0%, #2A1C12 52%, #221609 100%),
    radial-gradient(1600px 1200px at -8% -12%, var(--ink-blob-1), transparent 62%),
    radial-gradient(1300px 1050px at 108% 112%, var(--ink-blob-2), transparent 60%),
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='220' height='220'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix type='matrix' values='0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 0.22 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
  background-repeat: no-repeat, no-repeat, no-repeat, no-repeat, no-repeat, no-repeat, repeat;
  background-size: auto, auto, auto, auto, auto, auto, 220px 220px;
  background-attachment: scroll;
}
.page { --ink-rgb: 42, 30, 21; }
.page.dark { --ink-rgb: 242, 230, 210; }

/* =========================================================================
   EN-TÊTES : sceau, titre, sous-titre (source : L.470-488, puis
   itération finale L.1829-1863 + L.1985)
   ========================================================================= */
.seal {
  width: 60px; height: 60px; line-height: 60px;
  margin: 0 auto 22px;
  background: linear-gradient(150deg, var(--cinabre), #7E2A20);
  color: #FBEDE4;
  font-size: 30px; text-align: center; border-radius: 16px;
  transform: rotate(-6deg);
  box-shadow: 0 16px 30px -14px rgba(74,47,38,0.7), inset 0 1px 0 rgba(255,255,255,0.18);
  font-family: var(--han);
}
.title {
  font-family: var(--serif);
  font-size: clamp(34px, 5vw, 46px);
  font-weight: 400; line-height: 1.05;
  margin: 0 0 10px; letter-spacing: -0.02em;
}
.title-sm { font-size: clamp(26px, 3.4vw, 32px); }
.subtitle { margin: 0; color: var(--ink-3); font-family: var(--ui); font-size: 15px; }
.homeHeader { text-align: center; margin-bottom: 48px; }
.screenHeader { text-align: center; margin-bottom: 32px; }
.title { letter-spacing: -0.03em; line-height: 1.03; }
.subtitle { font-size: 15.5px; color: var(--ink-3); line-height: 1.6; max-width: 62ch; margin-inline: auto; }
.homeHeader { margin-bottom: 52px; }

.homeHeader { animation: fadeUp 0.6s var(--ease-out); }
.seal {
  width: 72px; height: 72px; line-height: 70px; font-size: 34px;
  border-radius: 22px; position: relative;
  background: linear-gradient(145deg, #E2684A 0%, var(--word) 45%, #8C3123 100%);
  box-shadow:
    0 22px 40px -16px rgba(120,45,32,0.65),
    0 6px 14px -6px rgba(74,47,38,0.5),
    inset 0 2px 0 rgba(255,255,255,0.35),
    inset 0 -4px 8px rgba(0,0,0,0.25),
    0 0 0 3px rgba(var(--paper-2-rgb), 0.65);
}
.seal::before {
  content: ""; position: absolute; inset: 3px; border-radius: 18px;
  background: linear-gradient(160deg, rgba(255,255,255,0.35), transparent 55%);
  pointer-events: none;
}
.seal::after {
  content: ""; position: absolute; inset: -10px; border-radius: 27px;
  border: 1px dashed rgba(var(--ink-rgb, 42,30,21), 0.22);
  opacity: 0.8; pointer-events: none;
}
.title {
  font-size: clamp(40px, 5.6vw, 54px);
  background: linear-gradient(100deg, var(--ink) 32%, var(--word) 62%, var(--ink) 92%);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.homeHeader::after {
  content: ""; display: block; width: 64px; height: 2px; margin: 16px auto 0;
  background: linear-gradient(90deg, transparent, var(--word), transparent);
  opacity: 0.65;
}
.subtitle { font-weight: 500; }
.page.dark .seal { /* source : L.1224-1228 */
  background: linear-gradient(150deg, #A8412F, #6B2318);
  color: #F6E7DC;
  box-shadow: 0 18px 36px -16px rgba(46,25,8,0.8), inset 0 1px 0 rgba(237,226,212,0.16);
}
.page.dark .title {
  background: linear-gradient(100deg, var(--ink) 28%, var(--word-strong) 60%, var(--ink) 94%);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.page.dark .seal::after { border-color: rgba(var(--white-rgb), 0.3); }

@media (max-width: 560px) {
  .title { font-size: clamp(28px, 8vw, 36px); }
}

/* =========================================================================
   .wordSidebar — base « papier plat » AVANT glassmorphism (source :
   L.701-710 du fichier original). Sélecteur autonome (pas de ".panel"
   dans la liste), repéré tardivement — voir correction du 2026-08-25 :
   omis de la première extraction car il n'apparaissait dans aucun des
   blocs ".panel, .wordSidebar" déjà suivis. Doit rester AVANT la section
   .panel ci-dessous : c'est elle qui le recouvre (fond vitré, bordure
   uniforme, rayon boosté, ombre) exactement comme dans le fichier source.
   ========================================================================= */
.wordSidebar {
  position: relative;
  width: 100%; display: flex; flex-direction: column;
  background:
    linear-gradient(180deg, rgba(255,250,236,0.38), rgba(255,250,236,0) 110px),
    var(--paper-2);
  border: 1px solid var(--line-strong); border-radius: var(--r-xl);
  overflow: hidden; box-shadow: var(--sh-2), 0 0 0 5px rgba(240,228,204,0.55);
  border-top: 3px solid var(--cinabre);
}

/* =========================================================================
   .panel — carte glassmorphism principale (source : L.490-527 base,
   L.1259-1260 taille de titre, L.1279-1300 couche « premium »,
   L.1301-1309 variante sombre, L.1570 responsive, L.1611-1638 couche
   glassmorphism (flou), L.1874-1888 sceau + trait pinceau finaux,
   L.1913-1963 grain de papier final (VERSION QUI GAGNE LA CASCADE),
   L.1978-1985 harmonisation sombre)
   ========================================================================= */
.panel {
  position: relative;
  z-index: 1;
  background:
    linear-gradient(180deg, rgba(255,250,236,0.4), rgba(255,250,236,0) 120px),
    var(--paper-2);
  border: 1px solid var(--line-strong);
  border-top: 3px solid var(--cinabre);
  border-radius: var(--r-xl);
  padding: 26px 28px;
  margin-bottom: 22px;
  box-shadow: var(--sh-2), 0 0 0 5px rgba(240,228,204,0.55);
}
.panelTitle {
  position: relative;
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.16em;
  color: var(--ink-2); font-family: var(--ui);
  margin: 0 0 16px; font-weight: 700;
  padding-left: 16px;
}
.panelTitle::before {
  content: ""; position: absolute; left: 0; top: 50%; transform: translateY(-50%);
  width: 8px; height: 8px; border-radius: 2px;
  background: linear-gradient(150deg, var(--cinabre), #7E2A20);
}
.panelTitle { font-size: 10.5px; letter-spacing: 0.18em; color: var(--ink-3); margin-bottom: 18px; }
.panelTitle::before { width: 7px; height: 7px; border-radius: 999px; background: var(--word); box-shadow: var(--glow-word); }

.panel, .wordSidebar {
  background:
    linear-gradient(180deg, var(--surface-veil), transparent 180px),
    var(--surface-1);
  border: 1px solid var(--line);
  border-top: 1px solid var(--line);
  border-radius: var(--r-xl);
  box-shadow: var(--sh-2), var(--sh-inset);
  padding: 28px 30px;
}
.wordSidebar { padding: 0; overflow: hidden; }
.panel { margin-bottom: 24px; }
/* Liseré cinabre de .panel::before RETIRÉ le 02/09/2026 (ornements &
   textures) : réintroduit comme couche de background-image de .panel
   lui-même (voir patch en fin de fichier), .panel n'a alors besoin de
   ses deux pseudo-éléments que pour le filigrane bambou (::before) et
   les équerres+colophon (::after). .wordSidebar garde son liseré en
   ::before (règle dédiée dans le patch, elle n'a pas de colophon). */
.page.dark .panel,
.page.dark .wordSidebar {
  background:
    linear-gradient(180deg, var(--surface-veil), transparent 180px),
    var(--surface-1);
  border-color: var(--line);
  box-shadow: var(--sh-2), var(--sh-inset);
}

@media (max-width: 860px) {
  .page { padding: 40px 16px 88px; }
  .panel { padding: 22px 18px; border-radius: var(--r-lg); }
  .homeHeader { margin-bottom: 34px; }
  .page::before, .page .lanternDecor { opacity: 0.22; }
}

/* --- Système "verre dépoli" (flou) : tokens ------------------------------
   ATTENTION PERFORMANCE : --glass-blur: 40px est la valeur pleine utilisée
   dans index.html (app installée, peu de pages, coût de flou payé une
   fois). Recommandation validée pour les pages SEO : réduire cette valeur
   (ex. 14-18px, cohérent avec seo-pages.css) via une redéfinition LOCALE
   de --glass-blur sur le wrapper des pages SEO, sans toucher à ce fichier
   ni à index.html. Voir section perf de l'analyse. */
:root {
  --paper-rgb:    224, 210, 180;
  --paper-2-rgb:  246, 238, 218;
  --paper-3-rgb:  234, 222, 196;
  --white-rgb:    255, 255, 255;

  --glass-blur: 40px;
  --glass-sat: 185%;
  --glass-alpha-1: 0.34;
  --glass-alpha-2: 0.4;
  --glass-alpha-compact: 0.68;
  --glass-alpha-nav: 0.3;
  --glass-border-alpha: 0.6;
  --glass-shine-alpha: 0.3;
  --glass-radius-boost: 12px;
}
.page.dark {
  --paper-rgb:    42, 28, 18;
  --paper-2-rgb:  58, 39, 24;
  --paper-3-rgb:  51, 34, 21;
  --white-rgb:    237, 226, 212;
}

.panel, .wordSidebar, .summaryCard, .wordCard {
  border-radius: calc(var(--r-xl) + var(--glass-radius-boost));
}

.panel, .wordSidebar {
  background:
    linear-gradient(135deg, rgba(var(--white-rgb), var(--glass-shine-alpha)), transparent 55%),
    linear-gradient(180deg, var(--surface-veil), transparent 180px),
    rgba(var(--paper-2-rgb), var(--glass-alpha-1));
  backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-sat));
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-sat));
  border: 1px solid rgba(var(--white-rgb), var(--glass-border-alpha));
  box-shadow: var(--sh-2), inset 0 1px 0 rgba(var(--white-rgb), calc(var(--glass-shine-alpha) * 1.4));
}
.page.dark .panel, .page.dark .wordSidebar {
  background:
    linear-gradient(135deg, rgba(var(--white-rgb), calc(var(--glass-shine-alpha) * 0.6)), transparent 55%),
    linear-gradient(180deg, var(--surface-veil), transparent 180px),
    rgba(var(--paper-2-rgb), var(--glass-alpha-1));
}
/* --- Petits ornements finaux de .panel ---------------------------------- */
.panel { position: relative; }
/* Sceau 印 de .panel::after RETIRÉ le 01/09/2026 (signalé par Jules) :
   posé sur CHAQUE panel en absolu (right:16px/bottom:14px), il tombait
   par-dessus le contenu des grands panneaux (constaté sur « Autres
   façons de t'entraîner », par-dessus la ligne « Atelier des
   composants ») et se lisait comme un carré parasite, pas comme un
   ornement. Le sceau subsiste sur .footerNote::after : UN SEUL par page,
   centré, hors flux de contenu.
   Ne pas réintroduire d'ornement en position absolue dans la zone de
   contenu d'un panel : sa hauteur est variable, aucune marge ne peut
   garantir qu'il ne rencontrera pas de texte.
   RÉINTRODUIT le 02/09/2026 (ornements & textures) sous une forme qui ne
   peut plus reproduire ce bug : le sceau revient dans .panel::after, mais
   plus jamais en position libre — il vit dans une bande de 52px RÉSERVÉE
   par padding-bottom, hors de la zone de contenu (patch en fin de
   fichier). Le filigrane bambou revient de même façon, borné par
   overflow:hidden et éteint par un masque avant tout bord. Voir le patch
   « ORNEMENTS & TEXTURES » en fin de fichier pour le mécanisme complet. */
.panelTitle::before {
  width: 13px; height: 5px; border-radius: 60% 30% 55% 25%;
  background: linear-gradient(100deg, var(--word), transparent);
  box-shadow: none; transform: translateY(-50%) rotate(-4deg);
}
.panel, .wordSidebar {
  background:
    var(--hatch-tex),
    linear-gradient(135deg, rgba(var(--white-rgb), var(--glass-shine-alpha)), transparent 55%),
    linear-gradient(180deg, var(--surface-veil), transparent 180px),
    rgba(var(--paper-2-rgb), var(--glass-alpha-1));
}
/* .page.dark .panel::after retiré avec .panel::after (voir plus haut). */
.page.dark .panel,
.page.dark .wordSidebar {
  background:
    var(--hatch-tex),
    linear-gradient(135deg, rgba(var(--white-rgb), calc(var(--glass-shine-alpha) * 0.6)), transparent 55%),
    linear-gradient(180deg, var(--surface-veil), transparent 180px),
    rgba(var(--paper-2-rgb), var(--glass-alpha-1));
}
.page.dark .panelTitle::before {
  background: linear-gradient(100deg, var(--word-strong), transparent);
}

/* =========================================================================
   .hubPanel — variante de .panel pour une carte-lien cliquable entière
   (source : L.577-587). Composition : className="panel hubPanel".
   ========================================================================= */
.hubPanel {
  display: block;
  text-decoration: none;
  color: inherit;
  cursor: pointer;
  transition: transform 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease;
}
.hubPanel:hover { transform: translateY(-2px); border-color: var(--line-strong); }
.hubPanelRow { display: flex; align-items: center; gap: 18px; }
.hubPanelIcon { flex: none; margin: 0; }
.hubPanelText { flex: 1 1 auto; min-width: 0; }

/* =========================================================================
   .footerNote (source : L.692, 1932-1939, 1981-1984)
   ========================================================================= */
.footerNote { text-align: center; font-size: 12.5px; color: var(--ink-4); font-family: var(--ui); margin-top: 12px; line-height: 1.6; }
.footerNote { position: relative; padding-bottom: 44px; }
.footerNote::after {
  content: "印"; position: absolute; left: 50%; bottom: 0; transform: translateX(-50%) rotate(-3deg);
  width: 26px; height: 26px; display: flex; align-items: center; justify-content: center;
  font-family: var(--han); font-size: 13px; color: var(--word);
  border: 1px solid var(--word); border-radius: 4px; opacity: 0.32;
  pointer-events: none;
}
.page.dark .footerNote::after {
  opacity: 0.42; color: var(--word-strong); border-color: var(--word-strong);
  background: rgba(var(--white-rgb), 0.04);
}

/* =========================================================================
   ORNEMENTS & TEXTURES — équerres de coin, colophon, filigrane bambou,
   grain de fibre        (à coller EN FIN de site-theme.css, après toutes
   les règles .panel existantes)
   -------------------------------------------------------------------------
   Réintroduit, sous une forme non recouvrante, les trois ornements retirés
   le 01/09/2026, puis étendu et corrigé le 03/09/2026 après retour de
   Jules (captures à l'appui) :
     — le sceau 印 : plus jamais en absolu dans la zone de contenu, il vit
       dans une bande RÉSERVÉE par le padding-bottom du panneau ;
     — le filigrane bambou : à l'intérieur du panneau (overflow: hidden),
       derrière le contenu, éteint par un masque avant tout bord — et
       depuis le 03/09/2026, dimensionné en pourcentages du panneau (plus
       une boîte fixe de 190px) pour atteindre visuellement ses bords sur
       une grande carte au lieu d'y paraître minuscule ;
     — la texture : bruit fractal apériodique au lieu d'une trame de
       période 5px à arête nette (la cause du moiré).
   Depuis le 03/09/2026, .wordSidebar (Liste des mots, Tableau de bord)
   reçoit exactement le même traitement que .panel (avant : liseré seul,
   pas d'équerres/colophon) — voir la règle combinée plus bas. Couleur du
   bambou en thème sombre changée à la même date (jade clair -> ton chaud,
   proche de --gold) : "vert sur marron" jugé peu harmonieux par Jules.
   .wordCard / .summaryCard ne sont pas touchées.
   ========================================================================= */

/* --- Grain de fibre apériodique (remplace la trame) ---------------------
   03/09/2026 : le bruit est TEINTÉ (ambre chaud, R > G > B) au lieu de
   rester en niveaux de gris — retour de Jules, un grain gris pur en
   thème sombre (blend `screen`, donc éclairci) lisait comme "du gris qui
   délave le marron", pas comme un grain de papier. Une deuxième feColorMatrix
   (matrix, après le saturate(0)) recolore le bruit une fois désaturé, au
   lieu de le garder achromatique. */
:root {
  --paper-noise: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3CfeColorMatrix type='matrix' values='1 0 0 0 0  0.7 0 0 0 0  0.38 0 0 0 0  0 0 0 1 0'/%3E%3C/filter%3E%3Crect width='220' height='220' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E");
  --hatch-tex: var(--paper-noise);
  --hatch: var(--hatch-tex);
  --noise-tile: 220px 220px;
  --noise-blend: multiply;   /* le bruit assombrit le parchemin */
}
/* En sombre : `screen` (qui ÉCLAIRCIT) donnait un halo gris terne une fois
   le bruit teinté testé -- `multiply` (qui ASSOMBRIT, comme en clair)
   avec ce même bruit ambre lit comme un grain plus profond, jamais gris,
   cohérent avec la demande de Jules ("plus foncé"). */
.page.dark { --noise-blend: multiply; }

/* Un bruit n'est pas une trame : deux grains superposés ne peuvent pas
   battre l'un contre l'autre — contrairement à l'ancienne trame à période
   fixe, empiler ce bruit sur lui-même ne peut plus créer de moiré.
   La distinction --hatch-tex / --hatch reste néanmoins utile et est
   CONSERVÉE (03/09/2026, restaure l'architecture documentée dans
   index.html) : --hatch-tex est la texture que peint une "surface
   porteuse" (.panel, .wordSidebar, .modalCard.panel, .pathHeroCard) POUR
   ELLE-MÊME (voir la règle .panel, .wordSidebar juste en dessous, qui lit
   var(--hatch-tex) directement) ; --hatch est ce que ses DESCENDANTS
   lisent (.modeCard, .toneChip, etc., dans index.html), mis à `none` par
   ces mêmes surfaces porteuses pour éviter un empilement visuel trop
   chargé à l'intérieur d'un panel déjà grainé (index.html, règle
   "Surfaces PORTEUSES"). Ne pas faire lire --hatch à .panel/.wordSidebar
   elles-mêmes : cette même règle "surfaces porteuses" leur poserait alors
   --hatch: none à elles aussi, et elles perdraient leur propre grain. */

/* --- .panel, .wordSidebar : fond = grain + liseré + verre --------------
   .wordSidebar rejoint .panel ici (03/09/2026) : avant, elle n'avait droit
   qu'au liseré (règle dédiée en ::before) ; les listes "Liste des mots" et
   "Tableau de bord" en restaient visuellement à l'écart de cette livraison.
   Le principe reste identique à .panel : le liseré quitte son propre
   pseudo-élément pour devenir une couche de background-image, ce qui
   libère ::before pour le bambou et ::after pour l'anneau équerres+
   colophon (elle n'en avait ni l'un ni l'autre avant). */
.panel, .wordSidebar {
  position: relative;
  isolation: isolate;
  overflow: hidden;              /* borne le filigrane */
  padding-bottom: 52px;          /* réserve la bande du colophon */
  background-image:
    var(--hatch-tex),                                                       /* grain */
    linear-gradient(90deg, transparent, rgba(217,86,58,0.75), transparent), /* liseré */
    linear-gradient(135deg, rgba(var(--white-rgb), var(--glass-shine-alpha)), transparent 55%),
    linear-gradient(180deg, var(--surface-veil), transparent 180px),
    linear-gradient(0deg, rgba(var(--paper-2-rgb), var(--glass-alpha-1)),
                          rgba(var(--paper-2-rgb), var(--glass-alpha-1)));
  background-size: var(--noise-tile), calc(100% - 52px) 2px, auto, auto, auto;
  background-position: 0 0, center top, 0 0, 0 0, 0 0;
  background-repeat: repeat, no-repeat, repeat, repeat, repeat;
  background-blend-mode: var(--noise-blend), normal, normal, normal, normal;
}
.page.dark .panel, .page.dark .wordSidebar {
  background-image:
    var(--hatch-tex),
    linear-gradient(90deg, transparent, rgba(226,114,79,0.80), transparent),
    linear-gradient(135deg, rgba(var(--white-rgb), calc(var(--glass-shine-alpha) * 0.6)), transparent 55%),
    linear-gradient(180deg, var(--surface-veil), transparent 180px),
    linear-gradient(0deg, rgba(var(--paper-2-rgb), var(--glass-alpha-1)),
                          rgba(var(--paper-2-rgb), var(--glass-alpha-1)));
  /* Répété ici (02/09/2026, testé en navigateur réel) : ce sélecteur à 2-3
     classes gagne la cascade sur .panel/.wordSidebar pour background-image,
     mais SANS redéclarer aussi size/position/repeat/blend-mode ici, ces 4
     longhand retombaient à leur valeur initiale (5x "auto", plus de trame
     2px pour le liseré) — le liseré cinabre s'étalait alors sur tout le
     panneau, un gros halo clair illisible en thème sombre. Garder ces 4
     lignes synchronisées avec la règle .panel, .wordSidebar plus haut si
     l'une change. */
  background-size: var(--noise-tile), calc(100% - 52px) 2px, auto, auto, auto;
  background-position: 0 0, center top, 0 0, 0 0, 0 0;
  background-repeat: repeat, no-repeat, repeat, repeat, repeat;
  background-blend-mode: var(--noise-blend), normal, normal, normal, normal;
}
/* le contenu passe au-dessus du filigrane, sous le cadre */
.panel > *, .wordSidebar > * { position: relative; z-index: 1; }

/* --- Filigrane bambou, contenu et éteint par un masque ------------------
   03/09/2026 : la boîte n'est plus une taille fixe (190×210px, minuscule
   et identique sur chaque panneau, "spam" du même motif partout et à peine
   visible sur un grand panneau) mais couvre tout le panneau jusqu'à la
   bande du colophon (inset 0 sur 3 côtés) — le masque radial reste en
   pourcentages, donc sa portée suit désormais la taille réelle du panneau
   au lieu d'être plafonnée à 190px : le filigrane atteint visuellement les
   bords sur une grande carte, sans avoir besoin d'un second réglage. */
.panel::before, .wordSidebar::before {
  content: ""; position: absolute; z-index: 0; pointer-events: none;
  inset: 0 0 34px 0;              /* meurt AVANT la bande du colophon */
  background-image:
    repeating-linear-gradient(97deg, transparent 0px,
      rgba(76,124,96,0.16) 9px, rgba(76,124,96,0.16) 12px, transparent 21px),
    repeating-linear-gradient(97deg, transparent 0px,
      rgba(var(--ink-rgb), 0.05) 3px, transparent 7px);
  mask-image: radial-gradient(85% 95% at 100% 42%,
    #000 6%, rgba(0,0,0,0.5) 30%, transparent 58%);
  -webkit-mask-image: radial-gradient(85% 95% at 100% 42%,
    #000 6%, rgba(0,0,0,0.5) 30%, transparent 58%);
}
/* Thème sombre (03/09/2026) : le jade clair sur parchemin sombre lisait
   comme "du vert sur du marron", un mélange jugé peu harmonieux (retour
   direct) — remplacé par un ton chaud (même famille que --gold) cohérent
   avec le reste de la palette « Encre de nuit », qui n'utilise quasiment
   que des ambres/cinabres en accent sombre. */
.page.dark .panel::before, .page.dark .wordSidebar::before {
  background-image:
    repeating-linear-gradient(97deg, transparent 0px,
      rgba(201,166,105,0.18) 9px, rgba(201,166,105,0.18) 12px, transparent 21px),
    repeating-linear-gradient(97deg, transparent 0px,
      rgba(226,184,124,0.06) 3px, transparent 7px);
}

/* --- Équerres de coin ET colophon sur un seul anneau -------------------
   Anneau de bordure masqué en 5 endroits : les 4 angles (équerres) et une
   fenêtre basse centrée (le segment bas de l'anneau y devient le filet du
   colophon, sous les vaguelettes et le sceau). 03/09/2026 : étendu à
   .wordSidebar, qui n'avait ni équerres ni sceau (seulement des vaguelettes
   en ::after, remplacées — voir la suppression correspondante dans
   index.html, elles ne visaient qu'un ::after "nu" sans anneau). */
.panel::after, .wordSidebar::after {
  content: "印";
  position: absolute; inset: 11px; z-index: 2; pointer-events: none;
  display: flex; align-items: flex-end; justify-content: center;
  padding-bottom: 3px;
  font-family: var(--han); font-size: 13px; line-height: 26px;
  color: rgba(217,86,58,0.50);
  border: 1px solid rgba(217,86,58,0.34);
  border-radius: calc(var(--r-xl) + var(--glass-radius-boost) - 11px); /* 29px */
  background-image: repeating-radial-gradient(circle at 50% 150%,
    transparent 0, transparent 7px,
    rgba(var(--ink-rgb), 0.06) 10px, transparent 14px);
  background-size: 34px 26px;
  background-repeat: repeat-x;
  background-position: center bottom 3px;
  mask-image:
    linear-gradient(#000,#000), linear-gradient(#000,#000),
    linear-gradient(#000,#000), linear-gradient(#000,#000),
    linear-gradient(90deg, transparent, #000 26%, #000 74%, transparent);
  mask-size: 46px 46px, 46px 46px, 46px 46px, 46px 46px, calc(100% - 92px) 30px;
  mask-position: left top, right top, left bottom, right bottom, center bottom;
  mask-repeat: no-repeat;
  mask-composite: add;
  -webkit-mask-image:
    linear-gradient(#000,#000), linear-gradient(#000,#000),
    linear-gradient(#000,#000), linear-gradient(#000,#000),
    linear-gradient(90deg, transparent, #000 26%, #000 74%, transparent);
  -webkit-mask-size: 46px 46px, 46px 46px, 46px 46px, 46px 46px, calc(100% - 92px) 30px;
  -webkit-mask-position: left top, right top, left bottom, right bottom, center bottom;
  -webkit-mask-repeat: no-repeat;
  -webkit-mask-composite: source-over;
}
.page.dark .panel::after, .page.dark .wordSidebar::after {
  color: rgba(226,114,79,0.60);
  border-color: rgba(226,114,79,0.34);
  background-image: repeating-radial-gradient(circle at 50% 150%,
    transparent 0, transparent 7px,
    rgba(226,184,124,0.08) 10px, transparent 14px);
}

/* --- Variantes d'échappement ------------------------------------------- */
/* Panneau court (chips de niveaux, préférences rapides) : pas de
   filigrane, il n'a pas la place de s'éteindre proprement. */
.panel.panel--plain::before { content: none; }
/* Panneau sans colophon (ex. dernier panneau avant le pied de page) : */
.panel.panel--noColophon { padding-bottom: 28px; }
.panel.panel--noColophon::after { content: ""; }

/* --- Responsive --------------------------------------------------------- */
@media (max-width: 860px) {
  .panel { padding: 22px 18px 46px; border-radius: var(--r-lg); }
  .panel, .wordSidebar,
  .page.dark .panel, .page.dark .wordSidebar {
    background-size: var(--noise-tile), calc(100% - 36px) 2px, auto, auto, auto;
  }
  .panel::after, .wordSidebar::after {
    inset: 8px; border-radius: 16px;
    mask-size: 30px 30px, 30px 30px, 30px 30px, 30px 30px, calc(100% - 64px) 26px;
    -webkit-mask-size: 30px 30px, 30px 30px, 30px 30px, 30px 30px, calc(100% - 64px) 26px;
  }
  .panel::before, .wordSidebar::before { inset: 0 0 30px 0; }
}

/* --- Pied de page : le sceau y devient redondant ----------------------- */
/* Chaque panneau porte désormais son sceau : garder celui du pied de page
   fait doublon. Remplacé par un filet assorti au colophon. */
.footerNote { padding-bottom: 28px; }
.footerNote::after {
  content: ""; left: 50%; bottom: 10px; transform: translateX(-50%);
  width: 120px; height: 1px; border: 0; border-radius: 0; opacity: 1;
  background: linear-gradient(90deg, transparent, var(--line-contrast), transparent);
}
