:root {
  /* Neutres — brun-anthracite chaud (charte v2, voir design_handoff_charte_visuelle/DESIGN.md) */
  --bg: oklch(15% 0.012 50);
  --bg-canvas: oklch(10% 0.014 50);       /* zone carte (Vue MJ), plus sombre encore */
  --bg-canvas-tile: oklch(13% 0.016 50);  /* damier de la zone carte */
  --panel: oklch(19% 0.014 50);
  --panel-raised: oklch(23% 0.016 50);
  --border: oklch(30% 0.02 50);
  --border-strong: oklch(38% 0.022 50);
  --text: oklch(94% 0.008 60);
  --muted: oklch(68% 0.02 55);
  --muted-2: oklch(54% 0.02 55);

  /* Accent marron/cuivré + sémantique */
  --accent: oklch(64% 0.12 50);
  --accent-hover: oklch(70% 0.11 50);
  --accent-soft: oklch(64% 0.12 50 / 0.14);
  --danger: oklch(64% 0.17 25);
  --danger-hover: oklch(70% 0.17 25);
  --danger-soft: oklch(64% 0.17 25 / 0.14);
  --success: oklch(78% 0.15 150);   /* PV */
  --success-soft: oklch(78% 0.15 150 / 0.14);
  --amber: oklch(78% 0.13 80);      /* XP / niveau */
  --amber-soft: oklch(78% 0.13 80 / 0.16);

  --font-body: "Space Grotesk", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-mono: "Space Mono", ui-monospace, "SF Mono", Menlo, monospace;

  /* Rayons */
  --radius-sm: 6px;   /* inputs, boutons */
  --radius-md: 12px;  /* cartes, lignes de liste */
  --radius-lg: 16px;  /* modales, bulles d'outils */
  --radius-pill: 999px;

  /* Ombres */
  --shadow-sm: 0 2px 8px rgba(0,0,0,0.35);
  --shadow-md: 0 8px 28px rgba(0,0,0,0.45);
  --shadow-lg: 0 20px 60px rgba(0,0,0,0.35);
}

* { box-sizing: border-box; }

.campaign-row, .feedback-row, .map-item { box-shadow: var(--shadow-sm); }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
}

header {
  padding: 0.75rem 1.25rem;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: space-between;
}

header h1 {
  font-size: 1.1rem;
  margin: 0;
  font-weight: 600;
}

header a {
  color: var(--muted);
  text-decoration: none;
  font-size: 0.85rem;
}
header a:hover { color: var(--text); }

/* Logo losange — remplace l'ancien emoji d'en-tête (voir DESIGN.md §4/§6). */
.app-title { display: flex; align-items: center; }
.logo-diamond {
  display: inline-block;
  width: 14px;
  height: 14px;
  min-width: 14px;
  background: var(--accent);
  border-radius: 3px;
  transform: rotate(45deg);
  margin-right: 0.65rem;
}

.layout {
  display: flex;
  height: calc(100vh - 53px);
}

.sidebar {
  width: 300px;
  flex-shrink: 0;
  border-right: 1px solid var(--border);
  padding: 1rem;
  overflow-y: auto; /* filet de sécurité si la fenêtre est vraiment trop courte */
  background: var(--panel);
  display: flex;
  flex-direction: column;
}

/* Panneau "Gérer les joueurs" — repliable (masqué par défaut), pas
   permanent comme le Groupe côté Joueurs : sert ponctuellement, pas en
   continu pendant la partie. */
.sidebar-right {
  border-right: none;
  border-left: 1px solid var(--border);
}
.sidebar-right-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 0.75rem;
}
.sidebar-right-header h2 { margin: 0; font-size: 1rem; }

.sidebar h2 {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted-2);
  margin: 1.25rem 0 0.5rem;
}
.sidebar h2:first-child { margin-top: 0; }

.map-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

/* Passé quelques cartes, c'est cette liste qui défile — pas tout le menu
   latéral (Importer / bouton Réinitialiser restent toujours visibles). */
.map-list.scrollable {
  max-height: 38vh;
  overflow-y: auto;
  padding-right: 0.2rem;
}

.map-item {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 0.5rem 0.6rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
}
.map-item.active { border-color: var(--accent); background: var(--accent-soft); }

.map-item .name {
  font-size: 0.9rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.map-item .actions { display: flex; gap: 0.3rem; flex-shrink: 0; }

/* Les <button>/<select> ne suivent PAS body{font-family} par défaut (feuille
   agent des navigateurs : police système, pas héritage) — contrairement au
   texte courant et aux <input> (déjà en font-family:inherit plus bas) ; sans
   ce reset la police choisie (Space Grotesk/Space Mono) manquait tous les
   boutons de l'appli, la majorité du chrome interactif. */
button, .btn, select {
  font-family: inherit;
}

button, .btn {
  cursor: pointer;
  border: 1px solid var(--border);
  background: var(--panel-raised);
  color: var(--text);
  border-radius: var(--radius-sm);
  padding: 0.35rem 0.6rem;
  font-size: 0.8rem;
  text-decoration: none;
  display: inline-block;
}
button:hover { background: var(--border); }

button.primary, a.btn.primary { background: var(--accent); border-color: var(--accent); color: var(--bg); font-weight: 700; }
button.primary:hover, a.btn.primary:hover { background: var(--accent-hover); }

button.danger, a.btn.danger { background: transparent; border-color: var(--danger); color: var(--danger); }
button.danger:hover, a.btn.danger:hover { background: var(--danger-soft); color: var(--danger-hover); }

button.toggle.active { background: var(--accent); border-color: var(--accent); color: var(--bg); }

button:disabled { opacity: 0.4; cursor: not-allowed; }

input[type=text], input[type=file], input[type=password], input[type=number], textarea {
  width: 100%;
  background: var(--bg);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: var(--radius-sm);
  padding: 0.4rem 0.5rem;
  font-size: 0.85rem;
  font-family: inherit;
}
textarea { resize: vertical; }

/* Les <input type=checkbox/radio/range> se dessinent nativement (pas de
   background/border comme les autres champs) et prennent par défaut le
   bleu du navigateur, pas notre accent cuivré — accent-color couvre tous
   les trois d'un coup (case Bibliothèque/PDF, curseurs Rayon/Dégradé…). */
input[type=checkbox], input[type=radio], input[type=range] {
  accent-color: var(--accent);
}

/* Dans la barre d'outils (ligne flex), un champ texte/nombre ne doit pas
   s'étirer à 100% de la largeur dispo — seulement dans les panneaux
   verticaux (modales, formulaires) où cette règle a été pensée à l'origine. */
.toolbar-option-group input[type=text],
.toolbar-option-group input[type=number] {
  width: auto;
  min-width: 7rem;
}

.feedback-link {
  position: fixed;
  bottom: 0.75rem;
  right: 1rem;
  z-index: 10;
  color: var(--muted);
  text-decoration: none;
  font-size: 0.8rem;
  opacity: 0.6;
}
.feedback-link:hover { opacity: 1; color: var(--text); }

.upload-form { display: flex; flex-direction: column; gap: 0.5rem; }

/* "Réinitialiser la carte" — bouton d'en-tête de la Bibliothèque, toujours
   visible (pas caché par le repli de .collapsible-body). */
.sidebar-full-btn { width: 100%; margin: 0.75rem 0 0; }

.menu-tabs {
  display: flex;
  gap: 0;
  margin: 1.25rem 0 1rem;
  border-bottom: 1px solid var(--border);
}

.menu-tab {
  flex: 1;
  background: transparent;
  border: none;
  border-bottom: 2px solid transparent;
  border-radius: 0;
  padding: 0.55rem 0.4rem;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--muted);
  margin-bottom: -1px;
}
.menu-tab:hover { color: var(--text); background: transparent; }
.menu-tab.active { color: var(--accent); border-bottom-color: var(--accent); }

