* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

/* iOS : empêcher le navigateur de gonffler le texte automatiquement */
html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

/* Tactile : les éléments glissables ne déclenchent pas le scroll natif (le pont
   touch-dnd gère le glisser-déposer au doigt). */
[draggable="true"] { touch-action: none; }

/* ── Écran de chargement (overlay PWA) ─────────────────────────────────────── */
#app-loader {
  position: fixed;
  inset: 0;
  z-index: 100000;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #2a2a2a;
  color: #eee;
  font-family: Arial, sans-serif;
  transition: opacity 0.35s ease;
}
#app-loader.hidden { opacity: 0; pointer-events: none; }
.app-loader-box { text-align: center; width: min(320px, 70vw); }
.app-loader-logo { width: 96px; height: 96px; border-radius: 16px; margin-bottom: 14px; }
.app-loader-title { font-size: 1.1rem; font-weight: bold; margin-bottom: 14px; letter-spacing: .5px; }
.app-loader-track { height: 8px; border-radius: 6px; background: #444; overflow: hidden; }
#app-loader-bar {
  height: 100%; width: 0;
  background: linear-gradient(90deg, #4caf50, #8bc34a);
  border-radius: 6px;
  transition: width 0.2s ease;
}
/* Barre indéterminée (animée) tant qu'aucune progression chiffrée n'est connue */
#app-loader.indeterminate #app-loader-bar {
  width: 35%;
  transition: none;
  animation: ebs-indeterminate 1.1s ease-in-out infinite;
}
@keyframes ebs-indeterminate {
  0%   { margin-left: -35%; }
  100% { margin-left: 100%; }
}
.app-loader-label { margin-top: 10px; font-size: .8rem; color: #bbb; }

/* Bannière de mise à jour (PWA) */
#app-update-banner {
  position: fixed;
  left: 50%; bottom: max(16px, env(safe-area-inset-bottom));
  transform: translateX(-50%);
  z-index: 100001;
  display: flex; align-items: center; gap: 10px;
  background: #333; color: #fff;
  border: 1px solid #555; border-radius: 8px;
  padding: 8px 14px; font-size: .85rem;
  box-shadow: 0 4px 16px rgba(0,0,0,.4);
}
#app-update-reload {
  background: #4caf50; color: #fff; border: none; border-radius: 6px;
  padding: 4px 12px; cursor: pointer; font-weight: bold;
}
@media (hover: hover) {
  #app-update-reload:hover { background: #57bd5b; }
}

/* Téléchargement hors-ligne (Paramètres) — les boutons portent .param-btn (cf. bloc Paramètres). */
.local-dl-row { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 6px; }
.local-dl-row button:disabled { opacity: .6; cursor: default; }
.local-dl-track { height: 8px; border-radius: 6px; background: #ddd; overflow: hidden; margin-top: 10px; }
#local-dl-bar { height: 100%; width: 0; background: linear-gradient(90deg, #4caf50, #8bc34a); transition: width .2s ease; }
.local-dl-status { margin-top: 8px; font-size: .85rem; color: #555; }

ul {
  margin-left: 20px;
  /* remet une marge pour que les puces apparaissent */
  padding-left: 20px;
  /* important pour que les puces ne soient pas hors de l'écran */
  list-style-type: disc;
  /* assure qu’il y ait des puces rondes */
  /*list-style: none; à mettre pour remplacer les puces par des cases à cocher*/
}

/* 20260816 VCH liste qui MÊLE une puce et des cases à cocher : la puce se met dans la colonne
   des cases, et le texte de la ligne à puce dans celle du texte des cases.

   Cas d'ARE #000, signalé par Vincent : le <ul> y contient un <li> (« prenez la tuile
   personnage. ») suivi de <label> placés DIRECTEMENT dans la liste, sans <li>. Ces labels
   commencent donc au bord de contenu du <ul>, là où commence aussi la boîte du <li> — mais la
   puce du <li>, elle, est dessinée EN DEHORS de cette boîte (`list-style-position: outside`),
   donc plus à gauche. Mesuré en 1600×900 : boîte du li et case toutes deux à x = 1171, puce à
   gauche de 1171, texte du li à 1171 contre 1184 pour le texte des cases.

   La puce native est donc remplacée par un ::before de largeur fixe, ramené sur la marge par un
   retrait négatif : puce à 1171 = la case, texte à 1184 = le texte des cases (mesuré après).
   Les 13 px sont l'écart mesuré entre une case et son texte : ils ne dépendent pas de la police,
   une case à cocher native ayant une taille propre.

   ⚠️ Portée volontairement étroite (`:has`), et non « toutes les listes du livre » : sur les 360
   <ul> des paragraphes du jeu, UN SEUL mêle puce et cases (ARE #000) ; élargir déplacerait les
   puces de 163 listes qui n'ont aucune case. Aucune page de l'interface ne mêle les deux
   (vérifié) : le menu ☰, l'aide et le site ne sont pas concernés — ils le seraient par une règle
   `ul li` globale, `impression.html` chargeant lui aussi ce fichier.
   ⚠️ `> li` et non ` li` : une sous-liste imbriquée dans une liste à cases garde ses propres
   puces.
   ⚠️ Un <li> qui porte LUI-MÊME une case (forme correcte, absente aujourd'hui) reçoit seulement
   `list-style: none` : sa case tombe alors sur la même colonne, sans puce ajoutée devant.
   ⚠️ Sans `:has` (iOS < 15.4), rien de tout cela ne s'applique et l'affichage reste celui d'avant
   — dégradation sans casse. */
ul:has(input[type="checkbox"]) > li {
  list-style: none;
}
ul:has(input[type="checkbox"]) > li:not(:has(input[type="checkbox"])) {
  padding-left: 13px;
  text-indent: -13px;
}
ul:has(input[type="checkbox"]) > li:not(:has(input[type="checkbox"]))::before {
  content: "\2022";
  display: inline-block;
  width: 13px;
  text-indent: 0;
}

body,
html {
  height: 100%;
}

.page-wrapper {
  display: flex;
  flex-direction: column;
  height: 100vh;
  height: 100dvh; /* iOS : hauteur dynamique (barres Safari) → pas de contenu coupé */
  min-width: 320px;
}

#ambiance-audio {
  display: none;
}

header {
  padding: 11px 10px;
  /* iOS : on évite l'encoche (paysage = gauche/droite) et la barre d'état (haut).
     Le tout-en-haut de l'écran capte les gestes système (taps non transmis), donc
     on pousse le contenu ~6px SOUS la safe-area et on agrandit l'en-tête (~30%)
     pour offrir une zone de tap confortable et toujours cliquable. */
  padding-top: calc(max(6px, env(safe-area-inset-top)) + 6px);
  padding-bottom: 11px;
  padding-left: max(10px, env(safe-area-inset-left));
  padding-right: max(10px, env(safe-area-inset-right));
  background-color: #333;
  color: white;
  /* Toujours au-dessus de la zone de jeu : garantit que les boutons restent
     cliquables même si un panneau/le rail tente de la recouvrir (cas iOS PWA). */
  position: relative;
  z-index: 30;
}

.header-fenetre {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
  flex-wrap: nowrap;    /* jamais sur 2 lignes */
  overflow: hidden;
}

/* Le titre cède la place en premier : il rétrécit jusqu'à 0 et disparaît */
#app-title {
  flex: 0 1 auto;       /* peut rétrécir, pas agrandir */
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
}

/* Tous les autres éléments du header ne rétrécissent pas */
.header-des,
.header-rounds,
.header-btns-group,
#burger { flex-shrink: 0; }
.header-des {
  display: flex;
  align-items: center;
  gap: 0;
}
.header-rounds {
  display: flex;
  align-items: center;
  gap: 0;
}
.round-header-label {
  font-weight: bold;
  font-size: 1rem;
  text-align: center;
  color: #ffffff;
  letter-spacing: 0.03em;
  font-family: 'Courier New', monospace;
}

.header-cadre {
  display: flex;
  gap: 10px;
  align-items: center;
  /* centre verticalement */
  justify-content: center;
  /* centre horizontalement */
}

body {
  font-family: sans-serif;
  background-color: #747474;
  color: rgb(0, 0, 0);
  min-height: 100vh;
  min-height: 100dvh;
  overflow-y: overlay;
}

#burger {
  background: none;
  border: none;
  color: white;
  /* Grossi au maximum : remplit la hauteur de contenu de l'en-tête (~28px)
     sans l'agrandir. line-height:1 + padding:0 pour ne pas déborder. */
  font-size: 28px;
  line-height: 1;
  padding: 0;
  font-family: Arial, sans-serif;
  cursor: pointer;
}

#menu {
  position: fixed;
  top: max(30px, env(safe-area-inset-top));
  /* juste en dessous du header */
  right: 0;
  width: 250px;
  padding-right: env(safe-area-inset-right); /* iOS : encoche à droite en paysage */
  height: calc(100% - 20px);
  /* hauteur de l'écran moins le header */
  background-color: #ffffff;
  border-right: 1px solid #444;
  overflow-y: auto;
  transform: translateX(100%);
  transition: transform 0.3s ease;
  /* Très élevé : au-dessus des panneaux dont le z-index monte via _panelZCounter
     (incrémenté à chaque interaction) — un z fixe trop bas (ex. 1000) finissait par
     être dépassé sur une longue session, d'où le menu derrière les panneaux. */
  z-index: 2000000000;
}

#menu.show {
  transform: translateX(0);
}

#menu ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

#menu li {
  padding: 10px;
  border-bottom: 1px solid #444;
  cursor: pointer;
}

@media (hover: hover) {
  #menu li:hover:not(.menu-sep) {
    background-color: #a7a7a7;
  }
}

#menu li.menu-sep {
  padding: 0;
  height: 0;
  border-bottom: 2px solid #777;
  cursor: default;
}

#menu li[data-page="reseau"] {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

main#content {
  flex: 1;
  padding: 10px;
  overflow-y: auto;
}


/* ── Nouvelle mise en page principale ────────────────────────────────────── */

#app-layout {
  flex: 1;
  display: flex;
  flex-direction: row;
  overflow: hidden;
  min-height: 0;
}

/* Bandes d'onglets verticaux — absolus dans #game-area, centrés sur leur bord */
#left-tabs,
#right-tabs {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 4px;
  padding: 0;
  background: transparent;
  overflow: visible;
  z-index: 15;
}

#left-tabs  { left: env(safe-area-inset-left);  transition: opacity 0.2s ease; }
#right-tabs { right: env(safe-area-inset-right); transition: opacity 0.2s ease; }

/* Mode non épinglé : masqué sauf si la souris est proche du bord */
#left-tabs.unpinned:not(.peek),
#right-tabs.unpinned:not(.peek) {
  opacity: 0;
  pointer-events: none;
}

/* Bouton épingle */
.tab-pin-btn {
  writing-mode: horizontal-tb;
  background: none;
  border: none;
  color: #666;
  font-size: 0.85rem;
  cursor: pointer;
  padding: 4px 2px;
  line-height: 1;
  align-self: center;
  transition: color 0.15s;
}
.tab-pin-btn.pinned { color: #ccc; }
.tab-pin-btn:hover  { color: #fff; }

.tab-btn {
  writing-mode: vertical-rl;
  padding: 16px 6px;
  background: #3d3d3d;
  border: none;
  color: #c0c0c0;
  font-size: 0.85rem;
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  flex-shrink: 0;
  font-family: sans-serif;
  transition: background 0.15s, color 0.15s;
}

/* Texte gauche : lecture de bas en haut ; coins arrondis côté panneau (droite) */
#left-tabs .tab-btn {
  transform: rotate(180deg);
  border-radius: 0 5px 5px 0;
}

/* Coins arrondis côté panneau (gauche) */
#right-tabs .tab-btn {
  border-radius: 5px 0 0 5px;
}

@media (hover: hover) {
  .tab-btn:hover {
    background: #525252;
    color: #fff;
  }
}

.tab-btn.active {
  background: #5e5e5e;
  color: #fff;
}

/* Bordure côté panneau sur l'onglet actif */
#left-tabs .tab-btn.active {
  box-shadow: inset -3px 0 0 #bbb;
}

#right-tabs .tab-btn.active {
  box-shadow: inset 3px 0 0 #bbb;
}

/* Barre d'onglets bas — absolue dans #game-area, centrée horizontalement */
#bottom-tabs {
  position: absolute;
  bottom: env(safe-area-inset-bottom); /* iOS : au-dessus de la barre home */
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: flex-end;
  gap: 4px;
  padding: 0;
  background: transparent;
  z-index: 15;
  transition: opacity 0.2s ease;
}

#bottom-tabs.unpinned:not(.peek) {
  opacity: 0;
  pointer-events: none;
}

