/* ========== Invite code ========== */

.invite-code-display {
  font-size: 1.75rem;
  font-weight: 700;
  letter-spacing: 0.4em;
  color: var(--accent);
  font-family: 'JetBrains Mono', monospace;
}


/* ========== Rangée de lieu (en-tête repliable) ==========

   Les deux boutons de droite — « Visible joueurs » et « Supprimer » — disparaissaient
   purement et simplement, sans barre de défilement et sans le moindre signe. Deux causes
   qui se cumulent, et il faut les deux pour comprendre pourquoi c'était SILENCIEUX :

   1. Les boutons étaient en `flex-shrink: 0` et le titre en `flex: 1` sans `min-width: 0`.
      Un enfant flex ne descend pas sous sa taille min-content sans cette déclaration ; le
      titre gardait donc une largeur plancher, et la somme des largeurs dépassait la
      rangée. Sur téléphone la barre d'actions mesure à elle seule plus que la rangée
      entière, si bien que le débordement existait DÈS UN NOM DE QUATRE LETTRES et
      grandissait avec le nom — d'où le symptôme rapporté, « selon la longueur du nom ».
   2. `.card` porte `overflow: clip` (components.css), pour le filet doré de son
      `::before`. Le débordement était donc rogné net par la carte : rien à faire défiler,
      rien à voir, les boutons n'existaient plus.

   Le correctif ne touche pas au rognage — le filet doré en dépend — il supprime le
   débordement. `flex-wrap` laisse la barre d'actions passer à la ligne quand elle ne
   tient plus (c'est le cas de tous les téléphones), et `margin-left: auto` la garde à
   droite. Le titre passe en base `auto` : sa largeur de contenu compte, c'est ce qui
   DÉCLENCHE le passage à la ligne — avec la base 0 d'un `flex: 1`, sa taille hypothétique
   vaut zéro, la barre resterait sur la première ligne et le titre serait écrasé à rien.
   `min-width: 0` + `overflow-wrap: anywhere` traitent l'autre moitié du défaut : un nom
   d'un seul long mot, que rien ne peut couper, poussait la barre dehors même au bureau. */

.anima-place-row {
  flex-wrap: wrap;
}

.anima-place-row-title {
  flex: 1 1 auto;
  min-width: 0;
  overflow-wrap: anywhere;
}

.anima-place-row-actions {
  /* Base `auto` (largeur des deux boutons) mais AUTORISÉE À RÉTRÉCIR : sur un écran de
     360 px, la barre à elle seule reste plus large que la rangée une fois passée à la
     ligne, et un `flex-shrink: 0` la ferait déborder de vingt pixels — rognés en silence
     par le `overflow: clip` de la carte, c'est-à-dire le défaut d'origine en plus petit.
     En cédant, elle rend la main aux boutons, qui replient leur libellé. */
  flex: 0 1 auto;
  margin-left: auto;
}


/* ========== Place map ========== */

.place-map {
  max-width: 100%;
  border-radius: 2px;
  margin-top: 10px;
}


/* ========== Adventure card elements ========== */

.anima-role-label {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
}

.anima-role-gm {
  color: var(--accent);
}

.anima-role-player {
  color: var(--muted);
}

.anima-adv-name {
  font-family: 'Cinzel', Georgia, serif;
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--ink);
  letter-spacing: 0.03em;
  line-height: 1.3;
  margin-bottom: 6px;
}

.anima-adv-name a {
  color: inherit;
  text-decoration: none;
}

.anima-adv-name a:hover {
  color: var(--accent);
}

.anima-adv-desc {
  font-family: 'Roboto', sans-serif;
  font-size: 0.9rem;
  color: var(--muted);
  line-height: 1.5;
  margin: 0;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}


/* ========== Participant avatar ========== */

.anima-avatar {
  width: 28px;
  height: 28px;
  min-width: 28px;
  background: var(--surface-2);
  border: 1px solid color-mix(in srgb, var(--accent) 18%, transparent);
  border-radius: 2px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.8rem;
  color: var(--muted);
}


/* ========== Participant avatar ========== */

.anima-participant-avatar {
  width: 28px;
  height: 28px;
  background: var(--surface-2);
  border: 1px solid color-mix(in srgb, var(--accent) 18%, transparent);
  border-radius: 2px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.8rem;
  color: var(--muted);
  flex-shrink: 0;
}


/* ========== GM label (icon + plain text, no border) ========== */

.anima-gm-label {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--accent);
}


/* ========== Adventure detail title (24px, matches Figma text-2xl) ========== */

.anima-adventure-title {
  font-family: 'Cinzel', Georgia, serif;
  font-size: 1.55rem;
  font-weight: 600;
  color: var(--ink);
  letter-spacing: 0.05em;
  margin-bottom: 4px;
  line-height: 1.3;
}


/* Tag pills */
.anima-tag-pill {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 0.83rem;
  font-weight: 500;
  background: color-mix(in srgb, var(--tag-color) 18%, transparent);
  color: var(--tag-color);
  border: 1px solid color-mix(in srgb, var(--tag-color) 35%, transparent);
}
.anima-tag-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--tag-color);
  flex-shrink: 0;
}
.anima-tag-remove {
  background: none;
  border: none;
  color: var(--tag-color);
  cursor: pointer;
  font-size: 0.8rem;
  padding: 0;
  opacity: 0.7;
  line-height: 1;
}
.anima-tag-remove:hover { opacity: 1; }
.anima-tag-add-btn {
  display: inline-flex;
  align-items: center;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 0.83rem;
  border: 1px dashed var(--border);
  color: var(--muted);
  background: transparent;
  cursor: pointer;
}
.anima-tag-add-btn:hover { border-color: var(--muted); color: var(--ink); }
.anima-tag-color-swatch {
  width: 18px;
  height: 18px;
  border-radius: 4px;
  flex-shrink: 0;
  /* anneau clair pour contraster sur une couleur de tag arbitraire, indépendant du thème */
  border: 1px solid rgba(255,255,255,0.2);
  cursor: pointer;
}
.anima-tag-suggestions {
  background: var(--surface-2);
  border-radius: 6px;
  overflow: hidden;
}
.anima-tag-suggestion-item {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  text-align: left;
  padding: 5px 10px;
  background: none;
  border: none;
  color: var(--ink);
  font-size: 0.94rem;
  cursor: pointer;
}
.anima-tag-suggestion-item:hover { background: var(--surface-2); }
.anima-tag-color-grid {
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  gap: 4px;
}
.anima-tag-color-opt {
  width: 22px;
  height: 22px;
  border-radius: 5px;
  cursor: pointer;
  border: 2px solid transparent;
  padding: 0;
}
.anima-tag-color-opt:hover { transform: scale(1.1); }
/* anneau de sélection blanc: doit contraster sur toutes les couleurs de la grille, pas de jeton */
.anima-tag-color-opt.selected { border-color: #fff; }


/* ========== Encounter Participant Rows ========== */

.anima-participant-row {
  display: grid;
  grid-template-columns: 22px 16px 1fr 64px auto 30px;
  align-items: center;
  column-gap: 6px;
}

.anima-participant-col-pos {
  font-size: 0.8rem;
  text-align: right;
  color: var(--muted);
}

.anima-participant-col-icon {
  font-size: 0.8rem;
  text-align: center;
}

.anima-participant-col-name {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
  overflow: hidden;
}

.anima-participant-col-name-text {
  font-size: 0.95rem;
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.anima-participant-col-badge {
  text-align: center;
}

.anima-participant-col-del {
  text-align: right;
}


/* ========== NPC Rows ========== */

.anima-npc-row {
  display: grid;
  grid-template-columns: 32px 1fr 1fr;
  align-items: center;
  column-gap: 6px;
}

.anima-npc-col-star {
  text-align: center;
}

.anima-npc-col-name {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  overflow: hidden;
}

.anima-npc-col-name .anima-character-avatar {
  flex: 0 0 auto;
}

.anima-npc-col-tags {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: 4px;
  min-width: 0;
  overflow: hidden;
}


/* ========== Linked Character Rows ========== */

.anima-linked-char-row {
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.anima-linked-char-main {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  min-width: 0;
}

.anima-linked-char-hp {
  display: block;
  cursor: pointer;
}


/* ========== GM Artifact Manager ========== */

.gm-artifact-manager {
  margin-top: 0.5rem;
}

.gm-artifact-manager__panel {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin-top: 0.35rem;
  padding: 0.5rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--surface-2);
}

.gm-artifact-manager__panel .error {
  color: var(--danger);
  font-size: 0.8rem;
  margin: 0;
}

.gm-artifact-manager__add {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  flex-wrap: wrap;
}

.gm-artifact-manager__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  font-size: 0.85rem;
  flex-wrap: wrap;
}


/* ========== NPC HP Badge ========== */

.anima-npc-hp-badge {
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--accent);
  font-family: monospace;
  white-space: nowrap;
  text-align: center;
}

.anima-npc-tag-overflow {
  font-size: 0.8rem;
  color: var(--muted);
  white-space: nowrap;
  cursor: default;
  flex-shrink: 0;
}

/* ── Accidents & États panel ── */
.anima-effects-participant-row {
  padding: 0.75rem 1rem;
}

.anima-effect-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.15rem 0.5rem;
  border-radius: 4px;
  font-size: 0.8rem;
  font-weight: 600;
  background: var(--surface-2);
  color: var(--ink);
  border: 1px solid var(--border);
}

.anima-effect-badge.penalty {
  background: color-mix(in srgb, var(--hp) 15%, transparent);
  border-color: var(--hp);
  color: var(--hp);
}

.anima-effect-badge.neutral {
  background: color-mix(in srgb, var(--muted) 15%, transparent);
  border-color: var(--muted);
}

.anima-effect-detail {
  font-weight: 500;
  opacity: 0.85;
}

.anima-effect-remove {
  background: none;
  border: none;
  color: inherit;
  cursor: pointer;
  padding: 0 0.1rem;
  font-size: 1rem;
  line-height: 1;
  opacity: 0.7;
}

.anima-effect-remove:hover {
  opacity: 1;
}

.anima-shield-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.15rem 0.5rem;
  border-radius: 4px;
  font-size: 0.8rem;
  font-weight: 600;
  background: color-mix(in srgb, var(--zeon) 15%, transparent);
  color: var(--zeon);
  border: 1px solid var(--zeon);
}

/* Forme `@iconOnly` (rangée d'initiative) : l'icône seule, rendue exactement
   comme une pastille d'état — ni cadre, ni fond, ni marge intérieure. Ce n'est
   pas de la coquetterie : mesuré à 360 px, la pastille encadrée « 🛡 12/20 »
   coûtait 71,8 px à la piste du nom, dont 12,8 px pour le seul cadre (bordure
   1+1 et padding 0,3rem de chaque côté). L'icône nue en coûte 12,1.
   La police reste à 0,8rem — règle du projet. */
.anima-shield-badge.is-icon-only {
  gap: 0;
  padding: 0;
  background: none;
  border: none;
  color: inherit;
  font-weight: 400;
}

.anima-shield-badge__remove {
  background: none;
  border: none;
  color: inherit;
  cursor: pointer;
  padding: 0 0.1rem;
  font-size: 1rem;
  line-height: 1;
  opacity: 0.7;
}

.anima-shield-badge__remove:hover {
  opacity: 1;
}

.anima-effect-add-btn {
  background: none;
  border: none;
  cursor: pointer;
  font-size: 0.85rem;
  padding: 0 0.25rem;
  color: var(--warning);
  opacity: 0.8;
}

.anima-effect-add-btn:hover {
  opacity: 1;
}

/* ── Calculateurs ── */
.anima-calculator-panel {
  padding: 0.75rem 0;
}

.anima-calculator-title {
  font-size: 1rem;
  font-weight: 600;
  margin-bottom: 1rem;
  color: var(--ink);
}

.anima-calculator-result {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.75rem 1rem;
}

.anima-calc-label {
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
  margin-bottom: 0.2rem;
}

.anima-calc-value {
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--ink);
}

.anima-calc-failure-box {
  padding: 0.5rem 0.75rem;
  border-left: 3px solid var(--hp);
  background: color-mix(in srgb, var(--hp) 12%, transparent);
  color: var(--hp);
  font-size: 0.85rem;
  border-radius: 0 4px 4px 0;
}

/* ── Affliction resolver ── */
form.anima-calculator-panel .list-group {
  border-radius: 6px;
  overflow: hidden;
}

form.anima-calculator-panel .list-group-item {
  background: var(--surface-2);
  border-color: var(--border);
  color: var(--ink);
}

form.anima-calculator-panel .list-group-item-action:hover,
form.anima-calculator-panel .list-group-item-action:focus {
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  color: var(--ink);
}

form.anima-calculator-panel .list-group-item.active {
  background: color-mix(in srgb, var(--accent) 22%, transparent);
  border-color: color-mix(in srgb, var(--accent) 65%, transparent);
  color: var(--ink);
}

form.anima-calculator-panel .list-group-item.active .text-secondary,
form.anima-calculator-panel .list-group-item-action:hover .text-secondary,
form.anima-calculator-panel .list-group-item-action:focus .text-secondary {
  color: var(--accent) !important;
}

.anima-affliction-input-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1rem;
  align-items: end;
}

form.anima-calculator-panel .form-control,
form.anima-calculator-panel .form-select {
  background-color: var(--surface);
  border-color: color-mix(in srgb, var(--accent) 24%, transparent);
  color: var(--ink);
}

form.anima-calculator-panel .form-control:focus,
form.anima-calculator-panel .form-select:focus {
  border-color: color-mix(in srgb, var(--accent) 72%, transparent);
  box-shadow: 0 0 0 0.18rem color-mix(in srgb, var(--accent) 16%, transparent);
}

form.anima-calculator-panel .input-group .btn {
  border-color: color-mix(in srgb, var(--accent) 24%, transparent);
}