.tools {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  margin-top: 1rem;
}

.tool-group {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}

.field-label {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 600;
  color: var(--muted-2);
}

.tool-divider {
  border: none;
  border-top: 1px solid var(--border);
  margin: 0.1rem 0;
  width: 100%;
}

.tools .row { display: flex; gap: 0.4rem; }
.tools .row button { flex: 1; }

#tokenPanel, #styloPanel { display: flex; flex-direction: column; gap: 0.6rem; }

.radius-row { display: flex; align-items: center; gap: 0.5rem; font-size: 0.8rem; color: var(--muted); }
.radius-row input[type=range] { flex: 1; }

.main-column {
  flex: 1;
  min-width: 0;
  /* Ancre .dice-controls, .toolbar-icons et .toolbar-bubble, tous en
     superposition flottante par-dessus la carte — et surtout PAS enfants de
     .canvas-area : ce dernier défile (overflow:auto), et un enfant absolute
     d'un ancêtre positionné qui défile fait partie du contenu qui défile
     avec lui. C'est exactement ce qui faisait disparaître les contrôles de
     zoom au zoom, à l'époque où ils vivaient ici (désormais dans la bulle
     de la loupe, voir #zoomOptionsBubble). */
  position: relative;
  display: flex;
  flex-direction: column;
}

.canvas-area {
  flex: 1;
  min-height: 0; /* indispensable pour qu'overflow:auto marche dans une colonne flex */
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: auto;
  background: var(--bg-canvas);
  background-image:
    linear-gradient(45deg, var(--bg-canvas-tile) 25%, transparent 25%),
    linear-gradient(-45deg, var(--bg-canvas-tile) 25%, transparent 25%),
    linear-gradient(45deg, transparent 75%, var(--bg-canvas-tile) 75%),
    linear-gradient(-45deg, transparent 75%, var(--bg-canvas-tile) 75%);
  background-size: 24px 24px;
  background-position: 0 0, 0 12px, 12px -12px, -12px 0px;
  padding: 1rem;
}

.canvas-host {
  width: 100%;
  height: 100%;
  display: flex;
  /* "safe" : centre quand le canvas tient dans la fenêtre (zoom ajusté),
     mais bascule en alignement au bord dès qu'il déborde (zoom > 100%) —
     sans ça, .canvas-area{overflow:auto} a un point de défilement de départ
     ambigu selon les navigateurs quand le contenu centré déborde, ce qui
     rendait le calcul de scrollLeft/scrollTop de gm.js imprévisible. */
  align-items: safe center;
  justify-content: safe center;
}

/* Pas de max-width/max-height ici : la taille affichée (ajustée au
   conteneur à 100%, agrandie au-delà en zoom) est calculée et posée en
   pixels par gm.js — voir applyZoom()/baseFitSize(). */
canvas {
  cursor: crosshair;
  box-shadow: 0 4px 30px rgba(0,0,0,0.5);
}

/* Pourcentage de zoom, affiché dynamiquement au-dessus de la loupe à chaque
   changement — même langage visuel que les bulles des autres outils, mais
   transitoire (se referme tout seul après un court instant sans nouveau
   changement). Les boutons −/+/⛶ eux-mêmes vivent dans #zoomOptionsBubble,
   une .toolbar-bubble ordinaire ouverte tant que la loupe est active. */
.zoom-level-badge {
  width: auto;
  min-width: 0;
  padding: 0.4rem 0.75rem;
  font-family: var(--font-mono);
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--muted-2);
  text-align: center;
  gap: 0;
}
.zoom-controls-sep {
  width: 1px;
  align-self: stretch;
  background: var(--border);
  margin: 0 0.15rem;
}

/* -- Barre d'outils : pilule d'icônes flottante + bulle d'options ---------- */
/* Deux éléments flottants distincts plutôt qu'un seul bloc qui grossit avec
   l'outil actif : la pilule d'icônes (déplaçable) garde toujours la même
   taille, et la bulle d'options s'ouvre à part, au-dessus, repositionnée en
   JS (voir positionToolbarBubble() dans shared.js) — elle ne fait donc
   jamais "gonfler" ni mal se replacer la barre elle-même en la déplaçant. */

.toolbar-icons {
  position: absolute;
  left: 50%;
  bottom: 1rem;
  transform: translateX(-50%);
  z-index: 6;
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.45rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  background: oklch(19% 0.014 50 / 0.92);
  backdrop-filter: blur(6px);
  box-shadow: var(--shadow-md);
}

.toolbar-drag-handle {
  cursor: grab;
  font-size: 1rem;
  line-height: 1;
  color: var(--muted);
  padding: 0 0.2rem;
  user-select: none;
}
.toolbar-drag-handle:hover { color: var(--text); }
.toolbar-drag-handle:active { cursor: grabbing; }