/* Bouton épingle du bas */
.bottom-pin-btn {
  background: none;
  border: none;
  color: #666;
  font-size: 0.85rem;
  cursor: pointer;
  padding: 4px 6px;
  line-height: 1;
  align-self: center;
  transition: color 0.15s;
}
.bottom-pin-btn.pinned { color: #ccc; }
.bottom-pin-btn:hover  { color: #fff; }

.bottom-tab-btn {
  padding: 6px 16px;
  background: #3d3d3d;
  border: none;
  color: #c0c0c0;
  font-size: 0.85rem;
  cursor: pointer;
  white-space: nowrap;
  font-family: sans-serif;
  border-radius: 5px 5px 0 0;
  transition: background 0.15s, color 0.15s;
}

.bottom-tab-btn:hover {
  background: #525252;
  color: #fff;
}

.bottom-tab-btn.active {
  background: #5e5e5e;
  color: #fff;
  box-shadow: inset 0 3px 0 #bbb;
}

/* Panneau personnage — monte depuis le bas */
#bottom-panel {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  height: 526px;
  background: #fff;
  border: 1px solid #8f8f8f;
  border-bottom: none;
  z-index: 10;
  display: flex;
  flex-direction: column;
  transform: translateY(100%);
  transition: transform 0.25s ease, bottom 0.2s ease, left 0.2s ease, right 0.2s ease;
  overflow: hidden;
}

#bottom-panel.open { transform: translateY(0); }

.bottom-panel-header {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 3px 6px;
  background: #3a3a3a;
  border-bottom: 1px solid #555;
  flex-shrink: 0;
}

.bottom-panel-pin {
  background: none;
  border: none;
  cursor: pointer;
  padding: 4px 6px;
  line-height: 1;
  font-size: 0.95rem;
  align-self: center;
  filter: grayscale(100%) opacity(0.5);   /* inactive : épingle grisée */
  transition: filter 0.15s;
}
.bottom-panel-pin.active { filter: none; } /* cochée : épingle rouge pleine */
.bottom-panel-pin:hover  { filter: none; }

.bottom-panel-title {
  flex: 1;
  text-align: center;
  color: #fff;
  font-weight: bold;
  font-size: 0.9rem;
}

/* Bouton « réduire l'affichage » (toujours visible, mobile + PC) : bascule le
   contenu du panneau perso entre 100 % et 50 % (rivière/cartes trop grandes). */
.bottom-panel-zoom {
  background: none;
  border: none;
  cursor: pointer;
  color: #ddd;
  padding: 0 6px;
  line-height: 1;
  display: inline-flex;
  align-items: center;
}
.bottom-panel-zoom:hover { color: #fff; }
.bottom-panel-zoom .zoom-icon {            /* flèche « réduire la hauteur » (affichage normal) */
  display: block;
  font-size: 1.05rem;
  line-height: 1;
}
.bottom-panel-zoom .zoom-icon::before { content: "\2913"; }   /* ⤓ */
/* État réduit : flèche « étendre la hauteur » (indique « affichage compact actif ») */
#bottom-panel.compact .bottom-panel-zoom .zoom-icon::before { content: "\2912"; }  /* ⤒ */

/* Bouton « replier le bloc du haut » — visible uniquement en latéral (style repris du zoom). */
.bottom-panel-collapse { display: none; }
body.perso-lateral .bottom-panel-collapse {
  background: none;
  border: none;
  cursor: pointer;
  color: #ddd;
  padding: 0 6px;
  line-height: 1;
  display: inline-flex;
  align-items: center;
}
body.perso-lateral .bottom-panel-collapse:hover { color: #fff; }
.bottom-panel-collapse .collapse-icon { display: block; font-size: 0.95rem; line-height: 1; }
.bottom-panel-collapse .collapse-icon::before { content: "\25B2"; }   /* ▲ déployé */
body.perso-top-collapsed .bottom-panel-collapse .collapse-icon::before { content: "\25BC"; }  /* ▼ replié */

.bottom-panel-close {
  background: none;
  border: none;
  font-size: 1.2rem;
  cursor: pointer;
  color: #ddd;
  line-height: 1;
  padding: 0 2px;
}
.bottom-panel-close:hover { color: #fff; }

/* Affichage compact (50 %) du contenu personnage. Les modales superposées
   (zoom carte, cartes perdues) sont remises à l'échelle normale pour rester lisibles. */
/* En mode compact, le panneau est ~moitié moins haut : le contenu zoomé (×0.5) le
   remplit naturellement (plus de grand vide sous la rivière) et libère de la place
   pour le plan au-dessus. */
/* Affichage réduit de la perso (manuel via le bouton ⤓ → .compact).
   NB : l'affichage réduit FORCÉ sur écran court (paysage téléphone) est plus bas,
   après la règle de hauteur du #bottom-panel (sinon elle l'emporterait). */
#bottom-panel.compact { height: 280px; }
#bottom-panel.compact .bottom-panel-content { zoom: 0.5; }
#bottom-panel.compact .bottom-panel-content .perso-zoom-modal,
#bottom-panel.compact .bottom-panel-content .perso-perdues-modal { zoom: 2; }

.bottom-panel-content {
  flex: 1;
  overflow-y: auto;
  padding: 10px;
}

/* Zone de jeu (exploration en fond) */
#game-area {
  flex: 1;
  position: relative;
  /* 20260806 VCH la zone de jeu ne doit JAMAIS défiler : tout ce qu'elle contient est
     positionné en absolu, elle n'a pas de contenu à faire défiler. Or `overflow: hidden`
     en fait quand même un conteneur DÉFILABLE : on ne voit pas de barre, mais le
     navigateur peut le défiler par programme — et rien ne le ramène ensuite.
     C'est ce qui est arrivé : la page personnage FERMÉE est en `translateY(100%)`
     (elle se pose intégralement SOUS la zone), ce qui étend la zone défilable de sa
     propre hauteur (mesuré : 526 px en 1600x900). Il a suffi d'un `scrollIntoView`
     — celui qui amène dans le champ une destination d'animation hors écran,
     src/app_anim_coche.js — pour que toute la zone glisse vers le haut : le rail
     remontait d'autant (ses premiers boutons passant sous l'en-tête, qui est à un
     z-index supérieur) et un « reste de page personnage » apparaissait en bas, que
     l'on ne pouvait ni réduire ni fermer puisqu'il était déjà fermé. Défaut signalé
     par Vincent, capture à l'appui, puis reproduit et mesuré ici.
     `overflow: clip` clippe pareil mais ne crée PAS de conteneur de défilement : le
     scrollIntoView remonte alors au conteneur défilable suivant, celui qu'il visait.
     La déclaration `hidden` reste en repli pour les navigateurs sans `clip`
     (iOS < 16) ; pour ceux-là, un garde-fou JS remet le défilement à zéro (app.js).
     Verrouillé par tests/e2e/28-z-index-panneaux.spec.js. */
  overflow: hidden;
  overflow: clip;
  background: #747474;
  display: flex;
  flex-direction: column;
}

/* Panneaux latéraux : position absolute dans game-area, glissent par-dessus */
.side-panel {
  position: absolute;
  top: 0;
  height: 100%;
  width: 600px;
  background: #ffffff;
  border: 1px solid #8f8f8f;
  display: flex;
  flex-direction: column;
  z-index: 10;
  transition: transform 0.25s ease, left 0.2s ease, right 0.2s ease;
  overflow: hidden;
  container-type: inline-size;
}
@media (max-width: 900px) {
  .side-panel { width: 400px; }
}

/* Le panneau gauche splitté est transparent : seuls les sous-panneaux ont un fond */
.left-split-panel {
  background: transparent;
  border: none;
  overflow: visible;
  /* Le conteneur transparent ne doit pas avaler les clics destinés à la carte
     en-dessous : seuls les sous-panneaux (fond blanc) restent cliquables. */
  pointer-events: none;
}
.left-split-panel > .left-sub-panel {
  pointer-events: auto;
}
.left-sub-panel {
  background: #ffffff;
  border: 1px solid #8f8f8f;
}

#left-panel {
  left: 0;
  transform: translateX(-100%);
}

#right-panel {
  right: 0;
  transform: translateX(100%);
}

#left-panel.open  { transform: translateX(0); }
#right-panel.open { transform: translateX(0); }

.side-panel-header {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 3px 6px;
  background: #555;
  border-bottom: 1px solid #444;
  flex-shrink: 0;
}
.side-panel-header .side-panel-close {
  margin-left: auto;
}
/* Épingle d'un panneau latéral : si cochée, la page personnage n'empiète plus dessus */
.side-panel-pin {
  background: none;
  border: none;
  cursor: pointer;
  padding: 2px 4px;
  line-height: 1;
  font-size: 0.95rem;
  align-self: center;
  filter: grayscale(100%) opacity(0.5);   /* inactive : épingle grisée */
  transition: filter 0.15s;
}
.side-panel-pin.active { filter: none; }   /* cochée : épingle rouge pleine */
.side-panel-pin:hover  { filter: none; }
.side-panel-title {
  flex: 1;
  text-align: center;
  color: #fff;
  font-weight: bold;
  font-size: 0.9rem;
}
/* En-tête livret personnel : police blanche. Règles indépendantes du panneau :
   scénario/livret peuvent être relocalisés à gauche OU à droite (et en bas en portrait). */
.left-sub-panel[data-sub-page="personnel"] .side-panel-header .perso {
  color: #fff;
}
/* Titre générique masqué pour scénario et livret personnel : l'en-tête affiche le
   titre de campagne (.info) / le sélecteur perso + le code paragraphe, qui suffisent. */
.left-sub-panel[data-sub-page="scenario"] .side-panel-title,
.left-sub-panel[data-sub-page="personnel"] .side-panel-title {
  display: none;
}
/* Titre du scénario en blanc */
.left-sub-panel[data-sub-page="scenario"] .info {
  color: #fff;
}
/* Centrer le bloc « titre + code paragraphe » dans l'en-tête du livre du scénario.
   Marges auto de part et d'autre du bloc : .info (à gauche) et .CodePar (à droite)
   absorbent un espace égal → le bloc est centré quels que soient les boutons présents
   à droite (le bouton plein écran est masqué en mode desktop, ex. iPhone en paysage).
   Le bouton 📄 reste calé à gauche ; on neutralise la marge auto par défaut de la
   croix pour qu'elle reste collée à droite. */
.left-sub-panel[data-sub-page="scenario"] .side-panel-header .side-panel-page1 { margin-right: 0; }
.left-sub-panel[data-sub-page="scenario"] .side-panel-header .info { margin-left: auto; }
.left-sub-panel[data-sub-page="scenario"] .side-panel-header .CodePar { margin-right: auto; }
.left-sub-panel[data-sub-page="scenario"] .side-panel-header .side-panel-close { margin-left: 0; }
/* Idem pour l'en-tête du livret personnel : on centre le bloc « Livret personnel +
   sélecteur de perso + code @ » (.perso à gauche, .CodeParPerso à droite). */
.left-sub-panel[data-sub-page="personnel"] .side-panel-header .side-panel-page1 { margin-right: 0; }
.left-sub-panel[data-sub-page="personnel"] .side-panel-header .perso { margin-left: auto; }
.left-sub-panel[data-sub-page="personnel"] .side-panel-header .CodeParPerso { margin-right: auto; }
.left-sub-panel[data-sub-page="personnel"] .side-panel-header .side-panel-close { margin-left: 0; }
/* Sous-panneaux gauche empilés */
.left-split-panel {
  display: flex;
  flex-direction: column;
}
.left-sub-panel {
  display: none;
  flex-direction: column;
  overflow: hidden;
  border-bottom: 1px solid #444;
  position: relative;
}
.left-sub-panel.open {
  display: flex;
}
.left-sub-panel .side-panel-content {
  flex: 1;
  overflow-y: auto;
  padding: 10px;
}
.left-sub-flex {
  flex: 1;
  min-height: 0;
}

.side-panel-page1 {
  background: none;
  border: none;
  font-size: 1rem;
  cursor: pointer;
  color: #ddd;
  padding: 0 4px;
  margin-right: auto;
}
.side-panel-page1:hover { color: #fff; }

.side-panel-close {
  background: none;
  border: none;
  font-size: 1.4rem;
  cursor: pointer;
  color: #ddd;
  line-height: 1;
  padding: 0 2px;
}
.side-panel-close:hover { color: #fff; }

/* ── Bouton « ? » : ouvre la section d'aide de la page (app.js, src/app_aide.js) ──
   Posé dans les en-têtes de panneaux ET dans les barres d'outils des zones de jeu.
   `margin-left:auto` le colle à droite : il précède .side-panel-fs et .side-panel-close
   dans le DOM, c'est donc lui qui absorbe l'espace libre et emmène le groupe à droite. */
.aide-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; flex: 0 0 auto;
  background: none; border: 1px solid currentColor; border-radius: 50%;
  color: #ddd; font-size: 0.72rem; font-weight: 700; line-height: 1;
  padding: 0; cursor: pointer; opacity: 0.75;
}
.aide-btn:hover { color: #fff; opacity: 1; }
.side-panel-header .aide-btn,
.bottom-panel-header .aide-btn,
.center-panel-header .aide-btn,
.explo-toolbar .aide-btn,
.plan-toolbar .aide-btn { margin-left: auto; }
/* .plan-pions-bar est en `order:1` : sans ordre explicite, le « ? » (order 0) se placerait
   AVANT la barre de pions au lieu de finir la barre d'outils. */
.plan-toolbar .aide-btn { order: 2; }

/* ── Bouton plein écran (CSS) des panneaux livre — tactile/mobile uniquement ── */
.side-panel-fs { display: none; }            /* masqué sur desktop (souris) */
@media (hover: none) and (pointer: coarse) {
  .side-panel-fs {
    display: inline-flex; align-items: center; justify-content: center;
    margin-left: auto;                        /* colle le groupe (plein écran + croix) à droite */
    background: none; border: none; cursor: pointer; color: #ddd;
    padding: 0 4px; line-height: 1;
  }
  .side-panel-fs + .side-panel-close { margin-left: 6px; } /* la croix juste à droite */
  .side-panel-fs .fs-icon {                   /* rectangle = passer en plein écran */
    display: block; width: 15px; height: 12px;
    border: 2px solid currentColor; border-radius: 2px;
  }
  .left-sub-panel.panel-fullscreen .side-panel-fs .fs-icon {  /* trait = revenir à la normale */
    height: 0; width: 15px; border-width: 2px 0 0 0; border-radius: 0;
  }
}

/* Sous-panneau en plein écran (CSS, sans l'API Fullscreen — inopérante sur iOS).
   Démarre SOUS l'en-tête de l'appli (--ebs-fs-top fixé en JS = hauteur du header),
   qui reste donc visible. */
.left-sub-panel.panel-fullscreen {
  position: fixed !important;
  top: var(--ebs-fs-top, 0px) !important;
  left: 0 !important; right: 0 !important; bottom: 0 !important;
  inset: auto;
  width: auto !important;
  height: auto !important;
  max-height: none !important;
  min-height: 0 !important;
  margin: 0 !important;
  border: none !important;
  transform: none !important;
  z-index: 6000 !important;
  display: flex !important;
  flex-direction: column;
}
.left-sub-panel.panel-fullscreen .side-panel-content {
  flex: 1 1 auto;
  max-height: none !important;
  padding-bottom: env(safe-area-inset-bottom);
}
.left-sub-panel.panel-fullscreen .side-panel-header {
  padding-top: 3px;
  padding-left: max(6px, env(safe-area-inset-left));
  padding-right: max(6px, env(safe-area-inset-right));
}
/* En plein écran, masquer les barres d'onglets (sinon visibles par-dessus le panneau) */
body.panel-fs-active #left-tabs,
body.panel-fs-active #right-tabs,
body.panel-fs-active #bottom-tabs { display: none !important; }

.side-panel-content {
  flex: 1;
  overflow-y: auto;
  padding: 8px;
}

/* Modal centré (par-dessus le canvas) */
.center-panel {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  /* Fenêtres du menu burger : au-dessus des panneaux (cf. #menu).
     20260814 VCH descendu de 1999999999 à 1999999990 pour libérer la bande où logent désormais
     les animations d'action (.anim-coche-overlay / .anim-pioche-overlay) : le journal de bord
     est une fenêtre centrale, et il recouvrait le vol de la carte de quête qui le rejoint.
     L'ordre relatif ne change pour personne — rien d'autre ne vit entre 100001
     (#app-update-banner) et 2000000000 (#menu). */
  z-index: 1999999990;
  background: #fff;
  border: 1px solid #8f8f8f;
  border-radius: 4px;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);
  width: min(90%, 600px);
  max-height: calc(100% - 16px);
  display: flex;
  flex-direction: column;
}

.center-panel.hidden { display: none; }

.center-panel-header {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 3px 6px;
  background: #555;
  border-bottom: 1px solid #444;
  border-radius: 4px 4px 0 0;
  flex-shrink: 0;
  cursor: move;
}

.modal-drag-header {
  cursor: move;
  user-select: none;
  padding-bottom: 4px;
}
.center-panel-title {
  flex: 1;
  text-align: center;
  color: #fff;
  font-weight: bold;
  font-size: 0.9rem;
}
.center-panel-header .center-panel-close {
  margin-left: auto;
}
.center-panel-content {
  flex: 1;
  overflow-y: auto;
  padding: 10px;
  position: relative;
}

.center-panel-close {
  background: none;
  border: none;
  font-size: 1.4rem;
  cursor: pointer;
  color: #ddd;
  line-height: 1;
  padding: 0 2px;
}
.center-panel-close:hover { color: #fff; }

/* ── Fenêtre « Jeu en réseau » (center-panel, fond blanc) ─────────────────────
   Reprend l'identité EBS : accent rouge (--ebs-accent #b8332a), boutons arrondis,
   code de partie dans un bloc vert cohérent avec le badge du menu burger. */
.reseau-page { padding: 18px 20px 20px; color: #2a2a2a; }
.reseau-intro {
  margin: 0 0 18px;
  font-size: 0.9rem;
  line-height: 1.45;
  color: #555;
}
.reseau-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 10px 16px;
  border-radius: 8px;
  border: 1px solid transparent;
  font-size: 0.95rem;
  font-weight: 600;
  cursor: pointer;
  transition: background .15s, color .15s, box-shadow .15s;
}
.reseau-btn--primary {
  width: 100%;
  background: var(--ebs-accent, #b8332a);
  color: #fff;
  border-color: var(--ebs-accent, #b8332a);
}
.reseau-btn--primary:hover { background: var(--ebs-accent-hi, #d6473c); border-color: var(--ebs-accent-hi, #d6473c); }
.reseau-btn-plus { font-size: 1.25em; font-weight: 700; line-height: 0; }
.reseau-btn--secondary {
  background: #2a2a2a;
  color: #eee;
  border-color: #555;
  white-space: nowrap;
}
.reseau-btn--secondary:hover { background: #444; }
.reseau-btn--danger {
  width: 100%;
  background: #fff;
  color: var(--ebs-accent, #b8332a);
  border-color: var(--ebs-accent, #b8332a);
}
.reseau-btn--danger:hover { background: var(--ebs-accent, #b8332a); color: #fff; }

.reseau-sep {
  display: flex;
  align-items: center;
  text-align: center;
  color: #999;
  font-size: 0.8rem;
  margin: 16px 0;
}
.reseau-sep::before, .reseau-sep::after {
  content: "";
  flex: 1;
  border-bottom: 1px solid #ddd;
}
.reseau-sep span { padding: 0 12px; text-transform: uppercase; letter-spacing: .1em; }

.reseau-label {
  display: block;
  font-size: 0.85rem;
  font-weight: 600;
  color: #444;
  margin-bottom: 8px;
}
.reseau-label--center { text-align: center; }
.reseau-join-row {
  display: flex;
  gap: 8px;
  align-items: stretch;
}
.reseau-code-input {
  flex: 1;
  min-width: 0;
  padding: 9px 12px;
  border: 1px solid #bbb;
  border-radius: 8px;
  font-family: monospace;
  font-size: 1.1rem;
  letter-spacing: .18em;
  text-transform: uppercase;
  text-align: center;
}
.reseau-code-input:focus {
  outline: none;
  border-color: var(--ebs-accent, #b8332a);
  box-shadow: 0 0 0 2px rgba(184, 51, 42, .2);
}

.reseau-code-display {
  text-align: center;
  font-family: monospace;
  font-size: 2rem;
  font-weight: bold;
  letter-spacing: .25em;
  color: #fff;
  background: #2e7d32;
  border-radius: 10px;
  padding: 12px;
  margin: 4px 0 16px;
}

.reseau-msg {
  padding-top: 10px;
  min-height: 1.2em;
  text-align: center;
  color: var(--ebs-accent, #b8332a);
  font-size: .9rem;
}

/* Historique des sauvegardes (parties créées + rejointes) */
.reseau-histo { margin-top: 4px; }
.reseau-histo-note {
  margin: -2px 0 10px;
  font-size: 0.78rem;
  line-height: 1.35;
  color: #888;
}
.reseau-histo-vide { color: #888; font-size: .85rem; font-style: italic; margin: 4px 0 0; }
.reseau-histo-ligne {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 0;
  border-bottom: 1px solid #eee;
}
.reseau-histo-ligne:last-child { border-bottom: none; }
/* Partie en cours : surlignée dans la liste. */
.reseau-histo-ligne--courante {
  background: rgba(46, 125, 50, .10);
  border-left: 3px solid #2e7d32;
  padding-left: 8px;
  border-radius: 6px;
}
.reseau-histo-ligne--courante .reseau-histo-code { color: #2e7d32; font-weight: 600; }
.reseau-histo-info {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.reseau-histo-titre { font-weight: 600; color: #2a2a2a; }
.reseau-histo-perso { font-size: .82rem; color: #2e7d32; font-weight: 600; }
.reseau-histo-date { font-size: .8rem; color: #777; }
.reseau-histo-code {
  font-family: monospace;
  font-size: .85rem;
  letter-spacing: .12em;
  color: #555;
}
.reseau-histo-actions {
  display: flex;
  gap: 6px;
  flex-shrink: 0;
}
.reseau-histo-actions .reseau-btn { width: auto; padding: 7px 12px; font-size: .85rem; }

.reseau-diag-box { margin-top: 18px; border-top: 1px solid #eee; padding-top: 12px; }
.reseau-diag-box summary { cursor: pointer; color: #888; font-size: .85rem; }
.reseau-diag-box pre {
  font-size: 11px;
  white-space: pre-wrap;
  background: #1c1c1c;
  color: #ddd;
  padding: 8px;
  border-radius: 6px;
  overflow: auto;
  margin-top: 8px;
}

/* ── Fenêtre « Paramètres » (center-panel, fond blanc) ────────────────────────
   Même identité que la fenêtre réseau : accent rouge EBS, bascules à état
   visuel (vert = activé / gris = désactivé), actions destructives en danger. */
.param-page { padding: 6px 20px 14px; color: #2a2a2a; }
.param-section {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px 0;
  border-bottom: 1px solid #eee;
}
.param-section:last-child { border-bottom: none; }
.param-section--stack {
  flex-direction: column;
  align-items: stretch;
}
.param-section--stack .param-label { margin-bottom: 8px; }
.param-note {
  margin-top: 8px;
  font-size: 0.75rem;
  line-height: 1.35;
  color: #888;
}
/* Tableau à 2 colonnes 50/50 : à gauche le libellé (au-dessus) + le contrôle
   (en dessous) ; à droite la note explicative, centrée verticalement.
   Empilé en portrait. */
.param-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: 24px;
  row-gap: 20px;
  align-items: center;
  padding: 14px 0;
  border-bottom: 1px solid #eee;
}
.param-grid-sep {
  grid-column: 1 / -1;
  border-top: 1px solid #eee;
}
.param-cell-left {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}
.param-cell-left .param-label { white-space: nowrap; margin-bottom: 16px; }
.param-cell-left .param-ctrl {
  display: flex;
  align-items: center;
  gap: 8px;
}
.param-cell-left .btn-nb-joueurs-group { margin-left: 0; }
.param-grid > .param-note { margin: 0; align-self: center; }
.param-grid > .param-note:empty { display: none; }
body[data-mode="portrait"] .param-grid { grid-template-columns: 1fr; row-gap: 8px; }
body[data-mode="portrait"] .param-cell-left .param-label { margin-bottom: 8px; }
body[data-mode="portrait"] .param-grid-sep { margin: 6px 0; }
/* « Jouer hors-ligne » : libellé + boutons sur une ligne ; barre/statut en dessous. */
.param-dl-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}
.param-dl-head .param-label { margin-bottom: 0; }
.param-dl-head .local-dl-row { margin-top: 0; flex-wrap: nowrap; }
/* Boutons un peu plus compacts pour tenir sur la ligne du libellé. */
.param-dl-head .param-btn { font-size: 0.82rem; padding: 7px 12px; white-space: nowrap; }
/* Portrait : on réempile pour éviter tout débordement horizontal. */
body[data-mode="portrait"] .param-section { flex-wrap: wrap; }
body[data-mode="portrait"] .param-dl-head { flex-direction: column; align-items: stretch; }
body[data-mode="portrait"] .param-dl-head .param-label { margin-bottom: 8px; }
body[data-mode="portrait"] .param-dl-head .local-dl-row { flex-wrap: wrap; }
body[data-mode="portrait"] .param-dl-head .param-btn { font-size: 0.9rem; padding: 9px 16px; }
.param-label {
  font-size: 0.9rem;
  font-weight: 600;
  color: #333;
  white-space: nowrap;
}
.param-section--stack .param-label { white-space: normal; }
.param-controls { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; justify-content: flex-end; }
/* 20260817 VCH jauges de volume des Paramètres (musique, sons ponctuels).
   La valeur chiffrée est en largeur fixe et alignée à droite : sans cela, passer
   de 100 à 9 décale la jauge sous le doigt qui la fait glisser. */
.param-jauge { width: 120px; max-width: 40vw; accent-color: var(--r-or, #c9a227); cursor: pointer; }
.param-jauge:disabled { opacity: .4; cursor: default; }
.param-valeur { min-width: 2.4em; text-align: right; font-variant-numeric: tabular-nums;
                opacity: .8; font-size: .9em; }

.param-toggle {
  padding: 7px 16px;
  border-radius: 999px;
  border: 1px solid #ccc;
  background: #ececec;
  color: #777;
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  transition: background .15s, color .15s, border-color .15s;
}
.param-toggle.is-on {
  background: #2e7d32;
  border-color: #2e7d32;
  color: #fff;
}
.param-toggle.is-off {
  background: #ececec;
  border-color: #ccc;
  color: #777;
}

.param-btn {
  padding: 9px 16px;
  border-radius: 8px;
  border: 1px solid #555;
  background: #2a2a2a;
  color: #eee;
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  transition: background .15s, color .15s, border-color .15s;
}
.param-btn:hover { background: #444; }
.param-btn--ghost {
  background: #fff;
  color: #555;
  border-color: #bbb;
}
.param-btn--ghost:hover { background: #f0f0f0; color: #333; }
.param-btn--danger {
  background: #fff;
  color: var(--ebs-accent, #b8332a);
  border-color: var(--ebs-accent, #b8332a);
}
.param-btn--danger:hover { background: var(--ebs-accent, #b8332a); color: #fff; }

.param-select {
  padding: 7px 10px;
  border: 1px solid #bbb;
  border-radius: 8px;
  background: #fff;
  color: #2a2a2a;
  font-size: 0.9rem;
  cursor: pointer;
}
.param-select:focus {
  outline: none;
  border-color: var(--ebs-accent, #b8332a);
  box-shadow: 0 0 0 2px rgba(184, 51, 42, .2);
}

.centered-link {
  text-align: center;
  /* centre horizontalement le contenu */
}

.centered-link a {
  color: rgb(0, 0, 0);
  /* texte blanc */
  font-size: 16px;
}

.centered-link a:hover {
  text-decoration: underline;
  /* effet au survol */
}

.image-wrapper {
  width: 100%;
}

.image-wrapper img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  /* ou cover (voir ci-dessous) */
  display: block;
}

/* Choix du scénario — grille de cartes (20260802 VCH). La couverture n'est plus qu'un
   bandeau en haut de chaque carte : six scénarios tiennent en un peu plus d'un écran au
   lieu de trois. `auto-fit` plutôt qu'une media query : le nombre de colonnes suit la
   largeur reelle du conteneur (deux dans la fenêtre de 600 px, une sur téléphone), sans
   dépendre de la largeur de l'écran, qui n'est pas celle de la modale. */
#campagnes-container {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 12px;
  align-content: start;
}
/* Messages « Chargement… » / erreur, et compteur : sur toute la largeur de la grille. */
#campagnes-container > p,
.campagnes-compte {
  grid-column: 1 / -1;
}
.campagnes-compte {
  font-size: 0.72rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  margin: 2px 2px -2px;
}

.campagne {
  all: unset;                /* <button> : on repart de zéro plutôt que de défaire au cas par cas */
  box-sizing: border-box;
  display: block;
  position: relative;
  width: 100%;
  cursor: pointer;
  border: 1px solid transparent;
  border-radius: 12px;
  overflow: hidden;          /* la couverture épouse les coins arrondis */
  transition: border-color 0.2s;
}
.campagne:focus-visible {
  outline: 2px solid #888;
  outline-offset: 2px;
}

.campagne-img {
  display: block;
  width: 100%;
  height: 88px;              /* bandeau : hauteur de carte constante quel que soit le format source */
  object-fit: cover;
}

.campagne-corps {
  display: block;
  padding: 8px 10px 10px;
}
.campagne-titre {
  display: block;
  font-size: 0.9rem;
  line-height: 1.15;
  font-weight: 600;
}
.campagne-version {
  display: block;
  font-size: 0.72rem;
  line-height: 1.3;
}

/* Pastille posée sur la couverture : « En cours », ou cadenas si le scénario est verrouillé. */
.campagne-tag {
  position: absolute;
  top: 7px;
  right: 7px;
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  border-radius: 999px;
  padding: 3px 8px;
  white-space: nowrap;
}

.campagne-locked {
  opacity: 0.6;
  cursor: not-allowed;
}

/* #content-container supprimé — remplacé par #app-layout */


.cadre {
  flex: 1;
  overflow-y: auto;
  /* scroll local vertical */
  display: none;
}

.cadre.visible {
  display: block;
}

.modal {
  display: none;
  position: fixed;
  z-index: 2000;
  left: 50%;
  top: 30px;
  /* juste en dessous du header */
  transform: translateX(-50%);
  background-color: rgba(0, 0, 0, 0.6);
  border: 3px solid #555;
}

.modal-content {
  background-color: rgb(194, 194, 194);
  padding: 20px;
  width: 200px;
  border-radius: 8px;
  text-align: center;
}

.modal-close {
  position: absolute;
  top: 5px;
  right: 10px;
  cursor: pointer;
  font-size: 20px;
  touch-action: manipulation;
}

.modal input {
  padding: 5px;
  font-size: 1em;
  width: 100px;
}

.modal button {
  padding: 5px 10px;
  cursor: pointer;
  width: auto;
  font-size: 1em;
  touch-action: manipulation;
}

#modal-unsaved .modal-content {
  width: 320px;
  text-align: left;
}

#modal-unsaved .danger {
  border: 1px solid #a33;
  background: #d9534f;
  color: #fff;
}

#newsletter-modal .modal-content {
  width: 300px;
}

#newsletter-email {
  width: 240px;
  box-sizing: border-box;
}

#paragraphe-input {
  text-align: center;
}

.bouton-paragraphe-suivant {
  background-color: #444;
  font-family: Arial, sans-serif;
  font-size: 1em;
  color: white;
  padding: 2px 5px;
  margin: 1px 4px;
  border: 1px solid #888;
  border-radius: 5px;
  cursor: pointer;
}

.bouton-paragraphe-suivant:hover {
  background-color: #666;
}


.bouton-titre {
  font-size: 1em;
  font-weight: bold;
  padding: 5px 10px;
  margin: 2px 10px;
  border: 1px solid #888;
  border-radius: 5px;
  cursor: pointer;
  width: calc(100% - 20px);
}

.contenu-titre {
  background-color: rgb(240, 240, 240);
  padding: 5px 10px;
  margin: 2px 10px;
  width: calc(100% - 20px);
}

input[type="checkbox"].ebs-action {
  accent-color: #c0392b;
  outline: 2px solid #c0392b;
  outline-offset: 1px;
}

/* 20260819 VCH coche SANS automatisation : rendue en PUCE. Une case promet un effet dans
   l'appli, une puce n'en promet aucune (classe posée par majPucesCoches, src/app_livre.js ;
   posée aussi sur TOUTES les cases par impression.html, où rien n'est automatisable).

   ⚠️ L'input n'est ni retiré ni masqué : la persistance de l'état coché et la synchro réseau
   le repèrent par son index ordinal dans le paragraphe (bindLivreCoches, src/app_livre.js).
   ⚠️ `appearance:none` supprime la taille intrinsèque d'un élément remplacé : SANS width et
   height explicites, la case tombe à 0 et la colonne du texte se décale de 13 px (règle
   `ul:has(input[type="checkbox"]) > li` en tête de cette feuille). 13×13 est la taille
   mesurée dans l'appli le 20260819 sur une case native, en 1600×900 comme en 390×844 ; les
   marges sont déjà nulles pour tout le monde (`* { margin: 0 }`, en tête de cette feuille) et
   ne sont donc pas redéclarées, et `vertical-align` reste à `baseline` comme une case.
   ⚠️ `color: inherit` est INDISPENSABLE : un input n'hérite pas de la couleur du texte, et un
   input `disabled` reçoit en plus le gris des champs inactifs. Mesuré le 20260819 : sans lui, le
   disque sortait en rgb(84,84,84) à côté d'une puce native noire (TST #153). Hérité, il suit
   l'encre du livre à l'écran et sort noir sur le papier, sans connaître le thème.
   ⚠️ Le disque est calé à GAUCHE de la boîte (`at 3px`), pas au centre : le glyphe « • » d'un
   ::before de liste est dessiné dans les premiers pixels de son avance (mesuré : avance 5,6 px,
   disque entre 1 et 5 px, donc centre à ~2,8 px), tandis que le centre des 13 px serait à 6,5 px.
   Centré, la puce d'une ex-case était décalée de ~4 px vers la droite par rapport aux puces
   natives de la même liste (constaté sur TST #153 et ARE #000, qui mêlent les deux). */
input[type="checkbox"].ebs-puce,
#wysiwyg.apercu-print input[type="checkbox"] {
  -webkit-appearance: none;   /* avant `appearance` : iOS Safari ancien ne connaît que celui-ci */
  appearance: none;
  width: 13px;
  height: 13px;
  border: none;
  outline: none;
  color: inherit;
  background: radial-gradient(circle at 3px 50%, currentColor 2.5px, transparent 2.6px);
  cursor: default;
}

.texte-narration {
  font-family: Arial, sans-serif;
  font-size: 1em;
  font-style: italic;
}

.texte-dialogue {
  font-family: "Caveat", cursive;
  font-size: 1.2em;
  font-style: italic;
  line-height: 0.9;
}

.texte-normal {
  font-family: Arial, sans-serif;
  font-size: 1em;
}
.texte-normal img { vertical-align: middle; }

/* Centrage vertical de toutes les images inline (pions) du contenu de paragraphe,
   quel que soit l'ancêtre (labels/listes/narration sans classe .texte-normal). */
#livre-container img,
#wysiwyg img { vertical-align: middle; }

.texte-largeur-fixe {
  font-family: 'Courier Prime', 'Courier New', monospace;
  font-size: 1em;
}

.header-btns-group {
  display: flex;
  align-items: center;
  gap: 2px;
}
#toggle-audio {
  background: none;
  /* supprime le fond */
  border: none;
  /* supprime la bordure */
  color: white;
  /* couleur de l’icône */
  font-size: 20px;
  /* taille de l’emoji */
  cursor: pointer;
  padding: 0;
  /* enlève les marges internes */
  line-height: 1;
  /* évite les décalages verticaux */
  appearance: none;
  /* neutralise les styles iOS natifs */
  -webkit-appearance: none;
  /* idem pour Safari mobile */
}

.cadre_condition {
  border: 0px solid black;
  padding: 5px;
  margin: 0;
  width: 100%;
  background-color: #d7d7d7;
  box-sizing: border-box;
}

.cadre_impression {
  border: 1px dashed black;
  padding: 5px;
  margin: 20px 0;
  width: 100%;
  background-color: #ffffff;
  box-sizing: border-box;
}

/* Par défaut : visible sur l'écran, caché à l'impression */
.visible-appli {
  display: block;
}

.visible-print {
  display: none;
}

/* Quand on imprime */
@media print {
  .visible-appli {
    display: none !important;
    /* on cache */
  }

  .visible-print {
    display: block !important;
    /* on affiche */
  }
}

/* 20260819 VCH sur le papier, AUCUNE coche n'est automatisable : toutes deviennent des puces,
   celles qui agissent dans l'appli comprises. Vaut pour un Ctrl+P lancé depuis l'appli ; la page
   d'impression dédiée (impression.html) passe, elle, par la classe `.ebs-puce`, qu'elle pose sur
   toutes ses cases pour que son aperçu à l'écran soit fidèle au papier.
   Les déclarations sont celles de `.ebs-puce` ci-dessus (voir ses avertissements) : une media
   query ne peut pas être mêlée à une liste de sélecteurs, d'où cette copie. */
@media print {
  :is(#livre-container, #livre-perso-container) input[type="checkbox"] {
    -webkit-appearance: none;
    appearance: none;
    width: 13px;
    height: 13px;
    border: none;
    outline: none;
    color: inherit;
    background: radial-gradient(circle at 3px 50%, currentColor 2.5px, transparent 2.6px);
    cursor: default;
  }
}

/* === ÉDITEUR HTML === */
/* ── Blocage éditeurs sur mobile ────────────────────────────────────────── */
.editor-mobile-block {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: #1a1a1a;
  color: #fff;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 32px;
  gap: 16px;
}
.editor-mobile-block__icon { font-size: 4rem; }
.editor-mobile-block__msg  { font-size: 1.1rem; line-height: 1.6; }

@media (max-width: 900px) {
  .editor-mobile-block   { display: flex; }
  .editor-desktop-only   { display: none !important; }
}

/* ── Barre de masquage des panneaux (les 3 éditeurs) — 20260816 VCH ─────────
   Construite par src/app_editeur_panneaux.js et insérée AVANT .editeur-page.
   Sa hauteur est publiée en variable : .editeur-page.horizontal la retranche de
   la hauteur de fenêtre, sinon la barre pousserait le bas des panneaux dehors. */
:root { --ed-bar-h: 34px; }

.ed-bar {
  display: flex;
  align-items: center;
  gap: 6px;
  height: var(--ed-bar-h);
  box-sizing: border-box;
  padding: 0 8px;
  background: var(--r-surface1, #1f1b14);
  border-bottom: 1px solid var(--r-border, #423a2b);
  overflow-x: auto;
}

.ed-bar-titre {
  color: var(--r-text2, #ac9f86);
  font-size: .8rem;
  white-space: nowrap;
}

.ed-bar-btn {
  padding: 3px 10px;
  border: 1px solid var(--r-border-hi, #5a4f3a);
  border-radius: 6px;
  background: var(--r-surface3, #342e22);
  color: var(--r-text, #ece3d0);
  font-size: .8rem;
  white-space: nowrap;
  cursor: pointer;
}

.ed-bar-btn:hover { border-color: var(--r-gold, #d4a24c); }

/* Panneau masqué : bouton éteint, pour distinguer d'un coup d'œil ce qui est caché. */
.ed-bar-btn[aria-pressed="false"] {
  background: transparent;
  color: var(--r-text3, #746a56);
  border-style: dashed;
}

.ed-masque { display: none !important; }

/* Posée sur le dernier panneau visible quand le panneau extensible est masqué : sans elle,
   les panneaux restants gardent leur largeur fixe et laissent une bande vide. */
.ed-etire { flex-grow: 1 !important; }

/* ── Bouton d'action validante (Enregistrer) — 20260817 VCH ─────────────────
   Le vert du thème, celui des états validés (.param-toggle.is-on, coches à effet
   du livre), et non un vert étranger à la palette parchemin. */
.editeur-toolbar .btn-valider,
.code-toolbar .btn-valider {
  background: var(--r-ok, #7da85f);
  border: 1px solid var(--r-ok, #7da85f);
  color: #10210a;
  font-weight: 600;
}

.editeur-toolbar .btn-valider:hover,
.code-toolbar .btn-valider:hover {
  background: #8dbd6c;
  border-color: #8dbd6c;
}

/* ── Aperçu Impression de la surface d'édition — 20260817 VCH ───────────────
   Hors impression, `.visible-print` est en display:none (règles plus haut dans cette
   feuille) : ces blocs sont donc invisibles dans le WYSIWYG, où on ne peut ni les lire
   ni les corriger. La classe posée sur la surface inverse les deux, le temps de les
   regarder. Ces sélecteurs sont plus spécifiques que les règles globales, ils l'emportent
   sans `!important` — et le contenu enregistré, lui, ne bouge pas. */
#wysiwyg.apercu-print .visible-appli { display: none; }
#wysiwyg.apercu-print .visible-print { display: block; }

.editeur-page {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 8px;
  height: 100%;
  box-sizing: border-box;
  background: #000000;
  /* ton thème sombre probable */
}

.editeur-toolbar,
.code-toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  padding: 8px;
  background: #000000;
  border-bottom: 1px solid #444;
  position: sticky;
  top: 0;
  z-index: 1;
}

.tool-group {
  display: inline-flex;
  gap: 6px;
  padding-right: 6px;
  border-right: 1px solid #3a3a3a;
}

.tool-group:last-child {
  border-right: none;
}

.editeur-toolbar button,
.code-toolbar button,
.editeur-toolbar select,
.code-toolbar label {
  font: inherit;
  padding: 6px 10px;
  border-radius: 6px;
  border: 1px solid #555;
  background: #333;
  color: #eee;
  cursor: pointer;
}

.editeur-toolbar select {
  cursor: default;
}

.editeur-toolbar button:hover,
.code-toolbar button:hover {
  background: #3a3a3a;
}

/* Bouton de suppression (paragraphe) */
.code-toolbar button.danger {
  border-color: #a33;
  color: #f0a8a8;
}
.code-toolbar button.danger:hover {
  background: #5a2a2a;
}

/* Séparateur visuel */
.editeur-divider {
  height: 2px;
  background: linear-gradient(90deg, transparent, #555, transparent);
}

/* Accessibilité "screen-reader only" */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* === LAYOUT CÔTE À CÔTE POUR L'ÉDITEUR === */
.editeur-page.horizontal {
  display: flex;
  flex-direction: row;
  align-items: stretch;
  height: calc(100vh - 30px - var(--ed-bar-h, 0px));
  height: calc(100dvh - 30px - var(--ed-bar-h, 0px)); /* iOS : hauteur dynamique */
  /* plein écran sous le header de 30px et sous la barre des panneaux */
  min-height: 400px;
  gap: 0;
  /* pas d’espace, le divider prend la place */
}

/* Panneaux */
.editeur-page.horizontal .pane {
  display: flex;
  flex-direction: column;
  min-width: 200px;
  /* limite */
  overflow: hidden;
  /* évite scrolls multiples */
}

.editeur-page.horizontal .left {
  width: 55%;
}

/* largeur par défaut */
.editeur-page.horizontal .right {
  width: 45%;
}

/* Toolbars collées en haut */
.editeur-toolbar,
.code-toolbar {
  flex: 0 0 auto;
  position: sticky;
  top: 0;
  z-index: 1;
}

.editeur-surface {
  flex: 1 1 auto;
  min-height: 0;
  /* important pour que flex-basis ne force pas la hauteur */
  overflow: auto;
  /* scroll interne si besoin */
  padding: 12px;
  height: 100%;
  max-width: 600px;
  line-height: 1.5;
  outline: none;
  resize: vertical;
  border: none;
  background: #ffffff;
}

.code-surface {
  flex: 1 1 auto;
  min-height: 0;
  /* important pour que flex-basis ne force pas la hauteur */
  overflow: auto;
  /* scroll interne si besoin */
  padding: 12px;
  height: 100%;
  width: 100%;
  line-height: 1.5;
  outline: none;
  resize: vertical;
  border: none;
  background: #0f0f0f;
  color: #ffffff;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
}

/* === Onglets de la zone droite (HTML / Lien) === */
.code-tabs {
  flex: 0 0 auto;
  display: flex;
  gap: 2px;
  background: #000000;
  border-bottom: 1px solid #444;
}

.code-tab {
  font: inherit;
  padding: 8px 16px;
  border: none;
  border-top: 2px solid transparent;
  background: #1a1a1a;
  color: #bbb;
  cursor: pointer;
}

.code-tab:hover {
  background: #2a2a2a;
}

.code-tab.active {
  background: #0f0f0f;
  color: #fff;
  border-top-color: #6aa3ff;
}

/* Panneaux d'onglet : le panneau visible remplit la hauteur restante */
.tab-panel {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

.tab-panel[hidden] {
  display: none;
}

/* === Grille des liens === */
.lien-titre {
  font-weight: bold;
  color: #eee;
  align-self: center;
}

.lien-grid-wrap {
  flex: 1 1 auto;
  min-height: 0;
  overflow: auto;
  background: #0f0f0f;
}

.lien-grid {
  width: 100%;
  border-collapse: collapse;
  color: #eee;
  font-size: 14px;
}

.lien-grid th,
.lien-grid td {
  padding: 6px 8px;
  border-bottom: 1px solid #2a2a2a;
  text-align: left;
}

.lien-grid th {
  position: sticky;
  top: 0;
  background: #1a1a1a;
  color: #bbb;
  font-weight: 600;
  z-index: 1;
}

.lien-grid input {
  font: inherit;
  padding: 4px 6px;
  border: 1px solid #555;
  border-radius: 4px;
  background: #222;
  color: #eee;
}

.lien-grid input.lien-enfant {
  width: 110px;
}

.lien-grid input.lien-ordre {
  width: 64px;
}

.lien-grid button.lien-del {
  font: inherit;
  padding: 2px 8px;
  border: 1px solid #a33;
  border-radius: 4px;
  background: #331818;
  color: #f0a8a8;
  cursor: pointer;
}

.lien-grid button.lien-del:hover {
  background: #5a2a2a;
}

/* === Schéma d'arborescence des paragraphes === */
#schema-viewport {
  flex: 1 1 auto;
  min-height: 0;
  position: relative;
  overflow: hidden;
  background: #0f0f0f;
  cursor: grab;
}

#schema-viewport.panning {
  cursor: grabbing;
}

#schema-canvas {
  position: absolute;
  top: 0;
  left: 0;
  transform-origin: 0 0;
}

#schema-edges {
  position: absolute;
  top: 0;
  left: 0;
  pointer-events: none;
  overflow: visible;
}

.schema-edge {
  stroke: #6aa3ff;
  stroke-width: 1.5;
  opacity: 0.55;
}

/* Pointe de flèche des arêtes du schéma (père → enfant) */
.schema-arrow-head {
  fill: #6aa3ff;
}

.schema-node {
  position: absolute;
  width: 64px;
  height: 30px;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: center;
  font: 12px ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  color: #eee;
  background: #1e2a3a;
  border: 1px solid #3a567d;
  border-radius: 6px;
  cursor: grab;
  user-select: none;
  z-index: 1;
}

.schema-node:hover {
  background: #26354a;
}

.schema-node.current {
  background: #6aa3ff;
  color: #08111f;
  border-color: #cfe2ff;
  font-weight: bold;
  z-index: 2;
}

/* Nœuds de paragraphes @ (livrets personnels) liés mais hors campagne courante. */
.schema-node.livret {
  background: #3a3a3a;
  border-color: #6b6b6b;
  color: #cfcfcf;
}


/* Diviseur vertical draggable */
.v-split {
  flex: 0 0 8px;
  /* largeur de la barre */
  cursor: col-resize;
  position: relative;
  background: #2a2a2a;
  border-left: 1px solid #444;
  border-right: 1px solid #444;
}

.v-split .grip {
  position: absolute;
  top: 50%;
  left: 70%;
  width: 2px;
  height: 28px;
  transform: translate(-50%, -50%);
  background: #666;
  border-radius: 1px;
}

/* Feedback pendant le drag */
.editeur-page.horizontal.resizing {
  user-select: none;
  cursor: col-resize;
}

/* (optionnel) Responsive : en dessous de 900px, repasse en vertical */
@media (max-width: 900px) {
  .editeur-page.horizontal {
    flex-direction: column;
  }

  .v-split {
    display: none;
  }

  .editeur-page.horizontal .left,
  .editeur-page.horizontal .right {
    width: 100% !important;
    min-height: 40vh;
  }
}

.pane.left {
  display: flex;
  align-items: stretch;
  min-width: 300px;
}

.image-palette {
  flex: 0 0 180px;
  max-width: 40%;
  border-right: 1px solid #444;
  background: #ffffff;
  color: #000000;
  padding: 8px 6px;
  overflow: auto;
}

.left-editor {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

/* Pane GAUCHE en rangée : sélecteur | palette | éditeur */
.editeur-page.horizontal .pane.left {
  flex-direction: row;
}

.editeur-page.horizontal .pane.left .image-palette {
  flex: 0 0 150px;
  max-width: 40%;
}

.editeur-page.horizontal .pane.left .left-editor {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

/* enlève la limite 600px qui rétrécit l'éditeur */
.editeur-page.horizontal .left-editor {
  max-width: none;
}

/* === Sélecteur de paragraphes === */
.editeur-page.horizontal .pane.left {
  flex-direction: row;
}

/* palette + selector + éditeur */

.paragraphe-selector {
  flex: 0 0 50px;
  max-width: 20%;
  border-right: 1px solid #444;
  background: #1f1f1f;
  color: #eee;
  display: flex;
  flex-direction: column;
  min-height: 0;
  /* important pour overflow */
}

.paragraphe-selector .para-tools {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 8px;
  position: sticky;
  top: 0;
  background: #262626;
  border-bottom: 1px solid #444;
  z-index: 1;
}

.paragraphe-selector .para-tools input {
  flex: 1 1 auto;
  min-width: 0;
  padding: 6px 8px;
  border: 1px solid #555;
  border-radius: 6px;
  background: #151515;
  color: #eee;
}

.paragraphe-selector .para-tools button {
  padding: 6px 10px;
  border: 1px solid #555;
  border-radius: 6px;
  background: #333;
  color: #eee;
  cursor: pointer;
}

.paragraphe-selector .para-tools select {
  padding: 6px 8px;
  border: 1px solid #555;
  border-radius: 6px;
  background: #151515;
  color: #eee;
}

.tools-row {
  display: flex;
  gap: 6px;
}
#lang-select {
  width: 48px;
  flex-shrink: 0;
  font-size: 0.8rem;
  padding: 2px 2px;
}

.paragraphe-selector {
  flex: 0 0 50px;
}

.para-list {
  list-style: none;
  margin: 0;
  padding: 6px;
  overflow: auto;
  /* scroll interne */
  flex: 1 1 auto;
}

.para-list li {
  display: block;
  margin: 2px 0;
}

.para-list button {
  width: 100%;
  text-align: left;
  padding: 6px 8px;
  border: 1px solid transparent;
  border-radius: 6px;
  background: transparent;
  color: #eee;
  cursor: pointer;
}

.para-list button:hover {
  background: #2b2b2b;
  border-color: #444;
}

.para-list button.active {
  background: #3a3a3a;
  border-color: #666;
  font-weight: 700;
}

.para-list button.selected {
  background: #2a3a4a;
  border-color: #5a7090;
}
.para-list button.selected.active {
  background: #3a4a5a;
  border-color: #7a90b0;
  font-weight: 700;
}

.modal-content input[readonly] {
  background: #2c2c2c;
  color: #bbb;
  cursor: not-allowed;
}

/* --- Ennemis --- */

.ennemis-wrapper {
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 12px;
  width: 100%;
}

@media (min-width: 800px) {
  .ennemis-wrapper {
    grid-template-columns: 1fr 1fr 1fr;
  }
}

.ennemi-groupe {
  border: 1px solid var(--border-color, #444);
  border-radius: 8px;
  padding: 10px;
  background: var(--panel-bg, #ffffff);
  width: 100%;
}

.ennemi-groupe[data-groupe="vert"] {
  box-shadow: inset 0 0 0 5px rgba(25, 135, 84, 0.25);
}

.ennemi-groupe[data-groupe="rouge"] {
  box-shadow: inset 0 0 0 5px rgba(220, 53, 69, 0.25);
}

.ennemi-groupe[data-groupe="bleu"] {
  box-shadow: inset 0 0 0 5px rgba(13, 110, 253, 0.25);
}

.groupe-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 8px;
}

.groupe-header h2 {
  margin: 0;
  font-size: 1.1rem;
}

.groupe-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.groupe-actions label {
  display: flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
}

.groupe-actions .input-pvmax {
  width: 64px;
  height: 32px;
  font-size: 1rem;
}

.groupe-body .groupe-hint {
  font-size: 0.9rem;
  opacity: 0.8;
  margin-bottom: 6px;
}

.ennemis-liste {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.ennemi-item {
  display: grid;
  grid-template-columns: auto auto auto 1fr auto;
  align-items: center;
  gap: 4px;
  border: 1px solid var(--border-color, #333);
  border-radius: 8px;
  padding: 6px 8px;
  background: #ffffff;
}

.ennemi-badge {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-weight: 700;
  background: #ffffff;
}

.ennemi-pions {
  display: flex;
  align-items: center;
  gap: 2px;
  flex-wrap: wrap;
}

.ennemi-pion {
  display: block;
  width: 32px !important;
  height: 32px !important;
  object-fit: contain;
  cursor: pointer;
  transition: filter 150ms ease;
}

.btn-add-pion {
  padding: 2px 6px;
  height: 32px;
  border: 1px solid #999;
  border-radius: 4px;
  background: #f0f0f0;
  cursor: pointer;
  white-space: nowrap;
  flex-shrink: 0;
}

.btn-add-pion:hover {
  background: #ddd;
}

.pion-picker {
  position: absolute;
  z-index: 1000;
  background: #fff;
  border: 1px solid #999;
  border-radius: 8px;
  padding: 8px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
  max-height: 300px;
  overflow-y: auto;
}

.pion-picker.hidden {
  display: none;
}

.pion-picker-list {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 4px;
}

.pion-picker-item {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 4px;
  border-radius: 4px;
  cursor: pointer;
}

.pion-picker-item:hover {
  background: #e8e8e8;
}

.pion-picker-item.already-added {
  opacity: 0.3;
  pointer-events: none;
}

.pion-picker-item img {
  width: 32px !important;
  height: 32px !important;
  object-fit: contain;
}

.ennemi-mid {
  display: grid;
  gap: 4px;
}

.pv-bar {
  height: 10px;
  background: #ffffff;
  border-radius: 6px;
  overflow: hidden;
}

.pv-fill {
  height: 100%;
  background: linear-gradient(90deg, #df6d6d, #006afd);
  transition: width 120ms linear;
}

.pv-text {
  font-size: 0.9rem;
  opacity: 0.9;
}

.ennemi-right {
  display: flex;
  align-items: center;
  gap: 6px;
}

.pv-btn-stack {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.ennemi-right .btn-pv {
  width: 36px;
  height: 15px;
  border-radius: 4px;
  border: 1px solid #444;
  background: #ffffff;
  font-size: 0.8rem;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}

.ennemi-right .btn-pv:active {
  transform: translateY(1px);
}

.btn-add-ennemi,
.btn-remove-ennemi {
  height: 32px;
  border-radius: 6px;
  border: 1px solid #444;
  background: #ffffff;
  padding: 0 10px;
  cursor: pointer;
}

.btn-add-ennemi[disabled],
.btn-remove-ennemi[disabled] {
  opacity: 0.5;
  cursor: not-allowed;
}

.ennemis-container {
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-items: stretch;
}

.ennemi-right .btn-del {
  width: 36px;
  height: 32px;
  border-radius: 6px;
  border: 1px solid #444;
  background: rgb(255, 255, 255);
  color: #fff;
  font-size: 1rem;
  cursor: pointer;
}

.ennemi-right .btn-del:hover {
  background: #c44;
}

.CodePar {
  background: #ffffff;
  color: #000000;
  padding: 0px 5px;
}

.CodeParPerso {
  background: #ffffff;
  color: #000000;
  padding: 0px 5px;
}

.login-container {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 80vh;
  padding: 20px;
}

.login-box {
  background: #fff;
  border-radius: 12px;
  padding: 40px 30px;
  max-width: 400px;
  width: 100%;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
  text-align: center;
}

.login-box h2 {
  color: #333;
  margin-bottom: 5px;
  font-size: 1.6em;
}

.login-subtitle {
  color: #777;
  margin-bottom: 25px;
  font-size: 0.9em;
}

.form-group {
  margin-bottom: 18px;
  text-align: left;
}

.form-group label {
  display: block;
  margin-bottom: 5px;
  color: #555;
  font-size: 0.9em;
}

.form-group input {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid #ccc;
  border-radius: 6px;
  font-size: 1em;
  outline: none;
  transition: border-color 0.2s;
}

.form-group input:focus {
  border-color: #555;
}

.login-btn {
  width: 100%;
  padding: 12px;
  background: #333;
  color: #fff;
  border: none;
  border-radius: 6px;
  font-size: 1em;
  cursor: pointer;
  margin-top: 10px;
  transition: background 0.2s;
}

.login-btn:hover {
  background: #555;
}

.login-error {
  color: #c0392b;
  background: #fde8e8;
  padding: 8px 12px;
  border-radius: 6px;
  margin-bottom: 10px;
  font-size: 0.9em;
}

.menu-user-info {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  cursor: default;
}

.menu-user-info .user-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.menu-user-info .btn-logout {
  background: none;
  border: 1px solid #444;
  padding: 4px 12px;
  border-radius: 4px;
  cursor: pointer;
  flex-shrink: 0;
  margin-left: 10px;
}

.menu-user-info .btn-logout:hover {
  background-color: #a7a7a7;
}

.admin-section {
  margin-top: 20px;
  padding: 15px;
  background: #f9f9f9;
  border-radius: 8px;
}

.admin-section h3 {
  margin-bottom: 15px;
  color: #333;
}

.admin-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9em;
}

.admin-table th,
.admin-table td {
  padding: 8px 10px;
  border: 1px solid #ddd;
  text-align: left;
}

.admin-table th {
  background: #333;
  color: #fff;
}

.admin-form {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: flex-end;
  margin-top: 15px;
}

.admin-form input,
.admin-form select {
  padding: 6px 10px;
  border: 1px solid #ccc;
  border-radius: 4px;
  font-size: 0.9em;
}

.admin-form button {
  padding: 6px 14px;
  background: #333;
  color: #fff;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.admin-form button:hover {
  background: #555;
}

.droits-campagne-block {
  margin-bottom: 25px;
  padding: 12px;
  background: #f9f9f9;
  border-radius: 6px;
  border: 1px solid #e0e0e0;
}

.droits-campagne-block h3 {
  margin: 0 0 10px 0;
  font-size: 1.1em;
  color: #333;
}

.droit-badge {
  display: inline-block;
  padding: 2px 10px;
  border-radius: 10px;
  font-size: 0.85em;
  font-weight: bold;
}

.badge-none {
  background: #eee;
  color: #999;
}

.badge-lecture {
  background: #d4edda;
  color: #155724;
}

.badge-ecriture {
  background: #cce5ff;
  color: #004085;
}

.droits-actions {
  display: flex;
  gap: 4px;
}

.btn-droit {
  padding: 4px 10px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 0.8em;
  color: #fff;
}

.btn-droit:disabled {
  opacity: 0.4;
  cursor: default;
}

.btn-lecture {
  background: #28a745;
}

.btn-ecriture {
  background: #007bff;
}

.btn-retirer {
  background: #dc3545;
}

/* 2026_03_15 ajout encadré de mise en place */
.setup-box {
  position: relative;
  margin: 10px 0;
  padding: 10px;
  border: 2px solid #7a6247;
  border-radius: 12px;
  background: #f3efe6;
}

/* Tableaux du livre (conditions, scores) - importés du livre ARE */

.tableau-livre {
  border-collapse: collapse;
  margin: 10px auto;
  width: 100%;
}

.tableau-livre td {
  border: 1px solid #7a6247;
  padding: 6px 10px;
  vertical-align: top;
}

/* Titre intégré */

.setup-label {
  position: absolute;
  top: -13px;
  left: 50%;
  transform: translateX(-50%);
  background: #f5f1e8;
  padding: 0 12px;
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: #7a6247;
}

/* Lignes décoratives */

.setup-label:before,
.setup-label:after {
  content: "";
  position: absolute;
  top: 50%;
  width: 70px;
  height: 2px;
  background: #7a6247;
}

.setup-label:before {
  right: 100%;
  margin-right: 10px;
}

.setup-label:after {
  left: 100%;
  margin-left: 10px;
}

.setup-box.mode-histoire {
  background-color: #b4b4b4;
  border-color: #888;
}

.setup-box.mode-histoire .setup-label {
  background: #b4b4b4;
  color: #333;
}

.setup-box.mode-histoire .setup-label:before,
.setup-box.mode-histoire .setup-label:after {
  background: #888;
}

.setup-box.condition {
  background-color: #b4b4b4;
  border-color: #BBB;
}

.setup-box.condition .setup-label {
  background: #b4b4b4;
  color: #333;
}

.setup-box.condition .setup-label:before,
.setup-box.condition .setup-label:after {
  background: #BBB;
}

/* ── Plateau d'avancement ─────────────────────────────────── */
.plateau-wrapper { padding: 0 0.6rem 0.3rem; }
.plateau-section { margin-bottom: 0.6rem; }
.left-sub-panel[data-sub-page="plateau"] .side-panel-content { padding: 4px 10px; }

/* Bouton « réduire aux pions d'activation » (même principe que .bottom-panel-zoom de la perso) */
.btn-plateau-compact {
    background: none;
    border: none;
    cursor: pointer;
    color: #ddd;
    padding: 0 6px;
    line-height: 1;
    display: inline-flex;
    align-items: center;
}
.btn-plateau-compact:hover { color: #fff; }
.btn-plateau-compact .plateau-compact-icon {
    display: block;
    font-size: 1.05rem;
    line-height: 1;
}
.btn-plateau-compact .plateau-compact-icon::before { content: "\2913"; }   /* ⤓ réduire */
/* État réduit : flèche « étendre » + on ne garde que la piste des tours */
.left-sub-panel[data-sub-page="plateau"].plateau-compact .btn-plateau-compact .plateau-compact-icon::before { content: "\2912"; }   /* ⤒ */
.left-sub-panel[data-sub-page="plateau"].plateau-compact .plateau-section:not(.tours-section) { display: none; }
.left-sub-panel[data-sub-page="plateau"].plateau-compact .tours-section .mode-titre { display: none; }

/* Compteurs (mode de jeu + interaction) */
.compteurs-section {
    display: flex;
    justify-content: center;
    gap: 2rem;
}
.compteur-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.4rem;
}
/* 20260805 VCH `.plateau-msg-overlay` supprimé : les avertissements du plateau passent par la
   fenêtre centrale à bouton OK (ebsInfo, src/app_modal.js). */

.mode-titre {
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    opacity: 0.6;
    text-align: center;
}
.mode-badge {
    font-size: 0.85rem;
    font-weight: bold;
    letter-spacing: 0.06em;
    padding: 6px 16px;
    border-radius: 4px;
    border: none;
    cursor: pointer;
    transition: opacity 0.15s;
}
.mode-badge:hover { opacity: 0.8; }
.compteur-y-row {
    display: flex;
    align-items: center;
    gap: 4px;
}
.btn-y {
    background: #444;
    color: #fff;
    border: 1px solid #666;
    border-radius: 4px;
    width: 26px;
    height: 26px;
    font-size: 1rem;
    line-height: 1;
    cursor: pointer;
    padding: 0;
}
.btn-y:hover { background: #555; }
.btn-y:disabled { opacity: 0.3; cursor: not-allowed; }
.interaction-select {
    font-size: 0.85rem;
    font-weight: bold;
    padding: 5px 24px 5px 12px;
    border-radius: 4px;
    border: 2px solid #888;
    background: #2a2a2a url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23ffffff'/%3E%3C/svg%3E") no-repeat right 8px center;
    color: #fff;
    cursor: pointer;
    text-align: center;
    appearance: none;
    -webkit-appearance: none;
}
.mode-badge[data-mode="exploration"] { background: #4caf50; color: #fff; }
.mode-badge[data-mode="infiltration"] { background: #f5c518; color: #222; }
.mode-badge[data-mode="combat"]       { background: #c0392b; color: #fff; }

/* Piste des rounds */
.round-nav-inline {
    display: flex;
    align-items: center;
    gap: 4px;
    justify-content: center;
    margin-bottom: 0.5rem;
}
.btn-round-arrow {
    flex-shrink: 0;
    background: none;
    border: 1px solid #888;
    border-radius: 4px;
    color: inherit;
    font-size: 1rem;
    padding: 4px 8px;
    cursor: pointer;
    line-height: 1;
}
.btn-round-arrow:hover { background: rgba(255,255,255,0.1); }
.btn-round-arrow:disabled { opacity: 0.25; cursor: not-allowed; }

.round-piste {
    display: flex;
    gap: 2px;
    justify-content: center;
}
.round-cell {
    display: flex;
    flex-direction: column;
    align-items: center;
    width: 44px;
    opacity: 0.45;
    transition: opacity 0.15s;
}
.round-cell.active { opacity: 1; }
.round-num {
    font-size: 0.85rem;
    font-weight: bold;
    background: transparent;
    border: 1px solid currentColor;
    border-radius: 4px;
    padding: 4px 6px;
    min-width: 36px;
    text-align: center;
}
.round-cell.active .round-num {
    background: #c0392b;
    color: #fff;
    border-color: transparent;
}
.round-num { cursor: pointer; }
.round-num:hover { opacity: 0.75; }


/* Événements placés sous le numéro */
.round-events {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    margin-top: 3px;
}
.round-eve-img {
    width: 36px;
    height: 36px;
    object-fit: contain;
    cursor: pointer;
    border-radius: 4px;
    transition: opacity 0.15s;
}
.round-eve-img.grayed {
    opacity: 0.25;
    filter: grayscale(1);
}
.round-eve-img:hover { opacity: 0.7; }
.round-eve-img.grayed:hover { opacity: 0.45; }

/* ── Piste des tours ──────────────────────────────────────── */
.tours-piste {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    justify-content: center;   /* pions centrés sur la largeur pleine */
    align-items: center;
}
.tour-slot {
    width: 44px;
    height: 44px;
    border: 2px solid #666;
    border-radius: 4px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    background: #2a2a2a;
    transition: opacity 0.15s, filter 0.15s;
    box-sizing: border-box;
}
.tour-slot:hover { border-color: #aaa; }
.tour-slot.tour-grayed {
    opacity: 0.3;
    filter: grayscale(1);
}
.tour-slot.tour-dragging { opacity: 0.4; }
.tour-pion-img {
    width: 36px;
    height: 36px;
    object-fit: contain;
    pointer-events: none;
}
.btn-tour-action {
    width: 36px;
    height: 44px;
    background: #444;
    color: #fff;
    border: 2px solid #666;
    border-radius: 4px;
    font-size: 1.1rem;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
}
.btn-tour-action:hover { background: #555; }

/* Boutons nombre de joueurs (page paramètres) */
.btn-nb-joueurs-group {
    display: inline-flex;
    gap: 6px;
    margin-left: 10px;
    vertical-align: middle;
}
.btn-nb-joueurs {
    padding: 4px 12px;
    border-radius: 6px;
    border: 1px solid #555;
    background: #2a2a2a;
    color: #ccc;
    cursor: pointer;
    font-size: 0.9rem;
}
.btn-nb-joueurs:hover { background: #444; }
.btn-nb-joueurs.actif {
    background: #c0392b;
    border-color: #c0392b;
    color: #fff;
    font-weight: bold;
}

/* Picker piste des tours */
.tours-picker {
    background: #2a2a2a;
    border: 1px solid #555;
    border-radius: 8px;
    padding: 8px;
    z-index: 9999;
    max-width: 260px;
}
.tours-picker.hidden { display: none; }
.tours-picker-list {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}
.tours-picker-item {
    width: 44px;
    height: 44px;
    object-fit: contain;
    cursor: pointer;
    border-radius: 4px;
    border: 2px solid transparent;
}
.tours-picker-item:hover { border-color: #aaa; }
.tours-picker-item.tours-picker-disabled {
    opacity: 0.25;
    filter: grayscale(1);
    cursor: not-allowed;
}

/* ── Responsive plateau (conteneur ≤ 480px) ──────────────── */
@container (max-width: 480px) {
    .plateau-wrapper { padding: 0 0.5rem 0.4rem; }

    /* Piste des rounds : cases plus petites */
    .round-piste { gap: 2px; }
    .round-cell { width: 30px; }
    .round-num {
        font-size: 0.7rem;
        min-width: 22px;
        padding: 3px 2px;
    }
    .round-eve-img { width: 24px; height: 24px; }
    .eve-para-label { font-size: 0.6rem; }

    /* Compteurs : 4 colonnes sur une seule ligne (contrôles réduits) */
    .compteurs-section {
        display: grid;
        grid-template-columns: repeat(4, 1fr);
        gap: 0.3rem;
        justify-items: center;
    }
    .compteur-item { min-width: 0; gap: 0.25rem; }
    .mode-titre {
        font-size: 0.55rem;
        letter-spacing: 0.02em;
        line-height: 1.1;
    }
    .mode-badge {
        font-size: 0.6rem;
        padding: 4px 6px;
        letter-spacing: 0.02em;
    }
    .interaction-select {
        font-size: 0.7rem;
        padding: 4px 18px 4px 6px;
        background-position: right 5px center;
    }
    .compteur-y-row { gap: 2px; }
    .btn-y { width: 20px; height: 20px; font-size: 0.85rem; }

    /* Piste des tours : slots plus petits, pleine largeur */
    .tours-piste {
        gap: 3px;
    }
    .tour-slot { width: 38px; height: 38px; }
    .tour-pion-img { width: 30px; height: 30px; }
    .btn-tour-action { width: 32px; height: 38px; font-size: 1rem; }
}

/* Picker d'événements */
.eve-picker {
    background: #2a2a2a;
    border: 1px solid #555;
    border-radius: 8px;
    padding: 8px;
    z-index: 9999;
    max-width: 220px;
}
.eve-picker.hidden { display: none; }
.eve-picker-list {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}
.eve-picker-item {
    width: 40px;
    height: 40px;
    object-fit: contain;
    cursor: pointer;
    border-radius: 4px;
    border: 1px solid transparent;
    transition: border-color 0.1s;
}
.eve-picker-item:hover { border-color: #c0392b; }

/* ── Popup de choix du mode de jeu (plateau d'avancement) ── */
.mode-picker {
    background: #2a2a2a;
    border: 1px solid #555;
    border-radius: 8px;
    padding: 8px;
    z-index: 9999;
}
.mode-picker.hidden { display: none; }
.mode-picker-list {
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.mode-picker-item {
    /* hérite des couleurs de .mode-badge[data-mode] ; ici : taille/alignement */
    width: 100%;
    text-align: center;
    padding: 8px 18px;
    border: 2px solid transparent;
}
.mode-picker-item.mode-picker-current { border-color: #fff; }

/* ── Dé à 6 faces ─────────────────────────────────────────── */
.d6-zone {
  display: flex;
  align-items: center;
  gap: 6px;
}
.btn-d6 {
  background: none;
  border: none;
  color: white;
  font-size: 1.4rem;
  cursor: pointer;
  padding: 2px 4px;
  line-height: 1;
  user-select: none;
}
.btn-d6:hover { opacity: 0.75; }
.btn-de-img {
  width: 24px;
  height: 24px;
  object-fit: contain;
  display: block;
  pointer-events: none;
}

.d6-history {
  display: flex;
  gap: 5px;
  align-items: center;
}
.d6-result {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  background: white;
  color: #1a1a1a;
  font-weight: bold;
  font-size: 0.85rem;
  border-radius: 4px;
  border: 1px solid rgba(255,255,255,0.3);
}
.d6-result:first-child { opacity: 1; }
.d6-result:last-child:not(:first-child) { opacity: 0.45; }
.d20-result {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 2px 6px;
  border-radius: 4px;
  font-weight: bold;
  font-size: 1.1rem;
}

/* Overlay transparent — le dé vole au-dessus du contenu */
.d6-overlay {
  position: fixed;
  inset: 0;
  z-index: 10000;
  pointer-events: none;
}
.d6-overlay.hidden { display: none; }

/* Scène 3D : positionnée par JS */
.d6-scene {
  position: absolute;
  width: 100px;
  height: 100px;
  perspective: 500px;
  filter: drop-shadow(0 8px 16px rgba(0,0,0,0.5));
}
.d6-cube {
  width: 100px;
  height: 100px;
  position: relative;
  transform-style: preserve-3d;
  transform: rotateX(0deg) rotateY(0deg);
}

/* 6 faces */
.d6-face {
  position: absolute;
  width: 100px;
  height: 100px;
  background: #fff;
  border: 3px solid #ccc;
  border-radius: 12px;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 1fr);
  padding: 10px;
  box-sizing: border-box;
}
.d6-front  { transform: translateZ(50px); }
.d6-back   { transform: rotateY(180deg) translateZ(50px); }
.d6-right  { transform: rotateY(90deg)  translateZ(50px); }
.d6-left   { transform: rotateY(-90deg) translateZ(50px); }
.d6-top    { transform: rotateX(90deg)  translateZ(50px); }
.d6-bottom { transform: rotateX(-90deg) translateZ(50px); }

/* Pips */
.d6-pip {
  width: 14px;
  height: 14px;
  background: #1a1a1a;
  border-radius: 50%;
  margin: auto;
}
.d6-face[data-val="1"] .d6-pip { background: #c0392b; } /* 1 = rouge, tradition */

/* ── Dé à 20 faces ────────────────────────────────────────── */
.d20-scene {
  position: absolute;
  width: 190px;
  height: 190px;
  filter: drop-shadow(0 8px 20px rgba(0,0,0,0.6));
}
#d20-canvas { display: block; width: 190px; height: 190px; }

.d20-result {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 28px;
  height: 22px;
  padding: 0 5px;
  font-weight: bold;
  font-size: 0.78rem;
  border-radius: 4px;
  border: 1px solid rgba(255,255,255,0.25);
}

@keyframes pion-spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

.eve-wrap {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  margin: 1px;
}

/* 20260802 VCH la référence de paragraphe sous un pion événement était en #000 sur le fond
   sombre de la piste des rounds : invisible (vérifié, « #250 » et « #940 » ne se lisaient
   pas). Le noir datait d'un plateau sur fond clair. */
.eve-para-label {
  font-size: 0.75rem;
  font-weight: bold;
  color: #fff;
  cursor: pointer;
  line-height: 1.2;
  text-align: center;
  white-space: nowrap;
}
.eve-para-label:hover {
  text-decoration: underline;
}

/* ── Journal de bord ──────────────────────────────────────────────────────── */

#journal-container {
  padding: 2px 8px 8px;
}
#journal-nav {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin-bottom: 6px;
  font-weight: bold;
  font-size: 0.85rem;
}
/* 20260808 VCH le RAZ est passé de l'en-tête du panneau à la ligne de pagination : en flexbox,
   la marge automatique absorbe l'espace libre AVANT que `justify-content: center` n'agisse —
   « ◀ Page N ▶ » se retrouve donc collé à GAUCHE et le RAZ à droite, le centrage de la ligne
   ne survit pas. Rendu vu et accepté par Vincent. */
#journal-nav #btn-raz-journal { margin-left: auto; }

/* Flèches identiques à celles du plateau d'avancement (.btn-round-arrow) */
.journal-nav-btn {
  flex-shrink: 0;
  background: none;
  border: 1px solid #888;
  border-radius: 4px;
  color: inherit;
  font-size: 1rem;
  padding: 4px 8px;
  line-height: 1;
  cursor: pointer;
}
.journal-nav-btn:disabled {
  opacity: 0.3;
  cursor: default;
}
.journal-nav-btn:not(:disabled):hover {
  background: rgba(0, 0, 0, 0.08);
}

#journal-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 6px;
}

.journal-slot {
  background: #e8e8e8;
  border: 1px solid #bbb;
  border-radius: 4px;
  overflow: hidden;
}

/* Emplacement vide : ratio de référence pour conserver la hauteur sans carte */
.journal-slot:not(.journal-slot--occupied) {
  aspect-ratio: 65 / 92;
}

.journal-slot--occupied {
  background: #fff;
  border-color: #888;
  cursor: zoom-in;
}

/* Modal zoom — positionné en absolu dans le `.center-panel-content` du journal (fenêtre
   centrale depuis le 20260808), qui est `position: relative`. */
#journal-modal {
  display: none;
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.80);
  z-index: 10;
  align-items: safe center;
  justify-content: safe center;
  overflow: auto;
  padding: 8px;
}
#journal-modal.journal-modal--visible {
  display: flex;
}
/* Wrapper : croix au-dessus, carte en-dessous, alignés à droite */
.journal-modal-wrapper {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}
.journal-modal-close {
  background: rgba(60, 60, 60, 0.95);
  color: #fff;
  border: 1px solid #888;
  border-radius: 4px;
  padding: 2px 10px;
  font-size: 1rem;
  line-height: 1.5;
  cursor: pointer;
}
.journal-modal-close:hover {
  background: rgba(100, 100, 100, 0.95);
}
.journal-modal-toolbar {
  display: flex;
  align-self: stretch;
  gap: 8px;
  justify-content: space-between;
  align-items: center;
}
.journal-modal-nav {
  display: flex;
  gap: 8px;
}
.journal-modal-nav button {
  background: rgba(60, 60, 60, 0.95);
  color: #fff;
  border: 1px solid #888;
  border-radius: 4px;
  padding: 2px 10px;
  font-size: 0.9rem;
  line-height: 1.5;
  cursor: pointer;
}
.journal-modal-nav button:hover:not(:disabled) {
  background: rgba(100, 100, 100, 0.95);
}
.journal-modal-nav button:disabled {
  opacity: 0.4;
  cursor: default;
}
.journal-modal-content {
  /* Taille fixe identique au zoom du panneau personnage : 300 px de large,
     hauteur calculée par l'aspect-ratio de la carte. */
  width: 300px;
  border-radius: 6px;
  box-shadow: 0 4px 24px rgba(0,0,0,0.6);
  overflow: hidden;
}
.journal-modal-content .carte-container.carte-ratio {
  width: 100%;
  height: auto;
  min-height: unset !important;
}
/* Dos de carte : pas de classe carte-ratio, aspect-ratio explicite requis */
.journal-modal-content .carte-dos {
  width: 100%;
  height: auto;
  aspect-ratio: var(--carte-ratio);
  position: relative;
  overflow: hidden;
  min-height: unset !important;
}
/* Boutons de paragraphe dans la vue zoom — même style que dans le livre */
.journal-para-link {
  display: inline-block;
  vertical-align: middle;
  background-color: #444;
  color: #fff;
  border: 1px solid #888;
  border-radius: 5px;
  padding: 2px 5px;
  margin: 1px 4px;
  font-family: Arial, sans-serif;
  font-size: inherit;
  cursor: pointer;
  text-decoration: none;
}
.journal-para-link:hover {
  background-color: #666;
}

/* ── Mode Exploration ────────────────────────────────────────────────────── */

/* Chaîne de hauteur : game-area (flex col) → #explo-container (flex:1) → view scrollable */

#explo-container {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
  overflow: hidden;
  position: relative;
}

.explo-toolbar {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 2;
  display: flex;
  gap: .4rem;
  align-items: center;
  justify-content: center;
  padding: 3px 8px;        /* barre compacte : réduit la hauteur de la zone grise */
  border-bottom: 1px solid #ccc;
  background: rgba(250, 250, 250, 0.92);
  transition: left 0.25s ease, right 0.25s ease;
}

.explo-toolbar input {
  width: 50px;                /* n° de carte : 3 chiffres max → champ étroit */
  padding: 2px 5px;
  border: 1px solid #bbb;
  border-radius: 4px;
  font-size: .8rem;
}

/* Mode de jeu affiché juste à gauche des objets centrés des barres.
   Style et couleurs repris du plateau d'avancement (.mode-badge[data-mode]). */
.mode-label {
  white-space: nowrap;
  pointer-events: none;   /* informatif (le mode se change depuis le plateau d'avancement) */
}

/* Barre d'exploration : badge « Exploration » et boutons compacts pour gagner
   de la hauteur (ne touche pas au badge du plateau d'avancement). */
.explo-toolbar .mode-badge {
  font-size: 0.7rem;
  padding: 2px 8px;
  letter-spacing: 0.02em;
}
.explo-toolbar button {
  font-size: 0.7rem;
  line-height: 1;          /* « cartes détruites » sur 2 lignes plus compactes */
  padding: 2px 6px;
}

/* Case « Attacher par les blasons » : compacte ; le libellé peut passer sur deux
   lignes si l'espace manque (notamment sur téléphone). */
.explo-attache-label {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 0.7rem;
  cursor: pointer;
}
.explo-attache-text {
  white-space: normal;     /* autorise le retour à la ligne si besoin */
  line-height: 1.05;       /* deux lignes compactes */
  min-width: 64px;         /* largeur mini → wrap sur 2 lignes (pas 3) quand l'espace
                              manque ; sur grand écran le texte reste sur 1 ligne */
}
/* .explo-toolbar input impose width:50px (champ n°) — neutralisé pour la checkbox. */
.explo-toolbar input[type="checkbox"] {
  width: auto;
  margin: 0;
}

/* Lignes roses reliant les blasons liés en mode éclaté. */
.explo-links {
  position: absolute;
  top: 0;
  left: 0;
  pointer-events: none;
  z-index: 200;
}
.explo-links line {
  stroke: #ff4fa3;
  stroke-width: 2;
}

#explo-view {
  flex: 1;
  overflow: hidden;
  background: #1c1c1c;   /* fond noir, identique à la vue plan (modes combat/infiltration) */
  position: relative;
  cursor: grab;
  user-select: none;
  touch-action: none;
}

#explo-canvas {
  position: absolute;
  top: 0;
  left: 0;
  transform-origin: 0 0;
  will-change: transform;
  backface-visibility: hidden;
}

/* ── Vue plan en jeu (modes Combat / Infiltration) ─────────────────────────── */
#plan-game {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
  overflow: hidden;
  position: relative;
}
.plan-toolbar {
  position: absolute;
  top: 0; left: 0; right: 0;
  z-index: 2;
  display: flex;
  flex-wrap: wrap;            /* écran étroit : le champ + boutons passent sous la barre de pions */
  gap: .4rem;
  align-items: center;
  justify-content: center;
  padding: 3px 8px;          /* uniformisé sur .explo-toolbar (barre compacte) */
  border-bottom: 1px solid #ccc;
  background: rgba(250, 250, 250, 0.92);
  transition: left 0.25s ease, right 0.25s ease;
}
.plan-toolbar input {
  width: 46px;                /* numéro de plan : 2 chiffres max → champ étroit */
  padding: 2px 5px;          /* uniformisé sur .explo-toolbar */
  border: 1px solid #bbb;
  border-radius: 4px;
  font-size: .8rem;
}
/* Badge de mode et boutons uniformisés sur la barre d'exploration (référence). */
.plan-toolbar .mode-badge {
  font-size: 0.7rem;
  padding: 2px 8px;
  letter-spacing: 0.02em;
}
.plan-toolbar button {
  font-size: 0.7rem;
  line-height: 1;
  padding: 2px 6px;
}
/* Barre des pions à glisser sur le plan. order:1 → elle passe en dernier dans le
   flux, ce qui fait remonter le bloc « champ + Ajouter + Vider » à droite du badge
   de mode (gagne une ligne : la barre grise passe de 3 à 2 lignes en mobile). */
.plan-pions-bar {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 2px 6px;
  border: 1px solid #ccc;
  border-radius: 4px;
  background: #fff;
  order: 1;
}
.plan-pion-src {
  width: 38px;
  height: 38px;
  object-fit: contain;
  cursor: grab;
}
/* Liste de choix d'un pion cyclable (clic sur la source) : tous les n° disponibles */
.plan-pion-list {
  position: fixed;
  z-index: 3000;
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  max-width: 320px;
  padding: 6px;
  background: #fff;
  border: 1px solid #999;
  border-radius: 6px;
  box-shadow: 0 3px 10px rgba(0,0,0,0.4);
}
.plan-pion-list-item {
  width: 36px;
  height: 36px;
  object-fit: contain;
  cursor: grab;
  border-radius: 4px;
}
.plan-pion-list-item:hover { outline: 2px solid #4a7c2f; }
/* Pion posé sur un hexagone du plan — au-dessus de la grille ET des zones
   d'annotation (dont le z-index = pos_z*4+8 peut dépasser 9). */
.plan-pion {
  position: absolute;
  transform: translate(-50%, -50%);
  z-index: 1000;
  cursor: grab;
  pointer-events: auto;   /* indispensable : le conteneur multi-pions est en pointer-events:none */
}
/* Plusieurs pions sur une même case : conteneur centré + libellé « N pions » + étalement au survol */
.plan-pion-cell {
  position: absolute;
  transform: translate(-50%, -50%);
  z-index: 1000;            /* le transform crée un contexte d'empilement : au-dessus des zones */
  pointer-events: none;     /* n'empêche pas le pan ; les pions (auto) reçoivent et font bouillonner le survol */
}
.plan-pion-cell .plan-pion {
  transition: left 0.15s ease;
}
.plan-pion-count {
  position: absolute;
  bottom: 100%;
  left: 50%;
  transform: translateX(-50%);
  margin-bottom: 4px;
  background: rgba(0,0,0,0.72);
  color: #fff;
  font-size: 0.7rem;
  padding: 1px 6px;
  border-radius: 8px;
  white-space: nowrap;
  pointer-events: none;
}

/* Petit menu d'actions au clic sur un pion posé (tourner / supprimer) */
.plan-pion-menu {
  position: absolute;
  transform: translate(-50%, calc(-100% - 6px));   /* au-dessus du pion, centré */
  z-index: 1001;
  display: flex;
  gap: 2px;
  padding: 3px;
  background: #fff;
  border: 1px solid #999;
  border-radius: 5px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.35);
}
.plan-pion-menu-btn {
  width: 26px;
  height: 26px;
  line-height: 1;
  font-size: 0.95rem;
  cursor: pointer;
  border: 1px solid #bbb;
  border-radius: 4px;
  background: #f2f2f2;
}
.plan-pion-menu-btn:hover:not(:disabled) { background: #e2e2e2; }
.plan-pion-menu-btn:disabled { opacity: 0.4; cursor: default; }

/* Indice « Échap pour annuler » — suit le pion en cours de déplacement (positionné en JS) */
.plan-trace-hint {
  position: absolute;
  transform: translateX(-50%);
  z-index: 1002;
  pointer-events: none;
  background: rgba(0,0,0,0.72);
  color: #fff;
  font-size: 0.75rem;
  padding: 2px 8px;
  border-radius: 10px;
  white-space: nowrap;
}

/* 20260805 VCH `.plan-msg` supprimé : le message de la vue plan passe par la fenêtre centrale à
   bouton OK (ebsInfo, src/app_modal.js). */

/* Tracé du déplacement d'un pion : numéros de case (SVG) + sens interdit clignotant (SVG <g>) */
.plan-trace-stop {
  animation: plan-stop-blink 0.5s steps(1) infinite;
}
@keyframes plan-stop-blink {
  0%, 50%  { opacity: 1; }
  50.01%, 100% { opacity: 0; }
}
#plan-view {
  flex: 1;
  overflow: hidden;
  background: #1c1c1c;
  position: relative;
  cursor: grab;
  user-select: none;
  touch-action: none;
}
#plan-canvas {
  position: absolute;
  top: 0;
  left: 0;
  transform-origin: 0 0;
  will-change: transform;
  backface-visibility: hidden;
}

/* ── Rendu d'un plan (partagé éditeur ↔ jeu) ───────────────────────────────── */
.plan-container {
  position: relative;
  width: 100%;
  container-type: inline-size;
  font-family: Arial, sans-serif;
  background: #111;
  overflow: hidden;
}
.plan-container.carte-ratio { aspect-ratio: var(--carte-ratio); }
.plan-etiquette {
  position: absolute;
  top: 1.2%; left: 0.8%;
  z-index: 10;
  border: 0.25cqw solid #fff;
  border-radius: 0.6cqw;
  padding: 0.4cqw 1cqw;
  background: rgba(0,0,0,0.55);
  color: #fff;
  font-weight: bold;
  font-size: 2cqw;
  letter-spacing: 0.5px;
  pointer-events: none;
  white-space: nowrap;
}
.carte-zone--pastille {
  border-radius: 50%;
  background: #37a93c;
  border: 0.25cqw solid #fff;
  color: #fff;
  font-weight: bold;
  justify-content: center;
  align-items: center;
  text-align: center;
  padding: 0;
}
.carte-zone--label_case {
  color: #fff;
  font-weight: bold;
  justify-content: center;
  align-items: center;
  text-align: center;
  border-radius: 0.4cqw;
  padding: 0.2cqw 0.4cqw;
}
.carte-zone--encadre {
  border: 0.18cqw dashed #fff;
  color: #fff;
  border-radius: 0.4cqw;
}
.ev-triangle {
  width: 0; height: 0;
  border-left: 2.2cqw solid transparent;
  border-right: 2.2cqw solid transparent;
  border-bottom: 3.8cqw solid #f4d22a;
  position: relative;
  margin: 0 auto;
}
.ev-triangle > span {
  position: absolute;
  top: 1.3cqw; left: 50%;
  transform: translateX(-50%);
  color: #000; font-weight: bold; font-size: 1.7cqw;
}
.ev-code { color: #fff; font-weight: bold; font-size: 1.5cqw; text-align: center; }

/* ── Panneau Cartes détruites ─────────────────────────────────────────────── */
#explo-detruites-modal {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.82);
  z-index: 200;
  align-items: safe center;
  justify-content: safe center;
  overflow: auto;
  padding: 8px;
}
#explo-detruites-modal.ed-modal--visible { display: flex; }

.ed-wrapper {
  background: #fff;
  border-radius: 6px;
  padding: 12px;
  width: min(92%, 640px);
  max-height: 90vh;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.ed-header {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}
.ed-title {
  flex: 1;
  font-weight: bold;
  font-size: 1rem;
}
.ed-raz-btn {
  background: #c0392b;
  color: #fff;
  border: none;
  border-radius: 4px;
  padding: 3px 10px;
  cursor: pointer;
  font-size: 0.85rem;
}
.ed-raz-btn:hover { background: #a93226; }
.ed-close-btn {
  background: #555;
  color: #fff;
  border: none;
  border-radius: 4px;
  padding: 3px 8px;
  cursor: pointer;
  font-size: 1rem;
}
.ed-close-btn:hover { background: #333; }

.ed-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 6px;
  overflow-y: auto;
}
.ed-slot {
  aspect-ratio: 65 / 92;
  background: #e8e8e8;
  border: 1px solid #bbb;
  border-radius: 4px;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}
.ed-slot-code { font-size: 0.8rem; color: #555; }
.ed-empty { color: #888; font-style: italic; margin: 0; }


.explo-card-wrap {
  position: absolute;
  cursor: default;
}

/* Deux sélecteurs, une seule règle : le clone que l'animation de coche fait voler perd l'id
   (sinon deux nœuds au même id dans le document) et garde la classe. Voir renderPion,
   src/app_explo.js. Le positionnement (position/transform/z-index) est neutralisé en inline sur
   le clone, qui doit remplir son vol au lieu de se placer dans le canvas. */
#pion-groupe,
.pion-groupe {
  position: absolute;
  width: 36px;
  height: 36px;
  transform: translate(-50%, -50%);
  z-index: 100;
  cursor: grab;
  background: #3a7a3a;
  border: 3px solid #fff;
  border-radius: 50%;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-size: 16px;
  font-weight: bold;
  user-select: none;
  touch-action: none;
  pointer-events: auto;
}
#pion-groupe:active {
  cursor: grabbing;
}

/* Liens paragraphes dans les zones de carte */
.carte-para-link {
  color: #fff;
  cursor: pointer;
  text-decoration: none;
}
.carte-para-link:hover {
  color: #ddd;
}
/* Paragraphe bloqué : icône sens interdit posée par-dessus le numéro, clic désactivé.
   On grise le numéro via color (pas opacity, qui affecterait aussi l'icône enfant). */
.carte-para-link.carte-para-bloque {
  position: relative;
  pointer-events: none;
  color: #999;
}
.carte-para-sens-interdit {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  height: 1.6em;
  width: auto;
  z-index: 5;
}


/* ── Carte renderer ──────────────────────────────────────────────────────── */

/* Conteneur de carte : position relative, ratio largeur/hauteur */
.carte-container {
  position: relative;
  width: 100%;
  height: 100%;
  border-radius: 4px;
  overflow: hidden;
  box-sizing: border-box;
  container-type: inline-size; /* permet aux enfants d'utiliser cqw */
  font-family: Arial, sans-serif; /* police par défaut, identique au print */
}
.carte-dos {
  font-family: Arial, sans-serif; /* identique au print pour le numéro sur le dos */
}

/* Quand un ratio est défini : aspect-ratio préserve les proportions */
.carte-container.carte-ratio {
  height: auto;
  aspect-ratio: var(--carte-ratio);
}

.carte-zone .texte-dialogue { line-height: 0.9; }
.carte-zone .texte-narration,
.carte-zone .texte-normal { line-height: 1; }

.carte-zone {
  position: absolute;
  box-sizing: border-box;
  overflow: hidden;
  /* Padding proportionnel à la carte, comme la font-size : en pixels fixes, la largeur
     utile pour le texte variait avec la taille d'affichage (0,9 % de la carte dans
     l'aperçu de l'éditeur contre 1,63 % à l'impression) et les retours à la ligne ne
     tombaient pas au même endroit. Conversion selon la convention du projet
     (cf. app_carte.js : 3.477 = 96/25.4 × 92mm_ref / 100) : 2px → 0.5752cqw,
     4px → 1.1504cqw. Redonne exactement 2px/4px à l'impression quelle que soit la
     largeur de carte — le rendu imprimé est inchangé, c'est l'écran qui s'y aligne.
     1re déclaration = repli pour les navigateurs sans container queries. */
  padding: 2px 4px;
  padding: calc(0.5752cqw * var(--font-scale, 1)) calc(1.1504cqw * var(--font-scale, 1));
  font-size: 12px; font-size: calc(4.2cqw * var(--font-scale, 1));
  line-height: 1.2;
  display: flex;
  flex-direction: column;
  justify-content: flex-start; /* défaut : haut */
}
.carte-zone img { vertical-align: middle; }
/* Alignement vertical dans le rendu */
.carte-zone[data-align-v="middle"] { justify-content: center; }
.carte-zone[data-align-v="bottom"] { justify-content: flex-end; }
/* Alignement horizontal dans le rendu */
.carte-zone[data-align-h="center"] { align-items: center; }
/* Les spans rotatés ne doivent pas être découpés en plusieurs lignes */
.carte-zone span[style*="rotate"],
.ec-z-contenu-html span[style*="rotate"] { white-space: nowrap; }
/* Dans la prévisualisation de l'éditeur, les zones sont cliquables */
#ec-preview .carte-zone {
  cursor: grab;
}
#ec-preview .carte-zone:active {
  cursor: grabbing;
}
#ec-preview .carte-zone:hover {
  outline: 1px solid rgba(100, 170, 255, 0.5);
}

/* Couche 1 — fond coloré (derrière l'image de fond) */
.carte-zone-bg {
  position: absolute;
  box-sizing: border-box;
}
.carte-zone-bg[data-fond="blanc"]  { background: #fff; }
.carte-zone-bg[data-fond="gris"]   { background: #d0d0d0; }
.carte-zone-bg[data-fond="bleu"]   { background: #aac4e8; }
.carte-zone-bg[data-fond="beige"]  { background: #e8d8b0; }
.carte-zone-bg[data-fond="rouge"]  { background: #e88080; }
.carte-zone-bg[data-fond="orange"] { background: #f0a050; }
.carte-zone-bg[data-fond="vert1"]  { background: #b8e0b0; }
.carte-zone-bg[data-fond="vert2"]  { background: #90cc88; }
.carte-zone-bg[data-fond="vert3"]  { background: #68b860; }
.carte-zone-bg[data-fond="vert4"]  { background: #40a438; }
.carte-zone-bg[data-fond="noir"]   { background: #000; }

/* Couleurs de fond (conservé pour l'éditeur / compatibilité) */
.carte-zone[data-fond="blanc"]  { background: #fff; }
.carte-zone[data-fond="gris"]   { background: #d0d0d0; }
.carte-zone[data-fond="bleu"]   { background: #aac4e8; }
.carte-zone[data-fond="beige"]  { background: #e8d8b0; }
.carte-zone[data-fond="rouge"]  { background: #e88080; }
.carte-zone[data-fond="orange"] { background: #f0a050; }
.carte-zone[data-fond="vert1"]  { background: #b8e0b0; }
.carte-zone[data-fond="vert2"]  { background: #90cc88; }
.carte-zone[data-fond="vert3"]  { background: #68b860; }
.carte-zone[data-fond="vert4"]  { background: #40a438; }
.carte-zone[data-fond="noir"]   { background: #000; color: #fff; }

/* Pas de styles spécifiques par type de zone — toutes héritent de .carte-zone (font-size, color, etc.).
   Le type ne détermine pas le rendu, seulement la sémantique métier. */

/* Modal sélection de modèle (éditeur de cartes) */
.ec-template-modal {
  position: fixed;
  inset: 0;
  z-index: 2000;
  background: rgba(0,0,0,0.45);
  display: flex;
  align-items: center;
  justify-content: center;
}
.ec-template-modal-content {
  background: #2a2a2a;
  border: 1px solid #555;
  border-radius: 8px;
  padding: 16px 20px;
  min-width: 300px;
  max-height: 70vh;
  overflow-y: auto;
  box-shadow: 0 6px 24px rgba(0,0,0,0.5);
  position: relative;
}
.ec-template-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 12px;
}
.ec-template-modal-header h3 {
  margin: 0;
  font-size: 1rem;
}
.ec-transfer-fields {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.ec-transfer-fields > label {
  display: flex;
  flex-direction: column;
  gap: 3px;
  font-size: 0.85rem;
}
.ec-transfer-fields select,
.ec-transfer-fields input[type="text"] {
  padding: 4px 6px;
}
.ec-transfer-mode {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 0.85rem;
}
.ec-transfer-mode label {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 6px;
}
.ec-transfer-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 4px;
}
.ec-template-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 5px;
}
.ec-template-list li button {
  width: 100%;
  text-align: left;
  padding: 6px 10px;
  cursor: pointer;
  border-radius: 4px;
}

/* Losange numéro de carte — coin supérieur gauche
   SVG inline : polygon avec stroke pour une bordure nette indépendante du fond.
   Ratio viewBox 106:50 ≈ 2:1 (losange aplati horizontal). */
/* ── Blasons exploration ─────────────────────────────────────────────────── */
.carte-blason {
  position: absolute;
  pointer-events: none;
}
.carte-blason img {
  width: 100%;
  height: auto;
  display: block;
}
.carte-blason-code {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  font-weight: bold;
  color: white;
  text-shadow: 1px 1px 3px rgba(0,0,0,0.9);
  pointer-events: none;
  line-height: 1;
  white-space: nowrap;
}
/* Texte rapproché du bord coupé selon l'orientation */
.carte-blason[data-type="haut"]   .carte-blason-code { top: 69%; }
.carte-blason[data-type="bas"]    .carte-blason-code { top: 31%; }
.carte-blason[data-type="gauche"] .carte-blason-code { left: 63%; }
.carte-blason[data-type="droite"] .carte-blason-code { left: 37%; }

/* ── Éditeur blasons (pane gauche) ───────────────────────────────────────── */
.ec-blasons-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 4px 0;
}
.ec-blason-row {
  display: flex;
  align-items: center;
  gap: 4px;
  flex-wrap: wrap;
  padding: 4px 6px;
  background: #1e1e1e;
  border-radius: 4px;
  font-size: 0.72rem;
}
.ec-blason-row label {
  display: flex;
  align-items: center;
  gap: 2px;
  color: #aaa;
}
.ec-blason-row input[type="number"],
.ec-blason-row input[type="text"] {
  background: #2a2a2a;
  border: 1px solid #444;
  color: #eee;
  border-radius: 3px;
  padding: 1px 3px;
}
.ec-blason-row select {
  background: #2a2a2a;
  border: 1px solid #444;
  color: #eee;
  border-radius: 3px;
  padding: 1px 3px;
}
.ec-blason-num {
  font-weight: bold;
  color: #7af;
  min-width: 1.4em;
}

.carte-num-losange {
  position: absolute;
  top: 0;
  left: 0;
  width: 22%;
  height: auto;
  display: block;
  z-index: 10;
  pointer-events: none;
  overflow: hidden;
}
.carte-num-losange--droite {
  left: auto;
  right: 0;
}

/* Carte dans le journal : largeur 100% du slot, hauteur imposée par l'aspect-ratio de la carte */
.journal-slot .carte-container {
  width: 100%;
}

/* ── Éditeur de cartes ───────────────────────────────────────────────────── */

/* Layout 3 panes : gauche | milieu | splitter | droite */
#editeur-carte-page.editeur-page.horizontal {
  flex-direction: row;
}

/* Pane gauche : sélecteur (fixe 300px) + formulaire (300px) */
.ec-pane-left {
  flex: 0 0 600px;
  min-width: 300px;
  display: flex;
  flex-direction: row;
  border-right: 1px solid #333;
  overflow: hidden;
}

/* Sélecteur de cartes */
#ec-selector {
  flex: 0 0 200px;
  max-width: none;
  display: flex;
  flex-direction: column;
  border-right: 1px solid #333;
  overflow: hidden;
}
#ec-selector .para-list {
  flex: 1 1 auto;
  overflow-y: auto;
}

/* Formulaire carte + liste zones */
.ec-form-area {
  flex: 1 1 auto;
  min-width: 0;
  overflow-y: auto;
  padding: 8px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* Pane palette : icônes entre liste zones et éditeur de zone */
.ec-pane-palette {
  flex: 0 0 200px;
  min-width: 120px;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  border-right: 1px solid #444;
  background: #2a2a2a;
  padding: 6px 4px;
}

/* Pane milieu : éditeur de zone */
.ec-pane-middle {
  flex: 1 1 auto;
  min-width: 280px;
  min-height: 0;   /* indispensable pour le scroll interne du flex child */
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border-right: 1px solid #333;
}

/* Pane droite : prévisualisation (largeur contrôlée par splitter) */
.ec-pane-right {
  flex: 0 0 480px;
  min-width: 160px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.ec-section {
  background: #1a1a1a;
  border: 1px solid #333;
  border-radius: 4px;
  padding: 8px;
}

.ec-section-header {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
}
.ec-autosave-label {
  margin-left: auto;
  font-size: 0.75rem;
  color: #aaa;
  display: flex;
  align-items: center;
  gap: 4px;
  cursor: pointer;
}
.ec-section-header h3 {
  margin: 0;
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: #aaa;
  flex: 1 1 auto;
}

/* Boutons génériques éditeur carte */
.ec-btn {
  padding: 3px 8px;
  border: 1px solid #555;
  background: #2a2a2a;
  color: #ddd;
  border-radius: 3px;
  cursor: pointer;
  font-size: 0.78rem;
  white-space: nowrap;
}
.ec-btn:hover { background: #3a3a3a; }
.ec-btn--small { padding: 2px 6px; font-size: 0.72rem; }
.ec-btn--danger { border-color: #aa4444; color: #e88; }
.ec-btn--danger:hover { background: #3a1a1a; }

/* Suppression de la carte : bloc en bas de la colonne, sous les blasons, bien visible */
.ec-delete-area { margin-top: 12px; }
.ec-delete-area .ec-btn--danger {
  display: block;
  width: 100%;
  background: #7a1f1f;
  border-color: #c05555;
  color: #fff;
  font-weight: 600;
  padding: 8px;
}
.ec-delete-area .ec-btn--danger:hover { background: #9a2626; }

/* Status */
.ec-status { font-size: 0.78rem; }
.ec-status--ok  { color: #6c6; }
.ec-status--err { color: #e66; }
#ec-save-status { display: block; margin: 0 0 8px; min-height: 1em; }
#ec-save-status:empty { margin: 0; }

/* Champs carte */
.ec-fields {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
}
.ec-fields label {
  display: flex;
  flex-direction: column;
  font-size: 0.72rem;
  color: #999;
  gap: 2px;
}
.ec-fields label:last-child { grid-column: span 2; }
.ec-fields .ec-field--full { grid-column: span 2; }
.ec-fields input, .ec-fields select {
  background: #111;
  border: 1px solid #444;
  color: #ddd;
  padding: 3px 6px;
  border-radius: 3px;
  font-size: 0.82rem;
}

/* Liste zones (lecture seule, pane gauche) */
.ec-zones-list {
  list-style: none;
  margin: 0;
  padding: 0;
}
.ec-zone-item {
  padding: 4px 8px;
  font-size: 0.72rem;
  color: #aaa;
  cursor: pointer;
  border-bottom: 1px solid #222;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ec-zone-item:hover { background: #252525; color: #ddd; }
.ec-zone-item--selected { background: #1a2a3a; color: #7af; border-left: 2px solid #4af; }

/* Éditeur de bordures de zone */
.ec-border-editor {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  padding: 4px 0;
  grid-column: 1 / -1;
}
.ec-border-label {
  font-size: 0.72rem;
  color: #aaa;
  min-width: 2.5em;
}
.ec-border-editor label {
  display: flex;
  align-items: center;
  gap: 3px;
  font-size: 0.8rem;
  color: #ccc;
  cursor: pointer;
}
.ec-border-editor input[type="color"] {
  width: 28px;
  height: 20px;
  padding: 0 1px;
  border: 1px solid #555;
  border-radius: 3px;
  background: #2a2a2a;
  cursor: pointer;
}
.ec-border-editor input[type="checkbox"] {
  width: 13px;
  height: 13px;
  cursor: pointer;
}
/* Désactiver visuellement le color picker quand la case est décochée */
.ec-border-editor label:has(input[type="checkbox"]:not(:checked)) input[type="color"] {
  opacity: 0.3;
  pointer-events: none;
}

/* Zone editor — état vide */
.ec-zone-editor-empty {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #555;
  font-style: italic;
  font-size: 0.85rem;
  padding: 2rem;
  text-align: center;
  margin: 0;
}

/* Zone editor — panneau interne (pleine hauteur, pas de scroll global) */
.ec-zone-editor-inner {
  flex: 1 1 auto;
  min-height: 0;
  overflow: hidden;
  padding: 8px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* Section props : taille naturelle */
#ec-zone-editor > .ec-section:first-child {
  flex: 0 0 auto;
}

/* Sections contenu + code : partagent l'espace restant à égalité */
#ec-zone-editor > .ec-section:not(:first-child) {
  flex: 1 1 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

#ec-zone-editor > .ec-section:not(:first-child) > .ec-section-header {
  flex: 0 0 auto;
}

/* Conteneur de l'éditeur HTML de zone : remplit sa section */
#ez-editor-container {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}

/* Wrapper zone HTML editor : remplit #ez-editor-container */
#ez-editor-container > .zone-html-editor {
  display: flex;
  flex-direction: column;
  height: 100%;
  min-height: 0;
}

/* Titre de la zone dans l'éditeur */
.ec-zone-editor-title {
  font-weight: bold;
  font-size: 0.85rem;
  color: #ccc;
}

/* Champs propriétés de zone */
.ec-zone-props-fields {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: flex-end;
}
.ec-zone-props-fields label {
  display: flex;
  flex-direction: column;
  font-size: 0.72rem;
  color: #999;
  gap: 2px;
}
.ec-zone-props-fields input,
.ec-zone-props-fields select {
  background: #111;
  border: 1px solid #444;
  color: #ddd;
  padding: 3px 6px;
  border-radius: 3px;
  font-size: 0.82rem;
}
.ec-zone-props-fields input[type="number"] { width: 4rem; }
.ec-zone-props-fields input[type="text"]   { width: 5rem; }

/* Code HTML de zone — fond noir, remplit sa section */
.ec-zone-code-area {
  flex: 1 1 auto;
  min-height: 0;
  resize: none;
  width: 100%;
  background: #0f0f0f;
  color: #ddd;
  border: 1px solid #aaa;
  border-radius: 3px;
  padding: 6px 8px;
  font-family: ui-monospace, Menlo, Consolas, monospace;
  font-size: 0.75rem;
  line-height: 1.4;
  resize: vertical;
  box-sizing: border-box;
}

/* Palette d'icônes */
.ec-zone-palette {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  padding: 2px;
  min-height: 2rem;
}
.ec-zone-palette .thumb {
  border: 1px solid #ccc;
  border-radius: 3px;
  background: #f5f5f5;
  padding: 2px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.ec-zone-palette .thumb:hover { background: #e0e8ff; border-color: #88a; }

/* Wrapper zone HTML editor */
.zone-html-editor {
  display: flex;
  flex-direction: column;
}

/* Toolbar pleine pour zones HTML — version compacte */
.zone-editeur-toolbar {
  position: static; /* pas sticky contrairement à l'éditeur de paragraphe */
  padding: 4px 6px;
  gap: 4px;
}
.zone-editeur-toolbar button,
.zone-editeur-toolbar select {
  padding: 2px 6px;
  font-size: 0.75rem;
}

/* Zone contenu éditable — remplit sa section */
.ec-z-contenu-html {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  justify-content: flex-start; /* défaut : haut */
  background: #696969; /* fond gris neutre : rend le texte blanc visible quand la zone n'a pas de fond sombre */
  color: #111;
  border: 1px solid #aaa;
  border-radius: 2px;
  padding: 6px 8px;
  font-size: 0.82rem;
  line-height: 1.4;
  outline: none;
  word-break: break-word;
}
.ec-z-contenu-html:focus { border-color: #666; }
/* Les images dans l'éditeur s'affichent comme une petite icône :
   les styles absolus (position, inset, width 100%, height 100%) sont neutralisés.
   Le HTML sauvegardé (lu via innerHTML) conserve les styles d'origine. */
.ec-z-contenu-html img {
  position: static !important;
  inset: auto !important;
  display: inline-block !important;
  width: 1.5em !important;
  height: 1.5em !important;
  object-fit: contain;
  vertical-align: middle;
  border: 1px solid #777;
  border-radius: 3px;
  background: #444;
}
/* Couleurs de fond selon la valeur de fond de la zone */
.ec-z-contenu-html[data-fond="blanc"]  { background: #d8d8d8; } /* gris clair : texte blanc visible */
.ec-z-contenu-html[data-fond="gris"]   { background: #d0d0d0; }
.ec-z-contenu-html[data-fond="bleu"]   { background: #aac4e8; }
.ec-z-contenu-html[data-fond="beige"]  { background: #e8d8b0; }
.ec-z-contenu-html[data-fond="rouge"]  { background: #e05050; }
.ec-z-contenu-html[data-fond="orange"] { background: #f0a050; }
.ec-z-contenu-html[data-fond="vert1"]  { background: #b8e0b0; }
.ec-z-contenu-html[data-fond="vert2"]  { background: #90cc88; }
.ec-z-contenu-html[data-fond="vert3"]  { background: #68b860; }
.ec-z-contenu-html[data-fond="vert4"]  { background: #40a438; }
.ec-z-contenu-html[data-fond="noir"]   { background: #000; color: #fff; }
/* Alignement vertical dans l'éditeur de zone — toujours flex-start pour éviter que le
   contenu déborde vers le haut (inaccessible car scrollTop ne peut pas être négatif) */
.ec-z-contenu-text {
  width: 100%;
  background: #0f0f0f;
  color: #ddd;
  border: 1px solid #333;
  border-radius: 2px;
  padding: 3px 6px;
  font-size: 0.78rem;
  box-sizing: border-box;
}

/* Pane droite : toolbar prévisualisation */
.ec-preview-toolbar {
  flex: 0 0 auto;
  padding: 6px 12px;
  background: #1a1a1a;
  border-bottom: 1px solid #333;
  font-size: 0.78rem;
  color: #aaa;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.ec-preview-toolbar-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
}
.ec-preview-info { color: #777; font-size: 0.72rem; }
.ec-borders-label {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 4px;
  cursor: pointer;
  font-size: 0.78rem;
  color: #ccc;
  user-select: none;
}
#ec-preview.ec-show-borders .carte-zone {
  box-shadow: inset 0 0 0 1px hotpink;
}
.ec-preview-toolbar button {
  padding: 3px 8px;
  background: #2a2a2a;
  border: 1px solid #444;
  color: #ccc;
  border-radius: 4px;
  cursor: pointer;
  font-size: 0.78rem;
}
.ec-preview-toolbar button:hover { background: #333; }
.ec-preview-container {
  flex: 1 1 auto;
  overflow: auto;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 20px;
  background: #888;
}
#ec-preview {
  width: 100%;  /* remplit toute la largeur disponible */
}
.ec-preview-empty {
  color: #555;
  font-size: 0.85rem;
  text-align: center;
  padding: 20px;
}


/* ── Ennemis v2 ──────────────────────────────────────────────────────────── */

.ennemisv2-wrapper {
  display: flex;
  flex-direction: column;
  gap: 0;
  padding: 2px 4px;
  width: 100%;
}
/* Réduit l'espace blanc au-dessus de la 1re ligne « PV max » */
.left-sub-panel[data-sub-page="ennemis-v2"] .side-panel-content { padding-top: 2px; }

.ennemisv2-groupe {
  border: none;
  border-radius: 0;
  padding: 10px 4px;
  background: var(--panel-bg, #ffffff);
  width: 100%;
  box-sizing: border-box;
}
.ennemisv2-groupe:first-child { padding-top: 2px; }

.ennemisv2-groupe + .ennemisv2-groupe {
  border-top: 1px solid #ccc;
}


.btn-raz-ennemis,
.btn-raz-journal,
.btn-raz-perso,
.btn-raz-plateau {
  background: #5a1a1a;
  color: #fff;
  border: 1px solid #8a3a3a;
  border-radius: 3px;
  padding: 2px 8px;
  font-size: 0.75rem;
  cursor: pointer;
}
.btn-raz-ennemis:hover,
.btn-raz-journal:hover,
.btn-raz-perso:hover,
.btn-raz-plateau:hover { background: #7a2a2a; }

.ennemisv2-header {
  display: flex;
  align-items: center;
  gap: 3px;
  flex-wrap: wrap;
  margin-bottom: 10px;
  font-size: 0.78rem;
}

.ennemisv2-header .header-sep {
  color: var(--border-color, #aaa);
}

.ennemisv2-header .header-label {
  white-space: nowrap;
}

.ennemisv2-header .input-pvmax {
  width: 3ch;
  padding: 2px 4px;
  -moz-appearance: textfield;
  appearance: textfield;
}
.ennemisv2-header .input-pvmax::-webkit-outer-spin-button,
.ennemisv2-header .input-pvmax::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

.ennemisv2-header .input-num-carac,
.ennemisv2-header .input-num-comport {
  width: 4.5ch;
  padding: 2px 4px;
}

.ennemisv2-header .btn-clear-carac,
.ennemisv2-header .btn-clear-comport {
  color: #dc3545;
  border: 1px solid #dc3545;
  background: transparent;
  border-radius: 4px;
  padding: 1px 5px;
  cursor: pointer;
  font-weight: bold;
  font-size: 0.75rem;
  line-height: 1;
}

.ennemisv2-body {
  overflow-x: auto;
}

/* Grid 3×4 : slots autour de la carte carac + carte de comportement alignée */
.ennemisv2-slots-layout {
  display: grid;
  grid-template-areas:
    ".    top    .    "
    "left card   right"
    ".    bottom .    ";
  grid-template-columns: max-content 180px max-content;
  grid-template-rows: max-content auto max-content;
  column-gap: 6px;
  row-gap: 6px;
  justify-content: center;   /* centre le bloc carac dans la largeur */
}

/* Placement des zones */
.ennemisv2-slot-pos[data-pos="top"]    { grid-area: top;    display: flex; flex-direction: row;    gap: 6px; }
.ennemisv2-slot-pos[data-pos="left"]   { grid-area: left;   display: flex; flex-direction: column; gap: 6px; }
.ennemisv2-carte-carac                 { grid-area: card;   width: 180px; min-height: 20px; }
.ennemisv2-slot-pos[data-pos="right"]  { grid-area: right;  display: flex; flex-direction: column; gap: 6px; }
.ennemisv2-slot-pos[data-pos="bottom"] { grid-area: bottom; display: flex; flex-direction: row;    gap: 6px; }

/* Slots haut/bas : largeur égale = moitié de la carte */
.ennemisv2-slot-pos[data-pos="top"] .ennemisv2-slot,
.ennemisv2-slot-pos[data-pos="bottom"] .ennemisv2-slot {
  flex: 1;
  min-width: 0;
}

/* Slots gauche/droite : hauteur égale = moitié de la carte */
.ennemisv2-slot-pos[data-pos="left"] .ennemisv2-slot,
.ennemisv2-slot-pos[data-pos="right"] .ennemisv2-slot {
  flex: 1;
  min-height: 0;
}

/* Comportement : sous la carac, carte centrée (compteur à gauche, bouton à droite) */
.ennemisv2-carte-comport {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  column-gap: 8px;
  width: 100%;
  margin-top: 8px;
}

.comport-card-area { width: 180px; }

.comport-deck-counter {
  justify-self: end;
  text-align: right;
  font-size: 0.75em;
  color: #aaa;
}

.carte-dos {
  display: block;
  position: relative;
  width: 100%;
  aspect-ratio: var(--carte-ratio, calc(63/88));
  min-height: 60px;
  background: linear-gradient(135deg, #1a3a6a 0%, #2a5a9a 100%);
  border-radius: 4px;
  container-type: inline-size; /* permet aux enfants (numéro losange) d'utiliser cqw */
}

/* 20260805 VCH indicateur d'attente partagé (src/app_attente.js) : l'appli charge une ressource.
   Deux signaux complémentaires, aucun n'est modal — rien n'est bloqué pendant l'attente.

   1. Le sablier du pointeur. `progress` et non `wait` : le pointeur reste visible à côté du sablier,
      ce qui dit « ça charge, tu peux continuer » là où `wait` dirait « bloqué ». */
html.ebs-attente,
html.ebs-attente * {
  cursor: progress !important;
}

/* 2. L'anneau posé sur l'élément qui a déclenché l'attente (la case cochée) : c'est le seul signal
      visible sur mobile et tablette, qui n'ont pas de pointeur. Centré sur son ancre, dont la
      position est suivie pendant le chargement (le panneau peut défiler ou se re-rendre). */
.ebs-anneau-attente {
  position: fixed;
  /* 20260814 VCH suit lui aussi la bande des animations : il se pose sur la case cochée, d'où
     part le vol, et doit rester visible par-dessus lui. */
  z-index: 1999999996;        /* juste au-dessus de l'overlay des vols de coche (1999999995) */
  width: 26px;
  height: 26px;
  margin: -13px 0 0 -13px;    /* centré sur (left, top) */
  border: 3px solid rgba(214, 178, 96, .35);
  border-top-color: #d6b260;  /* doré, comme le halo de flashCoche */
  border-radius: 50%;
  pointer-events: none;
  animation: ebs-anneau-tourne 800ms linear infinite;
}
@keyframes ebs-anneau-tourne {
  to { transform: rotate(360deg); }
}
/* Mouvement réduit : l'anneau reste, il ne tourne plus. C'est un indicateur d'état, pas une
   décoration — le supprimer priverait le joueur du seul signal disponible sans pointeur. */
@media (prefers-reduced-motion: reduce) {
  .ebs-anneau-attente { animation: none; border-top-color: rgba(214, 178, 96, .35); }
}

/* Overlay « Chargement en cours » : couvre une carte (face ou dos) tant que son image
   de fond n'est pas chargée — posé par attacherImageFond() dans src/app_carte.js. */
.carte-loading {
  position: absolute;
  inset: 0;
  z-index: 999;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 4px;
  background: #ececec;
  color: #555;
  font-family: Arial, sans-serif;
  font-size: 0.7rem;
  border-radius: 4px;
  transition: opacity 0.25s ease;
  pointer-events: none;
}


.zoom-flip-btn {
  background: rgba(60, 60, 60, 0.95);
  color: #fff;
  border: 1px solid #888;
  border-radius: 4px;
  padding: 2px 8px;
  font-size: 0.8rem;
  line-height: 1.5;
  cursor: pointer;
  white-space: nowrap;
  flex-shrink: 0;
  position: relative;
  z-index: 10;
}
.zoom-flip-btn:hover { background: rgba(100, 100, 100, 0.95); }

.btn-flow-riviere {
  display: block;
  width: 100%;
  margin-bottom: 8px;
  padding: 7px 4px;
  background: #2a4a7a;
  color: #fff;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 0.72rem;
  font-family: inherit;
  line-height: 1.3;
  text-align: center;
}
.btn-flow-riviere:hover { background: #3a6aaa; }

/* 20260803 VCH « Vider la rivière », sous la carte de test. Même géométrie que
   « Faire couler la rivière » (elles se lisent comme une paire), mais le rouge sombre du RAZ
   de l'en-tête : c'est une remise à zéro, pas un tour de jeu. */
.btn-vider-riviere {
  display: block;
  width: 100%;
  margin-top: 8px;
  padding: 6px 4px;
  background: #5a1a1a;
  color: #fff;
  border: 1px solid #8a3a3a;
  border-radius: 4px;
  cursor: pointer;
  font-size: 0.72rem;
  font-family: inherit;
  line-height: 1.3;
  text-align: center;
}
.btn-vider-riviere:hover { background: #7a2a2a; }

.btn-tirer-carte {
  justify-self: start;
  background: #2a2a2a; border: 1px solid #555; border-radius: 4px;
  color: #ddd; padding: 5px 8px; cursor: pointer; font-size: 0.78em;
}
.btn-tirer-carte:hover { background: #3a3a3a; }

/* ── Zoom modal ennemis ──────────────────────────────────────────────────── */
.ennemis-zoom-modal .journal-modal-wrapper {
  width: 100%;
  align-items: center;
}

.ennemis-zoom-modal {
  display: none;
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.82);
  z-index: 50;
  align-items: safe center;
  justify-content: safe center;
  overflow: auto;
  padding: 8px;
}
.ennemis-zoom-modal.ennemis-zoom-modal--visible {
  display: flex;
}
.ennemis-zoom-header {
  display: flex;
  align-self: stretch;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 28px;
  position: relative;
}
.ennemis-zoom-header .journal-modal-close {
  position: absolute;
  right: 0;
}
.ennemis-zoom-toggle {
  background: rgba(60, 60, 60, 0.95);
  color: #fff;
  border: 1px solid #888;
  border-radius: 4px;
  padding: 2px 10px;
  font-size: 0.8rem;
  line-height: 1.5;
  cursor: pointer;
}
.ennemis-zoom-toggle:hover {
  background: rgba(100, 100, 100, 0.95);
}

.ennemis-zoom-footer {
  display: flex;
  align-self: stretch;
  justify-content: center;
  margin-top: 6px;
}
.ennemis-zoom-tirer {
  background: rgba(60, 60, 60, 0.95);
  color: #fff;
  border: 1px solid #888;
  border-radius: 4px;
  padding: 3px 14px;
  font-size: 0.85rem;
  line-height: 1.5;
  cursor: pointer;
}
.ennemis-zoom-tirer:hover {
  background: rgba(100, 100, 100, 0.95);
}

.ennemis-zoom-content {
  width: 300px;
  height: auto;
  max-width: 90vw;
  overflow: hidden;
}
.ennemis-zoom-content .carte-container.carte-ratio {
  width: 100%;
  height: auto;
  min-height: unset !important;
}
.ennemis-zoom-content .carte-dos {
  width: 100%;
  height: auto;
  aspect-ratio: var(--carte-ratio);
  position: relative;
  overflow: hidden;
  min-height: unset !important;
}

.ennemisv2-loading {
  display: block;
  font-size: 0.8rem;
  opacity: 0.6;
  padding: 4px;
}

.ennemisv2-error {
  display: block;
  font-size: 0.8rem;
  color: #dc3545;
  padding: 4px;
}

/* Slots */

.ennemisv2-slot {
  border: 1px solid var(--border-color, #ccc);
  border-radius: 6px;
  padding: 4px 6px;
  min-width: 60px;
  background: var(--panel-bg, #f8f8f8);
  box-sizing: border-box;
}

/* ── Avertissement mode portrait ──────────────────────────────────────────── */
#portrait-warning {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 10000;
  background: #1a1a1a;
  color: #fff;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  font-size: 1.1rem;
  padding: 20px;
  gap: 8px;
}
.portrait-warning-icon {
  font-size: 4rem;
  animation: rotate-hint 2s ease-in-out infinite;
}
@keyframes rotate-hint {
  0%,100% { transform: rotate(0deg); }
  40%      { transform: rotate(90deg); }
  60%      { transform: rotate(90deg); }
}
/* Le mode portrait est désormais une disposition gérée (cf. ## Refonte navigation
   ci-dessous) : plus d'avertissement de rotation. #portrait-warning reste display:none. */

.ennemisv2-slot--vide {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  min-height: 52px;
  justify-content: center;
}

.ennemisv2-slot--occupe {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
}

.slot-num {
  display: block;
  font-size: 0.72rem;
  font-weight: bold;
  color: #888;
  text-align: center;
}

.btn-slot-add {
  width: 26px;
  height: 26px;
  padding: 0;
  font-size: 1.1rem;
  line-height: 1;
  border-radius: 4px;
  cursor: pointer;
  border: 1px solid #aaa;
  background: transparent;
}

.btn-slot-add:hover {
  background: #e8ffe8;
  border-color: #4caf50;
}

.slot-pv-row {
  display: flex;
  align-items: center;
  gap: 2px;
}

.slot-pv-row .input-pv {
  width: 26px;
  text-align: center;
  font-size: 0.85rem;
  padding: 1px 0;
  border: 1px solid #ccc;
  border-radius: 3px;
  -moz-appearance: textfield;
}

.slot-pv-row .input-pv::-webkit-outer-spin-button,
.slot-pv-row .input-pv::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

.slot-pv-row .btn-pv {
  width: 24px;
  height: auto;
  padding: 1px 0;
  font-size: 0.85rem;
  line-height: 1.2;
  cursor: pointer;
  border: 1px solid #aaa;
  background: transparent;
  border-radius: 3px;
}

.slot-pv-row .btn-pv:active {
  background: #ddd;
}

.slot-pions {
  display: flex;
  flex-wrap: wrap;
  gap: 2px;
  min-height: 0;
}

.slot-pion {
  width: 24px;
  height: 24px;
  cursor: pointer;
  transition: filter 150ms ease;
}

.slot-btns {
  display: flex;
  gap: 4px;
  align-items: center;
}

.slot-btns .btn-add-pion {
  height: auto;
  font-size: 0.85rem;
  line-height: 1.2;
  padding: 1px 5px;
  cursor: pointer;
  border: 1px solid #aaa;
  background: transparent;
  border-radius: 3px;
  white-space: nowrap;
}

.slot-btns .btn-add-pion:hover {
  background: #eee;
}

.btn-del-ennemi {
  color: #dc3545;
  border: 1px solid #dc3545;
  background: transparent;
  border-radius: 4px;
  padding: 1px 5px;
  cursor: pointer;
  font-weight: bold;
  font-size: 0.85rem;
  line-height: 1.2;
}

.btn-del-ennemi:hover {
  background: #dc3545;
  color: #fff;
}

/* ══════════════════════════════════════════════════════════════════════════════
   Panneaux personnages (bottom panel)
   ══════════════════════════════════════════════════════════════════════════════ */

.perso-loading {
  padding: 20px;
  color: #888;
  font-size: 0.85rem;
}

/* Layout flex-row à 3 colonnes */
.perso-layout {
  display: flex;
  flex-direction: row;
  height: 100%;
  /* Quand les 3 colonnes ne tiennent pas dans la fenêtre (mobile / affichage réduit),
     on peut glisser horizontalement pour atteindre les cartes (gauche) et la zone test
     (droite) au lieu de les voir coupées. */
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  /* Barre de défilement masquée : le glisser tactile reste actif, mais elle ne
     réserve plus d'espace en bas (sinon elle rognait le bas de la rivière). */
  scrollbar-width: none;
  gap: 0;
  position: relative; /* ancre le modal zoom */
}
.perso-layout::-webkit-scrollbar { display: none; }

/* ── Gauche : cartes disponibles ─────────────────────────────────────────── */

.perso-cartes-zone {
  flex: 1;
  min-width: 240px;   /* ne pas s'écraser à 0 sur écran étroit (sinon cartes illisibles) ;
                         la page perso devient alors défilable horizontalement */
  overflow-x: hidden;
  overflow-y: auto;
  background: #f0f0f0;
  border-right: 2px solid #ccc;
}

.perso-cartes-list {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: flex-start;
  align-content: flex-start;
  gap: 6px;
  padding: 6px 8px;
}

/* Barre d'ajout de carte (numéro ou code) */
.perso-add-bar {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 3px 8px;
  flex-wrap: wrap;
  border-bottom: 1px solid #ccc;
}
/* Rangée des contrôles en CSS GRID (et non flex) : la colonne du champ vaut 1fr
   (largeur DÉFINIE) que le champ remplit de façon fiable, y compris sur iOS Safari
   où un <input> en flex ignore sa largeur. Grid ne wrappe pas → une seule ligne
   garantie. Colonnes : champ(1fr) | Ajouter | label Butin | dé | dé | dé. */
.perso-add-row {
  flex: 1 1 100%;          /* la rangée occupe toute la largeur de la barre */
  display: grid;
  /* 20260803 VCH 7 colonnes auto, et non 5 : « Ajouter », « Butin : » + 3 butins, puis
     « Blessure : » + son bouton. Le compte doit suivre le contenu de la rangée — à 5, les deux
     éléments du bouton blessure tombaient sur une 2e ligne implicite, ce que cette rangée est
     précisément censée éviter. Vérifié par tests/e2e/25-blessure-perso.spec.js (une seule ligne
     rendue, pas de débordement horizontal). */
  grid-template-columns: minmax(0, 1fr) repeat(7, auto);
  align-items: center;
  gap: 4px;
  min-width: 0;
}
.perso-add-input {
  width: 100%;             /* remplit la cellule 1fr (largeur définie → fiable iOS) */
  min-width: 0;
  box-sizing: border-box;
  font-size: 0.75rem;
  padding: 3px 5px;
  border: 1px solid #aaa;
  border-radius: 3px;
}
.perso-add-btn {
  flex-shrink: 0;          /* « Ajouter » garde sa taille ; seul le champ rétrécit */
  font-size: 0.75rem;
  padding: 3px 8px;
  border: 1px solid #999;
  border-radius: 3px;
  background: #f0f0f0;
  cursor: pointer;
  white-space: nowrap;
}
.perso-add-btn:hover { background: #ddd; }
.perso-butin-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 2px;
  border: 1px solid #999;
  border-radius: 3px;
  background: #f0f0f0;
  cursor: pointer;
  flex-shrink: 0;
}
.perso-butin-btn:hover { background: #ddd; }
.perso-butin-btn img { width: 22px; height: 22px; object-fit: contain; display: block; }
.perso-butin-prefixe { font-size: 0.7rem; font-weight: bold; color: #333; }
.perso-butin-label { font-size: 0.75rem; font-weight: bold; color: #444; margin-left: 4px; white-space: nowrap; }

/* Bouton « cartes perdues » */
.perso-perdues-btn {
  display: block;
  width: 100%;
  margin-bottom: 8px;
  padding: 7px 4px;
  background: #9e2a2a;
  color: #fff;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 0.72rem;
  font-family: inherit;
  line-height: 1.3;
  text-align: center;
}
.perso-perdues-btn:hover { background: #c23b3b; }

/* Bouton « perdre » sur une carte posée (coin bas) */
.ti-lose-btn {
  position: absolute;
  bottom: 1px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 10;
  background: rgba(140, 30, 30, 0.85);
  color: #fff;
  border: none;
  border-radius: 3px;
  font-size: 0.6rem;
  line-height: 1.1;
  padding: 1px 5px;
  cursor: pointer;
}
.ti-lose-btn:hover { background: #b0392b; }

/* Modal « cartes perdues » */
.perso-perdues-modal {
  display: none;
  position: absolute;
  inset: 0;
  background: rgba(0,0,0,0.6);
  z-index: 210;
  align-items: center;
  justify-content: center;
}
.perso-perdues-modal.open { display: flex; }
.perso-perdues-inner {
  background: #fff;
  border-radius: 6px;
  max-height: 90%;
  max-width: 90%;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.perso-perdues-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 6px 10px;
  background: #3a3a3a;
  color: #fff;
  font-weight: bold;
}
.perso-perdues-close {
  background: none;
  border: none;
  color: #ddd;
  font-size: 1.2rem;
  line-height: 1;
  cursor: pointer;
}
.perso-perdues-close:hover { color: #fff; }
.perso-perdues-content {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  padding: 12px;
  overflow: auto;
  justify-content: center;
  align-items: flex-start;
}
.perso-perdue-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}
.perso-perdue-carte {
  width: 180px;
  cursor: zoom-in;
}
.perso-recuperer-btn {
  font-size: 0.8rem;
  padding: 3px 10px;
  border: 1px solid #2a7;
  background: #eafbe9;
  border-radius: 3px;
  cursor: pointer;
}
.perso-recuperer-btn:hover { background: #d2f3d0; }
.perso-add-status {
  flex-basis: 100%;
  font-size: 0.7rem;
  color: #c0392b;
}
/* Vide la plupart du temps : on ne réserve PAS de ligne sous les contrôles (sinon
   espace vide permanent dans la barre). La ligne n'apparaît qu'en cas de message. */
.perso-add-status:empty { display: none; }

/* Encart « Petit format » (équipements du personnage) */
.perso-equip-header {
  margin-top: 4px;
  padding: 3px 8px;
  font-size: 0.7rem;
  font-weight: bold;
  color: #444;
  background: #e2e2e2;
  border-top: 1px solid #ccc;
  border-bottom: 1px solid #ccc;
}

.perso-equip-vide {
  font-size: 0.7rem;
  font-style: italic;
  color: #999;
  padding: 4px 2px;
}

/* 20260805 VCH `.ebs-toast` supprimé : plus aucun toast dans l'appli, tous les messages passent par
   la fenêtre centrale à bouton OK (ebsInfo, src/app_modal.js, qui injecte son propre CSS). */

.perso-carte-wrapper {
  width: 170px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 3px;
  position: relative;
}

.perso-carte-toolbar {
  display: flex;
  flex-direction: row;
  gap: 3px;
}
.perso-carte-toolbar .btn-action-basique {
  flex: 1 1 0;
  min-width: 0;
}

.btn-action-basique {
  font-size: 0.6rem;
  padding: 2px 4px;
  cursor: pointer;
  background: #eee;
  border: 1px solid #bbb;
  border-radius: 3px;
  white-space: nowrap;
  flex-shrink: 0;
  text-align: center;
  line-height: 1.4;
}

.btn-action-basique:hover {
  background: #ddd;
}

.btn-action-basique.active {
  background: #4a7c2f;
  color: #fff;
  border-color: #3a6020;
}

.btn-action-basique.active:hover {
  background: #3a6020;
}

/* Toolbar des cartes actions en overlay : petits boutons ronds façon rivière
   (.ti-remove-btn / .ti-rotate-btn) sur le bord droit de la carte.
   pointer-events:none sur le conteneur → le clic (zoom) et le drag passent vers la
   carte, sauf sur les boutons (pointer-events:auto). */
.perso-carte-toolbar-overlay {
  position: absolute;
  inset: 0;
  display: block;
  pointer-events: none;
  z-index: 10;
}
.perso-carte-ovbtn {
  position: absolute;
  width: 16px;
  height: 16px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  font-size: 0.72rem;
  line-height: 1;
  cursor: pointer;
  pointer-events: auto;
  display: flex;
  align-items: center;
  justify-content: center;
}
.perso-carte-ovbtn:hover { background: #333; }
/* ↻ rotation en haut-gauche, ⇄ dos juste à sa droite, ✕ retirer en haut-droite. */
.pcb-rot  { top: 2px; left: 2px; }
.pcb-rot:hover { background: #2a6; }
.pcb-rot.active { background: #4a7c2f; }
.pcb-flip { top: 2px; left: 20px; }
.pcb-flip.active { background: #2a6; }
.pcb-del  { top: 2px; right: 2px; }
.pcb-del:hover { background: #c0392b; }

.perso-carte-inner {
  cursor: pointer;
  border-radius: 4px;
  overflow: hidden;
  transition: box-shadow 0.15s, transform 0.4s ease;
}

.perso-carte-inner:hover {
  box-shadow: 0 0 0 2px #4a7c2f;
}


/* ── Milieu : plateau personnage ─────────────────────────────────────────── */

.perso-plateau {
  display: grid;
  grid-template-columns: 52px repeat(4, 174px);
  /* Rangée rivière à sa hauteur de contenu (≈408px) + align-content:end → le bloc
     rivière reste collé en bas même quand le panneau est plus haut (écrans 2K). */
  grid-template-rows: repeat(6, auto) 408px;
  align-content: end;
  width: 748px;
  flex-shrink: 0;
  height: 100%;
  overflow: hidden;
  border-right: 2px solid #ccc;
  border-left: 1px solid #aaa;
}

/* Cellules de la tuile personnage */
.tp-cell {
  padding: 1px 3px;
  font-size: 0.6rem;
  line-height: 1.1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  border-right: 1px dashed #aaa;
  border-bottom: 1px dashed #aaa;
  text-align: center;
  vertical-align: middle;
  display: flex;
  align-items: center;
  justify-content: center;
  white-space: pre-line;
  background: #f8f8f8;
}

.tp-cell.tp-header {
  font-weight: bold;
  font-size: 0.62rem;
  background: #4a7c2f;
  color: #fff;
  border-color: #3a6020;
}

.tp-cell.tp-label {
  font-weight: bold;
  font-size: 0.58rem;
  background: #d0e8b8;
  border-right: 2px solid #4a7c2f;
  text-align: right;
  justify-content: flex-end;
}

.tp-cell.tp-header.tp-label {
  background: #2f5a1e;
  justify-content: center;
  text-align: center;
  font-size: 0.5rem;
  line-height: 1.05;
}

.tp-cell.tp-green {
  background: #b8e090;
}

/* Teintes de vert par intensité (échantillonnées sur la tuile réelle), appliquées
   aux en-têtes « intensité N » et aux cases INTERACTION de la même colonne. */
.tp-cell.tp-int-0 { background: #d9ead3; }
.tp-cell.tp-int-1 { background: #b6d7a8; }
.tp-cell.tp-int-2 { background: #93c47d; }
.tp-cell.tp-int-3 { background: #6aa84f; }

/* En-têtes « intensité N » : texte noir, plus grand et gras (cf. tuile réelle). */
.tp-cell.tp-header.tp-int-0,
.tp-cell.tp-header.tp-int-1,
.tp-cell.tp-header.tp-int-2,
.tp-cell.tp-header.tp-int-3 {
  color: #000;
  font-size: 0.68rem;
  border-color: #7aa86a;
}

/* Cellule d'action basique : contenu HTML (texte + icônes), autorise le retour à la ligne */
.tp-cell.tp-action {
  white-space: normal;
}
.tp-action-inner {
  text-align: center;
  line-height: 1.15;
}
.tp-action-inner img {
  height: 1.1em;
  width: auto;
  vertical-align: middle;
  margin: 0 1px;
}

/* ── Rivière : 4 tuiles intensité ────────────────────────────────────────── */

/* Spacer sous la colonne "label" dans la ligne rivière */
.tp-river-spacer {
  background: #d0e8b8;
  border-right: 2px solid #4a7c2f;
}

/* Flèches creuses indiquant les deux séparations de la rivière (sur chaque tuile) */
.river-arrow {
  position: absolute;
  left: 2px;
  transform: translateY(-50%);
  pointer-events: none;
  height: auto;
  z-index: 1;             /* au-dessus des fonds de zones (toujours visibles), sous les cartes posées */
}
.river-arrow-1 {            /* séparation cartes actions / petit format (bas zone action) */
  top: 244px;
  width: 34px;
}
.river-arrow-2 {            /* séparation petit format / pions (bas zone petit format) */
  top: 368px;
  width: 22px;
}

.tuile-intensite {
  display: flex;
  flex-direction: column;
  border-left: 1px solid #bbb;
  overflow: hidden;
  background: #fff;
  position: relative;
  isolation: isolate;   /* contexte d'empilement : les flèches (z-index:-1) restent au-dessus du fond */
}

.ti-zone-action {
  flex: none;
  height: 244px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-bottom: 3px solid #555;
  position: relative;
  overflow: hidden;
  cursor: default;
}

.ti-zone-pf {
  flex: none;
  height: 124px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-bottom: 2px solid #bbb;
  position: relative;
  overflow: hidden;
  cursor: default;
}

.ti-zone-pions {
  flex: none;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 2px;
  padding: 2px;
  overflow: auto;
  background: #f5f5f5;
  min-height: 40px;
  flex-shrink: 0;
}

/* Pions réduits pour que 2 lignes tiennent dans la zone (40px) sans ascenseur vertical */
.ti-zone-pions .ti-pion {
  width: 16px;
  height: 16px;
  object-fit: contain;
  cursor: pointer;
}

.ti-zone-pions .ti-add-pion {
  height: auto;
  font-size: 0.6rem;
  line-height: 1;
  padding: 1px 5px;
}

.ti-zone-label {
  font-size: 0.52rem;
  color: #aaa;
  text-align: center;
  white-space: pre-line;
  line-height: 1.3;
  padding: 2px;
  pointer-events: none;
}

.ti-drop-active {
  background: #e8f5d8 !important;
  outline: 2px dashed #4a7c2f;
  outline-offset: -2px;
}

/* Carte posée sur une tuile */
.ti-carte-posee {
  position: absolute;
  inset: 0;
  cursor: zoom-in;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 2;            /* au-dessus des flèches de séparation (qui restent visibles ailleurs) */
}

.ti-carte-posee.rotated {
  transform: rotate(180deg);
}

/* La carte tient dans la zone en gardant ses proportions : on la cale sur la
   largeur (dimension limitante pour les cartes action/petit format dans ces
   zones étroites), la hauteur découle de l'aspect-ratio, plafonnée à la zone. */
.ti-carte-posee .carte-container {
  width: 170px;
  max-width: 100%;
  height: auto;
  max-height: 100%;
}

.ti-remove-btn {
  position: absolute;
  top: 1px;
  right: 1px;
  z-index: 10;
  background: rgba(0,0,0,0.55);
  color: #fff;
  border: none;
  border-radius: 50%;
  width: 16px;
  height: 16px;
  font-size: 0.7rem;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
}

.ti-remove-btn:hover {
  background: #c0392b;
}

/* Bouton rotation 180° d'une carte posée (coin haut-gauche) */
.ti-rotate-btn {
  position: absolute;
  top: 1px;
  left: 1px;
  z-index: 10;
  background: rgba(0,0,0,0.55);
  color: #fff;
  border: none;
  border-radius: 50%;
  width: 16px;
  height: 16px;
  font-size: 0.7rem;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
}
.ti-rotate-btn:hover { background: #2a6; }

.ti-stack-badge {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 10;
  padding: 2px 4px;
  background: rgba(30, 60, 110, 0.88);
  color: #fff;
  font-size: 0.68rem;
  font-weight: bold;
  text-align: center;
  border: none;
  border-bottom: 1px solid rgba(255,255,255,0.2);
  cursor: pointer;
  letter-spacing: 0.03em;
}
.ti-stack-badge:hover { background: rgba(50, 90, 160, 0.95); }

/* ── Vue pile (stack view dans le zoom modal) ───────────────────────────── */

.perso-stack-view {
  display: flex;
  flex-direction: row;
  gap: 12px;
  padding: 8px;
  flex-wrap: wrap;
  justify-content: center;
  align-items: flex-start;
}

.perso-stack-item {
  width: 220px;
  flex-shrink: 0;
}

.perso-stack-item .carte-container,
.perso-stack-item .carte-dos {
  width: 220px !important;
  height: auto !important;
  min-height: unset !important;
}

/* ── Droite : carte test ─────────────────────────────────────────────────── */

.perso-test-zone {
  width: 182px;
  flex-shrink: 0;
  padding: 6px;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 6px;
  background: #f7f7f7;
}

.perso-test-wrapper {
  width: 100%;
  cursor: zoom-in;
}

.perso-test-wrapper .carte-container.carte-ratio {
  width: 170px;
  max-width: 100%;
  height: auto;
}

/* Carte « carac. perso » (paysage 65×42 mm) affichée à droite */
.perso-carac-wrapper {
  width: 100%;
  cursor: zoom-in;
  display: flex;
  justify-content: center;
}
.perso-carac-wrapper .carte-container.carte-ratio {
  width: 170px;
  max-width: 100%;
  height: auto;
}

/* Encadré quand aucune carte carac n'est ajoutée (mêmes proportions que la carte) */
.perso-carac-placeholder {
  width: 170px;
  max-width: 100%;
  aspect-ratio: 65 / 42;
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 6px;
  box-sizing: border-box;
  border: 2px dashed #b0b0b0;
  border-radius: 4px;
  background: #fdfdfd;
  color: #888;
  font-size: 0.72rem;
  line-height: 1.3;
}

/* Encart PV (compteur -/+) au-dessus du bouton « Cartes perdues » */
.perso-pv-encart {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  min-height: 30px;
  padding: 3px 6px;
  border: 1px solid #c9a23a;
  border-radius: 4px;
  background: #fbf4dd;
}
.perso-pv-btn {
  flex: 0 0 auto;
  width: 26px;
  height: 26px;
  line-height: 1;
  font-size: 1rem;
  font-weight: bold;
  cursor: pointer;
  border: 1px solid #b9962f;
  border-radius: 4px;
  background: #f1e3ab;
  color: #5a4a10;
}
.perso-pv-btn:hover:not(:disabled) { background: #e6d18a; }
.perso-pv-btn:disabled { opacity: 0.4; cursor: default; }
.perso-pv-val {
  flex: 1 1 auto;
  text-align: center;
  font-size: 0.78rem;
  color: #5a4a10;
  white-space: nowrap;
}
.perso-pv-val .perso-pv-cur {
  font-size: 1.05rem;
  font-weight: bold;
  color: #8a1f1f;
}

/* ── Modal zoom ──────────────────────────────────────────────────────────── */

.perso-zoom-modal {
  display: none;
  position: absolute;
  inset: 0;
  background: rgba(0,0,0,0.6);
  z-index: 220;        /* au-dessus de la modale « cartes perdues » (210) et des piles */
  align-items: center;
  justify-content: center;
}

.perso-zoom-modal.open {
  display: flex;
}

.perso-zoom-inner {
  position: relative;
  max-height: 90%;
  max-width: 90%;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.perso-zoom-toolbar {
  display: flex;
  justify-content: flex-start;
  align-items: center;
  gap: 6px;
  width: 100%;
  margin-bottom: 6px;
  flex-shrink: 0;
}
.perso-zoom-toolbar .zoom-flip-btn.active {
  background: rgba(74, 124, 47, 0.95);
  border-color: rgba(58, 96, 32, 0.95);
}

.perso-zoom-close {
  position: absolute;
  top: -10px;
  right: -10px;
  z-index: 10;
  background: #333;
  color: #fff;
  border: none;
  border-radius: 50%;
  width: 24px;
  height: 24px;
  font-size: 1rem;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}

.perso-zoom-close:hover {
  background: #c0392b;
}

.perso-zoom-content {
  max-height: 80vh;
  max-width: 80vw;
  overflow: auto;
}

.perso-zoom-content .carte-container.carte-ratio,
.perso-zoom-content .carte-dos {
  width: 300px;
  height: auto;
  min-height: unset;
}

/* ===================== VUE SITE (vitrine recréée) ===================== */
/* Affichage/masquage : en mode site, on cache l'appli et on montre le site. */
#site-view { display: none; }
#site-view[hidden] { display: none; }
body.site-mode #app-layout { display: none; }
body.site-mode #site-view {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  background: #0f0f12;
  color: #e8e8e8;
}
/* 20260810 VCH en vue site, TOUT l'en-tête de l'appli disparaît : dés, compteurs de round, menu,
   mais aussi les boutons son et plein écran, sans objet sur un site vitrine, et le titre lui-même.
   Le retour vers l'appli est repris par #site-vers-appli, dans la barre du site. */
body.site-mode header,
body.site-mode #menu,
body.site-mode #portrait-warning { display: none !important; }

/* #app-title devient un bouton de navigation (flèche + destination) */
#app-title { cursor: pointer; }

/* Menu de navigation du site */
#site-nav {
  position: sticky;
  top: 0;
  z-index: 10;
  background: #16161b;
  border-bottom: 1px solid #2a2a33;
  /* Le retour vers l'appli à gauche, les rubriques au centre de la place restante. */
  display: flex;
  align-items: center;
  flex-wrap: wrap;
}
#site-nav ul {
  flex: 1;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.25rem 0.5rem;
  list-style: none;
  margin: 0;
  padding: 0.6rem 1rem;
}
/* Retour vers l'appli : c'est une sortie du site, pas une rubrique — d'où le doré du jeu et la
   flèche, qui reprennent l'ancien libellé de l'en-tête. */
#site-vers-appli {
  flex: none;
  padding: 0.6rem 0.9rem;
  color: #e0b35a;
  font-weight: bold;
  text-decoration: none;
  white-space: nowrap;
}
#site-vers-appli::before { content: '\2190\00a0'; }   /* ← insécable */
#site-vers-appli:hover { color: #f0cd88; }
#site-nav .site-nav-item {
  cursor: pointer;
  padding: 0.4rem 0.8rem;
  color: #cfcfcf;
  white-space: nowrap;
  border-bottom: 2px solid transparent;
  transition: color .15s, border-color .15s;
}
#site-nav .site-nav-item:hover { color: #fff; }
#site-nav .site-nav-item.active { color: #fff; border-bottom-color: #c0392b; }

/* 20260816 VCH menu déroulant du site, MOBILE UNIQUEMENT. Ses deux éléments n'existent qu'en
   dessous de 768 px : au-dessus, ils sont masqués et la barre reste exactement celle du desktop. */
.site-burger, .site-rubrique-courante { display: none; }

@media (max-width: 768px) {
  /* Mesuré en 390 × 844 avant ce bloc : 237 px de haut, soit 28 % de l'écran, les six rubriques
     chacune sur sa ligne. La barre étant collante (top: 0), cette hauteur était perdue pendant
     TOUTE la lecture, pas seulement à l'arrivée. Une ligne de 48 px en rend 189 au contenu. */
  #site-nav {
    flex-wrap: nowrap;
    min-height: 48px;
    gap: 0.25rem;
    padding: 0 0.5rem;
  }
  /* 20260816 VCH la sortie vers l'appli à GAUCHE, comme en desktop, le repère au milieu et le
     bouton du menu à DROITE (demandé par Vincent). Par `order` et non en déplaçant le HTML :
     #site-vers-appli reste le premier enfant, comme le desktop l'attend. */
  #site-vers-appli { order: 1; padding: 0.5rem 0.25rem; font-size: 0.95rem; }
  .site-rubrique-courante { order: 2; }
  .site-burger { order: 3; }

  .site-burger {
    display: flex;
    align-items: center;
    justify-content: center;
    /* 44 px : la cible tactile minimale recommandée, sans quoi le bouton est manqué au pouce. */
    width: 44px;
    height: 44px;
    flex: none;
    padding: 0;
    border: 0;
    background: none;
    /* Les tokens du thème et non les couleurs figées : le bloc « SITE VITRINE » de la fin de cette
       feuille réharmonise le site en noirs chauds, et une couleur en dur y jurerait. */
    color: var(--r-gold, #e0b35a);
    font-size: 1.35rem;
    line-height: 1;
    cursor: pointer;
  }
  .site-burger .site-burger-icone::before { content: '\2630'; }          /* ☰ */
  #site-nav.ouvert .site-burger .site-burger-icone::before { content: '\2715'; }  /* ✕ */

  /* Où l'on est. Le libellé complet d'une rubrique peut dépasser la place laissée entre le bouton
     et la sortie (« Témoignages de joueurs ») : il s'y abrège au lieu de pousser la barre. */
  .site-rubrique-courante {
    display: block;
    flex: 1;
    min-width: 0;
    color: var(--r-text, #f0f0f0);
    font-size: 0.95rem;
    font-weight: bold;
    text-align: center;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  /* Les rubriques deviennent un panneau sous la barre, replié par défaut. Il se pose en absolu
     dans #site-nav (`position: sticky` établit bien un contexte de positionnement) pour ne rien
     réserver dans le flux : la barre garde ses 48 px, ouverte comme fermée. */
  #site-nav ul {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    flex-direction: column;
    flex-wrap: nowrap;
    gap: 0;
    padding: 0.25rem 0;
    background: var(--r-surface1, #16161b);
    border-bottom: 1px solid var(--r-border-hi, #2a2a33);
    box-shadow: 0 8px 16px rgba(0,0,0,0.45);
    /* Six lignes tiennent largement ; la borne protège les écrans bas (mobile en paysage). */
    max-height: calc(100dvh - 48px);
    overflow-y: auto;
  }
  #site-nav.ouvert ul { display: flex; }
  #site-nav .site-nav-item {
    padding: 0.75rem 1rem;
    white-space: normal;
    /* Le surlignage du desktop est un soulignement d'onglet : dans une liste verticale, il ferait
       une rangée de traits. Ici, un liseré doré en tête de ligne. */
    border-bottom: 0;
    border-left: 3px solid transparent;
  }
  #site-nav .site-nav-item.active {
    border-left-color: var(--r-gold, #e0b35a);
    background: rgba(224,179,90,0.08);
  }
}

/* Contenu des pages du site */
#site-content { flex: 1; }
.site-hero {
  position: relative;
  /* 20260809 VCH 58vh reléguait le début du contenu sous la ligne de flottaison : sur un écran
     d'ordinateur, la vidéo de présentation n'était pas visible à l'arrivée sur la page. */
  min-height: 40vh;
  background-size: cover;
  background-position: center;
  display: flex;
  align-items: flex-end;
}
.site-hero-inner {
  width: 100%;
  padding: 2.5rem 1.5rem 1.5rem;
  background: linear-gradient(transparent, rgba(0,0,0,0.78));
  text-align: center;
}
.site-hero h1 {
  margin: 0;
  font-size: clamp(1.8rem, 5vw, 3rem);
  text-shadow: 0 2px 8px rgba(0,0,0,0.8);
}
.site-hero p { margin: 0.4rem 0 0; color: #d8d8d8; }
.site-section {
  max-width: 840px;
  margin: 0 auto;
  padding: 2rem 1.5rem;
  line-height: 1.65;
}
/* 20260809 VCH aération de tout le site : le reset global (`* { margin: 0 }`, en tête de cette
   feuille) laissait paragraphes ET titres collés les uns aux autres, d'où une page compacte et
   fatigante à lire (signalé par Vincent). `p:not([class])` épargne les blocs qui portent déjà leur
   propre espacement (.site-cta, .site-quote, .site-accroche…) : `.site-section p` leur serait plus
   spécifique et aurait écrasé leurs marges. */
.site-section p:not([class]) { margin: 0 0 1.1rem; }
.site-section h2 {
  color: #e0b35a;
  margin: 2.2rem 0 0.7rem;
}
.site-section h3 { color: #f0f0f0; margin: 1.6rem 0 0.4rem; }
/* Pas de marge en haut du tout premier bloc : elle décollerait le contenu du bandeau. */
.site-section > :first-child { margin-top: 0; }
/* Respiration renforcée, là où le propos change de nature (fiche technique, accroche, contexte). */
.site-section .site-air { margin: 0 0 2.4rem; }
.site-section img { max-width: 100%; height: auto; border-radius: 4px; display: block; margin: 1rem auto; }
.site-section a { color: #6fb7e6; word-break: break-word; }
.site-figure { text-align: center; margin: 1.5rem 0; }
.site-figure figcaption { font-size: 0.85rem; color: #aaa; margin-top: 0.3rem; }
.site-video-wrap {
  position: relative;
  max-width: 840px;
  margin: 1.5rem auto;
  aspect-ratio: 16 / 9;
}
.site-video-wrap iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; border-radius: 6px; }

/* 20260809 VCH séquence « la rivière » (rubrique Présentation), pilotée par le défilement :
   src/app_site_riviere.js. La section sert de piste : sa hauteur donne la course disponible, et la
   figure collée reste à l'écran pendant qu'on la parcourt. --rs-etapes, --rs-pas, --rs-vue et
   --rs-nav sont posées par le module (les deux dernières sont des hauteurs mesurées : la zone
   visible #site-view, et le menu du site lui aussi collé en haut). */
.riviere-scroll {
  position: relative;
  /* 20260809 VCH piste = hauteur de la FIGURE plus un pas de défilement par étape. Un bloc collé
     reste fixe pendant exactement `hauteur de piste − sa propre hauteur` : cette formule aligne donc
     le trajet collé sur la course de progression, au pixel. Deux formules écartées, mesurées :
     `étapes × fraction d'écran` donnait une course réelle de `piste − écran`, soit 40 px par étape
     pour une piste courte (un cran de molette en sautait trois) ; et partir de la hauteur d'écran
     laissait la figure collée 344 px APRÈS la dernière étape, le texte disparaissant derrière elle
     sans raison. */
  height: calc(var(--rs-bloc, 0px) + var(--rs-etapes, 7) * var(--rs-pas, 130px));
  /* Plus large que la colonne de texte : la figure est panoramique, l'élargir la fait monter de
     318 à 425 px et réduit d'autant le vide au-dessous d'elle. Pas de `transform` ici — il créerait
     un contexte qui désactiverait le `position: sticky` de l'enfant. */
  width: min(1120px, 92vw);
  /* ⚠️ Pas de marge négative pour remonter le texte suivant : essayée et mesurée, elle rendait à la
     page la place même dont le défilement a besoin (course tombée de 910 à 21 px, séquence plafonnée
     à l'étape 5 sur 7). Le vide sous la figure est comblé par la liste des étapes, dans le bloc
     collé — voir construireListe(). */
  margin: 1.5rem 0 1.5rem calc((100% - min(1120px, 92vw)) / 2);
}
.riviere-scroll-sticky {
  position: sticky;
  /* 20260809 VCH hauteur du CONTENU, et figure calée au MILIEU de la zone visible (`--rs-centre`,
     mesurée par le module : la moitié de l'espace libre). Réserver toute la hauteur de l'écran
     l'entourait de bandes noires — elle est panoramique, 699 × 265, et ne peut pas remplir un écran
     haut. Le centrage n'est tenable que parce que le texte suivant remonte derrière elle (marge
     négative ci-dessus) : sans cela, il creusait un espace entre le texte précédent et la figure.
     Fond opaque et z-index : c'est ce texte qui doit passer DERRIÈRE la figure. */
  top: calc(var(--rs-nav, 0px) + var(--rs-centre, 0px));
  z-index: 2;
  padding-bottom: 0.6rem;
  display: flex;
  flex-direction: column;
  /* Opaque, car la piste défile DERRIÈRE la figure. La variable et non #0f0f12 : le thème
     réharmonise le fond du site en noirs chauds (`body.site-mode #site-view`, plus bas), et une
     couleur figée dessinait une bande visible au milieu de la page. */
  background: var(--r-bg, #0f0f12);
}
/* Les étapes sont superposées (donc toutes préchargées) : une seule est opaque à la fois. */
.riviere-scroll-vues { display: grid; }
.riviere-scroll-vues .rs-etape {
  grid-area: 1 / 1;
  margin: 0;
  opacity: 0;
  transition: opacity .25s ease;
  pointer-events: none;
}
.riviere-scroll-vues .rs-etape.active { opacity: 1; }
.riviere-scroll-vues .rs-etape img { margin: 0; width: 100%; height: auto; border-radius: 4px; }
/* En mode séquence, la légende de l'étape est portée par la liste ci-dessous : la garder ici
   ferait doublon. Elle reste dans le HTML pour le mode liste et pour la lecture d'écran. */
.riviere-scroll-vues .rs-etape figcaption { display: none; }
/* Les sept étapes, la courante en avant : c'est ce qui occupe la hauteur laissée libre par une
   figure panoramique, et qui dit d'un coup d'œil où l'on est et ce qui reste à voir. */
.riviere-scroll-legendes {
  margin: 0.7rem 0 0;
  padding: 0;
  list-style: none;
  counter-reset: rs;
}
.riviere-scroll-legendes li {
  counter-increment: rs;
  position: relative;
  padding: 0.16rem 0 0.16rem 1.9rem;
  color: #8b8b93;
  font-size: 0.94rem;
  line-height: 1.4;
  transition: color .2s ease;
}
.riviere-scroll-legendes li::before {
  content: counter(rs);
  position: absolute;
  left: 0;
  width: 1.3rem;
  text-align: right;
  color: #55555e;
  font-weight: bold;
}
.riviere-scroll-legendes li.active { color: #f2f2f2; }
.riviere-scroll-legendes li.active::before { color: #e0b35a; }

/* Repli : animations coupées, écran étroit, ou pas de JS. Les sept étapes se suivent simplement. */
.riviere-scroll--liste { height: auto; }
.riviere-scroll--liste .riviere-scroll-sticky {
  position: static;
  height: auto;
  display: block;
  background: none;
}
.riviere-scroll--liste .riviere-scroll-vues { display: block; }
.riviere-scroll--liste .rs-etape { opacity: 1; margin-bottom: 1.6rem; pointer-events: auto; }
.riviere-scroll--liste .rs-etape figcaption {
  display: block;
  margin-top: 0.6rem;
  text-align: center;
  color: #e8e8e8;
  line-height: 1.5;
}
/* La liste des étapes ne sert qu'au mode séquence : en repli, chaque image porte sa légende. */
.riviere-scroll--liste .riviere-scroll-legendes { display: none; }

/* 20260809 VCH fiches des personnages (rubrique Univers) : les portraits de src/img/perso sont
   carrés (1254×1254 et 1024×1024), d'où l'aspect-ratio 1/1 imposé aux vignettes. */
.site-persos {
  display: grid;
  /* Deux colonnes, donc 2×2 pour les quatre héros : `auto-fit` en donnait trois et laissait
     Deirdre seule sur une deuxième ligne (constaté en 1400 px). */
  grid-template-columns: repeat(2, 1fr);
  gap: 1.2rem;
  margin: 1.5rem 0;
}
@media (max-width: 560px) {
  .site-persos { grid-template-columns: 1fr; }
}
.site-perso {
  margin: 0;
  background: #16161b;
  border: 1px solid #2a2a33;
  border-radius: 6px;
  overflow: hidden;
}
/* Neutralise le `margin: 1rem auto` que .site-section applique à toute image. */
.site-perso img { margin: 0; width: 100%; aspect-ratio: 1 / 1; object-fit: cover; border-radius: 0; }
.site-perso figcaption { padding: 0.8rem 0.9rem 1rem; }
.site-perso-nom { display: block; color: #e0b35a; font-weight: bold; font-size: 1.15rem; }
.site-perso-alt { display: block; color: #9a9a9a; font-size: 0.82rem; font-style: italic; }
.site-perso-role { display: block; color: #f0f0f0; font-size: 0.95rem; margin: 0.35rem 0 0.4rem; }
.site-perso-txt { display: block; color: #ddd; font-size: 0.92rem; line-height: 1.5; }

/* 20260809 VCH appel à l'action de la rubrique « L'application » */
.site-cta { text-align: center; margin: 1.6rem 0; }
.site-btn {
  display: inline-block;
  padding: 0.75rem 1.8rem;
  border: 1px solid #e0b35a;
  border-radius: 4px;
  background: #c0392b;
  color: #fff !important;   /* l'emporte sur la couleur des liens de .site-section */
  font-size: 1.05rem;
  font-weight: bold;
  text-decoration: none;
  transition: background .15s, transform .15s;
}
.site-btn:hover { background: #d8452f; transform: translateY(-1px); }

.site-quote {
  border-left: 3px solid #c0392b;
  margin: 1.2rem 0;
  padding: 0.4rem 0 0.4rem 1rem;
  color: #ddd;
  font-style: italic;
}
.site-quote .site-quote-author { display: block; margin-top: 0.3rem; font-style: normal; color: #e0b35a; font-weight: bold; }

/* 20260809 VCH citation d'accroche, en tête des témoignages : c'est elle qui donne le ton de la
   page, elle n'est donc pas répétée plus bas dans les groupes thématiques. */
.site-accroche {
  margin: 0 0 1.5rem;
  padding: 0;
  border: 0;
  text-align: center;
  font-size: clamp(1.15rem, 2.4vw, 1.5rem);
  line-height: 1.45;
  font-style: italic;
  color: #f0f0f0;
}
.site-accroche .site-quote-author {
  display: block;
  margin-top: 0.6rem;
  font-size: 0.95rem;
  font-style: normal;
  color: #e0b35a;
  font-weight: bold;
}
#site-footer {
  text-align: center;
  padding: 1.5rem;
  color: #888;
  border-top: 1px solid #2a2a33;
  font-size: 0.85rem;
}

/* ───────────────────────────── TUTORIEL ───────────────────────────── */
.tuto-bubble {
  position: fixed;
  /* 20260801 VCH la bulle passe au-dessus des pages, du panneau central et du menu.
     Avant (z-index: 9999) elle passait DERRIÈRE tout ce qui compte : #menu (2e9),
     .center-panel (alors 1999999999, aujourd'hui 1999999990 — soit le choix du scénario,
     les paramètres, l'aide…), l'écran de chargement (100000) et le bandeau de mise à jour
     (100001). Elle reste au-dessus des animations d'action (1999999995/96). En portrait,
     le panneau central occupe presque tout l'écran : la bulle « accueil-choix », qui
     pointe pourtant #campagnes-container À L'INTÉRIEUR de ce panneau, était donc
     invisible — vérifié par elementFromPoint, qui renvoyait .campagne-img.
     Elle reste DÉLIBÉRÉMENT sous les boîtes de dialogue ebsConfirm/ebsAlert
     (2147483647, cf. src/app_modal.js) : celles-ci bloquent l'appli en attendant une
     réponse, et cliquer un scénario en ouvre justement une, sur la page même où cette
     bulle s'affiche. Une bulle par-dessus pourrait en couvrir les boutons.
     La bulle est ajoutée à document.body (src/app_tutorial.js), donc au contexte
     d'empilement racine : cette valeur est bien celle qui s'applique. */
  z-index: 2000000001;
  max-width: 300px;
  background: #ffe066;
  color: #1a1a1a;
  border: 2px solid #e0b000;
  border-radius: 10px;
  padding: 14px 16px 12px;
  box-shadow: 0 6px 22px rgba(0, 0, 0, 0.45);
  font-size: 0.9rem;
  line-height: 1.4;
}
/* 20260808 VCH une bulle centrée est posée en `left: 50%` sans `right` : sa largeur
   disponible n'est que la moitié droite de l'écran, et `max-width` n'y peut rien. Mesuré à
   390 px de large : la bulle d'accueil tombait à 195 px pour 490 px de haut, une colonne.
   Une largeur explicite la remet d'aplomb, en gardant une marge de 16 px de chaque côté sur
   les écrans étroits. */
.tuto-bubble.tuto-centre {
  width: min(360px, calc(100vw - 32px));
  max-width: none;
}

/* 20260817 VCH bulle BORNÉE : quand la place à côté de la cible ne suffit pas, positionnerBulle
   (src/app_tutorial.js) lui impose un max-width / max-height plutôt que de la poser SUR ce
   qu'elle explique. Le titre et les boutons restent visibles, seul le texte défile.
   `min-height: 0` est indispensable : sans lui, un enfant flex ne descend pas sous la hauteur
   de son contenu et la bulle déborderait quand même de son cadre. */
.tuto-bubble.tuto-borne {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  /* Habillage compact : chaque pixel repris à l'habillage est un pixel de texte visible.
     Mesuré en portrait sur « Lire une carte actions » (espace de 162 px au-dessus de la carte
     zoomée) : 64 px de texte visible avant, 98 après. */
  padding: 8px 10px;
  font-size: 0.85rem;
}
.tuto-bubble.tuto-borne .tuto-title { font-size: 0.92rem; margin-bottom: 4px; }
.tuto-bubble.tuto-borne .tuto-actions { margin-top: 6px; }
.tuto-bubble.tuto-borne .tuto-text {
  overflow-y: auto;
  min-height: 0;
  /* La bulle entière est en `touch-action: none` pour pouvoir être déplacée au doigt : il faut
     rendre ici le geste vertical au défilement, sinon le texte coupé est inatteignable sur
     téléphone. `contain` empêche le geste de se propager à la page derrière la bulle. */
  touch-action: pan-y;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  /* Deux liserés : ils disent que le texte est une zone à part, qui continue au-delà du cadre.
     Sur iOS la barre de défilement n'apparaît qu'au geste, rien d'autre ne le signalerait. */
  border-top: 1px solid rgba(0, 0, 0, 0.12);
  border-bottom: 1px solid rgba(0, 0, 0, 0.12);
  padding: 4px 0;
}

.tuto-bubble .tuto-title {
  font-weight: bold;
  font-size: 1rem;
  margin-bottom: 6px;
  /* Plus de gouttière à réserver : le bouton « Désactiver le tutoriel » est en flux,
     au-dessus, et ne recouvre plus rien. */
}
.tuto-bubble .tuto-text p { margin: 0 0 8px; }
.tuto-bubble .tuto-text p:last-child { margin-bottom: 0; }
.tuto-bubble .tuto-text ul { margin: 4px 0 8px; padding-left: 20px; }
.tuto-bubble .tuto-text li { margin: 2px 0; }
.tuto-bubble .tuto-text strong { font-weight: 700; }
.tuto-bubble .tuto-text code {
  background: rgba(0, 0, 0, 0.12);
  padding: 0 4px;
  border-radius: 3px;
  font-size: 0.85em;
}

/* 20260806 VCH la croix « × » est devenue un bouton qui dit ce qu'il fait : il n'a jamais
   fermé la bulle, il éteint le tutoriel. Libellé en toutes lettres, donc discret (petite
   police, contour léger) pour ne pas concurrencer « Suivant ». */
/* 20260808 VCH dans la barre du bas, à gauche, en face de la navigation. Habillage choisi par
   Vincent sur comparaison de neuf variantes rendues dans l'appli : le fond de la bulle
   lui-même, un liseré et des lettres en rouge sombre. Le bouton se réduit ainsi à son contour,
   présent mais sans peser, là où le fond noir à lettres rouges de la version précédente se
   lisait mal. Rouge SOMBRE (#8c2a22) et non l'accent `#b8332a` : sur du jaune, l'accent
   manque de contraste. Plus petit que la navigation (0,62 rem contre 0,85) parce que c'est
   une sortie de route, pas le chemin ordinaire. */
.tuto-bubble .tuto-actions .tuto-close {
  /* `margin-right: auto` pousse la navigation à droite. */
  margin-right: auto;
  background: #ffe066;
  border: 1px solid var(--ebs-accent, #b8332a);
  border-radius: 8px;
  color: #8c2a22;
  font-size: 0.62rem;
  font-weight: 600;
  line-height: 1.2;
  cursor: pointer;
  padding: 3px 8px;
  white-space: nowrap;
  transition: background .15s, color .15s, border-color .15s;
}
.tuto-bubble .tuto-actions .tuto-close:hover {
  background: var(--ebs-accent, #b8332a);
  color: #fff;
}

/* 20260806 VCH la bulle se déplace au doigt comme à la souris (rendreDeplacable,
   src/app_tutorial.js). `touch-action: none` est indispensable : sans lui, le doigt fait
   défiler la page au lieu de déplacer la bulle. */
.tuto-bubble { cursor: grab; touch-action: none; }
.tuto-bubble.tuto-deplacement { cursor: grabbing; user-select: none; }
.tuto-bubble button { cursor: pointer; }
/* Déplacée à la main, la bulle ne pointe plus sa cible : la flèche mentirait. */
.tuto-bubble.tuto-sans-fleche .tuto-arrow { display: none; }

.tuto-bubble .tuto-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 10px;
  /* 20260808 VCH navigation calée à DROITE. Seul `.tuto-count { margin-right: auto }` l'y
     poussait, or le compteur n'existe pas quand la séquence n'a qu'une étape : « Compris ✓ »
     restait alors à gauche (vu par Vincent sur la bulle d'accueil). */
  justify-content: flex-end;
  /* Par prudence sur les écrans très étroits : la ligne se replie plutôt que de déborder. */
  flex-wrap: wrap;
  row-gap: 6px;
}
/* 20260808 VCH en-tête : titre à gauche, rang de l'étape à droite. Alignés sur la ligne de
   base pour que « 1 / 2 » se pose au niveau du titre et non au-dessus. */
.tuto-bubble .tuto-entete {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin-bottom: 6px;
}
.tuto-bubble .tuto-entete .tuto-title { margin-bottom: 0; }
.tuto-bubble .tuto-count {
  font-size: 0.8rem;
  color: #6b5400;
  /* Calé à droite, et jamais rétréci : « 1 / 2 » doit rester lisible en face d'un titre long. */
  margin-left: auto;
  flex: 0 0 auto;
  white-space: nowrap;
}
.tuto-bubble .tuto-actions button {
  background: #1a1a1a;
  color: #ffe066;
  /* 20260808 VCH bordure TRANSPARENTE plutôt que `none` : « Précédent » en porte une, visible,
     et sans cette réserve il mesurait 30 px de haut contre 28 à « Suivant », dépassant d'un
     pixel en haut et en bas. Les deux boutons ont maintenant la même boîte. */
  border: 1px solid transparent;
  border-radius: 6px;
  padding: 5px 12px;
  font-size: 0.85rem;
  cursor: pointer;
}
.tuto-bubble .tuto-actions button:hover { background: #333; }
.tuto-bubble .tuto-actions .tuto-prev {
  background: transparent;
  color: #1a1a1a;
  border-color: #b89000;
}
.tuto-bubble .tuto-actions .tuto-prev:hover { background: rgba(0, 0, 0, 0.08); }

/* Flèche (triangle dépassant de la bulle, selon la position) */
.tuto-bubble .tuto-arrow {
  position: absolute;
  width: 0;
  height: 0;
  border: 10px solid transparent;
}
.tuto-bubble.tuto-pos-bas .tuto-arrow {
  top: -20px;
  left: 50%;
  transform: translateX(-50%);
  border-bottom-color: #ffe066;
}
.tuto-bubble.tuto-pos-haut .tuto-arrow {
  bottom: -20px;
  left: 50%;
  transform: translateX(-50%);
  border-top-color: #ffe066;
}
.tuto-bubble.tuto-pos-gauche .tuto-arrow {
  right: -20px;
  top: 50%;
  transform: translateY(-50%);
  border-left-color: #ffe066;
}
.tuto-bubble.tuto-pos-droite .tuto-arrow {
  left: -20px;
  top: 50%;
  transform: translateY(-50%);
  border-right-color: #ffe066;
}
.tuto-bubble.tuto-centre .tuto-arrow { display: none; }

/* Mise en évidence de l'élément ciblé */
.tuto-highlight {
  outline: 3px solid #ffe066 !important;
  outline-offset: 2px;
  border-radius: 4px;
  box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.04);
}

@media (max-width: 768px) {
  .tuto-bubble { max-width: calc(100vw - 24px); }
}

/* ============================================================================
   REFONTE NAVIGATION / FENÊTRAGE (3 modes) — 20260613 VCH
   Piloté par src/app_nav.js : body[data-mode] = portrait | landscape | desktop.
   portrait  = barre de nav basse, 1 page (½ écran) au-dessus ;
   landscape = rail vertical 6 boutons, docks gauche/droite (½ chacun) ;
   desktop   = rail large 9 boutons, docks empilables (Plateau en haut).
   ========================================================================== */
:root {
  --ebs-chrome: #23211e; --ebs-chrome-edge: #1b1916;
  --ebs-accent: #b8332a; --ebs-accent-hi: #d6473c;
  --ebs-rail-land: 112px; --ebs-rail-desk: 112px; --ebs-navh: 60px;
  --ebs-rail: 0px; --ebs-navh-cur: 0px; --ebs-bh: 0px;
}
/* En portrait, la hauteur réservée en bas inclut la safe-area (barre d'accueil iPhone). */
body[data-mode="portrait"]  { --ebs-rail: 0px;                  --ebs-navh-cur: calc(var(--ebs-navh) + env(safe-area-inset-bottom)); }
body[data-mode="landscape"] { --ebs-rail: var(--ebs-rail-land); --ebs-navh-cur: 0px; }
body[data-mode="desktop"]   { --ebs-rail: var(--ebs-rail-desk); --ebs-navh-cur: 0px; }
/* Quand la page perso est ouverte, les panneaux latéraux s'ajustent à l'espace au-dessus
   d'elle : --ebs-bh = hauteur réelle de la perso (cf. #bottom-panel height plus bas). */
body.perso-open:not(.perso-lateral)[data-mode="landscape"],
body.perso-open:not(.perso-lateral)[data-mode="desktop"] { --ebs-bh: max(50%, 526px); }
body.perso-open.perso-compact:not(.perso-lateral)[data-mode="landscape"],
body.perso-open.perso-compact:not(.perso-lateral)[data-mode="desktop"] { --ebs-bh: 280px; }

/* Zone de jeu : le canvas évite le rail (gauche) et la barre basse (portrait). */
body[data-mode] #explo-container,
body[data-mode] #plan-game {
  margin-left: var(--ebs-rail);
  margin-bottom: var(--ebs-navh-cur);
}

/* ── Barre de navigation ── */
#game-nav {
  position: absolute; z-index: 60; background: var(--ebs-chrome);
  display: flex; gap: 4px; box-sizing: border-box;
}
#game-nav::-webkit-scrollbar { display: none; }
body[data-mode="portrait"] #game-nav {
  left: 0; right: 0; bottom: 0;
  height: calc(var(--ebs-navh) + env(safe-area-inset-bottom));
  flex-direction: row; align-items: stretch;
  padding: 6px 6px env(safe-area-inset-bottom);
  border-top: 1px solid var(--ebs-chrome-edge);
}
body[data-mode="landscape"] #game-nav,
body[data-mode="desktop"] #game-nav {
  /* Rail à gauche, SOUS l'en-tête (qui reste pleine largeur en haut). position
     absolute (héritée) dans #game-area, donc occupe la hauteur de la zone de jeu. */
  left: 0; top: 0; bottom: 0;
  flex-direction: column; align-items: center;
  padding: 8px 6px;
  overflow-y: auto; border-right: 1px solid var(--ebs-chrome-edge);
}
body[data-mode="landscape"] #game-nav { width: var(--ebs-rail-land); }
body[data-mode="desktop"]   #game-nav { width: var(--ebs-rail-desk); }

/* Boutons */
.navbtn {
  position: relative; border: 0; background: transparent; color: #9b9486;
  border-radius: 10px; cursor: pointer; min-width: 0; overflow: hidden;
  /* CAUSE RACINE iOS : un <button> a une apparence native qui lui fait ignorer
     width/flex/align-items (d'où les libellés tronqués qui ne touchaient que les
     <button>, pas les <div>). appearance:none rétablit un comportement normal. */
  -webkit-appearance: none;
  appearance: none;
}
#game-nav button { -webkit-appearance: none; appearance: none; }
/* Mise en page interne en BLOCK (pas flex) : iOS Safari gère mal <button> comme
   conteneur flex (icône/libellé non centrés). block + text-align:center est fiable. */
button.navbtn {
  display: block; text-align: center;
  font-size: 10.5px; line-height: 1.12; padding: 6px 3px;
}
button.navbtn svg { width: 21px; height: 21px; display: block; margin: 0 auto 3px; }
/* Libellé : block pleine largeur + retour à la ligne normal. On évite
   display:-webkit-box / -webkit-line-clamp qui, sur iOS Safari, réduisent la
   largeur du libellé (texte coupé à quelques lettres). */
.navbtn .lbl {
  display: block; width: 100%; box-sizing: border-box; max-width: 100%;
  text-align: center; white-space: normal; overflow-wrap: break-word; word-break: break-word;
  line-height: 1.1;
}
.navbtn[data-active="true"] { color: #fff; background: rgba(184,51,42,.22); }
.navbtn[data-active="true"] svg { color: var(--ebs-accent-hi); }
.cbadge {
  width: 24px; height: 24px; border-radius: 50%; background: var(--ebs-accent);
  color: #fff; display: grid; place-items: center; font-size: 12px; font-weight: 700;
}
body[data-mode="portrait"] .navbtn { flex: 1 1 0; }
body[data-mode="landscape"] .navbtn,
body[data-mode="desktop"] .navbtn {
  flex: none;
  /* iOS Safari : ni align-items:stretch ni width:100% ne forcent la largeur des
     boutons (ils restent à la largeur de l'icône). On impose une largeur EXPLICITE
     en pixels (largeur du rail moins son padding) → fiable partout. */
  width: calc(var(--ebs-rail) - 14px);
  box-sizing: border-box;
}
/* Même cause pour le libellé : width:100% ne se résout pas dans un <button> sur iOS.
   On lui donne une largeur explicite en px → il est contraint et revient à la ligne
   (ex. « Deirdre » / « 5/5 ») au lieu d'être coupé. */
body[data-mode="landscape"] .navbtn .lbl,
body[data-mode="desktop"] .navbtn .lbl {
  width: calc(var(--ebs-rail) - 18px);
  max-width: calc(var(--ebs-rail) - 18px);
  margin-left: auto; margin-right: auto;
}
/* 20260808 VCH .navbtn.center-top/.center-bottom supprimées : posées seulement par l'ancienne
   branche 'split' du rail (boutons ‹/› de côté, réécrite par ce chantier), navModel ne les a
   jamais renseignées et plus aucun JS/HTML ne pose ces classes (vérifié). */
/* Ancre le bloc personnages en bas : les pages occupent le haut, l'espace libre
   se place entre les deux → toute la hauteur du rail est utilisée. */
body[data-mode="landscape"] .navbtn.push-bottom,
body[data-mode="desktop"] .navbtn.push-bottom { margin-top: auto; }
/* 20260809 VCH séparation des trois groupes du rail : les deux pages du dock droit, les deux
   du dock gauche, puis la fenêtre centrale (classe posée par buildNav, src/app_nav.js, d'après
   PAGES_LATERALES). Par l'ESPACE, pas par un trait : les boutons ont déjà un fond et une
   bordure — rouge quand la page est ouverte — et un filet entre deux boutons encadrés se perd
   (maquetté et comparé dans l'appli avant de choisir).
   ⚠️ Desktop UNIQUEMENT. En paysage le rail est plein à ras bord : mesuré en 844×390, 347 px de
   contenu pour 347 px de hauteur utile. Toute séparation d'au moins 8 px le fait déborder, donc
   défiler, et des boutons passent sous la ligne de flottaison ; les 6 px qui tiendraient encore
   ne se voient pas. Le portrait, lui, n'est pas concerné : rail horizontal en bas, avec sa
   propre liste (3 boutons + « Autre »). */
body[data-mode="desktop"] .navbtn.nav-groupe-debut { margin-top: 16px; }
/* En-tête « Personnages » du rail desktop : décoratif, non cliquable */
.nav-charhead { cursor: default; color: #6f6a60; }
.nav-charhead:hover, .nav-charhead:active { background: transparent; }
/* Rail desktop étroit (100px) : boutons verticaux, libellé sur 2 lignes. */
body[data-mode="desktop"] button.navbtn { padding: 8px 4px; font-size: 11px; }

/* Bouton perso « 3 voies » : icône/nom au-dessus, rangée ‹ V › (gauche/bas/droite) */
.navbtn.char3 { display: flex; flex-direction: column; align-items: stretch; gap: 1px; padding: 4px 0; font-size: 11px; }
.navbtn.char3 .hit {
  border: 0; background: transparent; cursor: pointer; color: #6f6a5e;
  border-radius: 4px; line-height: 1; -webkit-appearance: none; appearance: none;
}
.navbtn.char3 .hit:hover { background: rgba(184,51,42,.18); color: #fff; }
/* Ligne haute : nom/PV (overlay, non cliquable) + 2 demi-zones ‹/› cliquables.
   min-height pour une zone cliquable confortable ; 20260808 VCH ce bouton perso est désormais
   le SEUL du rail à garder des demi-zones ‹/›, celles de 'split' (PAGES_RAIL) ayant disparu
   avec le passage au clic simple. */
.navbtn.char3 .h3top { position: relative; display: flex; align-items: center; justify-content: center; min-height: 34px; }
.navbtn.char3 .visual {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 1px; pointer-events: none; padding: 1px 15px;   /* marge pour ne pas chevaucher ‹/› */
}
.navbtn.char3 .visual svg { width: 20px; height: 20px; display: block; }
.navbtn.char3 .visual .lbl { width: auto; max-width: 100%; display: block; text-align: center; line-height: 1.1; white-space: normal; overflow-wrap: break-word; }
.navbtn.char3 .visual .pv { font-size: 0.9em; opacity: 0.85; }
.navbtn.char3 .h3top .hit {
  position: absolute; top: 0; bottom: 0; width: 50%;     /* chaque demi-zone cliquable en entier */
  display: flex; align-items: center; font-size: 15px;
}
.navbtn.char3 .h3top .hit.hl { left: 0;  justify-content: flex-start; padding-left: 4px; }
.navbtn.char3 .h3top .hit.hr { right: 0; justify-content: flex-end;   padding-right: 4px; }
/* « v » (placement bas) en dessous, plus petit, pleine largeur cliquable */
.navbtn.char3 .hit.hb { display: block; width: 100%; font-size: 11px; padding: 1px 0; }
.navbtn.char3.on-l .h3top .hit.hl,
.navbtn.char3.on-b .hit.hb,
.navbtn.char3.on-r .h3top .hit.hr { background: rgba(184,51,42,.30); color: #fff; }

/* Menu déroulant (popover) */
.game-menu {
  position: absolute; z-index: 80; background: var(--ebs-chrome); color: #e8e3d8;
  border-radius: 12px; padding: 8px; box-shadow: 0 10px 30px rgba(0,0,0,.4);
  display: none; min-width: 200px;
}
.game-menu.show { display: block; }
.game-menu button {
  display: block; width: 100%; text-align: left; border: 0; background: transparent;
  color: #e3ddd0; cursor: pointer; min-height: 44px; padding: 0 12px; border-radius: 8px; font-size: 15px;
}
.game-menu button:hover { background: rgba(255,255,255,.1); }

/* ── Docks (panneaux latéraux) : positionnement déterministe par mode ── */
body[data-mode] #left-panel,
body[data-mode] #right-panel {
  transform: none !important; transition: none; height: auto;
  display: none; flex-direction: column; gap: 6px; width: auto;
}
body[data-mode] #left-panel.open,
body[data-mode] #right-panel.open { display: flex; }

body[data-mode="landscape"] #left-panel,
body[data-mode="desktop"] #left-panel {
  position: absolute; top: 0; bottom: var(--ebs-bh); left: var(--ebs-rail); right: auto;
  width: min(46%, 480px);
}
body[data-mode="landscape"] #right-panel,
body[data-mode="desktop"] #right-panel {
  position: absolute; top: 0; bottom: var(--ebs-bh); right: 0; left: auto;
  width: min(46%, 480px);
}
body[data-mode="portrait"] #left-panel {
  position: absolute; left: 0; right: 0; top: auto; bottom: var(--ebs-navh-cur);
  height: 50%; width: auto;
}
/* Plateau (hauteur de contenu) : le panneau se réduit à son contenu et se colle
   aux boutons du bas (pas de vide entre le plateau et la barre de navigation). */
body[data-mode="portrait"] #left-panel:has(> .left-sub-panel[data-sub-page="plateau"].open) {
  height: auto;
}
body[data-mode="portrait"] #right-panel { display: none !important; }

/* En empilement (desktop : 2/côté), chaque sous-panneau ouvert partage la hauteur. */
body[data-mode] #left-panel > .left-sub-panel.open,
body[data-mode] #right-panel > .left-sub-panel.open { flex: 1 1 0; min-height: 0; }

/* Le plateau d'avancement n'occupe que la hauteur de son contenu (pas d'étirement) */
body[data-mode] #left-panel  > .left-sub-panel[data-sub-page="plateau"].open,
body[data-mode] #right-panel > .left-sub-panel[data-sub-page="plateau"].open {
  flex: 0 0 auto;
}

/* ── Page personnage (dock bas) ── */
body[data-mode="landscape"] #bottom-panel,
body[data-mode="desktop"] #bottom-panel { left: var(--ebs-rail); right: 0; bottom: 0; height: max(50%, 526px); }
/* Portrait : la perso prend toute la hauteur disponible (sous l'en-tête, au-dessus de la
   barre de navigation). top:0 = haut de la zone de jeu (déjà sous le header). */
body[data-mode="portrait"] #bottom-panel { left: 0; right: 0; top: 0; bottom: var(--ebs-navh-cur); height: auto; }
/* 20260804 VCH FERMÉ, le panneau doit sortir de l'écran EN ENTIER. `translateY(100%)` le décale de
   sa propre hauteur, or sa boîte s'arrête au-dessus de la barre de navigation (bottom: navh) : il
   se reposait donc exactement dessus, et il ne restait caché que par l'ordre d'empilement. Il a
   suffi que le rang d'un panneau dépasse le palier CSS de la barre (60) pour qu'un « reste de page
   perso » recouvre les boutons du bas — défaut signalé par Vincent depuis son téléphone. On ajoute
   la hauteur de la barre au décalage : le panneau fermé est hors écran quel que soit son rang.
   Ceinture de sécurité : la cause racine (compteur de z-index non borné) est corrigée dans app.js.
   Le +2px absorbe l'arrondi sous-pixel : la hauteur de la boîte est fractionnaire, donc le seul
   `translateY(100% + navh)` laissait un liseré d'un pixel sur la barre (mesuré : 843 contre 844).
   Verrouillé par tests/e2e/28-z-index-panneaux.spec.js. */
body[data-mode="portrait"] #bottom-panel:not(.open) {
  transform: translateY(calc(100% + var(--ebs-navh-cur) + 2px));
}
/* Le zoom compact 50 % reste prioritaire sur la hauteur de mode (sauf en portrait : plein écran). */
body[data-mode] #bottom-panel.compact { height: 280px; }
body[data-mode="portrait"] #bottom-panel.compact { height: auto; }
body[data-mode="portrait"] #bottom-panel.compact .bottom-panel-content { zoom: 1; }
/* Bouton zoom (⤓ réduire 50%) inutile en portrait (perso plein écran). */
body[data-mode="portrait"] .bottom-panel-zoom { display: none; }

/* Écran COURT = téléphone en paysage (≤ ~600px de haut). L'iPhone en paysage fait
   ≥900px de large → il est classé "desktop" (pas "landscape"), d'où un ciblage sur la
   HAUTEUR et non le mode. Le grand format de la perso (526px) n'y tient pas → affichage
   réduit FORCÉ (panneau 280px + contenu à 50%), bouton ⤓ masqué. Placé APRÈS la règle de
   hauteur du #bottom-panel pour l'emporter ; exclut le portrait (un petit téléphone en
   portrait peut faire ≤600px de haut mais doit rester en plein écran). */
@media (max-height: 600px) {
  body[data-mode="landscape"] #bottom-panel,
  body[data-mode="desktop"]   #bottom-panel { height: 280px; }
  body[data-mode="landscape"] #bottom-panel .bottom-panel-content,
  body[data-mode="desktop"]   #bottom-panel .bottom-panel-content { zoom: 0.5; }
  body[data-mode="landscape"] #bottom-panel .bottom-panel-content .perso-zoom-modal,
  body[data-mode="landscape"] #bottom-panel .bottom-panel-content .perso-perdues-modal,
  body[data-mode="desktop"]   #bottom-panel .bottom-panel-content .perso-zoom-modal,
  body[data-mode="desktop"]   #bottom-panel .bottom-panel-content .perso-perdues-modal { zoom: 2; }
  body[data-mode="landscape"] .bottom-panel-zoom,
  body[data-mode="desktop"]   .bottom-panel-zoom { display: none; }
  /* iOS Safari ne réduit pas le texte en rem avec le zoom (contrairement aux cartes,
     en cqw, qui scalent bien) → le tableau d'intensité paraît trop gros. On réduit donc
     explicitement sa police dans l'affichage réduit. (valeurs à ajuster au besoin) */
  body:is([data-mode="landscape"],[data-mode="desktop"]) #bottom-panel .tp-cell { font-size: 0.34rem; line-height: 1.05; }
  body:is([data-mode="landscape"],[data-mode="desktop"]) #bottom-panel .tp-cell.tp-header { font-size: 0.36rem; }
  body:is([data-mode="landscape"],[data-mode="desktop"]) #bottom-panel .tp-cell.tp-label  { font-size: 0.34rem; }
  body:is([data-mode="landscape"],[data-mode="desktop"]) #bottom-panel .tp-cell.tp-header:is(.tp-int-0,.tp-int-1,.tp-int-2,.tp-int-3) { font-size: 0.4rem; }
}

/* ── Page perso en affichage latéral (gauche/droite) ──────────────────────────
   Le #bottom-panel est repositionné comme un panneau latéral (même largeur que les
   autres pages) ; les zones 1+3 passent côte à côte au-dessus de la rivière (zone 2). */
body[data-mode="landscape"] #bottom-panel.perso-dock-left,
body[data-mode="desktop"]   #bottom-panel.perso-dock-left {
  left: var(--ebs-rail); right: auto; top: 0; bottom: 0;
  width: min(46%, 480px); height: auto;
  transform: none;
}
body[data-mode="landscape"] #bottom-panel.perso-dock-right,
body[data-mode="desktop"]   #bottom-panel.perso-dock-right {
  right: 0; left: auto; top: 0; bottom: 0;
  width: min(46%, 480px); height: auto;
  transform: none;
}
/* En latéral, le bouton « réduire 50 % » n'a pas de sens (pas de hauteur fixe) */
#bottom-panel.perso-dock-left .bottom-panel-zoom,
#bottom-panel.perso-dock-right .bottom-panel-zoom { display: none; }

/* Sous-groupes de la zone droite : transparents par défaut (bas de fenêtre) → les
   enfants (PV, perdue, carac, rivière, carte test) s'empilent dans la colonne flex
   .perso-test-zone exactement comme avant. En latéral, ils redeviennent des boîtes. */
.perso-pv-group, .perso-test-card-zone { display: contents; }

/* Reflow latéral : bloc HAUT [zone PV | carte Test] repliable, cartes pleine largeur
   (2 par rangée) dessous, rivière inchangée tout en bas.
   Clé sur body.perso-lateral (posée de façon synchrone, indépendante du rendu async). */
body.perso-lateral .perso-layout {
  display: grid;
  grid-template-columns: 1fr 1fr;
  /* ZONE 1 (haut) : bloc PV/Test à la hauteur de son contenu, repliable (▲).
     ZONE 2 (milieu) : zone cartes — S'ÉTIRE sur la place restante (1fr), défilable.
     ZONE 3 (bas) : rivière à la hauteur de son contenu, collée en bas. */
  grid-template-rows: auto minmax(0, 1fr) auto;
  grid-template-areas:
    "z-pv     z-test"
    "z-cards  z-cards"
    "z-riv    z-riv";
  align-items: stretch;   /* surcharge le flex-start portrait : les zones se calent dans leur cellule */
  overflow: hidden;
}
/* La colonne droite devient transparente : ses 2 sous-groupes prennent place dans la grille. */
body.perso-lateral .perso-test-zone { display: contents; }
body.perso-lateral .perso-pv-group {
  grid-area: z-pv; min-width: 0; min-height: 0; overflow-y: auto;
  display: flex; flex-direction: column; gap: 6px;
}
body.perso-lateral .perso-test-card-zone { grid-area: z-test; display: block; min-width: 0; min-height: 0; overflow-y: auto; }
/* Centre la carte Test dans sa cellule (la carte est plus étroite que la demi-largeur). */
body.perso-lateral .perso-test-card-zone .carte-container { margin-left: auto; margin-right: auto; }
body.perso-lateral .perso-cartes-zone { grid-area: z-cards; min-width: 0; min-height: 0; overflow-y: auto; border-right: 0; }
/* ZONE 2 : en-tête d'ajout (champ n° + Ajouter + Butin) à hauteur fixe, collé en haut
   de la zone et toujours visible pendant que les cartes défilent en dessous. */
body.perso-lateral .perso-add-bar { position: sticky; top: 0; z-index: 2; background: #fff; }
body.perso-lateral .perso-plateau {
  grid-area: z-riv;
  width: 100%; height: 100%; min-height: 0;
  grid-template-columns: 40px repeat(4, 1fr);   /* tient dans la largeur (pas de scroll X) */
  grid-template-rows: repeat(7, auto);           /* rangées à la hauteur du contenu */
  align-content: start;                          /* PAS d'étirement des rangées (sinon lignes géantes) */
  overflow-x: hidden; overflow-y: auto;          /* la rivière défile verticalement si besoin */
  border-left: 0;
}
/* Cartes à 3 par rangée (liste seule, pas la barre d'ajout ni l'encart petit format) :
   chaque carte remplit sa colonne (≈10 % plus petite que les 2/rangée → 3 tiennent pile). */
body.perso-lateral .perso-cartes-list { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; align-content: start; }
body.perso-lateral .perso-carte-wrapper { width: auto; }
/* Bloc du haut replié : on masque les 2 sous-groupes ; leurs rangées « auto » retombent
   à 0 → les cartes occupent l'espace libéré. */
body.perso-lateral.perso-top-collapsed .perso-pv-group,
body.perso-lateral.perso-top-collapsed .perso-test-card-zone { display: none; }
/* Cellules d'action plus compactes en latéral (texte plus petit → lignes moins hautes) */
body.perso-lateral .tp-cell { font-size: 0.5rem; padding: 1px 2px; }
body.perso-lateral .tp-cell.tp-header { font-size: 0.52rem; }
body.perso-lateral .tp-cell.tp-header.tp-int-0,
body.perso-lateral .tp-cell.tp-header.tp-int-1,
body.perso-lateral .tp-cell.tp-header.tp-int-2,
body.perso-lateral .tp-cell.tp-header.tp-int-3 { font-size: 0.58rem; }
/* Hauteurs des zones de cartes proportionnelles à la largeur (colonnes étroites) via
   aspect-ratio : elles gardent les proportions d'origine (action 174/244, petit format
   174/124) mais à l'échelle des colonnes latérales → bonne hauteur de carte, sans vide.
   overflow:visible sur la tuile pour que la rangée prenne sa vraie hauteur. */
body.perso-lateral .tuile-intensite { overflow: visible; }
body.perso-lateral .ti-zone-action { height: auto; min-height: 0; aspect-ratio: 174 / 244; }
body.perso-lateral .ti-zone-pf     { height: auto; min-height: 0; aspect-ratio: 174 / 124; }
body.perso-lateral .river-arrow { display: none; }   /* positions fixes (244/368px) obsolètes ici */

/* ── Zoom d'une carte en dock latéral (paysage/desktop) : plein écran ──────────
   En dock latéral, le #bottom-panel ne fait que ~46 % de large : le modal de zoom y
   était confiné (carte tronquée, cf. capture). On veut un vrai plein écran.
   PROBLÈME iOS : position:fixed ne s'échappe PAS d'un ancêtre zoomé (.bottom-panel-content
   a zoom:0.5 en paysage sur écran court) ou transformé — Safari le confine/mal-positionne
   (Chromium, lui, l'échappe, d'où des tests trompeurs). MÊME constat que enterPanelFullscreen
   dans app.js. SOLUTION : en dock latéral, le JS (app_personnage.openZoom) DÉTACHE le modal
   vers <body> et lui ajoute .perso-zoom-detached → plus aucun ancêtre zoomé/transformé, le
   position:fixed couvre alors réellement le viewport, et le modal n'hérite plus du zoom.
   NB : on ne fait ça qu'en dock latéral (paysage/desktop) ; en PORTRAIT le panneau est déjà
   plein écran et la carte garde une taille modérée (cf. retour utilisateur).
   top = hauteur du header (--ebs-header-h, posée en JS) pour laisser le header visible et la
   barre d'outils ↻/⇄ + la croix accessibles. Carte dimensionnée par la HAUTEUR (au lieu d'une
   largeur fixe de 300px) ; cap à 620px pour le desktop. */
.perso-zoom-modal.perso-zoom-detached.open {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  top: var(--ebs-header-h, 52px);
}
.perso-zoom-detached .perso-zoom-inner { max-height: 100%; max-width: 96%; }
.perso-zoom-detached .perso-zoom-content {
  max-height: none; max-width: none; overflow: visible; display: flex;
}
.perso-zoom-detached .perso-zoom-content .carte-container.carte-ratio,
.perso-zoom-detached .perso-zoom-content .carte-dos {
  width: auto;
  height: min(calc(100vh - var(--ebs-header-h, 52px) - 42px), 620px);
}
/* La croix de fermeture ne doit pas déborder vers le haut (sinon masquée par le header). */
.perso-zoom-detached .perso-zoom-close { top: 2px; right: 2px; }

/* Mobile (layout en bas / flex uniquement, PAS en latéral) : la page perso défile aussi
   verticalement quand la rivière dépasse la hauteur (en plus du glissement horizontal). */
body[data-mode="portrait"]:not(.perso-lateral)  .perso-layout,
body[data-mode="landscape"]:not(.perso-lateral) .perso-layout {
  overflow-y: auto;            /* scroll vertical en plus de l'horizontal (2D) */
  align-items: flex-start;     /* ne pas étirer les colonnes : chacune garde sa hauteur */
}
body[data-mode="portrait"]:not(.perso-lateral)  .perso-plateau,
body[data-mode="landscape"]:not(.perso-lateral) .perso-plateau {
  height: auto;                /* hauteur naturelle (en-tête + rivière) → déborde → défilable */
}

/* ── Bouton plein écran (réutilise .side-panel-fs) : mobile uniquement (portrait/landscape) ── */
body[data-mode="portrait"] .side-panel-fs,
body[data-mode="landscape"] .side-panel-fs {
  display: inline-flex; align-items: center; justify-content: center;
  margin-left: 0; background: none; border: none; cursor: pointer; color: #ddd;
  padding: 0 4px; line-height: 1;
}
body[data-mode="desktop"] .side-panel-fs { display: none !important; }
body[data-mode] .side-panel-fs .fs-icon {
  display: block; width: 15px; height: 12px; border: 2px solid currentColor; border-radius: 2px;
}
body[data-mode] .left-sub-panel.panel-fullscreen .side-panel-fs .fs-icon {
  height: 2px; border-radius: 0;
}

/* ── Divers ── */
body[data-mode="portrait"] .center-panel { width: 96%; }
#portrait-warning { display: none !important; }
/* Bouton plein écran de l'en-tête inutile sur mobile (le plein écran natif n'existe
   pas sur iPhone Safari). Masqué en portrait via la largeur ET en paysage via la
   hauteur faible (un téléphone couché fait > 768px de large mais < 500px de haut ;
   un iPad garde une dimension >= 768px dans les deux sens, donc reste non masqué). */
@media (max-width: 768px), (max-height: 500px) { #toggle-fullscreen { display: none !important; } }

/* ── Cibles tactiles ≥ 40px sur mobile (portrait/paysage) ──────────────────────
   Sur mobile, les petits contrôles (steppers du plateau, slots de pions, boutons
   « + Pion ») sont agrandis pour rester confortablement tactiles. */
/* Boutons − / + du compteur Y réduits sur mobile pour que les 4 compteurs tiennent
   sur une seule ligne (cf. .compteurs-section ci-dessous). */
body[data-mode="portrait"]  .btn-y,
body[data-mode="landscape"] .btn-y {
  width: 26px;
  height: 26px;
  min-width: 26px;
  min-height: 26px;
  font-size: 0.9rem;
}
/* Portrait (téléphone) : les 4 compteurs (mode · interaction · compteur Y · portée
   de menace) tiennent sur une seule ligne, grâce aux boutons − / + réduits ci-dessus. */
body[data-mode="portrait"] .compteurs-section {
  grid-template-columns: repeat(4, 1fr);
  gap: 0.25rem;
}
/* Paysage : panneau en dock latéral étroit → 2 colonnes (une seule ligne déborderait). */
body[data-mode="landscape"] .compteurs-section {
  grid-template-columns: repeat(2, 1fr);
  row-gap: 0.5rem;
}
body[data-mode="portrait"]  .tour-slot,
body[data-mode="landscape"] .tour-slot,
body[data-mode="portrait"]  .btn-tour-action,
body[data-mode="landscape"] .btn-tour-action {
  min-width: 40px;
  min-height: 40px;
}
body[data-mode="portrait"]  .perso-add-btn,
body[data-mode="landscape"] .perso-add-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 28px;
  padding: 3px 10px;
}


/* ═══════════════════════════════════════════════════════════════════════════
   POLICES AUTO-HÉBERGÉES (subset latin) — VCH 20260726
   Remplacent les <link> Google Fonts (offline-first + RGPD). ═══════════════ */
@font-face{font-family:'Cinzel';font-style:normal;font-weight:600;font-display:swap;src:url('/src/fonts/cinzel-600.woff2') format('woff2');}
@font-face{font-family:'Cinzel';font-style:normal;font-weight:700;font-display:swap;src:url('/src/fonts/cinzel-700.woff2') format('woff2');}
@font-face{font-family:'Spectral';font-style:normal;font-weight:400;font-display:swap;src:url('/src/fonts/spectral-400.woff2') format('woff2');}
@font-face{font-family:'Spectral';font-style:italic;font-weight:400;font-display:swap;src:url('/src/fonts/spectral-400i.woff2') format('woff2');}
@font-face{font-family:'Inter';font-style:normal;font-weight:400;font-display:swap;src:url('/src/fonts/inter-400.woff2') format('woff2');}
@font-face{font-family:'Inter';font-style:normal;font-weight:500;font-display:swap;src:url('/src/fonts/inter-500.woff2') format('woff2');}
@font-face{font-family:'Inter';font-style:normal;font-weight:600;font-display:swap;src:url('/src/fonts/inter-600.woff2') format('woff2');}
@font-face{font-family:'Inter';font-style:normal;font-weight:700;font-display:swap;src:url('/src/fonts/inter-700.woff2') format('woff2');}
@font-face{font-family:'Caveat';font-style:normal;font-weight:400 700;font-display:swap;src:url('/src/fonts/caveat-var.woff2') format('woff2');}
@font-face{font-family:'Courier Prime';font-style:normal;font-weight:400;font-display:swap;src:url('/src/fonts/courierprime-400.woff2') format('woff2');}
@font-face{font-family:'Courier Prime';font-style:normal;font-weight:700;font-display:swap;src:url('/src/fonts/courierprime-700.woff2') format('woff2');}
@font-face{font-family:'Courier Prime';font-style:italic;font-weight:400;font-display:swap;src:url('/src/fonts/courierprime-400i.woff2') format('woff2');}
@font-face{font-family:'Courier Prime';font-style:italic;font-weight:700;font-display:swap;src:url('/src/fonts/courierprime-700i.woff2') format('woff2');}

/* ═══════════════════════════════════════════════════════════════════════════
   REFONTE DARK MODE « Parchemin & Sang » — fusionnée depuis
   refonte-ecran-principal.css (20260726). Placée en fin de fichier : l'ordre
   source préserve les surcharges. ═══════════════════════════════════════════ */
/* ============================================================
   REFONTE ÉCRAN PRINCIPAL — dark « Parchemin & Sang »
   Fichier ADDITIF chargé APRÈS styles.css : surcharge sans
   réécrire l'existant. Retirer le <link> = retour à l'état
   d'origine. À fusionner dans styles.css une fois validé.
   VCH 20260725 — refonte graphique dark mode (écran principal).

   Principe : le dark n'habille QUE le châssis (interface).
   Le matériel (cartes/pions) et le LIVRE (page imprimable)
   restent clairs.
   ============================================================ */

/* ---- Tokens (préfixe --r- pour ne pas heurter les --ebs-*) ---- */
:root{
  --r-bg:#16130E; --r-surface1:#1F1B14; --r-surface2:#29241B; --r-surface3:#342E22;
  --r-border:#423A2B; --r-border-hi:#5A4F3A;
  --r-text:#ECE3D0; --r-text2:#AC9F86; --r-text3:#746A56;
  --r-accent:#C0392B; --r-accent-hi:#D94A3B; --r-gold:#D4A24C; --r-gold-hi:#E8BC63;
  --r-ok:#7DA85F;
  --r-paper:#FAF6EC; --r-paper-ink:#24211C;
}

/* ============ Item 1 — châssis dark ============ */
body{ background:var(--r-bg); }
/* barre d'exploration + bandeaux d'en-tête de panneaux : surfaces sombres */
.explo-toolbar{ background:var(--r-surface1); border-color:var(--r-border); }

/* ============ Item 3 — en-tête (+ hauteur réduite) ============ */
.page-wrapper header{
  background:var(--r-surface1); border-bottom:1px solid var(--r-border-hi);
  /* hauteur réduite — on conserve la safe-area iOS en haut */
  padding-top:max(4px, env(safe-area-inset-top)); padding-bottom:5px;
}
#app-title{ font-family:"Cinzel",Georgia,serif; color:var(--r-gold); font-weight:600; letter-spacing:.03em; }
#app-title:hover{ color:var(--r-gold-hi); }

/* ============ Item 4 — compteurs dans UNE pastille : R1 I0 Y0 M0 ============ */
#header-rounds{
  display:inline-flex; align-items:center; gap:9px;
  background:var(--r-surface2); border:1px solid var(--r-border);
  border-radius:999px; padding:6px 15px;
}
/* masque les séparateurs « - » (spans à opacity) → espace via gap */
#header-rounds span[style*="opacity"]{ display:none; }
.round-header-label{ font-family:"Inter",system-ui,sans-serif; font-weight:700; color:var(--r-text); letter-spacing:.02em; }

/* ============ Item 5 — dés dans un encadré (comme les autres boutons) + séparés ============ */
.header-des{ display:flex; align-items:center; gap:14px; }
/* TOUS les boutons de l'en-tête ont le même encadré (dés inclus) */
.btn-d6, #toggle-audio, #toggle-fullscreen, #burger{
  background:var(--r-surface2); border:1px solid var(--r-border); border-radius:8px;
  width:34px; height:34px; min-width:34px; padding:0; color:var(--r-text2);
  font-size:1rem; cursor:pointer; display:inline-flex; align-items:center; justify-content:center;
}
.btn-d6:hover, #toggle-audio:hover, #toggle-fullscreen:hover, #burger:hover{
  background:var(--r-surface3); color:var(--r-text); border-color:var(--r-border-hi); opacity:1;
}
.btn-de-img{ width:22px; height:22px; }
.header-btns-group{ gap:6px; }

/* icône plein écran = rectangle CSS (identique au bouton « agrandir » des panneaux .fs-icon)
   rectangle = passer en plein écran · trait = revenir à la normale */
#toggle-fullscreen .fs-icon-hdr{ display:block; width:15px; height:12px; border:2px solid currentColor; border-radius:2px; }
#toggle-fullscreen.is-fs .fs-icon-hdr{ height:0; width:15px; border-width:2px 0 0 0; border-radius:0; }

/* ============ Item 6 — rail : onglet actif liseré rouge (icônes inchangées) ============ */
#game-nav{ background:var(--r-surface1); }
.navbtn[data-active="true"]{ background:rgba(192,57,43,.20); }
body[data-mode="landscape"] .navbtn[data-active="true"],
body[data-mode="desktop"]   .navbtn[data-active="true"]{ box-shadow:inset 3px 0 0 var(--r-accent); }
/* ============ Item 7 — tab bar mobile : liseré haut (icônes inchangées) ============ */
body[data-mode="portrait"] .navbtn[data-active="true"]{ box-shadow:inset 0 3px 0 var(--r-accent); }

/* ============ Item 6b — rail : boutons encadrés (tuiles, cohérence appli) ============ */
.navbtn{ background:var(--r-surface2); border:1px solid var(--r-border); color:var(--r-text2); }
.navbtn:hover{ border-color:var(--r-border-hi); color:var(--r-text); }
/* Actif : liseré rouge + cadre accentué (les fonds/box-shadow d'accent sont posés plus haut) */
.navbtn[data-active="true"]{ border-color:var(--r-accent); }
.navbtn.char3.on-l, .navbtn.char3.on-b, .navbtn.char3.on-r{ border-color:var(--r-accent); }
/* En-tête décoratif « Personnages » : titre, pas un bouton → aucun cadre */
.navbtn.nav-charhead,
.navbtn.nav-charhead:hover{ background:transparent; border-color:transparent; color:var(--r-text3); }

/* ============ Item 8 — LIVRE & LIVRET = page blanc cassé (imprimable) ============ */
.left-sub-panel:has(#livre-container),
.left-sub-panel:has(#livre-perso-container){ background:var(--r-paper); }
@media print{
  .left-sub-panel:has(#livre-container),
  .left-sub-panel:has(#livre-perso-container){ background:#ffffff; }
}

/* ============ Item 9 — polices des classes texte-* ============
   ⚠ SCOPÉ au LIVRE (#livre-container) : ces classes servent AUSSI au texte
   imprimé sur les cartes (.carte-zone) = matériel à ne PAS altérer. */
:is(#livre-container, #livre-perso-container) .texte-titre{ font-family:"Cinzel",Georgia,serif; font-weight:600; font-size:1.35em; line-height:1.2; display:block; color:#2a2016; }
:is(#livre-container, #livre-perso-container) .texte-normal{ font-family:"Inter",system-ui,sans-serif; }
:is(#livre-container, #livre-perso-container) .texte-narration{ font-family:"Spectral",Georgia,serif; font-style:italic; }
/* .texte-dialogue (Caveat) et .texte-largeur-fixe (Courier Prime) : inchangées */

/* ============ Item 11 — pastilles de référence : couleurs (forme conservée) ============ */
/* forme d'origine (radius 5px, padding 2px 5px) NON modifiée — on ne touche qu'aux couleurs */
.bouton-paragraphe-suivant{ background:rgba(212,162,76,.16); border:1px solid rgba(212,162,76,.55); color:#8a5a12; }
.bouton-paragraphe-suivant:hover{ background:rgba(212,162,76,.28); }
.bouton-paragraphe-suivant.ref-perso{ background:rgba(91,141,176,.16); border-color:rgba(91,141,176,.55); color:#2f6a92; }
.bouton-paragraphe-suivant.ref-perso:hover{ background:rgba(91,141,176,.28); }

/* ============ Item 12 — fond central : bureau sombre chaud ============ */
#game-area{ background:var(--r-bg); }

/* ============ MENU (drawer ☰) — dark + regroupé + icônes ============ */
#menu{ background:var(--r-surface1); border-right:1px solid var(--r-border-hi); }
#menu li{
  display:flex; align-items:center; gap:11px; padding:10px 16px;
  border-bottom:1px solid var(--r-border); color:var(--r-text);
}
@media (hover:hover){
  #menu li:hover:not(.menu-sep):not(.menu-group-title){ background:var(--r-surface3); color:#fff; }
}
#menu .menu-ico{ width:20px; flex:none; text-align:center; font-size:1rem; opacity:.9; }
#menu .menu-txt{ flex:1; }
/* reseau : icône + label collés à gauche (annule le space-between d'origine) */
#menu li[data-page="reseau"]{ justify-content:flex-start; }

/* titres de groupe (Jeu / Aide & infos / Édition & admin) */
#menu li.menu-group-title{
  border-bottom:none; padding:14px 16px 5px; cursor:default; background:none;
  font-family:"Inter",system-ui,sans-serif; font-size:.68rem; font-weight:700;
  letter-spacing:.14em; text-transform:uppercase; color:var(--r-gold);
}
#menu li.menu-group-title:hover{ background:none; }

/* séparateur (trait) avant le bloc utilisateur */
#menu li.menu-sep{ border-bottom:1px solid var(--r-border); }

/* entrées admin / éditeurs : atténuées */
#menu .menu-admin-item{ color:var(--r-text2); }
#menu .menu-admin-item .menu-ico{ opacity:.7; }

/* bloc utilisateur connecté (nom + déconnexion) */
#menu .menu-user-info{ color:var(--r-text2); font-size:.9rem; padding:10px 16px; }
#menu .menu-user-info .btn-logout{
  background:var(--r-surface2); border:1px solid var(--r-border); color:var(--r-text);
  border-radius:6px; cursor:pointer; padding:3px 10px;
}
#menu .menu-user-info .btn-logout:hover{ background:var(--r-accent); color:#fff; border-color:var(--r-accent); }

/* ============ LIVRE — raffinements validés (points 3, 4, 5) ============ */

/* Point 3 — cases à cocher du livre/livret : cochée = VERT (au lieu du rouge) */
:is(#livre-container, #livre-perso-container) input[type="checkbox"].ebs-action{ accent-color:var(--r-ok); outline:none; }

/* Point 4 — boutons « condition » (blocs (((titre|||contenu)))) en or/parchemin */
:is(#livre-container, #livre-perso-container) .bouton-titre{
  background:#efe4c8; border:1px solid var(--r-gold); border-radius:6px; color:#5a4010; font-weight:700;
}
:is(#livre-container, #livre-perso-container) .bouton-titre:hover{ background:#e6d6b0; }
:is(#livre-container, #livre-perso-container) .contenu-titre{
  background:#ffffff; border:1px solid #e4ddce; border-left:3px solid var(--r-gold);
  border-radius:0 6px 6px 6px; color:var(--r-paper-ink);
}
:is(#livre-container, #livre-perso-container) .cadre_condition{ background:transparent; }

/* Point 5 — bandeau des panneaux : châssis dark chaud */
.side-panel-header{ background:var(--r-surface1); border-bottom:1px solid var(--r-border-hi); color:var(--r-text); }
.side-panel-header .side-panel-close{ color:var(--r-text2); }
.side-panel-header .side-panel-close:hover{ color:#fff; }
/* scénario : titre + numéro de paragraphe CENTRÉS, boutons à droite */
.left-sub-panel[data-sub-page="scenario"] .side-panel-header{ position:relative; justify-content:center; gap:8px; }
.left-sub-panel[data-sub-page="scenario"] .side-panel-header .info{
  margin:0; color:var(--r-text); font-family:"Cinzel",Georgia,serif; font-size:.95rem;
}
.left-sub-panel[data-sub-page="scenario"] .side-panel-header .CodePar{
  margin:0; background:rgba(212,162,76,.14); border:1px solid rgba(212,162,76,.5);
  color:var(--r-gold-hi); border-radius:999px; padding:1px 10px; font-weight:700; font-size:.82rem;
}
.left-sub-panel[data-sub-page="scenario"] .side-panel-header .side-panel-fs,
.left-sub-panel[data-sub-page="scenario"] .side-panel-header .side-panel-close{
  position:absolute; top:50%; transform:translateY(-50%); margin:0;
}
.left-sub-panel[data-sub-page="scenario"] .side-panel-header .side-panel-close{ right:8px; }
.left-sub-panel[data-sub-page="scenario"] .side-panel-header .side-panel-fs{ right:36px; }
/* 20260801 VCH le « ? » du livre et du livret doit être ABSOLU comme ses voisins : ces deux
   en-têtes centrent leur contenu (justify-content:center), un élément dans le flux
   rejoindrait le groupe centré au lieu d'aller à droite, et passerait sous les boutons —
   la régression du 20260730 sur le numéro de paragraphe (10-entete-zones-cliquables.spec.js).
   .side-panel-fs étant masqué sur desktop (styles.css:6618 et suivantes), la place à 36px
   y est libre ; en portrait/paysage elle est prise, d'où le décalage à 64px. */
.left-sub-panel[data-sub-page="scenario"] .side-panel-header .aide-btn,
.left-sub-panel[data-sub-page="personnel"] .side-panel-header .aide-btn{
  position:absolute; top:50%; transform:translateY(-50%); margin:0; right:36px;
}
body[data-mode="portrait"]  .left-sub-panel[data-sub-page="scenario"]  .side-panel-header .aide-btn,
body[data-mode="landscape"] .left-sub-panel[data-sub-page="scenario"]  .side-panel-header .aide-btn,
body[data-mode="portrait"]  .left-sub-panel[data-sub-page="personnel"] .side-panel-header .aide-btn,
body[data-mode="landscape"] .left-sub-panel[data-sub-page="personnel"] .side-panel-header .aide-btn{
  right:64px;
}
/* bouton « page 1 » (📄) calé à GAUCHE (comme la croix à droite) → titre vraiment centré */
.left-sub-panel[data-sub-page="scenario"] .side-panel-header .side-panel-page1{
  position:absolute; left:8px; top:50%; transform:translateY(-50%); margin:0;
}

/* LIVRET personnel : idem — perso/select + numéro @N centrés, boutons à droite */
.left-sub-panel[data-sub-page="personnel"] .side-panel-header{ position:relative; justify-content:center; gap:8px; }
.left-sub-panel[data-sub-page="personnel"] .side-panel-header .perso{ color:var(--r-text2); }
.left-sub-panel[data-sub-page="personnel"] .side-panel-header #PersoSelector2{
  background:var(--r-surface2); border:1px solid var(--r-border); color:var(--r-text);
  border-radius:6px; padding:3px 8px;
}
.left-sub-panel[data-sub-page="personnel"] .side-panel-header .CodeParPerso{
  background:rgba(212,162,76,.14); border:1px solid rgba(212,162,76,.5);
  color:var(--r-gold-hi); border-radius:999px; padding:1px 10px; font-weight:700; font-size:.82rem;
}
.left-sub-panel[data-sub-page="personnel"] .side-panel-header .side-panel-fs,
.left-sub-panel[data-sub-page="personnel"] .side-panel-header .side-panel-close{
  position:absolute; top:50%; transform:translateY(-50%); margin:0;
}
.left-sub-panel[data-sub-page="personnel"] .side-panel-header .side-panel-close{ right:8px; }
.left-sub-panel[data-sub-page="personnel"] .side-panel-header .side-panel-fs{ right:36px; }
/* bouton « page 1 » (📄) calé à GAUCHE (comme la croix à droite) */
.left-sub-panel[data-sub-page="personnel"] .side-panel-header .side-panel-page1{
  position:absolute; left:8px; top:50%; transform:translateY(-50%); margin:0;
}

/* 20260730 VCH les boutons 📄 / plein écran / × étant en position absolue, le flux ne
   leur réserve aucune place : dans un en-tête étroit, le bloc centré (titre + numéro de
   paragraphe) passait SOUS eux et le clic sur le numéro déclenchait le plein écran ou la
   fermeture du panneau au lieu d'ouvrir la saisie. On réserve donc leur gouttière (en
   respectant la safe-area iOS du plein écran) et le titre est tronqué plutôt que de
   pousser le numéro sous les boutons. */
/* 20260801 VCH gouttière élargie de 28 px (une largeur de bouton) : le « ? » d'aide s'ajoute
   aux boutons absolus. Desktop = croix (8→25) + « ? » (36→54), soit 62 px ; portrait/paysage
   = croix (8→25) + plein écran (36→59) + « ? » (64→82), soit 90 px. Sans cet élargissement,
   mesuré à 580x400 sur un en-tête de 265 px, .CodePar occupait 152→203 et le « ? » 183→201 :
   18 px de recouvrement franc, attrapé par 10-entete-zones-cliquables.spec.js. */
:is(.left-sub-panel[data-sub-page="scenario"], .left-sub-panel[data-sub-page="personnel"]) .side-panel-header{
  padding-left:max(44px, env(safe-area-inset-left, 0px));
  padding-right:max(62px, env(safe-area-inset-right, 0px));
}
/* le bouton plein écran n'existe qu'en mobile (portrait/paysage) : une gouttière de plus */
body[data-mode="portrait"] :is(.left-sub-panel[data-sub-page="scenario"], .left-sub-panel[data-sub-page="personnel"]) .side-panel-header,
body[data-mode="landscape"] :is(.left-sub-panel[data-sub-page="scenario"], .left-sub-panel[data-sub-page="personnel"]) .side-panel-header{
  padding-right:max(90px, env(safe-area-inset-right, 0px));
}
/* 20260801 VCH le nom du personnage se tronque comme le titre du scénario : sinon le groupe
   centré du livret dépasse la place restante et repasse sous les boutons. */
.left-sub-panel[data-sub-page="scenario"] .side-panel-header .info,
.left-sub-panel[data-sub-page="personnel"] .side-panel-header .perso{
  min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.left-sub-panel[data-sub-page="scenario"] .side-panel-header .CodePar,
.left-sub-panel[data-sub-page="personnel"] .side-panel-header .CodeParPerso{ flex:0 0 auto; }

/* 20260731 VCH la gouttière ci-dessus (bloc du 20260730) réserve bien la place des
   boutons, mais ne suffit pas pour le livret : son bloc centré contient .perso (« Livret
   personnel ») ET #PersoSelector2, tous deux incompressibles par défaut (min-width:auto
   = leur largeur de contenu ; un <select> ne rétrécit pas sous sa largeur intrinsèque).
   .CodeParPerso ayant flex:0 0 auto (ligne ci-dessus, comme .CodePar), le bloc déborde
   alors par-dessus le padding au lieu de s'y adapter, ce qui fait chevaucher
   .CodeParPerso et .side-panel-fs à largeur étroite (~580 px, recouvrement mesuré et
   confirmé le 2026-07-31 par tests/e2e/10-entete-zones-cliquables.spec.js — le même bug
   que celui corrigé ci-dessus pour le livre, mais jamais traité pour le livret). Le livre
   y échappe car son titre .info a déjà une ellipse (min-width:0 + text-overflow, juste
   au-dessus) ; le livret n'avait pas d'équivalent. Le libellé .perso étant redondant avec
   le sélecteur (qui affiche déjà le personnage), on lui applique la même ellipse ; le
   sélecteur reçoit min-width:0 pour pouvoir rétrécir, plafonné pour ne jamais pousser le
   numéro sous les boutons même si un nom de personnage futur s'allongeait. */
.left-sub-panel[data-sub-page="personnel"] .side-panel-header .perso{
  min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.left-sub-panel[data-sub-page="personnel"] .side-panel-header #PersoSelector2{
  min-width:0; max-width:110px;
}

/* ============ MODE EXPLORATION — points validés (1, 2, 3) ============ */

/* Point 1 — barre d'outils harmonisée (le fond dark vient de l'item 1) */
.explo-toolbar{ flex-wrap:wrap; row-gap:8px; }          /* évite le débordement en mobile */
/* badge de mode (barres explo ET plan) : pastille translucide selon le mode */
.explo-toolbar .mode-badge, .plan-toolbar .mode-badge{
  border-radius:999px; padding:5px 13px; font-size:.72rem; font-weight:700;
  text-transform:uppercase; letter-spacing:.05em; border:1px solid transparent;
}
.explo-toolbar .mode-badge[data-mode="exploration"], .plan-toolbar .mode-badge[data-mode="exploration"]{
  background:rgba(125,168,95,.18); color:#a6cd88; border-color:rgba(125,168,95,.5);
}
.explo-toolbar .mode-badge[data-mode="combat"], .plan-toolbar .mode-badge[data-mode="combat"]{
  background:rgba(192,57,43,.18); color:#ef8478; border-color:rgba(192,57,43,.5);
}
.explo-toolbar .mode-badge[data-mode="infiltration"], .plan-toolbar .mode-badge[data-mode="infiltration"]{
  background:rgba(212,162,76,.18); color:#e8bc63; border-color:rgba(212,162,76,.5);
}
/* champ N° */
.explo-toolbar #explo-input{ background:var(--r-surface2); border:1px solid var(--r-border); color:var(--r-text); border-radius:6px; padding:7px 9px; }
/* boutons : Ajouter = or, Vider / Voir les cartes détruites = ghost */
#explo-add, #explo-clear, #explo-detruites{
  background:var(--r-surface2); border:1px solid var(--r-border); color:var(--r-text);
  border-radius:8px; padding:7px 12px; font-weight:600; font-size:.82rem; cursor:pointer;
}
#explo-add:hover, #explo-clear:hover, #explo-detruites:hover{ background:var(--r-surface3); border-color:var(--r-border-hi); }
#explo-add{ background:var(--r-gold); color:#241a06; border-color:transparent; }
#explo-add:hover{ background:var(--r-gold-hi); }
/* « Attacher par les blasons » : interrupteur */
.explo-attache-label{ color:var(--r-text2); }
.explo-toolbar #explo-attache{
  appearance:none; -webkit-appearance:none; width:40px; height:22px; border-radius:999px;
  background:var(--r-surface3); position:relative; cursor:pointer; border:1px solid var(--r-border); margin:0;
}
.explo-toolbar #explo-attache::after{
  content:""; position:absolute; top:2px; left:2px; width:16px; height:16px; border-radius:50%;
  background:#fff; transition:.15s;
}
.explo-toolbar #explo-attache:checked{ background:var(--r-gold); border-color:transparent; }
.explo-toolbar #explo-attache:checked::after{ left:20px; background:#241a06; }

/* Point 2 — fond du canvas : dark chaud (au lieu du gris froid) */
#explo-view{ background:radial-gradient(120% 80% at 50% 0%, #221d15, #100e0a); }

/* Zone de jeu VIDE (exploration / combat / infiltration) : placeholder grisé.
   Explo = aucune carte (.explo-card-wrap) ; plan = aucun plan (.plan-container). */
#explo-view:not(:has(.explo-card-wrap))::before,
#plan-view:not(:has(.plan-container))::before{
  content:"Zone de jeu";
  /* centré dans l'espace LIBRE (hors panneaux ouverts), pas dans toute la zone */
  position:absolute; top:0; bottom:0;
  left:var(--ebs-zone-l, 0px); right:var(--ebs-zone-r, 0px);
  display:grid; place-items:center;
  font-family:"Cinzel",Georgia,serif; font-size:clamp(1.1rem,2.4vw,1.6rem);
  letter-spacing:.14em; text-transform:uppercase; color:rgba(236,227,208,.13);
  pointer-events:none; z-index:0;
}

/* Point 3 — modal « Cartes détruites » : sombre chaud */
.ed-wrapper{ background:var(--r-bg); border:1px solid var(--r-border-hi); color:var(--r-text); }
.ed-title{ color:var(--r-text); font-family:"Cinzel",Georgia,serif; }
.ed-raz-btn{ background:transparent; color:#ef8478; border:1px solid rgba(192,57,43,.5); }
.ed-raz-btn:hover{ background:var(--r-accent); color:#fff; }
.ed-close-btn{ background:var(--r-surface2); color:var(--r-text2); }
.ed-close-btn:hover{ background:var(--r-surface3); color:#fff; }
.ed-slot{ background:var(--r-surface2); border:1px solid var(--r-border); }
.ed-slot-code{ color:var(--r-text2); }
.ed-empty{ color:var(--r-text3); }

/* ============ MODE COMBAT / INFILTRATION (plan) — points 1, 2, 3 ============ */

/* Point 1 — barre d'outils (elle était BLANCHE) → dark ; badge déjà en pastille (cf. plus haut) */
.plan-toolbar{ background:rgba(31,27,20,.94); border-bottom:1px solid var(--r-border-hi); }
.plan-toolbar #plan-input{ background:var(--r-surface2); border:1px solid var(--r-border); color:var(--r-text); border-radius:6px; }
#plan-add, #plan-clear{
  background:var(--r-surface2); border:1px solid var(--r-border); color:var(--r-text);
  border-radius:8px; padding:6px 11px; font-weight:600; cursor:pointer;
}
#plan-add:hover, #plan-clear:hover{ background:var(--r-surface3); border-color:var(--r-border-hi); }
#plan-add{ background:var(--r-gold); color:#241a06; border-color:transparent; }
#plan-add:hover{ background:var(--r-gold-hi); }
/* conteneur des pions à glisser (les pions eux-mêmes = matériel, inchangés) */
.plan-pions-bar{ background:var(--r-surface2); border:1px solid var(--r-border); border-radius:8px; }

/* Point 2 — fond du canvas : dark chaud */
#plan-view{ background:radial-gradient(120% 80% at 50% 0%, #221d15, #100e0a); }

/* Point 3 — menu contextuel d'un pion : sombre chaud */
.plan-pion-menu{ background:var(--r-surface2); border:1px solid var(--r-border-hi); }
.plan-pion-menu-btn{ background:var(--r-surface3); border:1px solid var(--r-border); color:var(--r-text); }
.plan-pion-menu-btn:hover:not(:disabled){ background:var(--r-border); }

/* ============ PLATEAU D'AVANCEMENT — points 1 à 6 ============
   Déjà sombre à l'origine mais en gris froids → tokens chauds.
   ⚠ Les IMAGES (pions d'activation, icônes d'événements) = matériel,
   jamais retintées : on ne touche qu'au châssis (cadres, boutons,
   selects, popovers, textes). Classes confinées au plateau. */

/* Fond du panneau : blanc d'origine → surface sombre (châssis) */
.left-sub-panel[data-sub-page="plateau"]{ background:var(--r-surface1); border-color:var(--r-border-hi); color:var(--r-text); }

/* Point 1 — pastille MODE DE JEU : aplat plein → pastille translucide */
#mode-compteur.mode-badge{
  border-radius:999px; padding:5px 14px; font-size:.72rem; font-weight:700;
  text-transform:uppercase; letter-spacing:.05em; border:1px solid transparent;
}
#mode-compteur.mode-badge[data-mode="exploration"]{ background:rgba(125,168,95,.18); color:#a6cd88; border-color:rgba(125,168,95,.5); }
#mode-compteur.mode-badge[data-mode="combat"]{ background:rgba(192,57,43,.18); color:#ef8478; border-color:rgba(192,57,43,.5); }
#mode-compteur.mode-badge[data-mode="infiltration"]{ background:rgba(212,162,76,.18); color:#e8bc63; border-color:rgba(212,162,76,.5); }

/* Point 2 — compteurs (Interaction / Y / Portée de menace) : selects + ± chauds, flèche or */
.interaction-select{
  border:1px solid var(--r-border); color:var(--r-text);
  background:var(--r-surface2) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23D4A24C'/%3E%3C/svg%3E") no-repeat right 8px center;
  border-radius:6px;
}
.btn-y{ background:var(--r-surface2); color:var(--r-text); border:1px solid var(--r-border); border-radius:6px; }
.btn-y:hover{ background:var(--r-surface3); border-color:var(--r-border-hi); }

/* Point 3 — piste des rounds : flèches chaudes, bords chauds (case active garde l'accent) */
.btn-round-arrow{ background:var(--r-surface2); border:1px solid var(--r-border); color:var(--r-text2); border-radius:6px; }
.btn-round-arrow:hover{ background:var(--r-surface3); border-color:var(--r-border-hi); color:var(--r-text); }
.round-num{ border:1px solid var(--r-border-hi); border-radius:6px; color:var(--r-text2); }
.round-cell.active .round-num{ background:var(--r-accent); color:#fff; border-color:transparent; }
/* Encadrés R1–R10 resserrés : l'encadré remplit sa case (plus de vide latéral),
   cases plus étroites et gap réduit → rangée compacte et uniforme */
.round-piste{ gap:2px; }
.round-cell{ width:30px; }
.round-num{ min-width:0; width:100%; box-sizing:border-box; padding:3px 2px; }

/* Point 4 — piste des tours : cadres des slots + boutons + / mélange chauds (pion intact) */
.tour-slot{ background:var(--r-surface2); border:2px solid var(--r-border); border-radius:6px; }
.tour-slot:hover{ border-color:var(--r-border-hi); }
.btn-tour-action{ background:var(--r-surface2); color:var(--r-text); border:2px solid var(--r-border); border-radius:6px; }
.btn-tour-action:hover{ background:var(--r-surface3); border-color:var(--r-border-hi); }

/* Point 5 — popovers (choix pion / événement / mode) : surface chaude */
.tours-picker, .eve-picker, .mode-picker{ background:var(--r-surface2); border:1px solid var(--r-border-hi); }
/* item de mode dans le picker : pastille translucide (comme point 1) */
.mode-picker-item.mode-badge{
  border-radius:999px; border:1px solid transparent;
}
.mode-picker-item.mode-badge[data-mode="exploration"]{ background:rgba(125,168,95,.18); color:#a6cd88; border-color:rgba(125,168,95,.5); }
.mode-picker-item.mode-badge[data-mode="combat"]{ background:rgba(192,57,43,.18); color:#ef8478; border-color:rgba(192,57,43,.5); }
.mode-picker-item.mode-badge[data-mode="infiltration"]{ background:rgba(212,162,76,.18); color:#e8bc63; border-color:rgba(212,162,76,.5); }
.mode-picker-item.mode-picker-current{ border-color:var(--r-gold); }

/* Point 6 — libellés de section : teinte or (cohérent avec les titres de groupe du menu) */
.mode-titre{ color:var(--r-gold); opacity:1; letter-spacing:.12em; font-weight:700; font-family:"Inter",system-ui,sans-serif; }

/* ============ JOURNAL DE BORD — points 0 à 4 ============
   Panneau blanc + slots gris clair → châssis chaud.
   ⚠ Les CARTES DE QUÊTE (.carte-container dans les slots / la modale) = matériel,
   jamais retintées. Classes .journal-* propres au journal ; .zoom-flip-btn
   partagée → scopée sous #journal-modal. */

/* Point 0 — fond du panneau : blanc → surface sombre
   ⚠ NE PAS poser color:var(--r-text) ici : ça se propagerait dans le texte des
   cartes de quête (.carte-zone hérite sa couleur) → texte clair sur carte claire.
   Les textes de châssis (titre, label) ont leur couleur claire explicite ailleurs. */
/* Le matériel (carte de quête) garde son texte noir + son fond blanc, quel que soit
   le fond sombre du panneau (slot occupé + modale de zoom) */
#journal-modal .carte-container{ color:#000; background:#fff; }

/* Point 3 — navigation de page : flèches chaudes, label clair */
.journal-nav-btn{ background:var(--r-surface2); border:1px solid var(--r-border); color:var(--r-text2); border-radius:6px; }
.journal-nav-btn:not(:disabled):hover{ background:var(--r-surface3); border-color:var(--r-border-hi); color:var(--r-text); }
#journal-page-label{ color:var(--r-text); }

/* Points 1 & 2 — slots vides = surface chaude ; slot occupé = bord chaud (carte intacte) */
.journal-slot{ background:var(--r-surface2); border:1px solid var(--r-border); border-radius:5px; }
.journal-slot--occupied{ background:transparent; border-color:var(--r-border-hi); }

/* Point 4 — modale de zoom : boutons gris froid → chassis chaud (overlay sombre conservé) */
#journal-modal .journal-modal-nav button,
#journal-modal .journal-modal-close{
  background:var(--r-surface2); color:var(--r-text); border:1px solid var(--r-border); border-radius:6px;
}
#journal-modal .journal-modal-nav button:hover:not(:disabled),
#journal-modal .journal-modal-close:hover{ background:var(--r-surface3); border-color:var(--r-border-hi); }
#journal-modal .zoom-flip-btn{
  background:var(--r-surface2); color:var(--r-gold-hi); border:1px solid rgba(212,162,76,.5); border-radius:6px;
}
#journal-modal .zoom-flip-btn:hover{ background:var(--r-surface3); }

/* ============ ENNEMIS (v2) — points 0 à 5 ============
   Panneau blanc + slots gris clair → châssis chaud.
   ⚠ Les CARTES (carac/comportement, zoom) et les PIONS = matériel : jamais retintés.
   Garde-fou anti-fuite de couleur : .carte-container forcé noir/blanc (cf. journal). */

/* Point 0 — panneau + groupes + séparateur */
.left-sub-panel[data-sub-page="ennemis-v2"]{ background:var(--r-surface1); border-color:var(--r-border-hi); color:var(--r-text); }
.left-sub-panel[data-sub-page="ennemis-v2"] .ennemisv2-groupe{ background:var(--r-surface1); }
.left-sub-panel[data-sub-page="ennemis-v2"] .ennemisv2-groupe + .ennemisv2-groupe{ border-top-color:var(--r-border); }
/* Matériel (cartes) lisible quel que soit le fond sombre */
.left-sub-panel[data-sub-page="ennemis-v2"] .carte-container,
.ennemis-zoom-content .carte-container{ color:#000; background:#fff; }

/* Point 1 — header : labels / séparateurs / inputs / boutons Charger / ✕ effacer */
.ennemisv2-header{ color:var(--r-text2); }
.ennemisv2-header .header-sep{ color:var(--r-border-hi); }
.ennemisv2-header .input-pvmax,
.ennemisv2-header .input-num-carac,
.ennemisv2-header .input-num-comport{
  background:var(--r-surface2); border:1px solid var(--r-border); color:var(--r-text); border-radius:5px;
}
.ennemisv2-header .btn-load-carac,
.ennemisv2-header .btn-load-comport{
  background:var(--r-surface2); border:1px solid var(--r-border); color:var(--r-text);
  border-radius:6px; padding:2px 9px; cursor:pointer;
}
.ennemisv2-header .btn-load-carac:hover,
.ennemisv2-header .btn-load-comport:hover{ background:var(--r-surface3); border-color:var(--r-border-hi); }
.ennemisv2-header .btn-clear-carac,
.ennemisv2-header .btn-clear-comport{ color:#ef8478; border-color:rgba(192,57,43,.55); }

/* Point 2 — slots vides : surface + bord chauds, bouton + (indice vert au survol) */
.ennemisv2-slot{ background:var(--r-surface2); border:1px solid var(--r-border); }
.slot-num{ color:var(--r-text2); }
.btn-slot-add{ background:var(--r-surface3); border:1px solid var(--r-border-hi); color:var(--r-text); }
.btn-slot-add:hover{ background:var(--r-surface3); border-color:var(--r-ok); color:#a6cd88; }

/* Point 3 — slots occupés : PV −/+, champ PV, + Pion (chassis chaud) ; ✕ supprimer (rouge) */
.slot-pv-row .input-pv{ background:var(--r-surface2); border:1px solid var(--r-border); color:var(--r-text); }
.slot-pv-row .btn-pv{ background:var(--r-surface3); border:1px solid var(--r-border); color:var(--r-text); }
.slot-pv-row .btn-pv:active{ background:var(--r-border); }
.slot-btns .btn-add-pion{ background:var(--r-surface3); border:1px solid var(--r-border); color:var(--r-text); }
.slot-btns .btn-add-pion:hover{ background:var(--r-border); }
.btn-del-ennemi{ color:#ef8478; border-color:rgba(192,57,43,.55); }
.btn-del-ennemi:hover{ background:var(--r-accent); color:#fff; }

/* Point 4 — picker de pions : surface chaude (pions = matériel, intacts) */
#pion-picker-v2{ background:var(--r-surface2); border:1px solid var(--r-border-hi); }
#pion-picker-v2 .pion-picker-item:hover{ background:var(--r-surface3); }

/* Point 5 — modale de zoom : boutons (recto/dos, tirer, ✕) en chassis chaud (overlay sombre conservé) */
.ennemis-zoom-toggle,
.ennemis-zoom-tirer,
.ennemis-zoom-header .journal-modal-close{
  background:var(--r-surface2); color:var(--r-text); border:1px solid var(--r-border); border-radius:6px;
}
.ennemis-zoom-toggle:hover,
.ennemis-zoom-tirer:hover,
.ennemis-zoom-header .journal-modal-close:hover{ background:var(--r-surface3); border-color:var(--r-border-hi); }

/* ============ FICHE PERSO & RIVIÈRE ============
   Châssis sombre ; rivière (plateau perso imprimé) en HYBRIDE : verts conservés
   mais désaturés/assombris pour s'intégrer au fond sombre, sans virer au brun.
   ⚠ Cartes (dispo, posées, zoom, pile) et pions = matériel : jamais retintés
   → garde-fou .carte-container noir/blanc. */

/* Tokens rivière : teintes d'intensité échantillonnées sur la tuile physique
   (fournies par VCH 20260725). 0→2 clairs (texte noir), 3 foncé (texte clair).
   En-tête/label conservés en vert foncé pour contraster avec les colonnes. */
:root{
  --riv-header:#2f4d22; --riv-label:#2a3320; --riv-corner:#24361a;
  --riv-0:#C8C0A0; --riv-1:#AAAB7C; --riv-2:#8A9460; --riv-3:#596634;
}

/* Panneau (bas) + en-tête */
#bottom-panel{ background:var(--r-surface1); border-color:var(--r-border-hi); }
.bottom-panel-header{ background:var(--r-surface1); border-bottom-color:var(--r-border-hi); }
/* Matériel (cartes) lisible sur fond sombre — inclut le zoom détaché (déplacé dans <body>) */
#bottom-panel .carte-container,
.perso-zoom-detached .carte-container{ color:#000; background:#fff; }

/* Zone cartes disponibles (gauche) */
.perso-cartes-zone{ background:var(--r-surface2); border-right-color:var(--r-border); }
.perso-add-bar{ border-bottom-color:var(--r-border); }
body.perso-lateral .perso-add-bar{ background:var(--r-surface2); }
.perso-add-input{ background:var(--r-surface1); border:1px solid var(--r-border); color:var(--r-text); }
.perso-add-btn{ background:var(--r-surface3); border:1px solid var(--r-border); color:var(--r-text); }
.perso-add-btn:hover{ background:var(--r-border); border-color:var(--r-border-hi); }
.perso-butin-btn{ background:var(--r-surface3); border:1px solid var(--r-border); }
.perso-butin-btn:hover{ background:var(--r-border); }
.perso-butin-prefixe, .perso-butin-label{ color:var(--r-text2); }
.perso-add-status{ color:var(--r-text2); }
/* « Cartes perdues » : rouge translucide (cohérent avec les autres actions destructives) */
.perso-perdues-btn{ background:transparent; color:#ef8478; border:1px solid rgba(192,57,43,.55); }
.perso-perdues-btn:hover{ background:var(--r-accent); color:#fff; }
/* liseré de survol d'une carte dispo : vert (conservé, harmonisé) */
.perso-carte-inner:hover{ box-shadow:0 0 0 2px var(--r-ok); }
/* boutons d'action basique (mode exploration) */
.btn-action-basique{ background:var(--r-surface3); border:1px solid var(--r-border); color:var(--r-text); }
.btn-action-basique:hover{ background:var(--r-border); }

/* Rivière (plateau) — bordures + cellules de la tuile */
.perso-plateau{ border-right-color:var(--r-border); border-left-color:var(--r-border); }
.tp-cell{ background:var(--r-surface2); color:var(--r-text); border-right-color:var(--r-border); border-bottom-color:var(--r-border); }
.tp-cell.tp-header{ background:var(--riv-header); color:var(--r-text); border-color:var(--riv-corner); }
.tp-cell.tp-label{ background:var(--riv-label); color:var(--r-text2); border-right-color:var(--riv-header); }
.tp-cell.tp-header.tp-label{ background:var(--riv-corner); color:var(--r-text); }
.tp-cell.tp-green{ background:var(--riv-2); }
/* Colonnes d'intensité : fond = teinte physique, texte noir (0-2) / clair (3) */
.tp-cell.tp-int-0{ background:var(--riv-0); color:#1a1a12; }
.tp-cell.tp-int-1{ background:var(--riv-1); color:#1a1a12; }
.tp-cell.tp-int-2{ background:var(--riv-2); color:#1a1a12; }
.tp-cell.tp-int-3{ background:var(--riv-3); color:#1a1a12; }
.tp-cell.tp-header.tp-int-0,
.tp-cell.tp-header.tp-int-1,
.tp-cell.tp-header.tp-int-2,
.tp-cell.tp-header.tp-int-3{ color:#1a1a12; border-color:#8a9a6a; }

/* Rivière — les 4 tuiles d'intensité */
.tuile-intensite{ background:var(--r-surface1); border-left-color:var(--r-border); }
.ti-zone-action{ border-bottom-color:var(--r-border-hi); }
.ti-zone-pf{ border-bottom-color:var(--r-border); }
.ti-zone-pions{ background:var(--r-surface2); }
.ti-zone-label{ color:var(--r-text3); }
.tp-river-spacer{ background:var(--riv-label); border-right-color:var(--riv-header); }
.ti-drop-active{ background:rgba(125,168,95,.18) !important; outline-color:var(--r-ok); }
/* Flèches de séparation de la rivière (SVG inline) : blanc → teinte chaude discrète
   (elles ressortaient trop sur le corps sombre des tuiles) */
.river-arrow path{ fill:var(--r-text3); stroke:var(--r-bg); }
/* (boutons overlay des cartes posées — ti-remove/rotate/lose, ti-stack-badge, pcb-* —
   restent des pastilles translucides sombres, lisibles sur le matériel : inchangés) */

/* Modale de zoom perso */
.perso-zoom-toolbar .zoom-flip-btn{ background:var(--r-surface2); color:var(--r-text); border:1px solid var(--r-border); border-radius:6px; }
.perso-zoom-toolbar .zoom-flip-btn:hover{ background:var(--r-surface3); border-color:var(--r-border-hi); }
.perso-zoom-close{ background:var(--r-surface2); }

/* Modale « cartes perdues » */
.perso-perdues-inner{ background:var(--r-surface1); color:var(--r-text); }
.perso-perdues-close{ color:var(--r-text2); }
.perso-perdues-close:hover{ color:#fff; }

/* Colonne droite : emplacement carac vide, bouton « couler la rivière », tirer, encart PV */
.perso-carac-placeholder{ background:var(--r-surface2); border-color:var(--r-border-hi); color:var(--r-text3); }
/* « Faire couler la rivière » : action principale → or (au lieu du bleu hors thème) */
.btn-flow-riviere{ background:var(--r-gold); color:#241a06; }
.btn-flow-riviere:hover{ background:var(--r-gold-hi); }
.btn-tirer-carte{ background:var(--r-surface3); border:1px solid var(--r-border); color:var(--r-text); }
.btn-tirer-carte:hover{ background:var(--r-border); }
/* Encart PV du personnage : parchemin clair → sombre teinté or (PV courant en rouge) */
.perso-pv-encart{ background:rgba(212,162,76,.12); border-color:rgba(212,162,76,.5); }
.perso-pv-btn{ background:var(--r-surface3); border:1px solid rgba(212,162,76,.5); color:var(--r-gold-hi); }
.perso-pv-btn:hover:not(:disabled){ background:var(--r-border); }
.perso-pv-val{ color:var(--r-text); }
.perso-pv-val .perso-pv-cur{ color:#ef8478; }
/* bouton « replier le bloc du haut » (mode latéral) */
body.perso-lateral .bottom-panel-collapse{ background:transparent; }

/* Éléments de châssis restés clairs (repérés en state Astrar : + Pion, zone test, équipement) */
#bottom-panel .btn-add-pion{ background:var(--r-surface3); border:1px solid var(--r-border); color:var(--r-text); }
#bottom-panel .btn-add-pion:hover{ background:var(--r-border); border-color:var(--r-border-hi); }
.perso-test-zone{ background:var(--r-surface1); }
.perso-equip-header{ background:var(--r-surface2); color:var(--r-text2); border-top-color:var(--r-border); border-bottom-color:var(--r-border); }
.perso-equip-vide{ color:var(--r-text3); }
.perso-recuperer-btn{ background:var(--r-surface3); border:1px solid var(--r-border); color:var(--r-ok); }
.perso-recuperer-btn:hover{ background:var(--r-border); }
.perso-add-status{ color:#ef8478; }
/* Encart infos « X PV / N cartes / Px / Nom » + message « Hors Combat » : ce sont des
   ZONES de la carte carac (matériel) → laissées claires par le garde-fou .carte-container. */

/* ============ ASCENSEURS (scrollbars) ============
   Thumb chaud + track transparent : discret aussi bien sur le châssis sombre
   que sur la page claire du livre (le track laisse voir le fond dessous). */
*{ scrollbar-width:thin; scrollbar-color:var(--r-border-hi) transparent; }
::-webkit-scrollbar{ width:11px; height:11px; }
::-webkit-scrollbar-track{ background:transparent; }
::-webkit-scrollbar-thumb{ background:var(--r-border-hi); border-radius:7px; border:2px solid transparent; background-clip:padding-box; }
::-webkit-scrollbar-thumb:hover{ background:var(--r-text3); background-clip:padding-box; }
::-webkit-scrollbar-corner{ background:transparent; }

/* ============ DÉS (d6 & d20) — faces sombres ============
   Les faces étaient trop claires sur le fond sombre. Dé « pierre sombre »
   à points/chiffres clairs. (Le d20 est dessiné sur canvas → couleurs dans
   app.js FACE_TYPES ; ici : le cube d6 CSS + les badges d'historique.) */
.d6-face{ background:#f2ece0; border-color:var(--r-border-hi); }
.d6-pip{ background:#24211c; }
.d6-face[data-val="1"] .d6-pip{ background:var(--r-accent); }
/* badge d'historique du d6 : même identité que la face (blanc cassé, points foncés) */
.d6-result{ background:#f2ece0; color:#24211c; border-color:var(--r-border-hi); }

/* ============ FENÊTRE « CHOIX DU SCÉNARIO » (modale accueil) ============
   Scopé via :has(#campagnes-container) → n'affecte PAS les autres fenêtres modales
   (paramètres, aide, à propos, réseau) pas encore traitées.
   Les images de couverture = artwork, conservées. */
.center-panel:has(#campagnes-container){ background:var(--r-surface1); border-color:var(--r-border-hi); }
.center-panel:has(#campagnes-container) .center-panel-header{ background:var(--r-surface1); border-bottom-color:var(--r-border-hi); }
.center-panel:has(#campagnes-container) .center-panel-title{ font-family:"Cinzel",Georgia,serif; letter-spacing:.03em; }
.center-panel:has(#campagnes-container) .center-panel-close{ color:var(--r-text2); }
/* 20260802 VCH grille de cartes : le titre et la version sont des <span> à l'intérieur du
   bouton (un <button> ne peut pas contenir de <h3>/<p>), et le cadenas est un vrai élément
   posé sur la couverture — l'ancien ::after l'affichait sous la carte. */
#campagnes-container .campagnes-compte{ color:var(--r-text3); font-family:Inter,sans-serif; }
#campagnes-container .campagne{ background:var(--r-surface2); border-color:var(--r-border); }
#campagnes-container .campagne:hover{ border-color:var(--r-gold); }
#campagnes-container .campagne-titre{ color:var(--r-gold); font-family:"Cinzel",Georgia,serif; }
#campagnes-container .campagne-version{ color:var(--r-text2); }
#campagnes-container .campagne-courante{ border-color:var(--r-gold); }
#campagnes-container .campagne-tag.encours{ color:#0B0907; background:var(--r-gold); }
#campagnes-container .campagne-tag.verrou{ color:var(--r-text3); background:var(--r-surface1); border:1px solid var(--r-border); }
/* scénario verrouillé : couverture désaturée/assombrie + titre grisé */
#campagnes-container .campagne-locked .campagne-img{ filter:grayscale(.6) brightness(.7); }
#campagnes-container .campagne-locked .campagne-titre{ color:var(--r-text3); }
#campagnes-container .campagne-locked:hover{ border-color:var(--r-border); }

/* ============ PAGES MODALES DU MENU (frame commun) ============
   Toutes les fenêtres du menu ☰ (paramètres, aide, à propos, réseau, accueil,
   journal) s'affichent dans .center-panel. On assombrit le châssis commun ici ;
   chaque contenu est thématisé plus bas. Le LIVRE reste hors modale (side panel). */
.center-panel{ background:var(--r-surface1); border-color:var(--r-border-hi); }
.center-panel-header{ background:var(--r-surface1); border-bottom-color:var(--r-border-hi); }
.center-panel-title{ color:var(--r-text); }
.center-panel-close{ color:var(--r-text2); }
.center-panel-close:hover{ color:#fff; }
.center-panel-content{ color:var(--r-text); }
/* garde-fou matériel : cartes rendues dans une modale (ex. zoom du journal) */
.center-panel-content .carte-container{ color:#000; background:#fff; }

/* ============ PARAMÈTRES ============ */
.param-page{ color:var(--r-text); }
.param-label{ color:var(--r-gold); }
.param-note{ color:var(--r-text3); }
.param-grid-sep{ background:var(--r-border); }
.param-toggle, .param-toggle.is-off{ background:var(--r-surface3); border-color:var(--r-border); color:var(--r-text2); }
.param-toggle.is-on{ background:rgba(125,168,95,.22); border-color:var(--r-ok); color:#a6cd88; }
.param-btn{ background:var(--r-surface3); border-color:var(--r-border); color:var(--r-text); }
.param-btn:hover{ background:var(--r-border); }
.param-btn--ghost{ background:transparent; color:var(--r-text2); border-color:var(--r-border); }
.param-btn--ghost:hover{ background:var(--r-surface3); color:var(--r-text); }
.param-btn--danger{ background:transparent; color:#ef8478; border-color:rgba(192,57,43,.55); }
.param-btn--danger:hover{ background:var(--r-accent); color:#fff; }
.param-select{ background:var(--r-surface2); border-color:var(--r-border); color:var(--r-text); }
.local-dl-status{ color:var(--r-text2); }
/* boutons nombre de personnages */
.btn-nb-joueurs{ background:var(--r-surface3); border-color:var(--r-border); color:var(--r-text2); }
.btn-nb-joueurs:hover{ background:var(--r-border); }
.btn-nb-joueurs.actif{ background:var(--r-accent); border-color:var(--r-accent); color:#fff; }

/* ============ RÉSEAU (sauvegarde / jeu en réseau) ============ */
.reseau-page{ color:var(--r-text); }
.reseau-intro{ color:var(--r-text2); }
.reseau-btn--secondary{ background:var(--r-surface3); border-color:var(--r-border); color:var(--r-text); }
.reseau-btn--secondary:hover{ background:var(--r-border); }
.reseau-btn--danger{ background:transparent; color:#ef8478; border-color:rgba(192,57,43,.55); }
.reseau-btn--danger:hover{ background:var(--r-accent); color:#fff; }
/* .reseau-btn--primary : accent rouge conservé (déjà sur l'identité EBS) */
.reseau-sep{ color:var(--r-text3); }
.reseau-sep::before, .reseau-sep::after{ border-bottom-color:var(--r-border); }
.reseau-label{ color:var(--r-text2); }
.reseau-code-input{ background:var(--r-surface2); border-color:var(--r-border); color:var(--r-text); }
/* .reseau-code-display : bloc vert conservé (cohérent avec le badge « code » du menu) */
.reseau-msg{ color:#ef8478; }
.reseau-histo-note, .reseau-histo-vide, .reseau-histo-date{ color:var(--r-text3); }
.reseau-histo-ligne{ border-bottom-color:var(--r-border); }
.reseau-histo-ligne--courante{ background:rgba(125,168,95,.10); border-left-color:var(--r-ok); }
.reseau-histo-titre{ color:var(--r-text); }
.reseau-histo-code{ color:var(--r-text2); }
.reseau-diag-box{ border-top-color:var(--r-border); }
.reseau-diag-box summary{ color:var(--r-text3); }

/* ============ À PROPOS ============ (contenu texte : hérite du clair ; liens en or) */
.center-panel-content .centered-link a{ color:var(--r-gold-hi); }

/* ============ ÉCRAN DE CONNEXION ============ */
.login-box{ background:var(--r-surface1); border:1px solid var(--r-border-hi); box-shadow:0 8px 28px rgba(0,0,0,.6); }
.login-box h2{ color:var(--r-gold); font-family:"Cinzel",Georgia,serif; }
.login-subtitle{ color:var(--r-text2); }
.form-group label{ color:var(--r-text2); }
.form-group input{ background:var(--r-surface2); border-color:var(--r-border); color:var(--r-text); }
.form-group input:focus{ border-color:var(--r-gold); }
.login-btn{ background:var(--r-accent); color:#fff; }
.login-btn:hover{ background:var(--r-accent-hi); }
.login-error{ color:#ef8478; background:rgba(192,57,43,.15); }
/* 20260808 VCH liens de l'encart de connexion (créer un compte, mot de passe oublié,
   newsletter, retour) : aucune règle ne les couvrait → bleu par défaut du navigateur
   sur fond brun. Or du thème, comme #app-title et les liens d'À propos. Le soulignement
   reste, atténué, pour qu'ils se lisent encore comme des liens. */
.login-box a{ color:var(--r-gold); text-decoration-color:rgba(212,162,76,.45); }
.login-box a:hover{ color:var(--r-gold-hi); text-decoration-color:currentColor; }

/* ============ DIALOGUES (ebsConfirm/Alert/Prompt) ============
   Leur CSS est injecté par JS APRÈS ce fichier → on gagne par une spécificité
   plus forte (préfixe .ebs-modal-overlay). Gris froids → surfaces chaudes. */
.ebs-modal-overlay .ebs-modal{ background:var(--r-surface2); color:var(--r-text); border-color:var(--r-border-hi); }
.ebs-modal-overlay .ebs-modal-input{ background:var(--r-surface1); border-color:var(--r-border); color:var(--r-text); }
.ebs-modal-overlay .ebs-modal-btn{ background:var(--r-surface3); border-color:var(--r-border); color:var(--r-text); }
.ebs-modal-overlay .ebs-modal-btn:hover{ background:var(--r-border); }
.ebs-modal-overlay .ebs-modal-btn.ebs-modal-ok{ background:var(--r-gold); border-color:transparent; color:#241a06; }
.ebs-modal-overlay .ebs-modal-btn.ebs-modal-ok:hover{ background:var(--r-gold-hi); }
.ebs-modal-overlay .ebs-modal-btn.ebs-modal-ok.ebs-modal-danger{ background:var(--r-accent); border-color:transparent; color:#fff; }
.ebs-modal-overlay .ebs-modal-btn.ebs-modal-ok.ebs-modal-danger:hover{ background:var(--r-accent-hi); }

/* 20260805 VCH plus de section TOASTS : la modale d'information est habillée par les règles
   `.ebs-modal-overlay` ci-dessus, comme les autres dialogues. */

/* ============ OUTILS D'ÉDITION (livre / cartes / plans) ============
   Déjà sombres mais en noirs/gris FROIDS → harmonisés aux tokens chauds.
   ⚠ Zones d'ÉDITION laissées telles quelles : .editeur-surface (page blanche du
   livre = contenu), #ec-preview (carte = matériel), .code-surface (éditeur de code). */
.editeur-page{ background:var(--r-bg); }
.editeur-toolbar, .code-toolbar, .code-tabs{ background:var(--r-surface1); border-bottom-color:var(--r-border-hi); }
.tool-group{ border-right-color:var(--r-border); }
.editeur-toolbar button, .code-toolbar button, .editeur-toolbar select, .code-toolbar label{
  background:var(--r-surface3); border-color:var(--r-border); color:var(--r-text);
}
.editeur-toolbar button:hover, .code-toolbar button:hover{ background:var(--r-border); }
.code-toolbar button.danger{ color:#ef8478; border-color:rgba(192,57,43,.55); }
.code-toolbar button.danger:hover{ background:var(--r-accent); color:#fff; }
.editeur-divider{ background:linear-gradient(90deg,transparent,var(--r-border-hi),transparent); }
/* onglets HTML / Lien / Schéma */
.code-tab{ background:var(--r-surface2); color:var(--r-text2); }
.code-tab:hover{ background:var(--r-surface3); }
.code-tab.active{ background:var(--r-bg); color:var(--r-text); border-top-color:var(--r-gold); }
.lien-titre{ color:var(--r-text); }
/* sélecteur de paragraphes (livre + plan) */
.paragraphe-selector{ background:var(--r-surface1); border-right-color:var(--r-border); color:var(--r-text); }
.paragraphe-selector .para-tools{ background:var(--r-surface2); border-bottom-color:var(--r-border); }
.paragraphe-selector .para-tools input, .paragraphe-selector .para-tools select{ background:var(--r-surface1); border-color:var(--r-border); color:var(--r-text); }
.paragraphe-selector .para-tools button{ background:var(--r-surface3); border-color:var(--r-border); color:var(--r-text); }
.para-list button{ color:var(--r-text); }
.para-list button:hover{ background:var(--r-surface2); border-color:var(--r-border); }
.para-list button.active{ background:var(--r-surface3); border-color:var(--r-border-hi); }
.para-list button.selected{ background:rgba(212,162,76,.14); border-color:rgba(212,162,76,.5); }
.para-list button.selected.active{ background:rgba(212,162,76,.24); border-color:var(--r-gold); }
/* éditeur de cartes : panes + sections + formulaire */
.ec-pane-left, #ec-selector, .ec-pane-middle{ border-right-color:var(--r-border); }
.ec-pane-palette{ background:var(--r-surface2); border-right-color:var(--r-border); }
.ec-section{ background:var(--r-surface1); border-color:var(--r-border); }
.ec-form-area input, .ec-form-area select, .ec-form-area textarea{ background:var(--r-surface2); border:1px solid var(--r-border); color:var(--r-text); }
.ec-preview-info, .ec-autosave-label{ color:var(--r-text2); }
.ec-preview-toolbar button{ background:var(--r-surface3); border:1px solid var(--r-border); color:var(--r-text); }
.ec-preview-toolbar button:hover{ background:var(--r-border); }

/* ============ ADMINISTRATION & GESTION DES DROITS (fragments) ============
   Clairs (#f9f9f9) → sombres. (Cadre modale déjà assombri par .center-panel.) */
.admin-section, .droits-campagne-block{ background:var(--r-surface1); border-color:var(--r-border); color:var(--r-text); }
.admin-section h3, .droits-campagne-block h3{ color:var(--r-gold); }
.admin-table th, .admin-table td{ border-color:var(--r-border); }
.admin-table th{ background:var(--r-surface3); color:var(--r-text); }
.admin-form input, .admin-form select{ background:var(--r-surface2); border:1px solid var(--r-border); color:var(--r-text); }
.admin-form button{ background:var(--r-surface3); border:1px solid var(--r-border); color:var(--r-text); }
.admin-form button:hover{ background:var(--r-border); }
.badge-none{ background:var(--r-surface3); color:var(--r-text3); }
.badge-lecture{ background:rgba(125,168,95,.2); color:#a6cd88; }
.badge-ecriture{ background:rgba(91,141,176,.2); color:#8fb0d8; }

/* ============ SITE VITRINE ============
   Déjà sombre mais en noirs FROIDS → harmonisé aux tokens chauds ; titres en or/Cinzel.
   Les images/vidéos = contenu, inchangées. */
body.site-mode #site-view{ background:var(--r-bg); color:var(--r-text); }
#site-nav{ background:var(--r-surface1); border-bottom-color:var(--r-border-hi); }
#site-nav .site-nav-item{ color:var(--r-text2); }
#site-nav .site-nav-item:hover{ color:var(--r-text); }
#site-nav .site-nav-item.active{ color:var(--r-gold); border-bottom-color:var(--r-accent); }
.site-hero h1{ color:var(--r-gold-hi); font-family:"Cinzel",Georgia,serif; }
.site-hero p{ color:var(--r-text2); }
.site-section h2{ color:var(--r-gold); font-family:"Cinzel",Georgia,serif; }
.site-section h3{ color:var(--r-text); }
.site-section a{ color:var(--r-gold-hi); }
.site-quote{ border-left-color:var(--r-accent); color:var(--r-text2); }
.site-quote .site-quote-author{ color:var(--r-gold); }
.site-figure figcaption{ color:var(--r-text3); }
#site-footer{ color:var(--r-text3); border-top-color:var(--r-border); }

/* ============ Item 9 — délimiter les pages : en-tête plus clair + contour marqué ============
   Constat : en-tête et corps partageaient --r-surface1 (aucune barre de titre distincte)
   et le contour --r-border-hi restait proche du fond de la zone de jeu → effet « plat ».
   Correctif : bandeaux éclaircis (--r-surface3), contour plus clair (--r-text3) + ombre
   portée pour un relief de « carte surélevée ». Placé en fin de fichier → l'emporte sur
   les règles par-page (border-color:--r-border-hi) grâce à l'ordre source.
   20260726 VCH */
/* En-têtes : bandeau éclairci + fine ombre sous le trait */
.side-panel-header,
.bottom-panel-header,
.center-panel:has(#campagnes-container) .center-panel-header{
  background:var(--r-surface3); box-shadow:0 1px 0 rgba(0,0,0,.4);
}
/* Contour + relief des pages (tous les sous-panneaux latéraux, quel que soit data-sub-page :
   couvre aussi le livre/livret qui gardaient l'ancien gris #8f8f8f) */
.left-sub-panel[data-sub-page]{
  border:1px solid var(--r-text3); box-shadow:0 12px 30px rgba(0,0,0,.55);
}
/* Panneau perso (bas) et fenêtre de choix des scénarios : même traitement */
#bottom-panel{ border:1px solid var(--r-text3); box-shadow:0 12px 30px rgba(0,0,0,.55); }
.center-panel:has(#campagnes-container){ border:1px solid var(--r-text3); box-shadow:0 16px 40px rgba(0,0,0,.6); }

/* Fond de la zone de jeu : noir chaud plus profond que --r-bg → creuse le contraste
   avec les pages (surface1) sans perdre la chaleur du thème. Scopé au jeu : les éditeurs
   et le site vitrine conservent --r-bg (#16130E). 20260726 VCH */
body,
#game-area{ background:#0B0907; }

/* Item 9 (suite) — encadrement UNIFORME de toutes les fenêtres du panneau central
   (À propos, Aide, Paramètres, Journal, Réseau…), pas seulement le choix des scénarios :
   contour clair + ombre « carte surélevée » + barre de titre éclaircie. Le placement en
   fin de fichier l'emporte sur le style de base (border --r-border-hi). L'écran de connexion
   (en-tête sans titre) garde le contour mais pas la barre éclaircie. 20260726 VCH */
.center-panel{ border:1px solid var(--r-text3); box-shadow:0 16px 40px rgba(0,0,0,.6); }
.center-panel:not([data-current-page="login"]) .center-panel-header{
  background:var(--r-surface3); box-shadow:0 1px 0 rgba(0,0,0,.4);
}

/* ============================================================================
   PAGE D'AIDE — sommaire + sections (refonte, tâche 1) — 20260801 VCH
   Rendue dans .center-panel-content (voir plus haut, `color:var(--r-text)`) : on
   réutilise ses variables de couleur plutôt que des couleurs en dur, pour rester
   cohérent quel que soit l'habillage du châssis. Le matériel (cartes/livre) n'est
   pas concerné ici, l'aide n'affiche que du texte de service.
   ========================================================================== */
.aide-sommaire{ display:flex; flex-direction:column; gap:6px; }
/* Le sommaire et les sections basculent via l'attribut HTML `hidden` (src/app_aide.js).
   Sans cette règle, notre propre `display:flex` (règle d'auteur) l'emporterait sur la
   feuille de style du navigateur (`[hidden]{display:none}`, d'origine UA) : l'origine
   prime sur la spécificité dans la cascade, donc une règle d'auteur bat toujours une
   règle UA à spécificité égale — l'élément resterait visuellement affiché malgré
   l'attribut `hidden` posé par le JS. */
.aide-sommaire[hidden],
.aide-section[hidden]{ display:none; }
.aide-intro{ color:var(--r-text2); margin:0 0 4px; }
.aide-lien{
  display:block; width:100%; min-height:44px; box-sizing:border-box;
  padding:10px 14px; text-align:left; font-size:1rem;
  background:var(--r-surface2); border:1px solid var(--r-border); border-radius:6px;
  color:var(--r-text); cursor:pointer;
}
.aide-lien:hover{ background:var(--r-surface3); border-color:var(--r-border-hi); }

.aide-section{ display:flex; flex-direction:column; }
.aide-retour{
  align-self:flex-start; margin-bottom:10px;
  background:none; border:none; padding:4px 0;
  color:var(--r-text2); font-size:0.9rem; cursor:pointer;
}
.aide-retour:hover{ color:var(--r-text); }
.aide-titre{
  margin:0 0 10px; color:var(--r-gold); font-family:"Cinzel",Georgia,serif;
  font-weight:600; letter-spacing:.02em;
}
/* 20260806 VCH les paragraphes de l'aide se touchaient : rien ne leur donnait de marge (ni
   `.texte-normal`, qui n'en porte pas, ni le navigateur, dont la marge par défaut est
   neutralisée plus haut). Peu gênant sur une section de trois paragraphes, illisible sur
   « Rappel des règles » qui en compte dix-huit. */
.aide-section p.texte-normal{ margin:0 0 10px; }
/* Intertitres de la section « Rappel des règles », la seule assez longue pour avoir besoin
   d'être découpée. Même famille que le titre de section, en plus petit et sans la majuscule
   d'apparat, pour rester une subdivision et non un second titre. */
.aide-sous-titre{
  margin:18px 0 6px; color:var(--r-gold); font-family:"Cinzel",Georgia,serif;
  font-weight:600; font-size:0.98rem; letter-spacing:.01em;
}
.aide-section .aide-sous-titre:first-of-type{ margin-top:10px; }
/* Pas de règle de couleur sur .texte-normal ici : .center-panel-content (plus haut,
   `color:var(--r-text)`) la fournit déjà par héritage. */

/* ─────────────────── Contrôle de zoom des zones de jeu (20260801 VCH) ───────────────────
   Bouton affichant le pourcentage courant, et petit ascenseur révélé au clic. Partagé par
   la barre d'outils de l'exploration et celle du plan (src/app_zoom.js). L'ascenseur est en
   `position: absolute` sous le bouton : il ne doit pas élargir la barre quand il s'ouvre,
   celle-ci étant déjà à l'étroit sur téléphone. */
.zoom-ctrl {
  position: relative;
  display: inline-flex;
  align-items: center;
}
.zoom-btn {
  font-variant-numeric: tabular-nums;   /* la largeur ne saute pas quand le nombre change */
  display: inline-flex;
  align-items: center;
  gap: 3px;
}
/* 20260816 VCH Loupe devant le pourcentage : le bouton ne disait rien de ce qu'il réglait,
   « 100 % » seul se confondant avec les autres boutons de la barre. SVG et non emoji, pour
   qu'elle suive la couleur du bouton (`currentColor`) au lieu d'imposer la sienne, dans le
   même trait que les icônes du rail de navigation (src/app_nav.js).
   Elle est DANS le bouton : une icône posée à côté ne serait pas cliquable, alors que c'est
   elle que l'œil vise. Le pourcentage vit donc dans .zoom-val (voir src/app_zoom.js). */
.zoom-icone {
  width: 1.05em;
  height: 1.05em;
  flex: none;                            /* jamais écrasée par le texte */
}
/* La largeur réservée porte sur le seul nombre (« 5 % » → « 100 % ») : sur le bouton, elle
   compterait aussi la loupe et laisserait un blanc à droite du pourcentage. */
.zoom-val {
  display: inline-block;
  min-width: 3.2em;
  text-align: center;
}
.zoom-range {
  position: absolute;
  top: calc(100% + 4px);
  left: 50%;
  transform: translateX(-50%);
  width: 140px;
  z-index: 3;                            /* au-dessus du canevas, sous les panneaux */
  background: var(--r-surface2, #2a2a2a);
  border: 1px solid var(--r-border, #555);
  border-radius: 6px;
  padding: 6px 8px;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.4);
}
.zoom-range[hidden] { display: none; }   /* une règle d'auteur l'emporterait sinon */

/* 20260802 VCH `.explo-toolbar input` et `.plan-toolbar input` (largeur du champ N°, 50 px et
   46 px) sont plus spécifiques que `.zoom-range` : elles écrasaient sa largeur, son padding et
   sa bordure. L'ascenseur ne mesurait donc que 50 px pour une plage de 15 à 200 %, soit 4 % par
   pixel — inutilisable. Ce sélecteur les reprend, à une largeur doublée (140 → 280 px).
   Le débordement hors écran, lui, ne peut pas se régler ici : `brancherZoom` (src/app_zoom.js)
   décale le popover à l'ouverture. */
.explo-toolbar .zoom-range,
.plan-toolbar .zoom-range {
  width: 280px;
  padding: 6px 8px;
  border: 1px solid var(--r-border, #555);
  border-radius: 6px;
}

/* 20260802 VCH accusé de réception visuel d'une coche du livre : rien ne disait au joueur
   qu'une case à cocher avait déclenché une action, l'effet se produisant souvent dans un
   panneau qu'il ne regarde pas (plateau, journal, personnage). La classe est posée par
   flashCoche (src/app_livre.js) sur le SCOPE que le parseur a lu — le <label>, ou le bloc
   parent quand le label est tronqué — et retirée à la fin de l'animation.

   Deux pulsations lentes (1,2 s au total, ~1,7 Hz) : bien en dessous du seuil de 3 Hz des
   recommandations sur la photosensibilité, et assez lent pour être vu du coin de l'œil sans
   être agressif au fil d'une lecture.

   Doré sur fond clair (--r-gold), jamais un assombrissement : le livre reste du papier
   imprimable. Le halo est un box-shadow et le fond une teinte à 12 % — rien qui masque le
   texte pendant l'animation. */
@keyframes ebs-flash-coche {
  0%   { box-shadow: 0 0 0 0 rgba(212, 162, 76, 0);    background-color: rgba(212, 162, 76, 0); }
  15%  { box-shadow: 0 0 0 3px rgba(212, 162, 76, .85); background-color: rgba(212, 162, 76, .12); }
  40%  { box-shadow: 0 0 0 3px rgba(212, 162, 76, .15); background-color: rgba(212, 162, 76, .02); }
  65%  { box-shadow: 0 0 0 3px rgba(212, 162, 76, .85); background-color: rgba(212, 162, 76, .12); }
  100% { box-shadow: 0 0 0 0 rgba(212, 162, 76, 0);    background-color: rgba(212, 162, 76, 0); }
}
.ebs-flash {
  animation: ebs-flash-coche 1.2s ease-out;
  border-radius: 4px;
}

/* Mouvement réduit : un seul fondu sortant, sans pulsation. Le repère reste (on voit bien
   quelle ligne a agi), mais plus rien ne clignote. */
@media (prefers-reduced-motion: reduce) {
  @keyframes ebs-flash-coche {
    0%   { box-shadow: 0 0 0 3px rgba(212, 162, 76, .85); background-color: rgba(212, 162, 76, .12); }
    100% { box-shadow: 0 0 0 0 rgba(212, 162, 76, 0);     background-color: rgba(212, 162, 76, 0); }
  }
  .ebs-flash { animation: ebs-flash-coche 1.2s ease-out; }
}

/* 20260803 VCH animation de pioche (butin, blessure) — src/app_anim_pioche.js.
   Les cartes de la pile apparaissent de dos, se mélangent, l'une sort du lot, se retourne et
   vole jusqu'à son emplacement. Un clic ou Échap coupe tout et donne le résultat.

   L'overlay capte les clics (pointer-events: auto) au lieu de les laisser passer : sinon le
   clic destiné à écourter l'animation traverserait jusqu'au bouton situé dessous et
   relancerait une pioche. Il absorbe le geste, l'écouteur de skip le reçoit par bulle. */
.anim-pioche-overlay {
  position: fixed;
  inset: 0;
  /* 20260814 VCH suit l'overlay des vols de coche dans sa nouvelle bande (voir plus bas), et
     garde son rang juste au-dessus de lui : une même coche peut produire les deux (« Piochez une
     arme », TST #144). Sa modalité y gagne au passage — le clic qui écourte l'animation était
     jusqu'ici avalé par une fenêtre centrale ouverte, alors qu'il doit être absorbé ici. */
  z-index: 1999999996;
  pointer-events: auto;
}

/* Chaque carte flottante : la largeur est posée en px par le JS, la hauteur suit via
   aspect-ratio: var(--carte-ratio) porté par .carte-container / .carte-dos. */
.anim-pioche-carte {
  position: fixed;
  pointer-events: none;
  opacity: 0;
  transform: translateY(12px) scale(.96);
  border-radius: 4px;
  box-shadow: 0 6px 18px rgba(0, 0, 0, .45);
  will-change: left, top, transform, opacity;
}

/* 20260803 VCH animation des coches du livre — src/app_anim_coche.js.
   Ce qu'une coche produit part de la case elle-même, grossit au centre de l'écran, puis rejoint
   sa place. Contrairement à l'overlay de pioche, celui-ci NE capte PAS les clics : une coche
   n'est pas un temps modal, le joueur doit pouvoir enchaîner ses cases pendant que ça vole.
   Le clic coupe l'animation (écouteur sur document) tout en atteignant sa cible. */
.anim-coche-overlay {
  position: fixed;
  inset: 0;
  /* 20260814 VCH monté de 9989 à cette bande : une destination peut vivre dans une FENÊTRE
     CENTRALE — le journal de bord, où atterrit la carte de quête (.journal-slot, DESTINATIONS
     de src/app_anim_coche.js). À 9989 le vol était dessiné derrière .center-panel (qui était à
     1999999999) : la carte traversait bien le journal, personne ne la voyait. Signalé par Vincent.
     Reste DÉLIBÉRÉMENT sous #menu (2e9), sous la bulle de tutoriel (2e9+1, qui explique ce que la
     coche vient de faire) et sous ebsConfirm/ebsAlert (2147483647, qui attendent une réponse),
     pour la même raison qui a fait monter la bulle le 20260801.
     Passe en revanche au-dessus des pickers du plateau (9999), du dé (10000) et de la bannière de
     mise à jour (100001) : tous transparents ou sans recouvrement possible avec un vol. */
  z-index: 1999999995;    /* juste sous l'overlay de pioche, qui lui est modal */
  pointer-events: none;
}

.anim-coche-vol {
  position: fixed;
  pointer-events: none;
  border-radius: 4px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, .5);
  will-change: left, top, transform;
}
/* Le clone hérite parfois de marges ou d'une largeur en % : on le force à remplir le vol. */
.anim-coche-vol > * {
  width: 100% !important;
  height: 100% !important;
  margin: 0 !important;
}

/* 20260804 VCH coche de RANGEMENT (« Rangez ⟨pion⟩ ») : le trajet est le même que pour un
   placement — de la coche au centre de l'écran — mais rien ne l'attend à l'arrivée puisque le pion
   quitte le jeu. Il éclate donc sur place, au centre : la dilatation + l'effacement + la rotation
   se lisent comme « retiré », là où un vol vers la piste des rounds dirait le contraire de l'effet.
   Durée alignée sur le `pause(420)` de voler() (src/app_anim_coche.js). */
.anim-coche-vol.anim-coche-explose {
  transition: none !important;
  animation: ebs-anim-explose 400ms cubic-bezier(.3, 0, .7, 1) forwards;
}
@keyframes ebs-anim-explose {
  0%   { filter: brightness(1);   opacity: 1; }
  30%  { filter: brightness(2.4); opacity: 1; }
  100% { filter: brightness(3);   opacity: 0;
         transform: translate(-50%, -50%) scale(var(--ebs-explose-echelle, 2.6)) rotate(14deg); }
}

/* Pastille pour ce qui n'a pas de nœud à cloner : un compteur, des PV. Doré comme le halo de
   flashCoche, pour rester dans le même vocabulaire visuel. */
.anim-coche-pastille {
  position: fixed;
  width: 14px;
  height: 14px;
  margin: -7px 0 0 -7px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(212, 162, 76, 1) 0%, rgba(212, 162, 76, .35) 70%, rgba(212, 162, 76, 0) 100%);
  pointer-events: none;
  opacity: .25;
  will-change: left, top, opacity, transform;
}

/* Mouvement réduit : les deux modules renoncent en amont (animationsCoupees), ce bloc n'est
   qu'une ceinture de sécurité si un vol était déjà en cours au changement de réglage. */
@media (prefers-reduced-motion: reduce) {
  .anim-coche-vol,
  .anim-coche-pastille { transition: none !important; }
  .anim-coche-vol.anim-coche-explose { animation: none !important; }
}

/* Pion qui se détache de la carte blessure quand celle-ci n'est pas conservée (personnage déjà
   blessé, règles p.21) : seul l'état rejoint la rivière. Part de l'opacité 0 pour éclore au
   centre de la carte. */
.anim-pioche-pion {
  position: fixed;
  pointer-events: none;
  opacity: 0;
  object-fit: contain;
  filter: drop-shadow(0 3px 8px rgba(0, 0, 0, .5));
  will-change: left, top, opacity;
}