form.anima-calculator-panel .form-check-input {
  background-color: var(--surface);
  border-color: color-mix(in srgb, var(--accent) 38%, transparent);
}

form.anima-calculator-panel .form-check-input:checked {
  background-color: var(--accent);
  border-color: var(--accent);
}

form.anima-calculator-panel h4.h6 {
  color: var(--ink);
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

form.anima-calculator-panel .btn-warning {
  /* texte sombre requis sur le fond jaune de bootstrap .btn-warning (non tokenisé) */
  color: #1f1609;
  font-weight: 700;
}

@media (max-width: 767.98px) {
  form.anima-calculator-panel {
    padding: 0.25rem 0;
  }

  form.anima-calculator-panel .list-group {
    max-height: 320px;
    overflow: auto;
  }

  .anima-affliction-input-grid {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ── Add-effect modal: description block ── */
.effect-desc-block {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  padding: 0.6rem 0.75rem;
  border-radius: 6px;
  background: color-mix(in srgb, var(--hp) 8%, transparent);
  border-left: 3px solid var(--hp);
  margin-bottom: 1rem;
  font-size: 0.82rem;
  line-height: 1.5;
  color: var(--ink);
}

.effect-desc-block.no-auto {
  background: color-mix(in srgb, var(--muted) 10%, transparent);
  border-left-color: var(--muted);
}

.effect-desc-icon {
  flex-shrink: 0;
  font-size: 1rem;
  line-height: 1.4;
}

.effect-desc-penalty {
  flex-shrink: 0;
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--hp);
  white-space: nowrap;
  line-height: 1.5;
}

.effect-desc-text {
  color: var(--ink);
}

/* ── CombatResultModal ────────────────────────────────────── */
/* LES TAILLES DE CETTE SECTION SONT EN rem, ET ELLES ÉTAIENT EN em.
   `em` se calcule contre le parent RENDU : les quatre déclarations de cette famille
   descendaient donc sous le plancher de 0,8 rem (14,4 px) sans qu'aucune garde le voie,
   parce que la conversion de modal-font-floor-guard ne lisait que `rem` et `px` et sautait
   en silence tout le reste. MESURÉ dans Chromium sur la page-témoin combat-modals.html,
   avant correction : `.anima-result-breakdown` et `.anima-result-hp-remaining` rendaient à
   12,24 px, `.anima-modal-subtitle` à 12,96 px, toutes trois sous un parent à 14,40 px.
   Le plancher n'est exprimable qu'en rem — n'en réécrire aucune en em. */
.anima-combat-result-modal {
  max-width: 560px;
}

.anima-combat-result-modal .anima-modal-subtitle {
  color: var(--muted);
  font-size: 0.8rem;
  margin-bottom: 12px;
}

.anima-result-breakdown {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 2px 16px;
  font-family: monospace;
  font-size: 0.8rem;
  margin-bottom: 12px;
  padding: 10px 12px;
  background: var(--surface-2);
  border-radius: 4px;
}

.anima-result-row {
  display: contents;
}

.anima-result-label {
  color: var(--muted);
}

/* AUCUN `white-space: nowrap` ICI, ET C'EST LE SUJET DE CE BLOC.
   Il y en avait un, et la règle mobile plus bas le levait sous 767,98 px — donc la
   table de calcul débordait à TOUTE largeur de bureau, coupée par l'`overflow-x:
   hidden` de `.anima-modal` sans ascenseur ni ellipse : rien à l'écran ne disait
   qu'il manquait quelque chose, et ce qui manquait était le total des équations.
   MESURÉ dans Chromium sur le décalque du pire cas (18 rangées, arme Fired parée),
   à 768 et à 1280 px : `.anima-modal` portait 786 px de contenu dans une boîte de
   558, soit 228 px coupés ; la colonne des valeurs réclamait 641 px pour la seule
   rangée « Type d'Armure effectif », et « Résultat », « Table 38 » et « Dégâts
   subis » n'affichaient plus aucune valeur.
   POURQUOI PAS LES DEUX AUTRES REMÈDES, mesurés eux aussi plutôt que jugés :
   — RACCOURCIR UN LIBELLÉ ne déplace rien. La chaîne la plus large n'est pas celle
     de la pénalité d'arme mais celle du Type d'Armure effectif (74 caractères) ;
     « Pénalité arme Fired » ramenée à « Portée » a laissé 786/558 inchangé.
   — ÉLARGIR LA MODALE ne suffit à aucune largeur utile. Le plafond du socle (760 px)
     donne 689 px de boîte à 768 px de fenêtre (`width: 90vw`) et 758 px à 1280 :
     dans les deux cas sous les 786 px demandés. Même `.anima-modal--wide` (1100 px)
     tient à 1280 et reste coupée à 768.
   CE QUE CELUI-CI COÛTE, mesuré sur les deux cas : le pire passe à 514/514, quatre
   valeurs sur dix-huit cèdent sur deux lignes, et la table ne grandit pas d'un pixel
   (1005 px avant comme après — les libellés, eux, cessent de s'entasser dans les
   107 px que le nowrap leur laissait). Le cas courant — six rangées, aucun terme
   optionnel — est INCHANGÉ : 514/514, 160 px de haut, colonne de valeurs à 225 px,
   aucun repli. Une équation courte tient toujours sur une ligne, parce que la
   colonne est en `auto` et se dimensionne sur son contenu tant qu'il y a la place.
   `overflow-wrap: anywhere` est le filet pour une chaîne sans espace sécable — un
   libellé d'arme, par exemple : sans lui une telle chaîne déborderait encore. */
.anima-result-value {
  color: var(--ink);
  text-align: right;
  overflow-wrap: anywhere;
}

.anima-result-hp-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--border);
  margin-top: 4px;
}

.anima-result-hp-label {
  font-weight: bold;
  color: var(--hp);
  min-width: 80px;
}

/* Le champ de PV perdus est un nombre à trois chiffres, pas un formulaire.
   `.anima-result-hp-input` est employée par la modale de RÉSULTAT et par celle de
   VALIDATION, mais cette règle n'était portée que par la première : dans la seconde,
   le `width: 100%` de `.form-control` (Bootstrap) l'emportait et le champ occupait
   toute la largeur. Mesuré à 360 px avant correction — résultat : champ de 70 px
   (15→85) ; validation : champ de 330 px (15→345), et la ligne « PV perdus » y
   occupait trois lignes au lieu de deux. Les deux modales sont nommées, plutôt que la
   règle dé-scopée, pour ne pas atteindre une troisième modale par surprise. */
.anima-combat-result-modal .anima-result-hp-input,
.anima-validation-modal .anima-result-hp-input {
  width: 70px;
  text-align: center;
  color: var(--hp);
  border-color: var(--hp);
}

/* ── Résultat et validation sous le seuil mobile ─────────────────────────────
   LE TABLEAU DE CALCUL passe sur une colonne. Il est en `1fr auto`, et les chaînes de
   `formatAttackBreakdown` (utils/combat.js) atteignent 74 caractères en monospace.
   Mais ce n'est pas la valeur seule qui contraint : libellé et valeur partagent la
   même LIGNE de grille, et la ligne la plus large est le Type d'Armure effectif —
   « Type d'Armure effectif » plus « 10 (portée) +2 (qualité armure +10) -2 (qualité
   arme +10) = 8 (borné 0–10) », 96 caractères à eux deux. Sur une colonne, chacun
   dispose de toute la largeur.
   CE BLOC NE LÈVE PLUS DE `nowrap` : il n'y en a plus à lever. La valeur est
   sécable à TOUTE largeur depuis que le débordement de bureau a été mesuré (voir le
   commentaire de `.anima-result-value` plus haut) ; ce qui reste ici est le seul
   réglage propre au téléphone, l'alignement à gauche sous son libellé.
   CES DEUX NOMBRES SONT MESURÉS, en appelant la fonction sur tout le domaine réaliste
   (AT portée 0–10, qualités au barème d'ItemQuality) et non en lisant le gabarit : la
   version précédente de ce commentaire annonçait 41 et 64, les six rangées
   inconditionnelles, en ignorant les douze rangées de détail que la fonction émet
   aussi. Les pages-témoins combat-modals.html et combat-frame.html décalquent
   désormais les dix-huit.
   `.anima-result-row` est en `display: contents` : ses deux enfants sont directement
   des cases de la grille, donc passer la grille à une colonne les empile
   naturellement, libellé au-dessus de sa valeur. */
@media (max-width: 767.98px) {
  .anima-result-breakdown {
    grid-template-columns: 1fr;
    gap: 0 0;
  }

  /* Chaque paire libellé/valeur devient un bloc : un filet d'espace au-dessus du
     libellé sépare les lignes, que rien d'autre ne sépare plus une fois la colonne
     unique. */
  .anima-result-label {
    margin-top: 6px;
  }

  .anima-result-breakdown .anima-result-row:first-child .anima-result-label {
    margin-top: 0;
  }

  /* `white-space` et `overflow-wrap` ne sont plus redéclarés ici : la règle de base
     les porte désormais pour toutes les largeurs. Ne reste que ce qui change vraiment
     en colonne unique — la valeur s'aligne sous son libellé, pas contre le bord droit. */
  .anima-result-value {
    text-align: left;
  }

  /* LA LIGNE « PV PERDUS » passe en colonne : trois éléments en ligne — libellé à
     `min-width: 80px`, champ de 70 px, « / 123 PV restants » — ne tiennent pas dans les
     332 px utiles d'une modale à 360. Le libellé passe au-dessus du champ.
     Cette règle sert les DEUX modales : la modale de résultat et celle de validation
     (une section par cible en attaque de zone) emploient la même classe. */
  .anima-result-hp-row {
    flex-wrap: wrap;
    gap: 4px 10px;
  }

  .anima-result-hp-label {
    /* Pleine largeur : le libellé occupe sa propre ligne, le champ et le reliquat de PV
       se partagent la suivante. */
    flex: 1 0 100%;
    min-width: 0;
  }
}

/* 0,88 rem = 15,84 px, exactement ce que rendait le `1.1em` précédent : le parent de cette
   rangée est à 14,40 px (mesuré). Celle-ci était la seule des quatre AU-DESSUS du plancher
   — elle change d'unité sans changer de taille. */
.anima-result-hp-value {
  font-size: 0.88rem;
  font-weight: bold;
  color: var(--hp);
}

.anima-result-hp-remaining {
  color: var(--muted);
  font-size: 0.8rem;
}

.anima-area-targets {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 4px;
}

.anima-area-target {
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 10px;
}

.anima-combat-result-modal .anima-area-target-header {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-bottom: 8px;
  flex-wrap: wrap;
}

.anima-area-target-name {
  font-weight: bold;
}

.anima-area-target-summary {
  font-size: 0.8rem;
  color: var(--muted);
}

/* ── Secret Rolls ─────────────────────────────────────────────────────── */
.anima-secret-rolls-btn {
  font-size: 0.8rem;
  background: transparent;
  border: 1px solid var(--border);
  color: var(--muted);
  position: relative;
  transition: border-color 0.2s, color 0.2s;
}

.anima-secret-rolls-btn--active {
  border-color: var(--accent);
  color: var(--accent);
  box-shadow: 0 0 6px color-mix(in srgb, var(--accent) 30%, transparent);
}

.anima-secret-rolls-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--accent);
  color: var(--on-accent);
  border-radius: 50%;
  width: 1.1rem;
  height: 1.1rem;
  font-size: 0.8rem;
  font-weight: bold;
  margin-left: 0.25rem;
  vertical-align: middle;
}

.anima-secret-rolls-modal {
  max-width: 420px;
  width: 100%;
}

.anima-secret-rolls-body {
  max-height: 60vh;
  overflow-y: auto;
  padding: 0.75rem;
}

.anima-secret-roll-entry {
  background: color-mix(in srgb, var(--success) 14%, var(--surface));
  border-left: 3px solid var(--success);
  border-radius: 4px;
  padding: 0.5rem 0.75rem;
  margin-bottom: 0.5rem;
}

.anima-secret-roll-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 0.2rem;
}

.anima-secret-roll-name {
  font-weight: bold;
  color: var(--ink);
  font-size: 0.85rem;
}

.anima-secret-roll-meta {
  color: var(--muted);
  font-size: 0.8rem;
}

.anima-secret-roll-skill {
  color: var(--muted);
  font-size: 0.8rem;
  margin-bottom: 0.2rem;
}

.anima-secret-roll-result {
  color: var(--accent);
  font-size: 1.1rem;
  font-weight: bold;
}

.anima-secret-roll-difficulty {
  display: inline-block;
  margin-left: 0.5rem;
  padding: 0.05rem 0.4rem;
  border-radius: 0.6rem;
  background: color-mix(in srgb, var(--accent) 15%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent);
  color: var(--accent);
  font-size: 0.8rem;
  font-weight: normal;
  vertical-align: middle;
}

.anima-secret-roll-difficulty--below {
  background: var(--surface-2);
  border-color: var(--border);
  color: var(--muted);
}

.anima-secret-roll-detail {
  color: var(--muted);
  font-size: 0.8rem;
}

.anima-secret-roll-fumble {
  color: var(--warning);
  font-size: 0.8rem;
  margin-top: 0.2rem;
}

.anima-secret-rolls-empty {
  color: var(--muted);
  font-style: italic;
  font-size: 0.85rem;
  text-align: center;
  padding: 1rem 0;
}

.anima-secret-rolls-footer {
  padding: 0.5rem 0.75rem;
  border-top: 1px solid var(--border);
  color: var(--muted);
  font-size: 0.8rem;
  text-align: right;
}

.anima-secret-toggle-row {
  padding: 0.4rem 0;
}

.anima-secret-toggle-label {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.82rem;
  color: var(--muted);
  cursor: pointer;
}

.anima-secret-toggle-checkbox {
  cursor: pointer;
}

.btn-secret-send {
  background: color-mix(in srgb, var(--accent) 18%, var(--surface));
  border: 1px solid var(--accent);
  color: var(--accent);
  font-size: 0.8rem;
}