.toolbar-icon-btn {
  position: relative;
  font-size: 1.3rem;
  line-height: 1;
  width: 2.6rem;
  height: 2.6rem;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-pill);
  background: var(--bg);
}
.toolbar-icon-btn.active {
  background: var(--accent);
  border-color: var(--accent);
}

/* Largeur fixe (ne "respire" jamais en changeant d'outil — c'était le
   défaut qui rendait mal en déplaçant la barre) ; la hauteur, elle, suit
   librement son contenu — pas de plafond/défilement interne (rendait une
   barre de défilement disgracieuse). Position (left/bottom) posée en JS. */
.toolbar-bubble {
  position: absolute;
  z-index: 6;
  width: min(320px, calc(100% - 2rem));
  padding: 0.85rem 1rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: oklch(19% 0.014 50 / 0.95);
  backdrop-filter: blur(6px);
  box-shadow: 0 10px 34px rgba(0,0,0,0.5);
  display: flex;
  flex-direction: column;
  gap: 0.65rem;
}
/* Petite pointe façon bulle de dialogue vers la barre d'icônes en dessous —
   sa position (--tail-left) suit la barre même quand la bulle est bornée
   pour ne pas déborder de l'écran (voir positionToolbarBubble()). */
.toolbar-bubble::after {
  content: "";
  position: absolute;
  left: var(--tail-left, 50%);
  bottom: -8px;
  transform: translateX(-50%);
  border: 8px solid transparent;
  border-top-color: oklch(19% 0.014 50 / 0.95);
  border-bottom: 0;
}

/* Chaque famille de réglages sur sa propre ligne (empilées), plutôt qu'un
   flux horizontal qui s'enroule — c'était le "tout sur la même ligne". */
.toolbar-option-group {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 0.5rem;
}
/* flex-wrap : la bulle a une largeur fixe (voir .toolbar-bubble) — sans ça,
   une ligne trop chargée (ex. calibration de la Règle : 2 champs + 2
   boutons) déborde hors de la bulle au lieu de passer à la ligne. C'était
   le bug du bouton "Annuler" qui se retrouvait visuellement hors de la
   fenêtre de l'outil Règle. */
.toolbar-option-group .row { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.toolbar-bubble > .row { display: flex; flex-wrap: wrap; gap: 0.4rem; } /* #modeRow, hors groupe (partagé Pinceau/Zone) */

/* -- Stats Monstre (Attaque/PV) — voir ADR 0009 ----------------------------- */

.monster-stats-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 0.1rem;
}
.monster-stats-header strong { font-size: 0.95rem; }

.stat-attack-label, .stat-attack-value, .stat-attack-input { color: var(--danger); }
.stat-hp-label, .stat-hp-value, .stat-hp-input { color: var(--success); }
.stat-attack-value, .stat-hp-value { margin: 0 0 0.4rem; font-weight: 600; font-family: var(--font-mono); }
.monster-stats-bubble input[type=text] { margin-bottom: 0.3rem; }

/* -- Annotation (bulle partage .monster-stats-bubble, voir gm.html/player.html) -- */

#annotationBubble textarea,
#annotationBubble .row:first-of-type { margin-bottom: 0.4rem; }
#annotationTextInput { width: 100%; }

/* Petit badge persistant (ex. dernier résultat de dé) sur l'icône d'un
   outil replié — visible sans avoir à l'ouvrir, façon badge de notification. */
.toolbar-icon-badge {
  position: absolute;
  top: -0.3rem;
  right: -0.3rem;
  min-width: 1.15rem;
  height: 1.15rem;
  padding: 0 0.3rem;
  border-radius: var(--radius-pill);
  background: var(--accent);
  color: var(--bg);
  font-family: var(--font-mono);
  font-size: 0.62rem;
  font-weight: 700;
  align-items: center;
  justify-content: center;
  line-height: 1;
  box-shadow: 0 0 0 2px var(--panel);
}
.toolbar-icon-badge.crit-success { background: var(--success); color: var(--bg); }
.toolbar-icon-badge.crit-fail { background: var(--danger); }

.empty-state {
  color: var(--muted);
  text-align: center;
  font-size: 1rem;
}

.player-layout {
  display: flex;
  height: 100vh;
}

.player-main {
  flex: 1;
  min-width: 0;
  position: relative; /* ancre .toolbar-icons, .toolbar-bubble et .dice-toast, tous en superposition flottante */
  display: flex;
  flex-direction: column;
}

/* Table en bois (bandes de lattes verticales + grain fin) plutôt qu'un fond
   noir plein — renforce l'idée de plateau de jeu physique, voir DESIGN.md
   §7. Généré en CSS par gradients répétés, pas d'image. */
/* Fond neutre (gris plat, chroma nulle — volontairement hors de la palette
   cuivrée) derrière la Carte : sert de socle au cadre "cartographie" de
   .player-map-svg, qui y paraît surélevé par son ombre portée. Remplace
   l'ancienne texture bois. */
.player-view {
  flex: 1;
  min-width: 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.75rem;
  padding: 1.5rem;
  overflow: hidden;
  background: oklch(24% 0 0);
}

.player-map-title {
  margin: 0;
  flex-shrink: 0;
  font-size: 2rem;
  font-weight: 700;
  color: #fff;
  text-align: center;
  text-shadow: 0 2px 10px rgba(0,0,0,0.9);
}

.player-svg-wrap {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 0;
  flex: 1;
}

/* Le viewBox (posé par gm.js/player.js) fait tout le travail de
   recadrage/zoom — le SVG lui-même n'a qu'à remplir l'espace disponible en
   gardant les proportions de la zone affichée. */
/* Cadre "cartographie" : liseré sombre + bande cuivre/parchemin (même
   teinte que le placeholder de carte importée, voir DESIGN.md §6) + liseré
   intérieur, empilés en box-shadow plutôt qu'en border — n'affecte pas la
   taille layoutée (width/height:auto restent pilotés par le viewBox), et
   l'ombre portée donne l'effet "surélevé" sur le fond gris de .player-view. */