.btn-secret-send:hover {
  background: color-mix(in srgb, var(--accent) 26%, var(--surface));
  border-color: var(--accent);
  color: var(--ink-strong);
}

/* ═══════════════════════════ Trade System ═══════════════════════════ */

.trade-modal-backdrop {
  position: fixed;
  inset: 0;
  background: var(--scrim);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1050;
}

.trade-modal {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  width: min(860px, 94vw);
  max-height: 80vh;
  display: flex;
  flex-direction: column;
}

.trade-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.75rem 1rem;
  border-bottom: 1px solid var(--border);
  font-family: Cinzel, serif;
  font-size: 0.95rem;
}

.trade-modal-close {
  background: none;
  border: none;
  color: var(--muted);
  cursor: pointer;
  font-size: 1rem;
  padding: 0 0.25rem;
}

.trade-modal-body {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  gap: 0;
  flex: 1;
  overflow-y: auto;
  min-height: 220px;
}

.trade-modal-divider {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 0.5rem;
  color: var(--accent);
  font-size: 1.25rem;
  border-left: 1px solid var(--border);
  border-right: 1px solid var(--border);
}

/* Ce pied porte AUSSI `.anima-modal-actions`, qui fournit `display: flex`, la
   gouttière et l'alignement à droite. Ne restent ici que les trois déclarations que
   le socle n'a pas — l'alignement vertical (le pied contient une ligne d'état entre
   deux boutons), la marge intérieure et le filet.
   La barre ne devient PAS collante pour autant : la règle mobile du socle est portée
   par `.anima-modal-backdrop .anima-modal-actions` / `.anima-modal-overlay …`
   (components.css), et la racine de cette modale est `.trade-modal-backdrop`. C'est
   D5 qui la fait entrer dans le socle. */
.trade-modal-footer {
  align-items: center;
  padding: 0.75rem 1rem;
  border-top: 1px solid var(--border);
}

.trade-status-text {
  flex: 1;
  text-align: center;
  font-size: 0.8rem;
  color: var(--muted);
}

.trade-modal-error {
  margin: 0.5rem 1rem 0;
  font-size: 0.8rem;
}

.trade-modal-loading {
  padding: 2rem;
  text-align: center;
  color: var(--muted);
}

/* Side */
.trade-side {
  padding: 0.75rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.trade-side-header {
  font-family: Cinzel, serif;
  font-size: 0.85rem;
  color: var(--accent);
  padding-bottom: 0.35rem;
  border-bottom: 1px solid var(--border);
}

.trade-side-items {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  flex: 1;
}

.trade-side-item {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  background: var(--surface-2);
  border-radius: 3px;
  padding: 0.3rem 0.5rem;
  font-size: 0.8rem;
}

.trade-item-name { flex: 1; }
.trade-item-qty { color: var(--accent); }

.trade-item-remove {
  background: none;
  border: none;
  color: var(--muted);
  cursor: pointer;
  font-size: 0.8rem;
  padding: 0 0.15rem;
}

.trade-side-empty {
  font-size: 0.8rem;
  color: var(--muted);
  font-style: italic;
  margin: 0;
  padding: 0.5rem 0;
}

.trade-side-actions {
  display: flex;
  gap: 0.4rem;
}

/* Money form */
.trade-money-form { font-size: 0.8rem; }
.trade-money-row { display: flex; align-items: center; gap: 0.4rem; flex-wrap: wrap; }
.trade-money-label { color: var(--muted); min-width: 1.5rem; text-align: right; }
.trade-money-value { color: var(--accent); min-width: 2rem; }
.trade-money-input { width: 3.5rem; background: var(--surface-2); border: 1px solid var(--border); color: var(--ink); border-radius: 3px; padding: 0.15rem 0.3rem; font-size: 0.8rem; }

.anima-adventure-note-form {
  border-bottom: 1px solid color-mix(in srgb, var(--accent) 16%, transparent);
  padding-bottom: 1rem;
}

.anima-adventure-note-content {
  min-height: 5.5rem;
}

.anima-note-character-picker {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
  margin-top: 0.75rem;
}

.anima-note-character-picker label {
  align-items: center;
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 22%, transparent);
  border-radius: 0.35rem;
  color: color-mix(in srgb, var(--ink) 86%, transparent);
  display: inline-flex;
  font-size: 0.8rem;
  gap: 0.35rem;
  padding: 0.22rem 0.5rem;
}

.anima-adventure-note-list {
  display: grid;
  gap: 0.85rem;
  margin-top: 1rem;
}

.anima-adventure-note {
  background: var(--surface-2);
  border: 1px solid color-mix(in srgb, var(--accent) 16%, transparent);
  border-radius: 0.35rem;
  display: grid;
  gap: 0.75rem;
  grid-template-columns: auto 1fr;
  padding: 0.85rem;
}

.anima-drag-handle {
  align-self: start;
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 28%, transparent);
  border-radius: 0.35rem;
  color: color-mix(in srgb, var(--ink) 86%, transparent);
  cursor: grab;
  font-size: 0.9rem;
  line-height: 1;
  min-height: 2rem;
  min-width: 2rem;
  padding: 0;
}

.anima-drag-handle:active {
  cursor: grabbing;
}

.anima-adventure-note-meta {
  color: color-mix(in srgb, var(--accent) 72%, transparent);
  display: flex;
  flex-wrap: wrap;
  font-size: 0.8rem;
  gap: 0.6rem;
  margin-bottom: 0.35rem;
  text-transform: uppercase;
}

.anima-adventure-note-meta .anima-note-timestamp {
  color: color-mix(in srgb, var(--accent) 50%, transparent);
  text-transform: none;
}

.anima-adventure-note-meta .anima-note-gm-only-badge {
  background: color-mix(in srgb, var(--accent) 18%, transparent);
  border-radius: 0.25rem;
  color: var(--ink);
  font-weight: 600;
  padding: 0.05rem 0.4rem;
}

.anima-note-gm-only-toggle {
  align-items: center;
  color: color-mix(in srgb, var(--ink) 82%, transparent);
  display: flex;
  font-size: 0.8rem;
  gap: 0.4rem;
  margin-top: 0.6rem;
}

.anima-note-gm-only-toggle input {
  margin: 0;
}

.anima-adventure-note h3 {
  color: var(--ink);
  font-family: Cinzel, serif;
  font-size: 0.95rem;
  margin: 0 0 0.35rem;
}

.anima-adventure-note-body {
  color: color-mix(in srgb, var(--ink) 82%, transparent);
  line-height: 1.65;
  margin: 0;
  overflow-wrap: anywhere;
}

.anima-adventure-note-body a {
  color: var(--link);
  text-decoration: underline;
}

.anima-adventure-note-body .anima-note-img {
  border: 1px solid color-mix(in srgb, var(--accent) 28%, transparent);
  border-radius: 0.4rem;
  display: block;
  margin: 0.5rem 0;
  max-width: 100%;
  height: auto;
}

.anima-note-content-header {
  align-items: baseline;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  justify-content: space-between;
}

.anima-note-content-tools {
  align-items: center;
  display: flex;
  gap: 0.6rem;
}

.anima-note-upload-status {
  color: color-mix(in srgb, var(--accent) 75%, transparent);
  font-size: 0.8rem;
}

.anima-note-content-hint {
  color: color-mix(in srgb, var(--accent) 55%, transparent);
  font-size: 0.8rem;
  margin: 0.35rem 0 0;
}

.anima-note-content-hint code {
  color: color-mix(in srgb, var(--ink) 80%, transparent);
}

.anima-adventure-note-links {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  margin-top: 0.65rem;
}

.anima-adventure-note-links span {
  border: 1px solid color-mix(in srgb, var(--accent) 28%, transparent);
  border-radius: 0.35rem;
  color: color-mix(in srgb, var(--ink) 85%, transparent);
  font-size: 0.8rem;
  padding: 0.12rem 0.42rem;
}

.anima-adventure-note-actions {
  display: flex;
  gap: 0.5rem;
  justify-content: flex-end;
  margin-top: 0.75rem;
}
.trade-money-balance { margin-top: 0.25rem; font-size: 0.8rem; color: var(--muted); display: flex; gap: 0.3rem; flex-wrap: wrap; }
.trade-money-over { margin-top: 0.15rem; font-size: 0.8rem; color: var(--hp); }
.trade-money-form--over .trade-money-input { border-color: var(--hp); }

/* Catalog picker (mode libre) */
.trade-catalog-results {
  max-height: 160px;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: 3px;
  background: var(--surface);
}

.trade-catalog-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.25rem 0.4rem;
  cursor: pointer;
  font-size: 0.8rem;
  border-bottom: 1px solid var(--border);
}

.trade-catalog-row:last-child { border-bottom: none; }

.trade-catalog-row:hover { background: var(--surface-2); }

.trade-catalog-row--selected { background: color-mix(in srgb, var(--success) 25%, var(--surface)) !important; }

.trade-catalog-name { color: var(--ink); flex: 1; }

.trade-catalog-group { color: var(--muted); font-size: 0.8rem; flex-shrink: 0; margin-left: 0.4rem; }

/* Item picker */
.trade-item-picker {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 0.5rem;
  font-size: 0.8rem;
}

.trade-item-picker-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 0.4rem;
  font-size: 0.8rem;
  color: var(--muted);
}

.trade-item-picker-close {
  background: none;
  border: none;
  color: var(--muted);
  cursor: pointer;
}

.trade-item-picker-body {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}

.trade-item-picker-qty {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.8rem;
}

.trade-qty-input { width: 4rem !important; }

/* Notification banner */
.trade-notification-banner {
  position: fixed;
  bottom: 1.5rem;
  right: 1.5rem;
  background: color-mix(in srgb, var(--success) 16%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--success) 45%, var(--surface));
  border-radius: 5px;
  padding: 0.6rem 0.9rem;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  font-size: 0.82rem;
  z-index: 1040;
  box-shadow: 0 3px 12px rgba(0,0,0,0.4); /* one-off shadow */
}

@media (max-width: 767.98px) {
  /* Sans ça, la bannière passe sous la barre de navigation : son `bottom: 1.5rem`
     (27 px) plaçait son bord bas à 663 px sur un écran de 690, quand le bord haut de
     la barre est à 640,16 px — 22,84 px de recouvrement, mesurés à 360 ET à 422 px
     (le recouvrement ne dépend pas de la hauteur de la bannière, seulement du
     décalage bas). Après correction : bord bas à 622 px, mêmes deux largeurs. */
  .trade-notification-banner {
    bottom: calc(var(--bottomnav-h) + 1rem);
  }
}

.trade-notification-text { flex: 1; }

/* Initiator popover */
.trade-initiator-popover {
  position: fixed;
  z-index: 1050;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 5px;
  width: 240px;
  box-shadow: 0 4px 16px rgba(0,0,0,0.5); /* one-off shadow */
}

.trade-initiator-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.5rem 0.75rem;
  border-bottom: 1px solid var(--border);
  font-size: 0.8rem;
  font-family: Cinzel, serif;
}

.trade-initiator-body { padding: 0.6rem 0.75rem; }
.trade-initiator-footer { padding: 0.5rem 0.75rem; border-top: 1px solid var(--border); }

.anima-participant-col-trade {
  display: flex;
  align-items: center;
  flex-shrink: 0;
}

/* ── La modale d'échange sur téléphone ────────────────────────────────────────
   Le socle (components.css, même seuil 767,98 px) lui donne désormais la largeur, les
   coins hauts arrondis, la gouttière de 14 px et la barre d'actions collante. Ce qui
   reste ici est ce que le socle ne peut pas savoir : la modale d'échange est une
   COLONNE FLEX à trois étages dont l'étage du milieu défile, et deux colonnes côte à
   côte.

   TROIS DÉFAUTS CUMULÉS, dans l'ordre où ils se voient — mesurés à 360 px sur une
   page-témoin décalquée de trade-modal.hbs, trade-side.hbs et trade-catalog-picker.hbs
   dans leur chaîne de conteneurs réelle :
   1. hors socle : 338 px de large, décalés de 11 px du bord gauche, quatre coins
      arrondis, ancrée au centre (réglé par components.css) ;
   2. `grid-template-columns: 1fr auto 1fr` — le minimum d'un `1fr` est `auto`,
      c'est-à-dire la largeur min-content de la colonne : `.trade-side` débordait de la
      boîte de contenu, et l'`overflow-x: hidden` de la modale le rognait sans le dire ;
   3. deux défilements emboîtés — `.trade-modal-body`, et, en mode libre avec le
      sélecteur ouvert, `.trade-catalog-results`. (Un relevé en annonçait trois ; il en
      compte un de trop : trade-side.hbs n'ouvre un sélecteur que sous `{{#unless
      @readonly}}` et le côté « eux » est monté `@readonly={{true}}`, et seul
      trade-catalog-picker.hbs porte `.trade-catalog-results` — trade-item-picker.hbs
      n'en a pas.)

   Ce bloc est écrit APRÈS les règles de base qu'il surcharge, dans ce même fichier :
   une media query n'ajoute aucune spécificité, et à spécificité égale c'est l'ordre
   des sources qui tranche. Le déplacer plus haut le tuerait. */
@media (max-width: 767.98px) {
  .trade-modal {
    /* C'est la MODALE qui défile, comme toute feuille du socle — et c'est ce qui donne
       son ancrage à la barre d'actions collante (`position: sticky` s'ancre sur la zone
       visible de son conteneur défilant). La colonne flex à trois étages est défaite
       pour que l'étage du milieu n'ait plus de raison d'avoir son propre défilement. */
    display: block;
    max-height: 90vh;
    overflow-x: hidden;
    overflow-y: auto;
  }

  .trade-modal-body {
    display: block;
    overflow-y: visible;
    /* `min-height: 220px` réservait la place des deux colonnes ; empilées, elles font
       leur hauteur. */
    min-height: 0;
  }

  /* Le séparateur « ↔ » était un trait VERTICAL entre deux colonnes. Empilé, il devient
     un trait horizontal, sans quoi il pose deux bordures latérales sur toute la
     largeur. */
  .trade-modal-divider {
    border-left: none;
    border-right: none;
    border-top: 1px solid var(--border);
    padding: 0.35rem 0;
  }

  /* Gouttières : le socle en pose 14 px sur la modale, et c'est exactement ce que les
     marges négatives de la barre collante annulent. Celles de l'en-tête et des deux
     colonnes s'y ajoutaient. Les horizontales sont remises à zéro, les verticales
     restent. */
  .trade-modal-header {
    padding-left: 0;
    padding-right: 0;
  }

  .trade-side {
    padding-left: 0;
    padding-right: 0;
  }

  /* Défilement imbriqué n°2 : le plafond est levé, la liste du catalogue s'allonge et
     c'est la modale qui défile. Même geste que D1 sur `.anima-modal-body`. */
  .trade-catalog-results {
    max-height: none;
    overflow-y: visible;
  }
}

/* ── Pre-combat panel ── */
.anima-precombat-toolbar {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  padding: 8px 10px;
  border-bottom: 1px solid color-mix(in srgb, var(--accent) 15%, transparent);
}

.anima-start-combat-btn {
  background: color-mix(in srgb, var(--accent) 18%, var(--surface));
  border: 2px solid var(--accent);
  color: var(--accent);
  font-size: 0.9rem;
  font-weight: 600;
  padding: 5px 14px;
}

.anima-start-combat-btn:hover {
  background: color-mix(in srgb, var(--accent) 26%, var(--surface));
  border-color: var(--accent-hover);
  color: var(--accent-hover);
}

.anima-stop-combat-btn {
  background: color-mix(in srgb, var(--hp) 14%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--hp) 45%, var(--surface));
  color: var(--hp);
  font-size: 0.8rem;
}

.anima-stop-combat-btn:hover {
  background: color-mix(in srgb, var(--hp) 20%, var(--surface));
  border-color: color-mix(in srgb, var(--hp) 55%, var(--surface));
  color: var(--hp);
}

.anima-precombat-list {
  padding: 6px 0;
}

.anima-precombat-row {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 5px 10px;
  border-bottom: 1px solid var(--border);
}

.anima-precombat-row:last-child {
  border-bottom: none;
}

.anima-precombat-avatar {
  flex-shrink: 0;
}

.anima-precombat-name {
  flex: 1;
  min-width: 0;
  font-size: 0.85rem;
  color: var(--ink);
  display: flex;
  align-items: center;
  gap: 5px;
}

.anima-precombat-unknown {
  color: var(--muted);
  font-style: italic;
}

.anima-precombat-hp {
  flex-shrink: 0;
}

.anima-hp-hidden {
  font-size: 0.8rem;
  color: var(--muted);
  font-style: italic;
  flex-shrink: 0;
}

.anima-precombat-secret-badge {
  font-size: 0.8rem;
  opacity: 0.8;
}

.anima-precombat-visibility-btn {
  font-size: 0.8rem;
  padding: 1px 5px;
  flex-shrink: 0;
}

.anima-visibility-on {
  background: color-mix(in srgb, var(--success) 15%, transparent);
  border-color: var(--success);
  color: var(--success);
}

.anima-visibility-off {
  background: color-mix(in srgb, var(--hp) 20%, transparent);
  border-color: var(--hp);
  color: var(--muted);
}

.anima-precombat-secret-roll-btn {
  font-size: 0.8rem;
  padding: 2px 7px;
  background: color-mix(in srgb, var(--accent) 15%, var(--surface));
  border: 1px solid var(--accent);
  color: var(--accent);
  flex-shrink: 0;
}

/* ── Init row: prominent Saisir init button ── */
.anima-init-btn--prominent {
  font-size: 0.85rem;
  padding: 3px 12px;
  background: color-mix(in srgb, var(--success) 15%, transparent);
  border: 1px solid var(--success);
  color: var(--success);
  font-weight: 500;
}

/* ── Combat toolbar: waiting hint ── */
.anima-init-waiting-hint {
  font-size: 0.8rem;
  color: var(--muted);
  text-align: center;
  margin: 6px 0;
  padding: 8px;
}

/* ── Adventure-level secret rolls ── */
.anima-adv-secret-rolls-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.3rem 0.75rem;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--ink);
  font-size: 0.85rem;
  cursor: pointer;
  transition: border-color 0.15s, color 0.15s;
}
.anima-adv-secret-rolls-btn:hover {
  border-color: var(--accent);
  color: var(--accent);
}
.anima-adv-secret-rolls-btn--active {
  border-color: var(--accent);
  color: var(--accent);
  box-shadow: 0 0 6px color-mix(in srgb, var(--accent) 38%, transparent);
}
.anima-secret-roll-badge {
  display: inline-block;
  min-width: 1.2rem;
  height: 1.2rem;
  line-height: 1.2rem;
  text-align: center;
  background: var(--accent);
  color: var(--on-accent);
  border-radius: 50%;
  font-size: 0.8rem;
  font-weight: 700;
  padding: 0 0.2rem;
}
.anima-adv-secret-roll-player-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.3rem 0.75rem;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--ink);
  font-size: 0.85rem;
  cursor: pointer;
  transition: border-color 0.15s, color 0.15s;
}
.anima-adv-secret-roll-player-btn:hover {
  border-color: var(--zeon);
  color: var(--zeon);
}

/* ── Onglet « Combats » (combats en cours) ── */
.anima-combats-tab {
  position: relative;
  cursor: pointer;
}

.anima-combats-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.1rem;
  height: 1.1rem;
  padding: 0 0.3rem;
  margin-left: 0.35rem;
  border-radius: 999px;
  background: var(--hp);
  color: #fff; /* texte badge sur fond --hp, pas de jeton on-hp dédié */
  font-size: 0.8rem;
  font-weight: 700;
  line-height: 1;
  animation: anima-combat-pulse 1.6s ease-in-out infinite;
}

@keyframes anima-combat-pulse {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--hp) 60%, transparent); }
  50% { box-shadow: 0 0 0 0.35rem transparent; }
}

.anima-combats-menu {
  position: absolute;
  z-index: 30;
  margin-top: 0.25rem;
  min-width: 14rem;
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.45); /* one-off shadow */
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* Téléphone : la barre d'onglets est ancrée en bas de l'écran (bloc mobile de
   .anima-tab-bar, dans layout.css). S'ouvrir vers le bas revenait à sortir de l'écran —
   mesuré à 422x690, le menu descendait à 705 pour un viewport de 690, en recouvrant au
   passage les onglets. Ce n'est pas un arbitrage de mise en page, c'est la seule
   direction possible : un menu accroché au bas de l'écran s'ouvre vers le haut.

   `position: fixed` plutôt qu'`absolute`, et `min-width: 0` : ce sont eux qui font
   RÉELLEMENT tenir le menu sur la largeur de l'écran. En absolute, `left: 0; right: 0`
   ne suffisait pas — le `min-width: 14rem` de la règle de base (252px) sur-contraint la
   boîte, et en LTR c'est `right` que CSS abandonne dans ce cas. Le menu restait large de
   252px, ancré au dernier onglet, et sortait de 167,6px à droite : les deux tiers des
   noms d'aventure invisibles, sans barre de défilement pour le signaler. Se caler sur le
   viewport et lever le plancher de largeur est ce qui réalise l'intention.

   Le décalage bas passe alors par --bottomnav-h : le bloc conteneur n'est plus la barre
   mais le viewport, donc la hauteur de la barre doit être nommée explicitement. */
@media (max-width: 767.98px) {
  .anima-combats-menu {
    position: fixed;
    left: 0;
    right: 0;
    bottom: var(--bottomnav-h);
    min-width: 0;
    margin-top: 0;
    margin-bottom: 0.25rem;
  }

  /* Pastille superposée au coin de l'icône, et non plus rangée du dessous. En
     `flex-direction: column` (bloc mobile de .anima-tab, layout.css) le badge
     cessait d'être à côté du libellé et devenait une TROISIÈME rangée : mesuré,
     l'onglet passait à 72,64px quand les quatre autres tenaient en 49,84, et
     comme il est le plus haut du ruban il dictait à lui seul --bottomnav-h —
     soit ~23px pris sur le contenu de TOUTES les pages. Le sortir du flux rend
     ces pixels et rejoint la maquette validée.
     L'ancrage vient du `position: relative` que .anima-combats-tab porte déjà
     dans sa règle de base, plus haut dans ce fichier.
     Le `margin-left: 0.35rem` de la règle de base creusait un écart AVANT le
     badge. Rejoué en remettant la pastille dans le flux, c'est le BADGE SEUL
     qu'il décentrait, de +3,15px — la moitié des 6,3px de marge, puisqu'il est
     un flex item centré parmi ses frères ; l'icône et le libellé restaient à
     +0,00px, et l'onglet lui-même n'a jamais bougé. Hors flux il ne décentre
     plus rien du tout — il ne fait que décaler la pastille — mais la valeur est
     réécrite quand même, parce qu'elle sert ici tout autre chose : depuis
     `left: 50%` (le centre de l'onglet, où l'icône est centrée), 0.25rem place
     le bord gauche de la pastille 4,5px à droite du centre, soit 4px en deçà du
     bord droit de l'icône de 17px — le chevauchement de coin recherché.

     Deux remarques de revue, mesurées mais NON corrigées, faute d'un cas réel :
     — `left: calc(50% + 0.25rem)` dirait plus directement ce que fait le couple
       `left` + `margin-left` sur une boîte absolue. Réécriture cosmétique.
     — la pastille est ancrée par sa GAUCHE, donc elle grandit vers la droite et
       le nombre de chiffres mange la marge au bord de l'écran. Relevé à 360px :
       un chiffre laisse 11,70px, deux n'en laissent plus que 3,19, et trois
       SORTENT de l'écran de 5,58px (à 422px les mêmes trois chiffres passent, à
       0,63px près). Il faudrait 100 combats simultanés pour y arriver, c'est
       donc théorique — mais c'est la direction de la panne, et 3,19px de marge
       à deux chiffres n'est pas si loin. */
  .anima-combats-badge {
    position: absolute;
    top: 2px;
    left: 50%;
    margin-left: 0.25rem;
  }
}

.anima-combats-menu-item {
  text-align: left;
  background: transparent;
  border: none;
  color: var(--ink);
  padding: 0.5rem 0.75rem;
  font-size: 0.8rem;
  cursor: pointer;
}

.anima-combats-menu-item:hover {
  background: var(--surface-2);
  color: var(--accent);
}

/* ── Galerie immersive de rencontre ── */
.anima-encounter-gallery-overlay {
  position: fixed;
  inset: 0;
  z-index: 1300; /* au-dessus de .anima-floating-window (1200) : atteignable depuis le HUD de combat flottant */
  display: flex;
  align-items: stretch;
  justify-content: center;
  padding: 1.5rem;
  overflow: hidden;
  background: var(--scrim);
}

/* Voile cliquable de la galerie, calqué sur `.anima-modal-scrim`. Il est absolu et
   sorti du flux flex de la racine, donc le panneau garde exactement la place qu'il
   avait ; l'assombrissement reste porté par la racine (`--scrim`), le voile ne fait
   que capter le clic. */
.anima-encounter-gallery-scrim {
  position: absolute;
  inset: 0;
  z-index: 0;
}

.anima-encounter-gallery-panel {
  display: flex;
  flex-direction: column;
  width: 100%;
  max-width: 100%;
  height: 100%;
  min-height: 0;
  /* Le voile est positionné et le précède dans le document : sans `position` à
     lui, le panneau se peindrait DESSOUS et ne recevrait plus aucun clic. */
  position: relative;
  z-index: 1;
}

.anima-encounter-gallery-header {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 1rem;
}

/* Le titre porte son propre fond, comme le bouton de fermeture à côté de lui et comme les
   vignettes en dessous (mêmes jetons : `--surface` + `--border`). Ce n'est pas un ornement :
   le panneau de la galerie ne déclare aucun fond, le titre était donc posé sur le voile de
   la page, et son rapport de contraste dépendait de ce qui passait DERRIÈRE. Mesuré (texte
   rendu transparent, pixel de fond échantillonné, transitions gelées), sur trois arrière-
   plans — la bannière, une carte noire, une carte blanche :

                  avant                    après
     clair        2,80 / 2,13 / 3,13       8,04 quel que soit le fond
     sombre       5,35 / 5,62 / 1,54       4,79 quel que soit le fond

   Le titre est du gros texte au sens WCAG (28,8 px calculés, seuil 3) : avant, le thème
   clair échouait sur deux fonds sur trois, et le sombre échouait sur le troisième. Poser le
   fond sur le PANNEAU aurait aussi réglé le contraste (8,04 mesuré), mais c'est justement
   l'absence de fond du panneau qui fait l'aspect pleine image : la gouttière entre vignettes
   passait de rgb(145,133,113) — le voile — à rgb(246,238,217), la couleur du panneau. Avec le
   fond sur le seul titre, ce pixel de gouttière reste le voile, et la pastille couvre 1,98 %
   de la surface du panneau sur grand écran (9,62 % à 360 px, où le titre passe sur deux
   lignes). Aucun débordement à 360 ni à 1280 px. */
.anima-encounter-gallery-title {
  margin: 0;
  padding: 0.15rem 0.7rem;
  border: 1px solid var(--border);
  border-radius: 0.3rem;
  background: var(--surface);
  font-family: 'Cinzel', serif;
  font-size: 1.6rem;
  color: var(--accent);
}