.player-map-svg {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  cursor: crosshair;
  border-radius: 4px;
  box-shadow:
    0 0 0 1px oklch(30% 0.02 50),
    0 0 0 6px oklch(38% 0.06 60),
    0 0 0 7px oklch(20% 0.02 50),
    0 16px 36px rgba(0,0,0,0.55);
}

/* Jeton Personnage : nom masqué par défaut, affiché seulement au survol —
   jetons plus discrets sur la carte (voir shared.js/tokenSizeMultiplier et
   player.js/refreshTokens). Les autres catégories gardent leur nom toujours
   visible (pas de règle équivalente pour elles). */
.token-personnage .token-name-label {
  opacity: 0;
  transition: opacity 0.12s ease;
}
.token-personnage:hover .token-name-label { opacity: 1; }

/* Vraie colonne latérale ancrée à droite (au lieu d'une fenêtre flottante) —
   sibling direct de .player-main dans .player-layout (flex row), pousse la
   Carte plutôt que de flotter par-dessus ; même ton opaque que
   .sidebar/.sidebar-right côté MJ. Repliable en bande étroite (voir
   .collapsed plus bas), état mémorisé par appareil (voir player.js). */
.player-side-panel {
  width: 300px;
  flex-shrink: 0;
  background: var(--panel);
  border-left: 1px solid var(--border);
  padding: 1rem;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 1rem;
  transition: width 0.15s ease;
}
/* Repliée : bande étroite (icône Groupe + chevron pour redéplier) — libère
   vraiment la largeur à la Carte, contrairement à un simple repli de
   contenu qui garderait la colonne pleine largeur (voir .dice-controls
   côté MJ, qui lui ne fait QUE masquer son contenu — cas différent, un
   panneau flottant n'a pas de largeur à rendre à personne). */
.player-side-panel.collapsed {
  width: 44px;
  padding: 0.75rem 0;
  overflow: visible;
  align-items: center;
}
.player-side-panel.collapsed .player-panel-header,
.player-side-panel.collapsed .player-general-note,
.player-side-panel.collapsed .player-roster {
  display: none;
}

/* Note générale (voir CONTEXT.md) : emplacement propre, pas rattaché au
   widget Dés — présent dans les deux modes de Vue Joueurs (contrairement
   aux Dés, masqués en Sur Place, voir "Barre d'outils Joueurs"). */
.player-general-note {
  padding: 0.6rem 0.7rem;
  margin-bottom: 0.8rem;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--panel-raised);
}
.player-general-note .field-label { margin-bottom: 0.3rem; }
.player-general-note p:last-child { margin: 0; white-space: pre-wrap; }
.player-panel-rail-btn {
  display: none;
  background: transparent;
  border: none;
  color: var(--muted);
  padding: 0;
  flex-direction: column;
  align-items: center;
  gap: 0.6rem;
}
.player-panel-rail-btn:hover { color: var(--text); background: transparent; }
.player-side-panel.collapsed .player-panel-rail-btn { display: flex; }
/* Chevron inversé (bande repliée : pointe vers l'intérieur, "déplier") —
   pas de fichier chevron-left séparé, un simple retournement suffit. */
.icon-flip { transform: scaleX(-1); }

.player-panel-title {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted-2);
  margin: 0 0 0.6rem;
}

.player-panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin-bottom: 0.6rem;
}
.player-panel-header .player-panel-title { margin-bottom: 0; }
.player-panel-header-actions { display: flex; align-items: center; gap: 0.4rem; flex-shrink: 0; }

/* -- Dés : icônes directes + résultat flottant ------------------------------ */

.dice-die-btn {
  width: auto;
  min-width: 2.75rem;
  padding: 0 0.55rem;
  font-size: 0.85rem;
  font-weight: 700;
}

.dice-toast {
  position: absolute;
  left: 50%;
  bottom: 4.75rem; /* au-dessus de la pilule d'icônes flottante */
  transform: translateX(-50%);
  z-index: 6;
  padding: 0.5rem 0.9rem;
  border-radius: var(--radius-pill);
  background: oklch(19% 0.014 50 / 0.92);
  border: 1px solid var(--border);
  backdrop-filter: blur(6px);
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: 0.95rem;
  white-space: nowrap;
  box-shadow: 0 6px 22px rgba(0,0,0,0.4);
  opacity: 1;
  transition: opacity 0.3s ease; /* disparition en fondu, Vue En Ligne uniquement — voir showDiceResult (player.js) */
}
.dice-toast.dice-toast-fading { opacity: 0; }
.dice-toast.crit-success { color: var(--success); border-color: var(--success); }
.dice-toast.crit-fail { color: var(--danger); border-color: var(--danger); animation: shake 0.4s; }

.dice-toast-lg { font-size: 1.3rem; padding: 0.75rem 1.3rem; }

/* -- Sélecteur de Personnage (Vue En Ligne) --------------------------------- */

.character-picker-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
  gap: 0.6rem;
  margin: 0.75rem 0;
}
.character-picker-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.4rem;
  padding: 0.75rem 0.5rem;
  background: var(--bg);
  border: 2px solid var(--border);
  border-radius: var(--radius-md);
  cursor: pointer;
}
.character-picker-card:hover { border-color: var(--accent); }
.character-picker-icon {
  width: 3rem;
  height: 3rem;
  min-width: 3rem;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.5rem;
  border: 2px solid rgba(255,255,255,0.3);
}
.character-picker-name {
  font-size: 0.85rem;
  font-weight: 600;
  text-align: center;
}

/* Léger accent pour repérer sa propre ligne dans le Groupe, en Vue En Ligne. */
.player-row.mine {
  border-color: var(--accent);
  background: var(--accent-soft);
}

/* -- Sections repliables (Bibliothèque MJ, Dés MJ) -------------------------- */

.collapsible-toggle {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: transparent;
  border: none;
  padding: 0.3rem 0;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted-2);
  font-weight: 600;
}
.collapsible-toggle:hover { color: var(--text); background: transparent; }

.collapsible-chevron { transition: transform 0.15s; }
.collapsible-toggle.open .collapsible-chevron { transform: rotate(90deg); }

.collapsible-body { margin-top: 0.5rem; }

.dice-row {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0.4rem;
  margin-bottom: 0.6rem;
}

.dice-roll-btn { width: 100%; margin-bottom: 0.6rem; }

/* d100 : reste dans la même grille que les autres dés (même bouton, même
   arrondi) mais étend ses colonnes pour combler le reste de sa ligne au
   lieu de laisser un trou — à côté de d20, pas sur une ligne à lui tout
   seul. Grille Joueurs à 4 colonnes : 6 dés avant lui remplissent une
   ligne + 2 (d12/d20), il prend donc les 2 colonnes restantes. Grille MJ à
   3 colonnes : 6 dés la remplissent exactement, il prend alors sa propre
   ligne pleine largeur (span 3) — même bouton, juste plus large. */
.dice-die-100-cell { grid-column: span 2; }
.dice-row-lg .dice-die-100-cell { grid-column: span 3; }

.dice-result {
  text-align: center;
  font-family: var(--font-mono);
  font-size: 1.6rem;
  font-weight: 700;
  padding: 0.6rem 0.5rem;
  border-radius: var(--radius-md);
  background: var(--bg);
  border: 1px solid var(--border);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: background 0.2s, border-color 0.2s, color 0.2s;
}

/* Un peu plus gros dans le panneau Dés du MJ, qui a la place (voir CONTEXT.md). */
.dice-row-lg { grid-template-columns: repeat(3, 1fr); gap: 0.5rem; }
.dice-row-lg button { padding: 0.55rem 0; font-size: 0.95rem; }
.dice-result-lg {
  font-size: 1.4rem;
  padding: 0.7rem 0.6rem;
  /* Passe sur 2 lignes plutôt que de tronquer — un nom de Personnage long
     coupé en plein milieu (ellipse) rendait le résultat illisible. */
  white-space: normal;
  overflow: visible;
  text-overflow: clip;
  line-height: 1.25;
}

/* Panneau flottant en haut à droite — remplace l'ancienne section repliable
   du menu latéral, dont la largeur fixe et étroite tronquait le résultat
   pour un nom de Personnage ou un type de dé un peu long. Repliable par le
   MJ (voir .collapsed) : se déplie automatiquement à chaque lancer. */
/* Empile Dés + Note générale en haut à droite sans dépendre d'un décalage
   en pixels codé en dur (la hauteur du panneau Dés varie : replié, ou pas)
   — voir gm.html. */
.top-right-stack {
  position: absolute;
  top: 0.75rem;
  right: 0.75rem;
  z-index: 6;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.5rem;
}
.top-right-stack .dice-controls { position: static; }

.dice-controls {
  width: min(260px, calc(100% - 1.5rem));
  padding: 0.75rem;
  border: 1px solid var(--border);
  border-radius: 14px;
  background: oklch(19% 0.014 50 / 0.92);
  backdrop-filter: blur(6px);
  box-shadow: var(--shadow-md);
}
#generalNotePanel textarea { margin-bottom: 0.5rem; }
#generalNotePanel.collapsed textarea,
#generalNotePanel.collapsed .row {
  display: none;
}
.dice-controls-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
}
.dice-controls-title {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--muted-2);
}
.dice-controls:not(.collapsed) .dice-controls-header { margin-bottom: 0.5rem; }
.dice-controls .dice-row-lg { margin-bottom: 0.5rem; }
.dice-controls .dice-roll-btn { margin-bottom: 0.5rem; }
.dice-controls.collapsed { width: auto; padding: 0.5rem 0.75rem; }
.dice-controls.collapsed .dice-row-lg,
.dice-controls.collapsed .dice-roll-btn,
.dice-controls.collapsed .dice-result-lg {
  display: none;
}

.dice-result.crit-success {
  color: var(--success);
  border-color: var(--success);
  background: var(--success-soft);
}
.dice-result.crit-fail {
  color: var(--danger);
  border-color: var(--danger);
  background: var(--danger-soft);
  animation: shake 0.4s;
}
@keyframes shake {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-4px); }
  75% { transform: translateX(4px); }
}

.stroke-layer {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

/* Repère discret "quelle vue/app" en haut à gauche, à côté du retour
   Accueil — jamais un vrai en-tête (la Carte reste plein cadre, voir
   DESIGN.md §7) : juste de quoi savoir où on est, comme un Joueur qui
   arrive par un lien direct sans être passé par l'Accueil. */
.player-brand-bar {
  position: fixed;
  top: 0.6rem;
  left: 0.6rem;
  z-index: 10;
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.player-home-link {
  color: rgba(255,255,255,0.35);
  text-decoration: none;
  font-size: 1.2rem;
  padding: 0.2rem 0.5rem;
}
.player-home-link:hover { color: rgba(255,255,255,0.9); }

.player-brand-label {
  display: flex;
  align-items: center;
  font-size: 0.8rem;
  font-weight: 600;
  color: rgba(255,255,255,0.5);
  text-shadow: 0 1px 6px rgba(0,0,0,0.85);
}
.player-brand-label .logo-diamond {
  width: 10px;
  height: 10px;
  min-width: 10px;
  margin-right: 0.5rem;
  filter: drop-shadow(0 1px 4px rgba(0,0,0,0.85));
}

.token-marker {
  position: absolute;
  transform: translate(-50%, -50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  pointer-events: none;
}

.token-marker .token-icon {
  width: 2.2em;
  height: 2.2em;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1rem;
  border: 2px solid rgba(255,255,255,0.6);
  box-shadow: 0 2px 8px rgba(0,0,0,0.5);
}
/* Le Boss n'agrandit QUE font-size : width/height sont en `em` sur la règle
   de base, donc ils grossissent avec elle en gardant la même proportion
   icône/cercle (les surcharger séparément désynchronise les deux). */
.token-marker.boss .token-icon { font-size: 1.3rem; }

.token-marker .token-icon.objet {
  background: transparent;
  border: none;
  box-shadow: 0 2px 6px rgba(0,0,0,0.7);
}

.token-marker .token-label {
  margin-top: 2px;
  font-size: 0.7rem;
  color: #fff;
  background: rgba(0,0,0,0.55);
  padding: 1px 6px;
  border-radius: 6px;
  white-space: nowrap;
}

.hint { font-size: 0.75rem; color: var(--muted); line-height: 1.4; }

/* -- Page d'accueil ------------------------------------------------------ */

.home {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  text-align: center;
  padding: 2rem 1rem;
}

.home-title { font-size: 1.8rem; margin: 0; }
.home-subtitle { color: var(--muted); margin: 0 0 1.5rem; }

.home-cards {
  display: flex;
  gap: 1.25rem;
  flex-wrap: wrap;
  justify-content: center;
}

.home-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.4rem;
  width: 220px;
  padding: 1.75rem 1.25rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--panel);
  color: var(--text);
  text-decoration: none;
  transition: border-color 0.15s, transform 0.15s;
}
.home-card:hover { border-color: var(--accent); background: var(--accent-soft); transform: translateY(-2px); }

.home-card-icon { font-size: 2.8rem; line-height: 1; }
.home-card-label { font-size: 1.05rem; font-weight: 600; }
.home-card-hint { font-size: 0.78rem; color: var(--muted); }

.admin-footer-link {
  margin-top: 2rem;
  font-size: 0.8rem;
  color: var(--muted-2);
  text-decoration: none;
}
.admin-footer-link:hover { color: var(--text); }
/* "← Changer de campagne" (choix du rôle) — en accent, voir DESIGN.md §5. */
.admin-footer-link.accent { color: var(--accent); }
.admin-footer-link.accent:hover { color: var(--accent-hover); }

.auth-gate {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.75rem;
  width: min(320px, 90vw);
}
.auth-gate input[type=password],
.auth-gate input[type=text] { width: 100%; text-align: center; }
.auth-gate .error { color: var(--danger); font-size: 0.85rem; min-height: 1.2em; }

/* Carte de connexion (Admin, choix de campagne) — voir DESIGN.md §4. */
.login-card {
  width: min(340px, 90vw);
  margin: 5rem auto;
  padding: 2rem 1.75rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--panel);
  box-shadow: var(--shadow-lg);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1rem;
}
/* Déjà centrée verticalement par .home (justify-content:center) — pas besoin
   de la marge supplémentaire pensée pour #loginSection (Admin), qui n'a pas
   ce centrage. */