/* Le panneau de la galerie ne déclare aucun fond — c'est ce qui lui donne son aspect
   pleine image. Le bouton de fermeture se posait donc directement sur le voile, et son
   contraste basculait avec le thème : mesuré, glyphe 2,57 en clair (seuil 3) et bordure
   1,37 en sombre. Lui donner son propre fond opaque le sort du voile et rend les deux
   mesures indépendantes de ce qui passe derrière : 8,04 / 8,04 en clair, 4,79 / 4,79 en
   sombre. Le glyphe en sombre descend de 5,41 à 4,79 — toujours largement au-dessus.
   Le TITRE de la galerie avait le même défaut ; il est traité de la même façon, par un
   fond qui lui est propre — cf. le bloc de `.anima-encounter-gallery-title`. */
.anima-encounter-gallery-close {
  border: 1px solid var(--accent);
  border-radius: 0.25rem;
  background: var(--surface);
  color: var(--accent);
  font-size: 1.4rem;
  line-height: 1;
  padding: 0.2rem 0.6rem;
  cursor: pointer;
}

.anima-encounter-gallery-close:hover {
  background: var(--surface-2);
}

.anima-encounter-gallery-empty {
  color: var(--muted);
  font-style: italic;
  text-align: center;
  padding: 3rem 0;
}

.anima-encounter-gallery-grid {
  flex: 1 1 auto;
  min-height: 0;
  display: grid;
  grid-template-columns: repeat(var(--gallery-cols, 4), 1fr);
  grid-auto-rows: 1fr;
  gap: 1.5rem;
  place-content: center;
  justify-items: center;
}

.anima-encounter-gallery-tile {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  margin: 0;
  padding: 0.75rem;
  min-width: 0;
  min-height: 0;
  width: 100%;
  height: 100%;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 0.4rem;
}

/* The avatar grows to fill the tile; the computed column count keeps every
   tile as large as the viewport allows while all of them stay visible. */
.anima-encounter-gallery-tile .anima-character-avatar--gallery {
  flex: 1 1 auto;
  width: auto;
  height: auto;
  min-height: 0;
  max-width: 100%;
  max-height: 100%;
  aspect-ratio: 1;
  font-size: clamp(1.5rem, 6vmin, 4rem);
}

.anima-encounter-gallery-name {
  font-family: 'Cinzel', serif;
  font-size: 0.95rem;
  color: var(--ink);
  text-align: center;
}

.anima-encounter-gallery-name--masked {
  color: var(--muted);
  font-style: italic;
}

.anima-encounter-gallery-badge {
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
  font-size: 0.8rem;
  padding: 0.05rem 0.4rem;
  border-radius: 0.2rem;
  background: transparent;
}

.anima-encounter-gallery-badge--pj {
  border: 1px solid var(--success);
  color: var(--success);
}

.anima-encounter-gallery-badge--pnj {
  border: 1px solid var(--hp);
  color: var(--hp);
}

@media (max-width: 575.98px) {
  .anima-encounter-gallery-overlay {
    padding: 1rem;
  }

  .anima-encounter-gallery-grid {
    gap: 0.75rem;
  }

  .anima-encounter-gallery-tile {
    padding: 0.5rem;
    gap: 0.35rem;
  }
}

/* ── NPC generator modal ── */

.npc-generator-modal .archetype-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0.5rem;
  margin: 1rem 0;
}

.npc-generator-modal .archetype-card {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  padding: 0.75rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  text-align: left;
  cursor: pointer;
  background: transparent;
  color: inherit;
}

.npc-generator-modal .archetype-card.is-selected {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px var(--accent);
}

.npc-generator-modal .archetype-name {
  font-weight: 600;
  font-size: 0.8rem;
  color: var(--accent);
}

.npc-generator-modal .archetype-desc {
  font-size: 0.8rem;
  opacity: 0.8;
}

.npc-generator-modal .npc-generator-field {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  margin-bottom: 0.75rem;
  font-size: 0.8rem;
}

.npc-generator-modal .npc-generator-checkbox {
  flex-direction: row;
  align-items: center;
  gap: 0.5rem;
}

.npc-pool-modal .npc-pool-list {
  list-style: none;
  margin: 1rem 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  max-height: 16rem;
  overflow-y: auto;
}

.npc-pool-modal .npc-pool-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.4rem 0.5rem;
  border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
  border-radius: 6px;
}

.npc-pool-modal .npc-pool-row.is-selected {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 50%, transparent);
}

.npc-pool-modal .npc-pool-pick {
  flex: 1;
  text-align: left;
  background: transparent;
  border: none;
  color: inherit;
  cursor: pointer;
  font-size: 0.85rem;
}

.npc-pool-modal .npc-generator-field {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  margin-bottom: 0.75rem;
  font-size: 0.8rem;
}

/* ── La modale de génération de PNJ sous le seuil mobile ──
   Trois défauts qui se cumulent sur la même carte, mesurés à 360 px.

   1. `.npc-pool-list` retient 673 px de contenu dans 288 : un défilement imbriqué
      dans une modale qui défile déjà. Plafond levé.
   2. `repeat(2, 1fr)` : `1fr` s'écrit `minmax(auto, 1fr)`. Par CSS Grid 1 §6.6
      « Automatic Minimum Size of Grid Items », la taille minimale automatique d'un item
      vaut sa taille fondée sur le contenu SI, entre autres, il occupe au moins une piste
      dont la fonction de dimensionnement minimale est `auto` ; sinon elle vaut zéro. Avec
      `minmax(0, 1fr)` cette fonction vaut `0` : la condition tombe, pistes ET cartes
      peuvent descendre sous leur min-content, et le conteneur cesse de déborder. C'est
      cette règle-ci, seule, qui répond aux +245 px mesurés.
   3. `white-space: normal` sur `.archetype-kind-badge` ne CONDITIONNE PAS le point 2 : le
      `minmax(0, 1fr)` opère que la pastille soit en `nowrap` ou non. Il ne décide plus que
      du sort du texte de la pastille une fois la carte rétrécie — coupé par
      l'`overflow-x: hidden` de `.anima-modal`, ou replié sur deux lignes. Et il n'a de
      prise que sur la moitié des cartes : les deux libellés possibles viennent de
      `npc-generator-modal.js` (`kindLabel`), ce sont « GM Kit » et « Aléatoire »
      (« Random » en anglais) ; un mot unique ne se replie pas, seul « GM Kit » le peut.
      Une version précédente de ce commentaire — et le message du commit 3c35a41b —
      affirmaient l'inverse : que sans ce `normal`, le `minmax(0, 1fr)` « ne servirait à
      rien ». C'était la causalité retournée.

   Le sélecteur de la pastille est SCOPÉ, et ce n'est pas un ornement. Sa règle de base
   `.archetype-kind-badge { … white-space: nowrap }` est près de cinq cents lignes PLUS
   BAS dans ce même fichier. Écrite nue ici, elle vaudrait 0,1,0 contre 0,1,0 : une media
   query n'apporte aucune spécificité, à égalité c'est l'ordre des sources qui tranche, et la
   déclaration la plus basse gagne — le `nowrap` survivrait et CETTE règle-ci serait morte.
   (Le `minmax(0, 1fr)` ci-dessus, lui, ne dépend pas de cette bataille de spécificité.)
   `.npc-generator-modal .archetype-kind-badge` vaut 0,2,0 et gagne quel que soit l'ordre.
   C'est le motif déjà employé par `.npc-pool-modal .npc-pool-list` juste au-dessus, et la
   même leçon que le bloc mobile de fin de `pages/encounter-combat.css`.
   Le scope ne prive personne : la pastille n'a qu'un seul usage dans tout `app/`,
   `npc-generator-modal.hbs`, à l'intérieur de `.anima-modal.npc-generator-modal`.

   Mesuré AVANT correction, à 360 px : +245 px de débordement, 10 éléments coupés. Ces
   trois règles visent ce débordement ; l'état APRÈS correction n'a pas été remesuré au
   navigateur — ne pas lire ici une réduction constatée. En particulier, ce que devient
   visuellement la pastille à 360 px (coupée ? repliée ? inchangée ?) n'a PAS été observé. */
@media (max-width: 767.98px) {
  .npc-pool-modal .npc-pool-list {
    max-height: none;
    overflow-y: visible;
  }

  .npc-generator-modal .archetype-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .npc-generator-modal .archetype-kind-badge {
    white-space: normal;
  }

  /* La question laissée ouverte par le commentaire ci-dessus — « ce que devient visuellement
     la pastille à 360 px (coupée ? repliée ? inchangée ?) n'a PAS été observé » — a été
     mesurée : elle était COUPÉE. `white-space: normal` ne peut rien pour « Aléatoire », qui est
     un mot unique et insécable ; l'en-tête de carte est un flex `nowrap` où la pastille et le
     nom se disputent la piste. À 360 px la pastille sortait de 33,8 px du bord de la grille
     (2,8 px à 422), rognée par l'`overflow-x: hidden` d'`.anima-modal`. Le débordement
     préexistait (18 px à 0,65 rem) ; le plancher de police l'a porté à 34. En passant
     l'en-tête en `wrap`, la pastille descend sur sa propre ligne au lieu d'être coupée.
     Au-dessus du seuil il n'y a rien à soulager : mesuré à 768, 800, 850, 900 et 1024 px,
     la boîte de la pastille (69 px pour « GM Kit », 99 px pour « Aléatoire ») dépasse
     toujours ce que le texte demande (53 et 83 px) — le `nowrap` de la règle de base n'y
     déborde pas. */
  .npc-generator-modal .archetype-card-head {
    flex-wrap: wrap;
  }
}

.anima-participant-thumb {
  width: 28px;
  height: 28px;
  border-radius: 4px;
  object-fit: cover;
  margin-right: 6px;
  vertical-align: middle;
}

.anima-npc-image-preview {
  display: block;
  max-width: 220px;
  margin: 0 auto 0.75rem;
  border-radius: 6px;
}

.anima-npc-image-hint {
  font-size: 0.8rem;
  color: var(--muted);
  margin: 0.15rem 0 0.6rem;
}

/* NPC portrait — web-session candidate gallery */
.anima-npc-image-session {
  font-family: monospace;
  font-size: 0.8rem;
  width: 100%;
}

.anima-npc-image-candidates {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.5rem;
}

.anima-npc-image-candidate {
  padding: 0;
  border: 2px solid transparent;
  border-radius: 6px;
  background: none;
  cursor: pointer;
  overflow: hidden;
}

.anima-npc-image-candidate:hover:not(:disabled) {
  border-color: var(--accent);
}

.anima-npc-image-candidate img {
  display: block;
  width: 100%;
  height: auto;
}

.anima-npc-image-candidate:disabled {
  opacity: 0.5;
  cursor: default;
}

.anima-npc-image-spinner {
  display: inline-block;
  width: 1rem;
  height: 1rem;
  border: 2px solid color-mix(in srgb, var(--ink) 15%, transparent);
  border-top-color: currentColor;
  border-radius: 50%;
  animation: anima-npc-image-spin 0.7s linear infinite;
}

@keyframes anima-npc-image-spin {
  to { transform: rotate(360deg); }
}

/* ========== Sous-barre d'onglets (détail aventure) ========== */

.anima-subtab-bar {
  display: flex;
  gap: 0;
  border-bottom: 1px solid color-mix(in srgb, var(--accent) 18%, transparent);
  margin: 0 0 1.5rem;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  /* Reste visible au scroll, calée sous la topnav (--topnav-h) + la barre d'onglets
     globale. Les 40px ne sont PAS la hauteur rendue de cette barre : elle mesure
     38,25px (relevée sur la page-témoin à 900px, police de repli — le témoin ne
     charge pas les webfonts, comme pour --bottomnav-h). Il reste donc sur grand
     écran une lucarne de 1,75px entre le bas de la barre d'onglets et le haut de
     celle-ci. Valeur laissée telle quelle à dessein : c'est le rendu approuvé
     depuis toujours, et 38,25 est mesuré sans JetBrains Mono — la corriger sur la
     foi de ce seul relevé, c'est risquer de déplacer la barre de 2px sur tous les
     écrans pour un chiffre que le vrai navigateur n'a pas confirmé.
     Le bloc mobile ci-dessous, lui, ne dépend d'aucune hauteur mesurée. */
  position: sticky;
  top: calc(var(--topnav-h) + 40px);
  z-index: 1040;
  background: var(--surface);
}

/* Sous 767,98px la barre d'onglets globale n'est plus en haut de l'écran : elle passe
   `fixed` en bas (bloc mobile de .anima-tab-bar, layout.css). La place qu'on lui
   réservait ici ne recouvrait donc plus rien — c'était un trou, mesuré à 40,00px aux
   deux largeurs du harnais (360 et 422), entre le bas de la bannière et cette barre,
   et le contenu défilait visiblement dedans. Sous la bannière il n'y a plus que la
   bannière : l'offset est --topnav-h tout court, et il ne dépend de la hauteur
   rendue d'aucune barre.
   Les deux barres que sélectionne cette classe sont concernées : les sous-onglets
   globaux de dashboard.hbs — rendus sous les deux SEULS onglets principaux qui en
   ont, « Ressources » et « Artefacts » (NAV_GROUPS, app/constants/nav.js) — et ceux
   du détail d'une aventure (dashboard/adventures/adventure.hbs, « Vue d'ensemble »,
   « Lieux »…), qui est le cas signalé.
   Vérifié après correction : 0,00px aux deux largeurs. */
@media (max-width: 767.98px) {
  .anima-subtab-bar {
    top: var(--topnav-h);
  }
}

.anima-subtab {
  display: inline-flex;
  align-items: center;
  white-space: nowrap;
  padding: 0.6rem 1.1rem;
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  font-family: 'Cinzel', serif;
  font-size: 0.85rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s;
}

.anima-subtab:hover {
  color: var(--ink);
}

.anima-subtab.active {
  color: var(--accent);
  border-bottom-color: var(--accent);
}