.home .login-card { margin: 0 auto; }
.login-card-title { font-size: 1rem; font-weight: 600; text-align: center; }
.login-card-subtitle { font-size: 0.8rem; color: var(--muted-2); text-align: center; margin-top: 4px; }

/* Icône cadenas (carte de connexion) — voir ADR 0011 : remplace l'ancienne
   forme dessinée en CSS par l'icône Untitled UI `lock-01`. */
.login-card-icon { font-size: 28px; color: var(--muted); }

.admin-page {
  max-width: 560px;
  margin: 2rem auto;
  padding: 0 1rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1rem;
}
.admin-page h2 { align-self: flex-start; font-size: 1rem; margin: 0; }
.admin-page .player-roster { width: 100%; }
.admin-page .upload-form { width: 100%; }
.admin-page .player-row-header { justify-content: space-between; }

/* Tableau de bord Admin — grille 2 colonnes (Campagnes / Retours), voir
   DESIGN.md §4. */
.admin-page-wide { max-width: 1000px; align-items: stretch; }
.admin-dashboard {
  width: 100%;
  display: grid;
  grid-template-columns: 1.4fr 1fr;
  gap: 2.5rem;
  align-items: start;
}
@media (max-width: 860px) {
  .admin-dashboard { grid-template-columns: 1fr; }
}
.admin-column-header {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 1rem;
}
.admin-kicker {
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted-2);
}
.admin-count-badge {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  padding: 2px 8px;
  border-radius: var(--radius-pill);
  background: var(--accent-soft);
  color: var(--accent);
}
.admin-count-badge.amber { background: var(--amber-soft); color: var(--amber); }

.campaign-list, .feedback-list {
  list-style: none;
  margin: 0 0 1.5rem;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.admin-create-card {
  padding: 1.25rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--panel);
}

/* Ligne de campagne (Admin) — avatar + nom/méta + actions. */
.campaign-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.7rem 0.85rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--panel-raised);
}
.campaign-row-avatar {
  width: 36px;
  height: 36px;
  min-width: 36px;
  border-radius: 50%;
  background: var(--panel);
  border: 2px solid var(--border-strong);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 16px;
  flex-shrink: 0;
}
.campaign-row-info { flex: 1; min-width: 0; }
.campaign-row-name {
  font-weight: 600;
  font-size: 0.875rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.campaign-row-meta {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  color: var(--muted-2);
  margin-top: 2px;
}

/* Ligne de retour utilisateur (Admin). */
.feedback-row {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  padding: 0.7rem 0.85rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--panel);
}
.feedback-row.resolved { opacity: 0.55; }
.feedback-row-icon {
  width: 22px;
  height: 22px;
  min-width: 22px;
  margin-top: 2px;
  border-radius: 50%;
  border: 2px solid var(--muted);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  flex-shrink: 0;
}
.feedback-row-body { flex: 1; min-width: 0; }
.feedback-row-text { margin: 0; font-size: 0.8rem; line-height: 1.45; }
.feedback-row.resolved .feedback-row-text { text-decoration: line-through; }
.feedback-row-meta {
  font-family: var(--font-mono);
  font-size: 0.65rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted-2);
  margin-top: 6px;
}
.feedback-row-actions { display: flex; gap: 6px; flex-shrink: 0; }

/* Bouton icône carré (crayon/corbeille/check…) — voir composant §2 de
   DESIGN.md. Hover neutre par défaut ; `.danger` teinte le hover pour une
   action destructive. */
.icon-btn-square {
  width: 30px;
  height: 30px;
  min-width: 30px;
  padding: 0;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  border-radius: var(--radius-sm);
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text);
}
.icon-btn-square:hover { background: var(--panel-raised); }
.icon-btn-square.danger:hover { background: var(--danger-soft); }

/* -- Icônes de trait (Untitled UI, chrome fonctionnel) — voir ADR 0011 ------ */
/* CSS mask plutôt que <img> : seule la forme (canal alpha) du SVG référencé
   est retenue, la couleur vient de background-color:currentColor sur CET
   élément — recolorable comme du texte (hover, --danger, --accent…) sans
   variante de fichier par couleur. Taille en 1em : suit le font-size du
   contexte, comme le faisait l'emoji qu'elle remplace. */
.icon {
  display: inline-block;
  width: 1em;
  height: 1em;
  flex-shrink: 0;
  background-color: currentColor;
  vertical-align: -0.15em;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
}
/* Icône suivie de texte dans le même bouton/libellé (au lieu de seule dans
   un bouton carré) : petit espace pour ne pas coller au mot suivant. */
.icon-inline { margin-right: 0.4em; }

.icon-edit-01 { -webkit-mask-image: url(/static/icons/edit-01.svg); mask-image: url(/static/icons/edit-01.svg); }
.icon-trash-01 { -webkit-mask-image: url(/static/icons/trash-01.svg); mask-image: url(/static/icons/trash-01.svg); }
.icon-check-circle { -webkit-mask-image: url(/static/icons/check-circle.svg); mask-image: url(/static/icons/check-circle.svg); }
.icon-plus { -webkit-mask-image: url(/static/icons/plus.svg); mask-image: url(/static/icons/plus.svg); }
.icon-x-close { -webkit-mask-image: url(/static/icons/x-close.svg); mask-image: url(/static/icons/x-close.svg); }
.icon-search-lg { -webkit-mask-image: url(/static/icons/search-lg.svg); mask-image: url(/static/icons/search-lg.svg); }
.icon-ruler { -webkit-mask-image: url(/static/icons/ruler.svg); mask-image: url(/static/icons/ruler.svg); }
.icon-lock-01 { -webkit-mask-image: url(/static/icons/lock-01.svg); mask-image: url(/static/icons/lock-01.svg); }
.icon-users-01 { -webkit-mask-image: url(/static/icons/users-01.svg); mask-image: url(/static/icons/users-01.svg); }
.icon-refresh-cw-01 { -webkit-mask-image: url(/static/icons/refresh-cw-01.svg); mask-image: url(/static/icons/refresh-cw-01.svg); }
.icon-dots-grid { -webkit-mask-image: url(/static/icons/dots-grid.svg); mask-image: url(/static/icons/dots-grid.svg); }
.icon-chevron-right { -webkit-mask-image: url(/static/icons/chevron-right.svg); mask-image: url(/static/icons/chevron-right.svg); }
.icon-chevron-down { -webkit-mask-image: url(/static/icons/chevron-down.svg); mask-image: url(/static/icons/chevron-down.svg); }
.icon-lightbulb-05 { -webkit-mask-image: url(/static/icons/lightbulb-05.svg); mask-image: url(/static/icons/lightbulb-05.svg); }
.icon-heart { -webkit-mask-image: url(/static/icons/heart.svg); mask-image: url(/static/icons/heart.svg); }
.icon-shield-01 { -webkit-mask-image: url(/static/icons/shield-01.svg); mask-image: url(/static/icons/shield-01.svg); }
.icon-backpack { -webkit-mask-image: url(/static/icons/backpack.svg); mask-image: url(/static/icons/backpack.svg); }
.icon-cloud-01 { -webkit-mask-image: url(/static/icons/cloud-01.svg); mask-image: url(/static/icons/cloud-01.svg); }
.icon-pen-tool-02 { -webkit-mask-image: url(/static/icons/pen-tool-02.svg); mask-image: url(/static/icons/pen-tool-02.svg); }
.icon-arrow-left { -webkit-mask-image: url(/static/icons/arrow-left.svg); mask-image: url(/static/icons/arrow-left.svg); }
.icon-globe-01 { -webkit-mask-image: url(/static/icons/globe-01.svg); mask-image: url(/static/icons/globe-01.svg); }
.icon-settings-01 { -webkit-mask-image: url(/static/icons/settings-01.svg); mask-image: url(/static/icons/settings-01.svg); }
.icon-upload-01 { -webkit-mask-image: url(/static/icons/upload-01.svg); mask-image: url(/static/icons/upload-01.svg); }
.icon-download-01 { -webkit-mask-image: url(/static/icons/download-01.svg); mask-image: url(/static/icons/download-01.svg); }
.icon-annotation { -webkit-mask-image: url(/static/icons/annotation.svg); mask-image: url(/static/icons/annotation.svg); }
.icon-eraser { -webkit-mask-image: url(/static/icons/eraser.svg); mask-image: url(/static/icons/eraser.svg); }

/* -- Jetons --------------------------------------------------------------- */

.color-swatches { display: flex; flex-wrap: wrap; gap: 0.4rem; }

.color-swatch {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: 2px solid transparent;
  cursor: pointer;
  padding: 0;
}
.color-swatch.selected { border-color: var(--text); }

.icon-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0.4rem;
}

.icon-swatch {
  font-size: 1.3rem;
  padding: 0.4rem 0;
  border-radius: 8px;
  background: var(--bg);
}
.icon-swatch.selected { border-color: var(--accent); background: var(--accent-soft); }
.icon-swatch img {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  object-fit: cover;
  display: block;
  margin: 0 auto;
}

/* -- Modale : gestion des joueurs ------------------------------------------ */

.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.6);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 100;
}

.modal {
  width: min(480px, 92vw);
  max-height: 85vh;
  overflow-y: auto;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 1.25rem;
}
/* Import PDF : grille de vignettes, a besoin de plus de place que les
   modales habituelles (confirmation, retour utilisateur…). */
.modal-wide { width: min(760px, 94vw); }

.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 1rem;
}
.modal-header h2 { margin: 0; font-size: 1.1rem; }

.icon-btn {
  background: transparent;
  border: none;
  font-size: 1.1rem;
  color: var(--muted);
  padding: 0.2rem 0.4rem;
}
.icon-btn:hover { color: var(--text); background: transparent; }