/* ── Messages privés : bulles de chat (gauche/droite + couleur par expéditeur) ── */
.anima-dm-thread {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.anima-dm-row {
  display: flex;
}

.anima-dm-row.mine {
  justify-content: flex-end;
}

.anima-dm-row.theirs {
  justify-content: flex-start;
}

.anima-dm-bubble {
  max-width: 78%;
  padding: 7px 11px;
  border-radius: 12px;
}

.anima-dm-row.mine .anima-dm-bubble {
  background: color-mix(in srgb, var(--accent) 20%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 38%, transparent);
  border-bottom-right-radius: 3px;
}

.anima-dm-row.theirs .anima-dm-bubble {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-bottom-left-radius: 3px;
}

.anima-dm-author {
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--accent);
  margin-bottom: 2px;
}

.anima-dm-text {
  font-size: 0.8rem;
  line-height: 1.5;
  word-break: break-word;
}

.anima-dm-meta {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 3px;
}

.anima-dm-time {
  font-size: 0.8rem;
  opacity: 0.6;
}

.anima-dm-del {
  padding: 1px 8px;
}


/* ========== Oneshot enrich editor (mirrors .patron-editor*, see patrons.css) ========== */

.oneshot-enrich-editor {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
  gap: 1.25rem;
  align-items: start;
}

.oneshot-enrich-main {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  min-width: 0;
}

.oneshot-enrich-header {
  display: flex;
  align-items: center;
}

.oneshot-enrich-name-field {
  flex: 1;
}

.oneshot-enrich-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  border-bottom: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
  padding-bottom: 0.4rem;
}

.oneshot-enrich-tab {
  background: none;
  border: 1px solid transparent;
  border-radius: 6px;
  padding: 0.35rem 0.7rem;
  font-family: 'Cinzel', serif;
  font-size: 0.8rem;
  text-transform: uppercase;
  color: var(--muted);
  cursor: pointer;
}

.oneshot-enrich-tab.is-active {
  border-color: color-mix(in srgb, var(--accent) 50%, transparent);
  color: inherit;
}

.oneshot-enrich-body {
  min-width: 0;
}

.oneshot-enrich-errors {
  margin: 0;
}

.oneshot-enrich-actions {
  display: flex;
  justify-content: flex-end;
  gap: 0.5rem;
}

.oneshot-enrich-preview {
  min-width: 0;
}

/* ── Rencontres : liste compacte ↔ vue focalisée plein écran ── */
.anima-encounter-list-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.6rem 0.9rem;
  cursor: pointer;
  background: var(--surface);
  border-bottom: 1px solid color-mix(in srgb, var(--accent) 15%, transparent);
  transition: background 0.12s;
}

.anima-encounter-list-row:hover {
  background: var(--surface-2);
}

.anima-encounter-list-row:hover .anima-encounter-list-chevron {
  color: var(--accent);
  transform: translateX(2px);
}

.anima-encounter-list-chevron {
  opacity: 0.6;
  color: var(--muted);
  transition: transform 0.12s, color 0.12s;
}

.anima-encounter-focus {
  padding: 0.9rem 1.1rem 1.1rem;
  background: var(--surface-2);
}

/* Sur téléphone, cette gouttière est la deuxième de trois emboîtées — après celle de
   `.anima-main-content` (16 px) et avant celle de `.anima-combat-panel` (14 px) — et
   c'est la liste de combat, tout au fond, qui paie l'addition. Mesuré à 360 px avant
   correction : la rangée d'initiative ne disposait que de 256,4 px, soit 103,6 px
   mangés par la chaîne, un cinquième de l'écran. Ramener 1,1rem à 0,25rem sous le seuil
   mobile rend 30,6 px ; le panneau en rend 16 de plus (cf. encounter-combat.css), et la
   rangée passe à 303,0 px.
   Au-dessus du seuil, la gouttière reste à 1,1rem : c'est du confort légitime quand la
   largeur ne manque pas. */
@media (max-width: 767.98px) {
  .anima-encounter-focus {
    padding-left: 0.25rem;
    padding-right: 0.25rem;
  }
}

.anima-encounter-back {
  margin-bottom: 0.75rem;
}

.anima-encounter-focus-title {
  margin-bottom: 0.5rem;
  font-family: 'Cinzel', serif;
  color: var(--ink-strong);
}

@media (max-width: 900px) {
  .oneshot-enrich-editor {
    grid-template-columns: 1fr;
  }
}

/* Aperçu de la carte actuelle en haut de la modale (miniature contrainte) */
.anima-map-gen-current {
  display: block;
  max-width: 100%;
  height: auto;
  max-height: 200px;
  object-fit: contain;
  margin: 0 auto 0.75rem;
  border-radius: 6px;
}

/* --- Génération de carte de lieu : galerie de propositions + aperçu zoomable --- */
.anima-map-gen-candidates-hint {
  color: var(--text-muted, #8a7f6f);
}

.anima-map-gen-candidates {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 0.5rem;
}

.anima-map-gen-candidate {
  padding: 0;
  border: 2px solid transparent;
  border-radius: 6px;
  background: none;
  cursor: pointer;
  overflow: hidden;
  line-height: 0;
}

.anima-map-gen-candidate:hover:not(:disabled) {
  border-color: var(--bs-primary, #c9a24b);
}

.anima-map-gen-candidate:disabled {
  opacity: 0.5;
  cursor: default;
}

.anima-map-gen-candidate img {
  width: 100%;
  height: 160px;
  object-fit: cover;
  display: block;
}

/* Aperçu plein écran, au-dessus de la modale (modale ~1300, dés ~1400) */
.anima-map-gen-lightbox {
  position: fixed;
  inset: 0;
  z-index: 1360;
  display: flex;
  flex-direction: column;
  background: rgba(12, 10, 8, 0.97);
}

.anima-map-gen-lightbox-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.5rem 0.9rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.15);
}

.anima-map-gen-lightbox-zoom {
  display: flex;
  align-items: center;
  gap: 0.4rem;
}

.anima-map-gen-lightbox-pct {
  min-width: 3.5rem;
  text-align: center;
  color: #eee;
  font-variant-numeric: tabular-nums;
}

.anima-map-gen-lightbox-canvas {
  flex: 1 1 auto;
  overflow: auto;
  padding: 0.5rem;
  text-align: center;
}

/* max-width:none => l'image peut déborder pour permettre le pan quand on zoome */
.anima-map-gen-lightbox-canvas img {
  display: inline-block;
  height: auto;
  max-width: none;
}

.anima-map-gen-lightbox-actions {
  display: flex;
  justify-content: flex-end;
  gap: 0.5rem;
  padding: 0.5rem 0.9rem;
  border-top: 1px solid rgba(255, 255, 255, 0.15);
}

/* --- Sélecteur de lieu avec recherche (liaison lieu ↔ rencontre) --- */
.anima-place-picker {
  display: flex;
  flex-direction: column;
  gap: 2px;
  max-height: 180px;
  overflow-y: auto;
  border: 1px solid var(--bs-border-color, rgba(0, 0, 0, 0.15));
  border-radius: 6px;
  padding: 4px;
}

.anima-place-option {
  display: block;
  width: 100%;
  text-align: left;
  padding: 0.3rem 0.55rem;
  border: 1px solid transparent;
  border-radius: 4px;
  background: none;
  color: inherit;
  cursor: pointer;
  font-size: 0.85rem;
}

.anima-place-option:hover {
  background: var(--bs-tertiary-bg, rgba(0, 0, 0, 0.05));
}

.anima-place-option.active {
  background: var(--bs-primary, #c9a24b);
  color: #fff;
  border-color: var(--bs-primary, #c9a24b);
}

.archetype-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
}
.archetype-kind-badge {
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 0.1rem 0.45rem;
  border-radius: 999px;
  border: 1px solid currentColor;
  white-space: nowrap;
}
.archetype-kind-badge.is-snapshot { color: var(--zeon, #b8860b); }
.archetype-kind-badge.is-bands { color: var(--accent, #6c757d); }
.npc-generator-locked-level { font-size: 0.85rem; opacity: 0.8; margin: 0.25rem 0; }

.snapshot-stat-block-modal { max-width: 680px; }

.snapshot-modal-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.75rem;
  margin-bottom: 1rem;
  padding-bottom: 0.75rem;
  border-bottom: 1px solid var(--border);
}
.snapshot-modal-head h4 {
  margin: 0;
  font-family: 'Cinzel', Georgia, serif;
  color: var(--accent);
}
.snapshot-modal-title { display: flex; align-items: baseline; flex-wrap: wrap; gap: 0.6rem; }
.snapshot-level { font-size: 0.85rem; opacity: 0.8; }

.snapshot-section { margin-top: 1.1rem; }
.snapshot-section h5 {
  font-family: 'Cinzel', Georgia, serif;
  font-size: 0.8rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--accent);
  margin-bottom: 0.5rem;
}

.snapshot-char-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0.4rem; }
.snapshot-char-cell {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 2px;
  padding: 0.4rem 0.25rem;
}
.snapshot-char-label {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--muted);
}
.snapshot-char-final {
  font-family: 'JetBrains Mono', monospace;
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--accent);
}

/* Grille de stats dérivées / résistances — réutilise .anima-derived-stat des fiches perso.
   Le minimum de piste est le seul levier qui décide de la largeur de la boîte de texte :
   `auto-fill` n'accepte pas de fonction de dimensionnement intrinsèque, on ne peut donc pas
   écrire `min-content` ici — c'est ce minimum-là qu'il faut tenir à jour à la main quand la
   police des libellés bouge. Il valait 88px quand `.anima-stat-label` était à 0,55 rem ; à
   0,8 rem le mot insécable le plus long, « INITIATIVE » (majuscules + letter-spacing 0,15em),
   demande 108 px, plus 26 px de rembourrage et de bordure d'`.anima-derived-stat` = 134 px.
   Mesuré à 360 px avant ce changement : trois pistes de 105,2 px, « INITIATIVE » et
   « MOUVEMENT » rognés dans leur cellule et la grille débordant de 5 px — invisible parce que
   `.anima-modal` porte `overflow-x: hidden`. 7,5 rem = 135 px : exprimé en rem, le minimum suit
   la même racine que les libellés. Donne 2 pistes à 360 et 422 px, 3 à 575, 4 au plafond de la
   modale (680 px) — et plus aucun libellé rogné à aucune de ces largeurs (remesuré). */
.snapshot-stat-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(7.5rem, 1fr)); gap: 0.4rem; }
.snapshot-stat-block-modal .anima-derived-value { font-size: 1.1rem; margin-top: 0; }

/* Détail « avec l'arme » sous les tuiles de combat : ce que le résolveur joue une fois la
   qualité de l'exemplaire ajoutée. Affiché seulement quand au moins une arme équipée porte
   une qualité — sinon il répéterait les tuiles. 0.8 rem = le plancher du projet.
   `overflow-x: auto` sur l'enveloppe : trois colonnes tiennent à 360 px, mais un nom d'arme
   long allonge la première et le tableau doit défiler chez lui, jamais la page. */
.snapshot-weapon-scores { margin-top: 0.7rem; overflow-x: auto; }
.snapshot-weapon-scores-note { font-size: 0.8rem; opacity: 0.85; margin-bottom: 0.4rem; }
.snapshot-weapon-scores-table { width: 100%; border-collapse: collapse; font-size: 0.8rem; }
.snapshot-weapon-scores-table th,
.snapshot-weapon-scores-table td {
  padding: 0.25rem 0.4rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.12);
  text-align: left;
}
.snapshot-weapon-scores-table td { text-align: right; font-variant-numeric: tabular-nums; }
.snapshot-weapon-scores-table thead th { opacity: 0.75; font-weight: 600; }
.snapshot-weapon-scores-table thead th + th { text-align: right; }
.snapshot-weapon-quality { opacity: 0.75; }

/* Bandeau « fiche incomplète » : le moteur n'a pas reconnu la classe ou la race du patron,
   et les valeurs dérivées affichées dessous sont calculées sans elles. 0.8 rem = le plancher
   du projet. */
.snapshot-derived-warning {
  font-size: 0.8rem;
  margin: 0 0 0.6rem;
  padding: 0.5rem 0.7rem;
  border-left: 3px solid #b8860b;
  background: rgba(184, 134, 11, 0.12);
  border-radius: 0.2rem;
}
/* Chaque clé fautive sur sa propre ligne, sous la phrase d'en-tête. */
.snapshot-derived-warning-key { display: block; margin-top: 0.25rem; }

/* Capacités secondaires — pastilles cohérentes avec le thème */
.snapshot-secondary-list { display: flex; flex-wrap: wrap; gap: 0.35rem; }
.snapshot-secondary-cell {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.8rem;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 2px;
  padding: 0.15rem 0.5rem;
  color: var(--ink);
}

/* Listes textuelles (inventaire, capacités, avantages, possessions) */
.snapshot-inventory-list,
.snapshot-display-list { margin: 0; padding-left: 1.1rem; font-size: 0.85rem; line-height: 1.5; }
.snapshot-inventory-list li,
.snapshot-display-list li { margin-bottom: 0.15rem; }
.snapshot-wallet { display: flex; gap: 0.6rem; font-size: 0.85rem; opacity: 0.85; margin-top: 0.4rem; }

/* ===== Ambient sounds ===== */
.anima-ambient-bar {
  margin: 0 0 1rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface);
}
.anima-ambient-bar__summary {
  cursor: pointer;
  padding: 0.5rem 0.75rem;
  font-weight: 600;
  font-size: 0.9rem;
}
.anima-ambient-bar__body {
  padding: 0.5rem 0.75rem 0.75rem;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}
.anima-ambient-unlock { align-self: flex-start; margin-bottom: 0.25rem; }
.anima-ambient-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.anima-ambient-row__label {
  flex: 0 0 8rem;
  font-size: 0.85rem;
}
.anima-ambient-row__label.is-paused { opacity: 0.55; font-style: italic; }
.anima-ambient-row input[type='range'] { flex: 1; }
.anima-ambient-play {
  flex: 0 0 auto;
  width: 1.6rem;
  height: 1.6rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 5px;
  background: transparent;
  color: var(--ink);
  font-size: 0.85rem;
  line-height: 1;
  cursor: pointer;
  transition: border-color 0.12s ease, color 0.12s ease;
}
.anima-ambient-play:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.anima-ambient-play:disabled { opacity: 0.5; cursor: default; }