.player-roster {
  list-style: none;
  margin: 0 0 1rem;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.player-row {
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 0.6rem 0.75rem;
}

.player-row-header {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.5rem;
}

.player-row-icon {
  font-size: 1.4rem;
  width: 2rem;
  text-align: center;
}

.player-row-name {
  flex: 1;
  font-weight: 600;
  font-size: 0.9rem;
}

.player-badge {
  width: 2.2rem;
  height: 2.2rem;
  min-width: 2.2rem;
  border-radius: 50%;
  border: 2px solid rgba(255,255,255,0.3);
  font-size: 1.1rem;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
.player-badge:hover { filter: brightness(1.15); }

.player-name-input {
  flex: 1;
  font-weight: 600;
  background: transparent;
  border: 1px solid transparent;
}
.player-name-input:hover, .player-name-input:focus {
  border-color: var(--border);
  background: var(--bg);
}

.player-edit-icon {
  flex-direction: column;
  gap: 0.4rem;
  margin-bottom: 0.5rem;
  padding: 0.5rem;
  background: var(--bg);
  border-radius: 8px;
}

.player-row .row { margin-bottom: 0.5rem; }
.player-row .row input { flex: 1; }

.inventory-list {
  list-style: none;
  margin: 0 0 0.5rem;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}

.inventory-list li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  font-size: 0.85rem;
  background: var(--bg);
  border-radius: 6px;
  padding: 0.3rem 0.5rem;
}

.inventory-list button {
  background: transparent;
  border: none;
  color: var(--muted);
  padding: 0 0.2rem;
  font-size: 0.8rem;
}
.inventory-list button:hover { color: var(--danger); background: transparent; }

.inventory-add-form {
  display: flex;
  gap: 0.4rem;
}
.inventory-add-form input { flex: 1; }

/* -- XP --------------------------------------------------------------------- */

.xp-row {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin-bottom: 0.6rem;
}
.xp-row .field-label { margin-right: 0.2rem; color: var(--amber); }
.xp-row button {
  width: 1.8rem;
  height: 1.8rem;
  padding: 0;
  flex-shrink: 0;
  font-weight: 700;
}
.xp-input {
  width: 4.5rem;
  background: var(--bg);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: var(--radius-sm);
  padding: 0.3rem 0.4rem;
  font-family: var(--font-mono);
  font-size: 0.85rem;
  font-weight: 700;
  text-align: center;
}
.xp-input:disabled { opacity: 0.5; cursor: not-allowed; }

/* XP et PV côte à côte plutôt qu'empilés — PV reprend exactement le style
   de XP (mêmes boutons +/-, même largeur de champ). */
.stats-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1rem;
}
.stats-row .xp-row, .stats-row .hp-row { margin-bottom: 0.6rem; }
.hp-row {
  display: flex;
  align-items: center;
  gap: 0.4rem;
}
.hp-row .field-label { margin-right: 0.2rem; color: var(--success); }
.hp-row button {
  width: 1.8rem;
  height: 1.8rem;
  padding: 0;
  flex-shrink: 0;
  font-weight: 700;
}
.hp-input {
  width: 4.5rem;
  background: var(--bg);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: var(--radius-sm);
  padding: 0.3rem 0.4rem;
  font-family: var(--font-mono);
  font-size: 0.85rem;
  font-weight: 700;
  text-align: center;
}
.hp-input:disabled { opacity: 0.5; cursor: not-allowed; }

/* -- Image de Jeton Personnage importée (remplace l'icône emoji) ----------- */

.player-badge img, .character-picker-icon img {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: cover;
}

.player-image-upload {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
}
.upload-label {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  font-size: 0.8rem;
  color: var(--muted);
  border: 1px dashed var(--border);
  border-radius: 6px;
  padding: 0.3rem 0.6rem;
  cursor: pointer;
}
.upload-label:hover { color: var(--text); border-color: var(--muted); }

/* -- Traits joueurs (Stylo côté Vue Joueurs) -------------------------------- */

.player-stroke { cursor: pointer; }

/* -- Réglage du dégradé du Brouillard (en-tête MJ) — voir CONTEXT.md
   "Brouillard — bord adouci" / ADR 0013 --------------------------------- */

.fog-softness-control {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.35rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--panel-raised);
  color: var(--muted);
}
.fog-softness-control input[type=range] { width: 70px; }
.fog-softness-control .icon { flex-shrink: 0; }
#fogSoftnessLabel {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  min-width: 2.4em;
  text-align: right;
}

/* -- Import PDF : grille de Candidats de carte (voir CONTEXT.md/ADR 0012) --- */

.pdf-candidate-toolbar {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0.75rem 0;
}
.pdf-candidate-toolbar .hint { margin-left: auto; }

.pdf-candidate-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: 0.75rem;
  max-height: 55vh;
  overflow-y: auto;
  margin-bottom: 0.75rem;
}

.pdf-candidate-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  padding: 0.5rem;
  border: 2px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--panel-raised);
}
.pdf-candidate-card.selected { border-color: var(--accent); background: var(--accent-soft); }

.pdf-candidate-thumb {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--radius-sm);
  background: var(--bg);
  cursor: pointer;
}

.pdf-candidate-checkbox {
  position: absolute;
  top: 0.6rem;
  right: 0.6rem;
  width: 18px;
  height: 18px;
}

.pdf-candidate-meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.4rem;
}
.pdf-candidate-page { font-family: var(--font-mono); font-size: 0.65rem; color: var(--muted-2); }
.pdf-candidate-low-confidence {
  font-family: var(--font-mono);
  font-size: 0.6rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--amber);
}

.pdf-candidate-name { font-size: 0.78rem; padding: 0.3rem 0.4rem; }

/* Barre de progression indéterminée le temps de l'analyse serveur (pas de
   pourcentage réel : traitement synchrone d'un seul bloc, voir ADR 0012) —
   juste un signal visuel que ça travaille, plus rassurant qu'un texte figé. */
.pdf-import-progress {
  height: 6px;
  border-radius: var(--radius-pill);
  background: var(--panel-raised);
  overflow: hidden;
  margin: 0.5rem 0 0.75rem;
}
.pdf-import-progress-bar {
  height: 100%;
  width: 40%;
  border-radius: var(--radius-pill);
  background: var(--accent);
  animation: pdf-import-indeterminate 1.1s ease-in-out infinite;
}
@keyframes pdf-import-indeterminate {
  0% { transform: translateX(-100%); }
  100% { transform: translateX(350%); }
}

.pdf-import-warning { color: var(--amber); margin-bottom: 0.5rem; }

.pdf-candidate-actions { display: flex; gap: 0.5rem; }
.pdf-candidate-actions button { flex: 1; }

/* -- Bibliothèque : suppression groupée -------------------------------------- */

.map-list-toolbar { display: flex; gap: 0.4rem; margin-bottom: 0.5rem; }
.map-list-toolbar button { flex: 1; }

.map-item-checkbox { flex-shrink: 0; }

/* "Supprimer la sélection" — sous la liste (voir #mapDeleteSelected), même
   gabarit que "Réinitialiser la carte" juste au-dessus dans la sidebar. */
#mapDeleteSelected { margin-top: 0.5rem; }