.anima-ambient-gm { margin-top: 1rem; }
.anima-ambient-active__list,
.anima-ambient-search__results,
.anima-ambient-uploads__list {
  list-style: none;
  padding: 0;
  margin: 0.25rem 0;
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}
.anima-ambient-active__item,
.anima-ambient-search__item,
.anima-ambient-uploads__item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.3rem 0.5rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 0.85rem;
}
.anima-ambient-search { margin-top: 0.75rem; }
.anima-ambient-search__results { max-height: 14rem; overflow-y: auto; }
.anima-ambient-uploads { margin-top: 0.75rem; }
.anima-ambient-upload-btn { display: inline-block; cursor: pointer; }

.anima-ambient-freesound,
.anima-ambient-freesound-refs {
  margin-top: 0.75rem;
}

.anima-ambient-freesound__status {
  font-size: 0.85rem;
  opacity: 0.75;
  margin: 0.4rem 0;
}

.anima-ambient-freesound__results,
.anima-ambient-freesound-refs__list {
  list-style: none;
  padding: 0;
  margin: 0.5rem 0 0;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.anima-ambient-freesound__results {
  max-height: 18rem;
  overflow-y: auto;
  padding-right: 0.15rem;
}

.anima-ambient-freesound__item,
.anima-ambient-freesound-refs__item {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.45rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface);
  transition: border-color 0.12s ease, background 0.12s ease, box-shadow 0.12s ease;
}

.anima-ambient-freesound__item:hover,
.anima-ambient-freesound-refs__item:hover {
  border-color: var(--accent);
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.15);
}

.anima-ambient-freesound__item.is-previewing,
.anima-ambient-freesound-refs__item.is-previewing {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 12%, var(--surface));
}

.anima-ambient-freesound__preview {
  flex: 0 0 auto;
}

.anima-ambient-freesound__item.is-previewing .anima-ambient-freesound__preview,
.anima-ambient-freesound-refs__item.is-previewing .anima-ambient-freesound__preview {
  border-color: var(--accent);
  color: var(--accent);
}

.anima-ambient-freesound__meta {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
}

.anima-ambient-freesound__meta strong {
  font-size: 0.9rem;
  line-height: 1.2;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.anima-ambient-freesound__meta small {
  font-size: 0.8rem;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.anima-ambient-freesound__dur {
  align-self: flex-start;
  margin-top: 0.05rem;
  padding: 0.02rem 0.4rem;
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--muted);
  font-size: 0.8rem;
}

/* Boutons d'action (renommer / supprimer) d'un son ajouté */
.anima-ambient-item__actions {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 0.35rem;
}

/* Champ d'édition inline du nom */
.anima-ambient-rename__input {
  flex: 1 1 auto;
  min-width: 0;
  height: auto;
  padding: 0.2rem 0.5rem;
  font-size: 0.85rem;
}

.anima-ambient-freesound__add {
  flex: 0 0 auto;
}

/* Panel body inside the floating ambient window */
.anima-ambient-panel {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  min-width: 18rem;
}
.anima-ambient-panel .anima-empty {
  margin: 0.25rem 0;
  color: var(--muted);
  font-size: 0.85rem;
  font-style: italic;
}
.anima-ambient-panel .anima-form-error {
  margin: 0 0 0.25rem;
  color: var(--danger);
  font-size: 0.85rem;
}

/* GM library section (search + add sounds + uploads) rendered inside the GM tab */
.anima-ambient-library {
  border: 1px solid var(--border);
  border-radius: 0.5rem;
  padding: 1rem;
  background: var(--surface-2);
  margin-top: 1rem;
}
.anima-ambient-library__title {
  font-family: 'Cinzel', serif;
  font-size: 1rem;
  margin: 0 0 0.75rem;
}

/* ── Sous-onglets MJ (Maîtrise / Ambiance) ── */
.anima-gm-section-nav {
  display: flex;
  gap: 0.4rem;
  margin: 0 0 1rem;
  border-bottom: 1px solid var(--border);
}

.anima-gm-section-tab {
  appearance: none;
  border: none;
  background: none;
  padding: 0.5rem 0.9rem;
  font-family: 'Cinzel', serif;
  font-size: 0.85rem;
  letter-spacing: 0.02em;
  color: var(--muted);
  cursor: pointer;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  transition: color 0.12s ease, border-color 0.12s ease;
}

.anima-gm-section-tab:hover {
  color: var(--ink);
}

.anima-gm-section-tab.active {
  color: var(--accent);
  border-bottom-color: var(--accent);
}

/* ── En-tête générique de section fournisseur (Freesound, YouTube, uploads… et Spotify plus tard) ── */
.anima-ambient-provider {
  margin-top: 1.25rem;
}

.anima-ambient-provider:first-of-type {
  margin-top: 0.5rem;
}

.anima-ambient-provider__head {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin: 0 0 0.5rem;
  padding-bottom: 0.4rem;
  border-bottom: 1px solid var(--border);
}

.anima-ambient-provider__icon {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  border-radius: 8px;
  background: var(--surface);
  border: 1px solid var(--border);
  font-size: 1.05rem;
  line-height: 1;
}

.anima-ambient-provider__titles {
  display: flex;
  flex-direction: column;
  gap: 0.05rem;
  min-width: 0;
}

.anima-ambient-provider__title {
  font-family: 'Cinzel', serif;
  font-size: 0.92rem;
  margin: 0;
}

.anima-ambient-provider__hint {
  margin: 0;
  font-size: 0.8rem;
  color: var(--muted);
}

/* Floating ambient FAB — stacked above the global dice FAB (bottom:24px, 56px tall) */
.anima-ambient-fab {
  position: fixed;
  bottom: 6rem;
  right: 24px;
  z-index: 1150; /* above page/map (1050) & window trigger, below the opened window (1200) and modals (1300) */
  width: 3rem;
  height: 3rem;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--ink);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.35);
  font-size: 1.3rem;
  line-height: 1;
  cursor: pointer;
  transition: transform 0.12s ease, box-shadow 0.12s ease;
}
.anima-ambient-fab:hover { transform: translateY(-2px); }
.anima-ambient-fab:active { transform: translateY(0); }
.anima-ambient-fab.is-live {
  border-color: var(--accent);
  animation: anima-ambient-pulse 2s ease-in-out infinite;
}
@keyframes anima-ambient-pulse {
  0%, 100% { box-shadow: 0 4px 12px rgba(0, 0, 0, 0.35), 0 0 0 0 var(--accent); }
  50% { box-shadow: 0 4px 12px rgba(0, 0, 0, 0.35), 0 0 0 5px transparent; }
}
.anima-ambient-fab__badge {
  position: absolute;
  top: -0.15rem;
  right: -0.15rem;
  min-width: 1.1rem;
  height: 1.1rem;
  padding: 0 0.25rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  background: var(--accent);
  color: var(--on-accent);
  font-size: 0.8rem;
  font-weight: 700;
  line-height: 1;
}

@media (prefers-reduced-motion: reduce) {
  .anima-ambient-fab { transition: none; }
  .anima-ambient-fab.is-live { animation: none; }
}

@media (max-width: 640px) {
  .anima-ambient-row__label { flex-basis: 5rem; }
}

/* Téléphone : le bas de l'écran appartient à la barre de navigation. Le déclencheur
   de l'ambiance vit alors dans la bannière du haut (cf. dashboard.hbs).
   Placé APRÈS le bloc 640 px, qui repositionnait le FAB (`bottom: 5.5rem; right: 16px`,
   pour dégager le FAB des dés) : cette règle-là ne s'appliquait qu'en dessous de 640 px,
   donc entièrement à l'intérieur de la plage où le FAB est maintenant masqué — morte, et
   retirée. L'ordre des deux blocs n'était de toute façon pas en cause : `display` et
   `bottom` sont des propriétés distinctes, il n'y avait pas de conflit de cascade.
   Mesuré (display CALCULÉ sur le vrai <button>) : `none` à 360 et 422 px, `block` à 768
   et à 900 px.
   `block` et non `inline-block`, alors qu'aucune règle ici ne déclare de `display` et
   qu'un <button> nu calcule `inline-block` — vérifié dans le même relevé : c'est le
   `position: fixed` de la règle de base qui blockifie l'élément. Mesuré côte à côte à
   900 px : bouton nu `inline-block`, `position: fixed` `block`, `position: absolute`
   `block`, et même `display: inline-block` écrit à la main avec `position: fixed`
   ressort `block`. La valeur ne se déduit donc pas du seul markup. */
@media (max-width: 767.98px) {
  .anima-ambient-fab { display: none; }
}

.anima-ambient-youtube__status {
  font-size: 0.85rem;
  opacity: 0.75;
  margin: 0.4rem 0;
}

.anima-ambient-youtube__results,
.anima-ambient-youtube-refs__list {
  list-style: none;
  padding: 0;
  margin: 0.5rem 0 0;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.anima-ambient-youtube__results {
  max-height: 18rem;
  overflow-y: auto;
  padding-right: 0.15rem;
}

.anima-ambient-youtube__item,
.anima-ambient-youtube-refs__item {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.45rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface);
  transition: border-color 0.12s ease, background 0.12s ease, box-shadow 0.12s ease;
}

.anima-ambient-youtube__item:hover,
.anima-ambient-youtube-refs__item:hover {
  border-color: var(--accent);
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.15);
}

.anima-ambient-youtube__item.is-previewing,
.anima-ambient-youtube-refs__item.is-previewing {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 12%, var(--surface));
}

.anima-ambient-youtube__preview {
  flex: 0 0 auto;
}

.anima-ambient-youtube__item.is-previewing .anima-ambient-youtube__preview,
.anima-ambient-youtube-refs__item.is-previewing .anima-ambient-youtube__preview {
  border-color: var(--accent);
  color: var(--accent);
}

.anima-ambient-youtube__meta {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  flex: 1 1 auto;
  min-width: 0;
}

.anima-ambient-youtube__meta strong {
  font-size: 0.9rem;
  line-height: 1.2;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.anima-ambient-youtube__meta small {
  font-size: 0.8rem;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.anima-ambient-youtube__dur {
  align-self: flex-start;
  margin-top: 0.05rem;
  padding: 0.02rem 0.4rem;
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--muted);
  font-size: 0.8rem;
}

.anima-ambient-youtube__add {
  flex: 0 0 auto;
}

.anima-ambient-youtube__thumb {
  width: 60px;
  height: 34px;
  object-fit: cover;
  border-radius: 4px;
  flex: 0 0 auto;
}

/* ── Ambiance : playlists de musique YouTube ── */
.anima-ambient-playlists__transport {
  display: flex;
  gap: 0.4rem;
  align-items: center;
  margin: 0.6rem 0;
}
.anima-ambient-playlists__transport .btn.is-active {
  background: var(--accent);
  color: var(--on-accent, #fff);
}
.anima-ambient-playlists__list {
  list-style: none;
  margin: 0.4rem 0 0;
  padding: 0;
}
.anima-ambient-playlists__item {
  padding: 0.3rem 0;
  border-top: 1px solid var(--border);
}
.anima-ambient-playlists__row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.anima-ambient-playlists__name {
  background: none;
  border: none;
  color: inherit;
  cursor: pointer;
  text-align: left;
  font-size: 0.9rem;
  flex: 1;
}
.anima-ambient-playlists__track-search {
  margin: 0.4rem 0 0.4rem 0.8rem;
}
.anima-ambient-playlists__track-results {
  list-style: none;
  margin: 0.3rem 0 0;
  padding: 0;
}
.anima-ambient-playlists__track-result {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.2rem 0;
}
.anima-ambient-playlists__tracks {
  list-style: none;
  margin: 0.4rem 0 0.6rem 0.8rem;
  padding: 0;
}
.anima-ambient-playlists__track {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.2rem 0;
}
.anima-ambient-playlists__track.is-current .anima-ambient-playlists__track-name {
  font-weight: 700;
  color: var(--accent);
}
.anima-ambient-playlists__track-name {
  background: none;
  border: none;
  color: inherit;
  cursor: pointer;
  text-align: left;
  font-size: 0.9rem;
  flex: 1;
}
.anima-ambient-playlists__track-channel {
  font-size: 0.8rem;
  opacity: 0.7;
}
.anima-ambient-hud__now-playing {
  font-size: 0.85rem;
  margin-top: 0.3rem;
  opacity: 0.9;
}

/* ── Tailles sorties du markup (plancher de police) ──────────────────────────
   Anciennes déclarations `style="font-size:…"` des gabarits d'aventure. Elles ne
   servent que sur cette page, d'où leur place ici plutôt que dans components.css.
   Plancher du projet : 0.8rem (CLAUDE.md). */

/* Nom cliquable d'un PNJ ou d'un personnage lié, souligné en pointillé. Le
   sélecteur est composé pour la même raison que `.anima-name-compact` : la
   taille de base de `.anima-char-name` est déclarée dans une feuille chargée
   après celle-ci, et gagnerait l'arbitrage de l'ordre source à spécificité
   égale. */
.anima-name-link-compact,
.anima-char-name.anima-name-link-compact {
  font-size: 0.8rem;
}

/* Dans la colonne « nom » de la grille PNJ, ce nom est en `white-space: nowrap`
   sous un conteneur en `overflow: hidden` : un nom long était déjà coupé net
   avant la remontée au plancher, sans aucun signe à l'écran, et la remontée
   creuse la coupe. La grille, elle, ne bouge pas — la piste est en `1fr` avec
   `min-width: 0`, mesuré à dix largeurs de 360 à 1920 px. Ces trois
   déclarations ne changent aucune boîte : elles rendent seulement la coupe
   lisible. */
.anima-npc-col-name .anima-name-link-compact {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Éditeur de PV en ligne dans la liste des personnages liés : le champ, puis le
   « / maximum » qui le suit. */
.anima-hp-inline-input,
.anima-hp-inline-max {
  font-size: 0.8rem;
}

/* Erreur du jet de PhR, dans la modale de jet. */
.anima-roll-modal-error {
  font-size: 0.8rem;
}

/* En-tête d'une section repliable de liste (favoris, sections par étiquette),
   avec son compteur et son chevron. */
.anima-list-section-label,
.anima-list-section-count,
.anima-list-section-caret {
  font-size: 0.8rem;
}

/* Chevron de dépliage d'une rangée de lieu. */
.anima-place-row-caret {
  font-size: 0.8rem;
}

/* Étoile de mise en favori. Seule taille de ce lot qui était DÉJÀ au-dessus du
   plancher : c'est un glyphe décoratif volontairement plus gros que le texte de
   la rangée, et le ramener au plancher l'aurait rapetissé. Elle bat le 0.8rem de
   `.btn-sm` par l'ordre des feuilles, à spécificité égale. */
.anima-favorite-toggle {
  font-size: 0.85rem;
}

/* Rangées du sélecteur de participants / de créatures du bestiaire : le texte,
   puis la pastille PJ/PNJ et l'étiquette « déjà ajouté ». */
.anima-picker-row-text,
.anima-picker-row-badge {
  font-size: 0.8rem;
}

/* Pastille PJ/PNJ encadrée. Ces déclarations étaient auparavant écrites dans un
   attribut `style` dont la bordure et la couleur étaient concaténées depuis une
   condition ; `ember-template-lint` refuse un style concaténé (il échappe à
   `htmlSafe`). L'étiquette « déjà ajouté » partage `.anima-picker-row-badge`
   sans être encadrée, d'où la classe supplémentaire plutôt qu'une reprise du
   sélecteur de base. */
.anima-picker-row-badge-outlined {
  padding: 1px 6px;
  border: 1px solid;
  border-radius: 3px;
}

.anima-picker-row-badge-outlined.is-pnj {
  border-color: var(--hp);
  color: var(--hp);
}

.anima-picker-row-badge-outlined.is-pj {
  border-color: var(--success);
  color: var(--success);
}

/* Le nom qui occupe le reste de la rangée. `min-width: 0` est ce qui empêche la
   rangée de déborder : un élément flex garde par défaut la largeur de son plus
   long mot comme minimum, et sur un écran étroit ce minimum poussait le bouton
   « Ajouter » hors de la rangée dès que le nom montait au plancher de police.
   Relevé sur page-témoin décalquant la chaîne de conteneurs réelle, à dix
   largeurs de 360 à 1920 px : le débordement n'apparaissait qu'à 360 px, et il
   disparaît avec ces quatre déclarations. Le nom est désormais coupé par des
   points de suspension au lieu de pousser ses voisins. */
.anima-picker-row-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Message privé du MJ : le corps, et la ligne d'expéditeur au-dessus. Deux
   tailles distinctes parce que la hiérarchie entre les deux était voulue — le
   corps restait plus gros que sa métadonnée, et l'écraser au même plancher
   aurait mis les deux au même niveau. */
.anima-dm-popup-body {
  font-size: 0.85rem;
}

.anima-dm-popup-from {
  font-size: 0.8rem;
}

/* Pastille « nouveaux messages » dans l'en-tête de la carte MJ. */
.anima-dm-unread-badge {
  font-size: 0.8rem;
}


/* ── Mises en forme sorties du markup (attribut `style` littéral) ─────────────
   Second lot après celui des tailles de police ci-dessus, et pour la même raison :
   une valeur écrite dans un attribut `style` n'est atteignable par aucune feuille
   sans `!important`, quelle que soit la spécificité et quel que soit l'ordre des
   sources. Toutes ces déclarations ne servent que sur les gabarits d'aventure,
   d'où leur place ici plutôt que dans components.css.

   Les valeurs sont reprises telles quelles ; aucune n'a été arrondie ni
   réharmonisée au passage. Ce lot déplace, il ne redessine pas. */

/* Nom cliquable d'un PNJ ou d'un personnage lié. Le sélecteur est composé pour la
   raison DÉJÀ écrite plus haut à propos de la taille : `.anima-char-name` est
   redéclarée dans `pages/characters.css`, chargée APRÈS cette feuille. Mesuré sur
   page-témoin — une classe simple perd ici l'arbitrage de l'ordre source à
   spécificité égale, et la couleur retombait sur `var(--ink)` de characters.css au
   lieu de `var(--link)`. La forme composée est ce qui rend le déplacement neutre. */
.anima-name-link-compact,
.anima-char-name.anima-name-link-compact {
  white-space: nowrap;
  color: var(--link);
  text-decoration: underline;
  text-decoration-style: dotted;
  cursor: pointer;
}

/* En-têtes de section des deux listes repliables (PNJ, lieux). Les quatre en-têtes
   partagent leur famille de déclarations deux à deux ; ce qui les sépare est la
   gouttière horizontale — la liste des PNJ est encadrée par sa carte, celle des
   lieux affleure son bord — et, pour les favoris, le fait que seul l'en-tête PNJ
   soit repliable au clic. */
.anima-npc-favorites-label,
.anima-place-favorites-label {
  color: var(--accent);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  opacity: 0.7;
}

.anima-npc-favorites-label {
  padding: 4px 14px 2px;
  display: flex;
  align-items: center;
  cursor: pointer;
}

.anima-place-favorites-label {
  padding: 4px 0 2px;
}

.anima-npc-tag-section-label,
.anima-place-tag-section-label {
  letter-spacing: 0.05em;
  text-transform: uppercase;
  opacity: 0.85;
  border-top: 1px dashed color-mix(in srgb, var(--accent) 15%, transparent);
  margin-top: 2px;
  display: flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
}

.anima-npc-tag-section-label {
  padding: 5px 14px;
}

.anima-place-tag-section-label {
  padding: 5px 0;
}

/* Le chevron est poussé au bout de sa rangée, le compteur reste en retrait. Ces
   deux classes ne servent que dans ces en-têtes et y portaient partout la même
   valeur : les déclarations rejoignent la classe de base plutôt qu'un modificateur. */
.anima-list-section-caret {
  margin-left: auto;
  opacity: 0.5;
}

.anima-list-section-count {
  opacity: 0.45;
}

/* Libellé « sans étiquette » d'une section de tags. Ses voisins portent une couleur
   calculée depuis l'étiquette (`css-prop`), qui reste en ligne — celui-ci est fixe. */
.anima-tag-section-uncategorized {
  color: var(--muted);
}

/* Étoile de mise en favori. La gouttière et l'interligne sont communs aux huit
   emplacements ; seule la couleur distingue l'état, d'où les deux modificateurs.
   Ces déclarations battent celles de `.btn-sm` par l'ordre des feuilles — vendor.css
   est chargée avant celle-ci — à spécificité égale. */
.anima-favorite-toggle {
  padding: 0 4px;
  line-height: 1;
}

.anima-favorite-toggle--on {
  color: var(--accent);
}

.anima-favorite-toggle--off {
  color: var(--muted);
}

/* Dans une rangée de lieu, l'étoile et le chevron ne doivent pas se laisser
   comprimer par le titre. Les trois rangées concernées sont toutes des
   `.anima-place-row`, et `.anima-place-row-caret` ne sert nulle part ailleurs. */
.anima-place-row .anima-favorite-toggle {
  flex-shrink: 0;
}

.anima-place-row-caret {
  opacity: 0.6;
  flex-shrink: 0;
}

/* Ce qui déplie le lieu est un `<button>` DANS le titre — chevron et nom réunis.
   La rangée elle-même ne peut pas l'être : elle contient l'étoile de favori et,
   pour le MJ, deux boutons de plus, et un bouton n'en contient pas d'autre. Un
   `role="button"` sur la rangée aurait en outre sorti ces trois boutons de l'arbre
   d'accessibilité.

   Le bouton reprend la disposition que le titre et le chevron tenaient de la
   rangée : même gouttière de 0,5 rem, chevron incompressible, titre qui coupe où
   il faut. La rangée, elle, n'a plus de curseur de main — plus rien ne s'y
   déclenche au clic hors de ses boutons. */
.anima-place-row-toggle {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  min-width: 0;
  overflow-wrap: anywhere;
}

/* Bande d'étiquettes d'une rangée de PNJ : elle prend la place restante et coupe
   au lieu de pousser ses voisins hors de la rangée. */
.anima-npc-tag-strip {
  flex: 1;
  overflow: hidden;
}

/* ── Rencontres ── */

/* Nom d'une rencontre dans la liste compacte : il prend la place restante entre
   l'icône et le compteur de participants. */
.anima-encounter-list-name {
  flex: 1;
}

/* Sélecteur d'onglets encadré de la modale « ajouter un participant » : le cadre
   est porté par le conteneur, les boutons perdent leurs coins pour s'y ajuster. */
.anima-tab-switcher {
  border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
  border-radius: 4px;
  overflow: hidden;
}

.anima-tab-switcher-btn {
  border-radius: 0;
  flex: 1;
}

/* Rangées des deux sélecteurs (personnages de l'aventure, créatures du bestiaire).
   La seconde est un `<button>` et non un `<div>`, d'où le `text-align` qui défait
   le centrage par défaut d'un bouton.

   Le nom porte « encounter » parce que `.anima-picker-row` TOUT COURT existe déjà
   dans `pages/characters.css`, chargée après celle-ci : mesuré sur page-témoin, la
   rangée héritait alors d'une bordure, d'un curseur et d'un `justify-content` qui
   ne sont pas les siens. */
.anima-encounter-picker-row {
  background: var(--surface);
  border-radius: 4px;
  border: 1px solid var(--surface-2);
}

.anima-bestiary-picker-row {
  border-radius: 4px;
  text-align: left;
}

.anima-picker-row-icon {
  color: var(--accent);
}

.anima-picker-row-add-btn {
  padding: 1px 8px;
}

.anima-bestiary-count-input {
  width: 80px;
}

/* ── Personnages liés : édition des PV en ligne ── */

/* Le champ et le « / maximum » qui le suit partagent déjà leur taille plus haut ;
   la largeur et la gouttière ne concernent que le champ, la couleur que le maximum. */
.anima-hp-inline-input {
  width: 64px;
  padding: 1px 4px;
}

.anima-hp-inline-max {
  color: var(--muted);
}

/* Bouton de jet de RP, sous la rangée d'un personnage agonisant. */
.anima-phr-roll-btn {
  margin-top: 2px;
}

/* Modale de jet de RP : l'erreur, la ligne de difficulté, le bouton de lancer. */
.anima-roll-modal-error {
  color: var(--danger);
}

.anima-roll-modal-hint {
  text-align: center;
  color: var(--muted);
}

.anima-roll-modal-submit {
  width: 100%;
  margin-top: 8px;
}

/* ── Participants ── */

/* Le bloc nom d'une rangée de participant prend la place restante ; `min-width: 0`
   est ce qui autorise la coupe — un élément flex garde sinon la largeur de son plus
   long mot comme minimum et pousse ses voisins hors de la rangée. La même paire sert
   dans la liste de participants de la page d'aventure. */
.anima-participant-identity {
  flex: 1;
  min-width: 0;
}

.anima-participant-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.anima-participant-role-badge {
  white-space: nowrap;
}

/* ── Message privé du MJ ── */

/* La modale d'annonce est étroite et centrée ; son pied est enfant direct de la
   boîte, pas du corps — il ne relève donc pas de la famille de pieds à bandeau
   pleine largeur, et sa gouttière ne s'accorde à aucune marge négative.

   Les quatre sélecteurs qui suivent sont COMPOSÉS avec la classe de socle qu'ils
   accompagnent. Mesuré sur page-témoin : `components.css` vise ces éléments par
   `.anima-modal > .anima-modal-actions` et consorts, à deux classes ; une classe
   simple perdait, et le pied reprenait la gouttière et la couleur de bordure du
   socle au lieu des siennes. La forme composée est à égalité de spécificité et
   gagne par l'ordre des feuilles, celle-ci étant chargée après components.css. */
.anima-modal.anima-dm-popup-modal {
  max-width: 380px;
  text-align: center;
}

.anima-modal-header.anima-dm-popup-header {
  justify-content: center;
}

.anima-modal-body.anima-dm-popup-body {
  padding: 16px;
  line-height: 1.6;
}

.anima-dm-popup-from {
  color: var(--accent);
  margin-bottom: 8px;
}

.anima-modal-actions.anima-dm-popup-actions {
  margin-top: 0;
  padding: 12px 16px;
  border-top: 1px solid color-mix(in srgb, var(--accent) 15%, transparent);
  justify-content: center;
}

/* Fil de discussion MJ de la page d'aventure, et sa pastille de non-lus. */
.anima-dm-thread-scroll {
  max-height: 50vh;
  overflow-y: auto;
  margin-bottom: 12px;
}

.anima-dm-unread-badge {
  background: color-mix(in srgb, var(--accent) 20%, transparent);
  color: var(--accent);
  border-radius: 10px;
  padding: 1px 8px;
}

/* Modale de discussion MJ. Même remarque que pour l'annonce : son pied est enfant
   direct de la boîte. */
.anima-modal-body.anima-dm-modal-body {
  padding: 12px 16px;
}

.anima-modal-actions.anima-dm-modal-actions {
  margin-top: 0;
  padding: 12px 16px;
  border-top: 1px solid color-mix(in srgb, var(--accent) 15%, transparent);
}

/* ── Modales plafonnées en largeur ──
   Composées avec `.anima-modal` pour la même raison que le pied ci-dessus. */

.anima-modal.anima-tag-popover-modal {
  max-width: 340px;
}

.anima-modal.anima-oneshot-stats-modal {
  max-width: 520px;
}

/* Titre de la section « aventures rejointes ». Le reste de la page laisse
   `.page-title` à sa couleur d'accent ; celui-ci est volontairement en encre. */
.anima-adventures-player-title {
  color: var(--ink);
}
