/* ========== Character card elements ========== */

.anima-character-toolbar {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 18px;
}

.anima-character-search {
  max-width: 420px;
}

.anima-character-create-actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-left: auto;
}

.anima-character-section {
  margin-top: 22px;
}

.anima-character-section-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 10px;
  border-bottom: 1px solid var(--border);
  padding-bottom: 6px;
}

.anima-character-section-header h2 {
  font-family: 'Cinzel', Georgia, serif;
  font-size: 1rem;
  color: var(--ink);
  margin: 0;
}

.anima-character-section-header span {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.8rem;
  color: var(--muted);
}

.anima-char-card--npc {
  border-color: color-mix(in srgb, var(--zeon) 38%, transparent);
  background: linear-gradient(180deg, color-mix(in srgb, var(--zeon) 8%, transparent), transparent);
}

.anima-char-card--npc:hover {
  border-color: color-mix(in srgb, var(--zeon) 62%, transparent);
}

.anima-card-type-badge {
  display: inline-flex;
  align-items: center;
  width: fit-content;
  border: 1px solid var(--border);
  color: var(--accent);
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.8rem;
  text-transform: uppercase;
  padding: 2px 6px;
  margin-bottom: 6px;
}

.anima-card-type-badge--npc {
  border-color: color-mix(in srgb, var(--zeon) 48%, transparent);
  color: var(--zeon);
}

.anima-character-avatar {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  overflow: hidden;
  background: var(--surface-2);
  border: 1px solid var(--border);
  color: var(--accent);
  font-family: 'Cinzel', Georgia, serif;
  font-size: 1rem;
  font-weight: 600;
  line-height: 1;
}

.anima-character-avatar img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.anima-character-avatar-preview-trigger {
  display: block;
  width: 100%;
  height: 100%;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: zoom-in;
}

/* `> span` et non `span` : le sélecteur descendant attrapait aussi les spans d'initiale
   ajoutés à l'intérieur (une lettre chacun), et deux boîtes à `width: 100%` dans un
   conteneur de 24 px en font 200 %. Aucun changement de rendu par ailleurs — un
   `.anima-character-avatar` ne contient qu'un `<button>` (portrait) ou ce span-ci
   (initiales), jamais un span imbriqué qui aurait besoin de la règle. */
.anima-character-avatar > span {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
}

.anima-character-avatar--mini {
  width: 32px;
  height: 32px;
  font-size: 0.8rem;
}

.anima-character-avatar--card {
  width: 48px;
  height: 48px;
  font-size: 1rem;
}

.anima-character-avatar--sheet {
  width: 5.333rem;
  height: 5.333rem;
  font-size: 1.8rem;
}

.anima-character-avatar--gallery {
  width: 10rem;
  height: 10rem;
  font-size: 3rem;
}

.anima-character-avatar--square {
  border-radius: 0.111rem;
}

.anima-character-avatar--round {
  border-radius: 50%;
}

.anima-character-avatar-preview {
  padding: 1.333rem;
}

.anima-character-avatar-preview-frame {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  max-width: min(92vw, 56rem);
  max-height: 88vh;
}

.anima-character-avatar-preview-frame img {
  display: block;
  max-width: 100%;
  max-height: 88vh;
  border: 1px solid var(--border);
  border-radius: 0.444rem;
  box-shadow: 0 1.333rem 3.333rem rgba(0, 0, 0, 0.5); /* one-off shadow, no matching shadow token */
  object-fit: contain;
}

.anima-character-avatar-preview-close {
  position: absolute;
  top: 0.667rem;
  right: 0.667rem;
  background: rgba(20, 20, 24, 0.82); /* one-off dark overlay button bg, invariant across theme */
}

.anima-char-card-heading {
  display: flex;
  align-items: flex-start;
  gap: 0.667rem;
  min-width: 0;
  flex: 1;
}

.anima-char-card-title {
  min-width: 0;
  flex: 1;
}

.anima-character-sheet-header {
  align-items: center;
}

.anima-character-sheet-title {
  display: flex;
  align-items: center;
  gap: 1rem;
  min-width: 0;
}

.anima-character-image-editor {
  display: flex;
  align-items: flex-start;
  gap: 1rem;
  margin-bottom: 0.889rem;
}

.anima-character-image-controls {
  display: flex;
  flex-direction: column;
  gap: 0.556rem;
  min-width: 0;
  flex: 1;
}

.anima-character-image-actions {
  display: flex;
  align-items: center;
  gap: 0.444rem;
  flex-wrap: wrap;
}

.anima-character-image-input {
  max-width: 22rem;
}

.anima-character-image-hint {
  font-size: 0.8rem;
  color: color-mix(in srgb, var(--ink) 58%, transparent);
  line-height: 1.4;
}

.anima-char-initial {
  width: 36px;
  height: 36px;
  min-width: 36px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 2px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: 'Cinzel', Georgia, serif;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--accent);
}

.anima-char-name {
  font-family: 'Cinzel', Georgia, serif;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--ink);
  letter-spacing: 0.04em;
  margin: 0;
  line-height: 1.4;
}


/* ========== Character card — rich data-defensive ========== */

.anima-char-card {
  transition: border-color 0.2s;
}

.anima-char-card:hover {
  border-color: var(--border);
}

.anima-char-actions .btn {
  flex: 0 0 auto;
}

.anima-char-class-line {
  font-family: 'Roboto', sans-serif;
  font-size: 0.85rem;
  color: var(--muted);
  margin-top: 2px;
}

.anima-char-level-badge {
  flex-shrink: 0;
  background: var(--surface-2);
  border: 1px solid var(--border);
  padding: 4px 10px;
  text-align: center;
}

.anima-char-level-number {
  font-family: 'Cinzel', Georgia, serif;
  font-size: 1.4rem;
  color: var(--accent);
  line-height: 1;
}


/* ========== Stat bars ========== */

.anima-stat-label {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.15em;
  color: var(--muted);
  margin-bottom: 4px;
}

.anima-stat-row {
  /* wrapper for label + bar */
}

.anima-stat-bar-wrap {
  display: flex;
  align-items: center;
  gap: 8px;
}

.anima-stat-bar {
  flex: 1;
  height: 3px;
  background: var(--surface-2);
  border-radius: 2px;
  overflow: hidden;
}

.anima-stat-bar-fill {
  height: 100%;
  border-radius: 2px;
  transition: width 0.4s ease;
}

.anima-stat-bar-fill--hp-high { background: var(--success); }
.anima-stat-bar-fill--hp-mid  { background: var(--warning); }
.anima-stat-bar-fill--hp-low  { background: var(--hp); }
.anima-stat-bar-fill--xp      { background: color-mix(in srgb, var(--accent) 45%, transparent); }

.anima-stat-value {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.8rem;
  color: var(--muted);
  white-space: nowrap;
  flex-shrink: 0;
}


/* ── Bandeau de carte repliable (onglet Aperçu de la fiche) ──
   Le bandeau EST le `.card-header`, devenu bouton : il garde ainsi son fond, sa teinte de
   section et sa typographie sans les redéclarer. Un bandeau posé À CÔTÉ du header aurait
   doublé la hauteur de chaque carte.

   Seules les propriétés qu'un `<button>` impose sont réécrites. Les bordures LATÉRALES et
   HAUTE sont annulées une par une, et jamais par le raccourci `border` : celui-ci
   remettrait aussi `border-bottom-color` à `currentcolor`, ce qui écraserait la teinte de
   section de `.anima-section-tint :where(.card) > :where(.card-header)` — cette feuille
   est chargée après components.css.

   TOUTES LARGEURS, pas seulement le téléphone. Un repli réservé au mobile laisserait un
   bloc replié sur un écran étroit devenir invisible ET inatteignable dès que la fenêtre
   passe le seuil, puisque le bandeau qui le rouvre aurait disparu avec lui. */
.anima-card-fold-toggle {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  width: 100%;
  text-align: left;
  cursor: pointer;
  line-height: inherit;
  border-top: 0;
  border-left: 0;
  border-right: 0;
  border-bottom-width: 1px;
  border-bottom-style: solid;
}

/* Le corps replié est masqué, jamais retiré du DOM : la recherche des compétences
   secondaires et l'édition de fatigue en cours vivent dedans, et les détruire viderait
   une saisie à l'écran. Classe distincte de `.anima-fold-body`, qui porte un
   `margin-top` fait pour les sections de modale — ici il décalerait le contenu de la
   carte. */
.anima-card-fold-body.is-folded {
  display: none;
}


/* ========== Stats table ========== */

.anima-stats-table-wrap {
  overflow-x: auto;
}

.anima-stats-table {
  width: 100%;
  border-collapse: collapse;
  min-width: 340px;
}

.anima-stats-table th {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--muted);
  padding: 8px 14px;
  text-align: center;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}

.anima-stats-table th:first-child {
  text-align: left;
}

.anima-stats-table td {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.85rem;
  color: var(--ink);
  padding: 8px 14px;
  text-align: center;
  border-bottom: 1px solid var(--border);
}

.anima-stats-table td:first-child {
  text-align: left;
}

.anima-stats-table tbody tr:last-child td {
  border-bottom: none;
}

.anima-stats-table tbody tr:hover {
  background: color-mix(in srgb, var(--accent) 4%, transparent);
}

.anima-stat-name-cell {
  font-weight: 700;
  font-size: 0.8rem !important;
  letter-spacing: 0.1em;
  color: var(--accent) !important;
}

.anima-stat-final-cell {
  font-weight: 700;
  color: var(--ink);
}

/* ── Colonne des noms figée — TÉLÉPHONE UNIQUEMENT ──
   Les deux tableaux de l'onglet Aperçu (caractéristiques, combat) défilaient DÉJÀ
   horizontalement : `.anima-stats-table-wrap` est en `overflow-x: auto` et le tableau est
   plus large que le corps de la fiche. Ce qui manquait, c'est que le nom de la stat
   sortait de l'écran avec le reste — relevé à 360 et 422 px dans la fiche ouverte depuis
   une rencontre, la première colonne n'avait plus aucune part visible une fois le
   conteneur défilé à fond, et il ne restait qu'une ligne de chiffres sans étiquette.

   SEULS les tableaux qui portent le modificateur sont concernés : les autres
   `.anima-stats-table` du dépôt (Ki, formulaire d'édition, rencontres) ne changent pas.

   `border-collapse: separate` est nécessaire, pas cosmétique : en `collapse`, les
   bordures appartiennent au tableau et non aux cellules, donc elles ne suivent pas une
   cellule collante. Ces cellules ne déclarent ni bordure haute ni bordure gauche et la
   seule bordure basse se dessine à l'identique, `border-spacing: 0` gardant les hauteurs.

   Le FOND OPAQUE n'est pas décoratif : sans lui les colonnes suivantes défilent en
   transparence sous la colonne figée et les deux se superposent illisiblement.
   `var(--surface)` est le fond de `.card`, celui sur lequel le tableau est déjà posé. */
@media (max-width: 767.98px) {
  .anima-stats-table--frozen-name {
    border-collapse: separate;
    border-spacing: 0;
  }

  .anima-stats-table--frozen-name th:first-child,
  .anima-stats-table--frozen-name td:first-child {
    position: sticky;
    left: 0;
    z-index: 1;
    background: var(--surface);
    /* Le liseré marque la couture. En `box-shadow` et non en `border` : une bordure
       élargirait la cellule et décalerait toutes les colonnes suivantes. */
    box-shadow: 1px 0 0 var(--border);
  }

  /* Le survol peint la RANGÉE ; le fond opaque de la cellule figée le recouvrirait, et la
     première colonne serait la seule à ne pas réagir. */
  .anima-stats-table--frozen-name tbody tr:hover > td:first-child {
    background: color-mix(in srgb, var(--accent) 4%, var(--surface));
  }
}

.anima-mod-pos {
  color: var(--success);
  font-weight: 600;
}

.anima-mod-neg {
  color: var(--hp);
  font-weight: 600;
}


/* ========== Resistance label (larger, no uppercase) ========== */

.anima-resistance-label {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.8rem;
  letter-spacing: 0.05em;
  color: var(--muted);
  margin-bottom: 4px;
}


/* ========== Derived stat box ========== */

.anima-derived-stat {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 2px;
  padding: 10px 12px;
  text-align: center;
}

.anima-derived-value {
  font-family: 'JetBrains Mono', monospace;
  font-size: 1.4rem;
  font-weight: 700;
  color: var(--accent);
  line-height: 1.2;
  margin-top: 2px;
}

.anima-hp-edit-form {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  max-width: 100%;
}

.anima-hp-edit-input {
  width: 54px;
  min-width: 0;
  padding: 1px 4px;
  text-align: center;
  font-size: 0.8rem;
  line-height: 1.2;
}

.anima-derived-value .anima-hp-edit-form {
  flex-wrap: nowrap;
}

.anima-derived-value .anima-hp-edit-input {
  flex: 0 1 44px;
  width: 44px;
  height: 24px;
}

.anima-derived-value .anima-hp-edit-form .btn {
  flex: 0 0 auto;
  min-width: 24px;
  height: 24px;
  line-height: 1;
}


/* ========== Stat edit form ========== */

.anima-stat-input {
  width: 60px;
  text-align: center;
  padding: 2px 4px;
}

.anima-edit-preview-title {
  font-size: 0.86rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
}


/* ========== HP Bar ========== */

.anima-hp-bar {
  display: inline-flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  width: 100%;
  min-width: 80px;
  vertical-align: middle;
}

/* 6 px, remontés de 4 : à 4 px la jauge était une ligne, pas une barre — surtout sur la
   fiche de personnage, où la piste est large de 431 px. L'épaisseur ne coûte rien
   en mise en page, et c'est vérifié plutôt que supposé : la hauteur de `.anima-hp-bar` est
   commandée par son LIBELLÉ (21,61 px mesurés, monospace 0,8 rem), pas par la piste — elle
   reste 21,61 px pour une piste de 4, 5, 6 comme 8 px. Et la hauteur de la rangée
   d'initiative est commandée par l'avatar (32 px) : mesurée 42,00 px aux quatre épaisseurs,
   à 360 comme à 422 px. La piste du nom ne bouge pas non plus (65,3 px à 360 px, pour un
   plancher de 64 px gardé par combat-roster-test.mjs) : l'épaisseur ne touche à aucune
   largeur.
   Pourquoi pas 8 : dans la rangée d'initiative la piste ne fait que 40 px de large
   au-dessus de 768 px, et à 8 px de haut le rayon de 99px en fait une pastille plutôt
   qu'une barre. */
.anima-hp-bar-track {
  flex: 1;
  height: 6px;
  background: var(--surface-2);
  border-radius: 99px;
  overflow: hidden;
  position: relative;
}

.anima-hp-bar-fill {
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  border-radius: 99px;
  transition: width 0.3s ease, background 0.3s ease;
}

/* 0,8 rem : le plancher du projet, atteint depuis 0,75. C'est la remontée la plus CHÈRE
   du lot, parce que ce libellé est monospace et qu'il vit dans la rangée d'initiative,
   dont le budget de largeur a été gagné au pixel près. Mesuré à 360 px : la piste des PV
   passe de 66,8 à 70,7 px et la piste du NOM, qui est celle qui encaisse, de 69,2 à
   65,3 px — pour un plancher de 64 px gardé par combat-roster-test.mjs. Il reste 1,3 px.
   La hauteur de rangée, elle, ne bouge pas (42,00 px avant comme après).
   Autrement dit : la prochaine chose qui s'élargit dans cette rangée fera virer
   combat-roster au rouge, et ce sera une vraie régression. */
.anima-hp-bar-label {
  font-size: 0.8rem;
  color: var(--muted);
  white-space: nowrap;
  font-family: monospace;
  letter-spacing: 0.02em;
}
.anima-hp-state-badge {
  display: inline-block;
  flex-basis: 100%;
  font-size: 0.8rem;
  font-weight: 600;
  margin-top: 2px;
  border-radius: 3px;
  padding: 1px 4px;
  text-align: center;
}
.anima-hp-state-dying {
  background: var(--hp);
  color: var(--on-accent);
}
.anima-hp-state-dead {
  background: var(--surface-2);
  color: var(--muted);
}


/* ========== Race badge ========== */

.anima-race-badge {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--accent);
  border: 1px solid var(--border);
  border-radius: 2px;
  padding: 2px 8px;
  white-space: nowrap;
}


/* ========== Class badge ========== */

.anima-class-badge {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--zeon);
  border: 1px solid color-mix(in srgb, var(--zeon) 40%, transparent);
  border-radius: 2px;
  padding: 2px 8px;
  white-space: nowrap;
}


/* ========== Archetype badge ========== */

.anima-archetype-badge {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--psychic);
  border: 1px solid color-mix(in srgb, var(--psychic) 40%, transparent);
  border-radius: 2px;
  padding: 2px 8px;
  white-space: nowrap;
}


/* ========== Race description ========== */

.anima-race-description {
  font-size: 0.8rem;
  color: var(--muted);
  font-style: italic;
  border-left: 2px solid var(--border);
  padding-left: 12px;
}

.anima-race-description-label {
  font-style: normal;
  font-weight: 600;
  color: var(--accent);
  margin-right: 6px;
}


/* ========== Characteristic tooltip ========== */

.anima-stat-tooltip-wrap {
  cursor: help;
  border-bottom: 1px dotted var(--border);
}


/* ========== Racial bonus tag on resistances ========== */

.anima-racial-tag {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.8rem;
  color: var(--accent);
  margin-top: 2px;
  opacity: 0.8;
}


/* ========== Racial powers list ========== */

.anima-powers-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.anima-power-item {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  font-size: 0.8rem;
}

.anima-power-name {
  font-family: 'JetBrains Mono', monospace;
  font-weight: 700;
  color: var(--accent);
  white-space: nowrap;
}

.anima-power-name::after {
  content: ' —';
  color: color-mix(in srgb, var(--accent) 50%, transparent);
}

.anima-power-desc {
  color: var(--muted);
}


/* ── Secondary Abilities ───────────────────────── */
.anima-secondary-budget-bar {
  position: sticky;
  top: var(--topnav-h);
  z-index: 10;
  background: var(--anima-card-bg, var(--surface-2));
  border-bottom: 1px solid var(--border);
  padding: 8px 16px;
  font-size: 0.9rem;
  color: var(--muted);
  display: flex;
  align-items: center;
  gap: 16px;
}
.anima-secondary-budget-spent { color: var(--accent); font-weight: 600; }
.anima-secondary-budget-remaining { color: var(--success); font-weight: 600; }

.anima-secondary-search {
  padding: 6px 16px;
  border-bottom: 1px solid var(--border);
}
.anima-secondary-search input {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 4px;
  color: inherit;
  padding: 4px 10px;
  font-size: 0.94rem;
  width: 100%;
}

/* `<button>` garde un gabarit « shrink-to-fit » même sous `display: flex` (mesuré en
   Chromium : la boîte ne fait que la largeur de son texte, ex. 154px pour « Athlétisme »
   à 1280px de fenêtre, contre 1242px pour la rangée juste en dessous) — ce n'est pas un
   effet du chantier Spé, la géométrie est identique avant/après (comparé au commit
   parent). `width: 100%` aligne le bouton sur la largeur de la rangée qu'il coiffe, pour
   que son `border-bottom` la souligne en entier au lieu de s'arrêter sous le texte. */
.anima-secondary-field-header {
  width: 100%;
  padding: 6px 16px;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 0.9rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
  border-bottom: 1px solid var(--border);
  user-select: none;
}
.anima-secondary-field-header:hover { color: var(--ink); }
.anima-secondary-field-chevron { font-size: 0.8rem; transition: transform 0.15s; }
.anima-secondary-field-chevron.collapsed { transform: rotate(-90deg); }

/* Colonne « Car. » à 64px (36px + 28px) : la caractéristique porteuse ET son modificateur
   signé y tiennent sur une seule ligne (mesuré : « per +10 », « wp −20 » — trois lettres,
   un espace, un signe et deux chiffres). En dessous, le texte revient à deux lignes plutôt
   que de déborder. */
.anima-secondary-row {
  display: grid;
  grid-template-columns: 24px 1fr 64px 44px 34px 36px;
  align-items: center;
  gap: 6px;
  padding: 6px 16px;
  border-bottom: 1px solid var(--border);
  font-size: 1.09rem;
  cursor: pointer;
}
.anima-secondary-row:last-child { border-bottom: none; }

.anima-secondary-star {
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
  color: var(--muted);
  font-size: 1.15rem;
  line-height: 1;
}
.anima-secondary-star.active { color: var(--accent); }

.anima-secondary-name-wrap {
  display: inline-flex;
  align-items: center;
  min-width: 0;
}

.anima-secondary-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.anima-secondary-char { font-size: 0.94rem; color: var(--zeon); font-weight: 600; }
.anima-secondary-final { font-weight: 600; text-align: right; }

.anima-secondary-badges { display: flex; gap: 3px; }
.anima-secondary-badge-k {
  font-size: 0.8rem; font-weight: 700;
  background: color-mix(in srgb, var(--zeon) 18%, transparent); color: var(--zeon);
  border-radius: 3px; padding: 1px 4px;
  cursor: help;
}

.anima-roll-btn {
  background: none;
  border: 1px solid var(--zeon);
  color: var(--zeon);
  border-radius: 3px;
  padding: 3px 7px;
  font-size: 0.95rem;
  cursor: pointer;
  line-height: 1;
}
.anima-roll-btn:hover { border-color: var(--zeon); color: var(--zeon); }

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

.anima-roll-modal {
  background: color-mix(in srgb, var(--zeon) 20%, var(--surface));
  border: 1px solid var(--zeon);
  border-radius: 10px;
  padding: 22px 28px;
  min-width: 280px;
  max-width: 400px;
  width: 90%;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.6); /* one-off shadow, no matching shadow token */
}

.anima-roll-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 16px;
}

.anima-roll-modal-title {
  font-size: 1.15rem;
  font-weight: 600;
  color: var(--ink);
}

.anima-roll-detail {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 7px 0;
  border-bottom: 1px solid var(--border);
  font-size: 1.01rem;
}

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

.anima-roll-detail-value { color: var(--ink); font-weight: 600; }

.anima-roll-open-tag {
  font-size: 0.8rem;
  background: color-mix(in srgb, var(--accent) 15%, transparent);
  color: var(--accent);
  border-radius: 3px;
  padding: 1px 5px;
  margin-left: 6px;
}

.anima-roll-modal-total {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-top: 14px;
  margin-top: 4px;
}

.anima-roll-modal-total-label { color: var(--muted); font-size: 1.03rem; }

.anima-roll-modal-result { font-size: 1.72rem; font-weight: 700; color: var(--zeon); }

.anima-roll-close {
  background: none;
  border: none;
  color: var(--muted);
  cursor: pointer;
  font-size: 1.15rem;
  line-height: 1;
  padding: 0;
}
.anima-roll-close:hover { color: var(--ink); }


/* Edit mode row: dp input + override input */
/* Colonne « Car. » à 64px (36px + 28px) : même mesure que .anima-secondary-row — la
   caractéristique et son modificateur signé tiennent sur une seule ligne. */
.anima-secondary-edit-row {
  display: grid;
  grid-template-columns: 24px 1fr 64px 60px 60px 50px 36px;
  align-items: center;
  gap: 6px;
  padding: 4px 16px;
  border-bottom: 1px solid var(--border);
  font-size: 0.94rem;
}


/* Spend DP panel row: no star button (7 colonnes depuis l'ajout de la colonne Spé).
   Colonne coût à 34px (et non 28px) : mesuré, le libellé d'en-tête « Coût » (30px à
   0.8rem) passait à la ligne dans les 28px que le badge « ×3 » suffisait à occuper seul.
   Colonne « Car. » à 64px (36px + 28px) : même mesure que .anima-secondary-row. */
.anima-secondary-spend-row {
  display: grid;
  grid-template-columns: 1fr 64px 34px 50px 50px 50px auto;
  align-items: center;
  gap: 4px;
  padding: 3px 8px;
  border-bottom: 1px solid var(--border);
}
.anima-secondary-spend-row:last-child {
  border-bottom: none;
}
/* `appearance: textfield` + la paire ::-webkit-*-spin-button ci-dessous retirent les
   flèches natives du <input type="number"> : sans elles, Chromium leur réserve quand même
   une piste interne même invisible, ce qui rognait « -15 » en « -1 » une fois la colonne
   compactée à 42 px sous 768 px (mesuré : rendu correct à 60 px, tronqué à 42 px). */
.anima-secondary-input {
  width: 60px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 4px;
  color: inherit;
  padding: 2px 6px;
  font-size: 0.92rem;
  text-align: center;
  appearance: textfield;
  -moz-appearance: textfield;
}
.anima-secondary-input::-webkit-inner-spin-button,
.anima-secondary-input::-webkit-outer-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
/* Sept colonnes ne tiennent pas dans 360 px : les saisies rétrécissent, le nom garde le reste.
   Colonne « Car. » élargie au minimum qui évite le vrai défaut mesuré à 360 px : sur 28px
   (édition) et 24px (dépense de PD), le modificateur signé (ex. « +10 ») ne tenait pas dans
   un seul « mot » et se coupait entre le signe et le chiffre. 40px suffit à loger n'importe
   quel jeton entier (max 3 caractères : « +45 », « −30 ») sans jamais le couper — la
   caractéristique et son modificateur reviennent alors sur deux lignes empilées (comme en
   bureau avant élargissement), lisible, plutôt que de retirer 28px de plus au nom : un
   élargissement identique au bureau (+28px) tronquait le nom à 2-3 lettres, mesuré illisible. */
@media (max-width: 767.98px) {
  .anima-secondary-row {
    grid-template-columns: 24px 1fr 40px 44px 34px 36px;
  }

  .anima-secondary-edit-row {
    grid-template-columns: 20px 1fr 40px 44px 44px 40px 28px;
    gap: 4px;
    padding: 4px 8px;
  }

  .anima-secondary-spend-row {
    grid-template-columns: 1fr 40px 24px 40px 40px 40px auto;
  }

  .anima-secondary-input { width: 42px; }

  /* Sous 768 px les colonnes compactées (jusqu'à 24 px pour Coût) ne laissent plus la
     place à un libellé, même abrégé (mesuré : « Coût » déborde à 24 px) — la rangée
     d'en-têtes de colonnes s'efface plutôt que de tronquer ; le nom de chaque
     compétence et son `aria-label` restent la seule façon de savoir quel champ est
     lequel sur téléphone. */
  .anima-secondary-edit-row--labels,
  .anima-secondary-spend-row--labels {
    display: none;
  }
}

/* ── Le nom de la compétence prend sa propre ligne sur les petits écrans ──────
   MESURÉ à 360 px avant correction, sur la page-témoin secondary-abilities.html : la
   colonne du nom ne fait que 86 px, pour 231 px de « Résistance à la Douleur » (37 %
   visibles), 185 px de « Détection Magique » (46 %) et 133 px de « Mémorisation » (64 %) —
   sept des douze noms amputés. Le groupe Intellectuel se lisait « A… Es… H… Hi… D… M…
   Mé… N… O… Sc… », dix compétences indiscernables. À 422 px il en restait trois ; la
   troncature disparaît vers 500 px, d'où le seuil de la table (575,98 px), qui couvre
   toute la plage abîmée avec de la marge sans toucher aux largeurs déjà saines.

   CETTE LIGNE NE COÛTE RIEN : LA RANGÉE EN AVAIT DÉJÀ DEUX. La grille déclare six
   colonnes et le gabarit rend SEPT enfants dès que le bouton de jet secret est là
   (`{{#if @onSecretRoll}}`, c'est-à-dire chez le MJ) — le septième, `.anima-secondary-badges`,
   retombait donc seul sur une seconde ligne, sous l'étoile, avec 300 px de vide à côté.
   Mesuré : rangée de 93,4 px de haut, badge à x=16 y=62,8. La grille avait été taillée
   pour la vue JOUEUR, à six enfants. On ne fait donc pas grandir la rangée, on remplit une
   ligne qui existait déjà — et elle RÉTRÉCIT au passage, de 93,4 px à 77,9 px, parce que la
   seconde ligne portait un badge de 24 px et porte maintenant des contrôles alignés.

   Ce qui est délibérément LAISSÉ EN L'ÉTAT : au-dessus de 575,98 px le badge orphelin
   demeure, jusqu'au bureau inclus. C'est un défaut réel, mais il est cosmétique, il est
   antérieur, et aucune garde ne mesure ces largeurs-là — le corriger ici serait changer
   une mise en page de bureau que rien ne surveille, pour un chantier qui porte sur le
   téléphone. Il est écrit ici pour ne pas être redécouvert.

   `.anima-secondary-name` garde `nowrap` + points de suspension : la ligne entière mesure
   264 px à 360 px de fenêtre, et le plus long nom du catalogue en fait 231 — plus aucun ne
   les atteint. Ils restent le filet pour un libellé futur démesuré, qui vaut mieux qu'un
   mot coupé en deux au milieu. */
@media (max-width: 575.98px) {
  .anima-secondary-row {
    grid-template-columns: 24px 1fr 44px 34px 36px auto;
  }

  /* Le nom occupe la fin de la PREMIÈRE ligne, à droite de l'étoile. */
  .anima-secondary-row .anima-secondary-name-wrap {
    grid-column: 2 / -1;
  }

  /* Et tout le reste repart en colonne 2 de la SECONDE : le placement automatique fait
     le reste, dans l'ordre du gabarit (caractéristique, total, jet, jet secret, badges).
     La colonne 1 reste vide sous l'étoile, ce qui aligne la seconde ligne sur le nom. */
  .anima-secondary-row .anima-secondary-char {
    grid-column-start: 2;
  }
}

/* Rangée d'en-têtes de colonnes (Car. / PD / Spé / Total / Coût) affichée sous chaque
   titre de section : réutilise la classe de rangée qu'elle coiffe (+ ce modificateur)
   pour rester alignée sur la même grille sans jamais pouvoir en dériver. Remplace les
   anciennes `.anima-secondary-dp-label` / `.anima-secondary-override-label`, mortes
   depuis le champ Spé (aucun template ne les posait) et de toute façon identiques —
   une seule classe partagée suffit à leurs cinq cellules. */
.anima-secondary-col-label {
  font-size: 0.8rem;
  color: var(--muted);
  text-align: center;
}

.anima-secondary-cost-badge {
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--anima-accent, var(--accent));
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
  border-radius: 3px;
  padding: 1px 4px;
  min-width: 24px;
  text-align: center;
  flex-shrink: 0;
}


/* ── Advantages & Disadvantages ─────────────────────────────────── */
.anima-adv-column-header {
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--anima-accent, var(--accent));
  padding: 0.25rem 0;
  border-bottom: 1px solid var(--border);
  margin-bottom: 0.5rem;
}
.anima-adv-column-header--dis {
  color: var(--hp);
}
.anima-adv-row {
  padding: 0.4rem 0.5rem;
  border-radius: 4px;
  margin-bottom: 0.3rem;
  background: var(--surface-2);
  border: 1px solid transparent;
}
.anima-adv-row--selected {
  border-color: color-mix(in srgb, var(--accent) 40%, transparent);
  background: color-mix(in srgb, var(--accent) 6%, transparent);
}
.anima-adv-row--dis.anima-adv-row--selected {
  border-color: color-mix(in srgb, var(--hp) 40%, transparent);
  background: color-mix(in srgb, var(--hp) 6%, transparent);
}
.anima-adv-row-top {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.anima-adv-costs {
  display: flex;
  gap: 0.2rem;
  flex-shrink: 0;
}
.anima-adv-cp-btn {
  font-size: 0.8rem;
  padding: 0.1rem 0.35rem;
  border-radius: 3px;
  border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent);
  background: transparent;
  color: color-mix(in srgb, var(--accent) 70%, transparent);
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}
.anima-adv-cp-btn:hover:not(:disabled),
.anima-adv-cp-btn.active {
  background: color-mix(in srgb, var(--accent) 25%, transparent);
  color: var(--accent);
  border-color: var(--accent);
}
.anima-adv-cp-btn--dis {
  border-color: color-mix(in srgb, var(--hp) 40%, transparent);
  color: color-mix(in srgb, var(--hp) 70%, transparent);
}
.anima-adv-cp-btn--dis:hover:not(:disabled),
.anima-adv-cp-btn--dis.active {
  background: color-mix(in srgb, var(--hp) 20%, transparent);
  color: var(--hp);
  border-color: var(--hp);
}
.anima-adv-cp-btn:disabled {
  opacity: 0.3;
  cursor: not-allowed;
}
.anima-adv-name {
  font-size: 0.94rem;
  font-weight: 500;
}
.anima-adv-desc {
  font-size: 0.83rem;
  color: var(--muted);
  margin-top: 0.15rem;
  line-height: 1.3;
}
.anima-adv-note {
  font-size: 0.8rem;
  color: color-mix(in srgb, var(--accent) 70%, transparent);
  font-style: italic;
}
.anima-adv-param select {
  max-width: 220px;
}

@media (max-width: 767.98px) {
  .anima-character-toolbar {
    align-items: stretch;
    flex-direction: column;
  }

  .anima-character-search {
    max-width: none;
  }

  .anima-character-create-actions {
    margin-left: 0;
  }

  .anima-character-sheet-header {
    align-items: flex-start;
    flex-direction: column;
  }

  .anima-character-sheet-title,
  .anima-character-image-editor {
    align-items: flex-start;
    flex-direction: column;
  }

  .anima-character-sheet-title .anima-character-avatar--sheet,
  .anima-character-image-editor .anima-character-avatar--sheet {
    width: 4.667rem;
    height: 4.667rem;
    font-size: 1.6rem;
  }
}

/* Display list (read mode) */
.anima-adv-display-list {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}
.anima-adv-display-item {
  display: flex;
  align-items: baseline;
  gap: 0.35rem;
  font-size: 0.94rem;
  flex-wrap: wrap;
}
.anima-adv-icon {
  flex-shrink: 0;
}
.anima-adv-display-item--adv .anima-adv-icon  { color: var(--accent); }
.anima-adv-display-item--dis .anima-adv-icon  { color: var(--hp); }
.anima-adv-display-name { font-weight: 500; }
.anima-adv-display-cp   { font-size: 0.83rem; color: var(--muted); }
.anima-adv-display-param { font-size: 0.86rem; color: var(--ink); }
.anima-adv-display-desc {
  font-size: 0.83rem;
  color: var(--muted);
  font-style: italic;
}


/* ── Fatigue / Recovery penalty / PhR outcome ── */
.anima-recovery-badge {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 0.8rem;
  color: var(--warning);
  margin-top: 2px;
}
.anima-recovery-btn {
  background: none;
  border: 1px solid var(--warning);
  border-radius: 3px;
  color: var(--warning);
  font-size: 0.8rem;
  padding: 0 4px;
  cursor: pointer;
}
.anima-roll-modal-outcome {
  text-align: center;
  padding: 8px;
  border-radius: 4px;
  font-weight: 600;
  margin-top: 8px;
}
.anima-outcome-success { background: color-mix(in srgb, var(--success) 22%, var(--surface)); color: var(--success); }
.anima-outcome-fail    { background: color-mix(in srgb, var(--hp) 22%, var(--surface)); color: var(--hp); }
.anima-outcome-dead    { background: var(--surface-2); color: var(--muted); }

/* Character inventory */
.anima-inventory-panel {
  border-top: 1px solid var(--border);
  padding-top: 1rem;
}

.anima-inventory-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
}

.anima-panel-title {
  font-size: 1.35rem;
  font-weight: 600;
}

.anima-panel-subtitle {
  color: var(--muted);
}

.anima-inventory-forms {
  display: grid;
  grid-template-columns: minmax(260px, 0.75fr) minmax(320px, 1.25fr);
  gap: 1rem;
  margin-top: 1rem;
}

.anima-inventory-wallet,
.anima-inventory-add {
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 1rem;
  background: var(--surface-2);
}

.anima-inventory-section-title {
  color: var(--ink);
  font-size: 0.9rem;
  font-weight: 600;
  margin-bottom: 0.75rem;
  text-transform: uppercase;
}

/* Inventaire : ce panneau n'a pas de .card-header, la recette partagée de
   components.css ne l'atteint pas. On rebranche ses deux repères sur --section.
   Le titre est mélangé à --ink plutôt que teinté à 100 % : c'est du texte courant
   en majuscules à 0.9rem, il doit rester lisible sur parchemin comme sur nuit. */
.anima-section-tint .anima-inventory-panel {
  border-top-color: color-mix(in srgb, var(--section) 40%, transparent);
}

.anima-section-tint .anima-inventory-section-title {
  color: color-mix(in srgb, var(--section) 80%, var(--ink));
}

.anima-inventory-wallet-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(64px, 1fr));
  gap: 0.5rem;
}

.anima-inventory-field {
  min-width: 0;
}

.anima-inventory-add-card {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.625rem 1rem;
  background: var(--surface-2);
  margin-top: 1rem;
  margin-bottom: 0.75rem;
}

.anima-inventory-table-wrap {
  overflow-x: auto;
}

.anima-inventory-table {
  min-width: 860px;
}

.anima-inventory-table th,
.anima-inventory-table td {
  white-space: nowrap;
}

/* ========== Inventory ========== */

.anima-inventory-name {
  font-weight: 600;
  white-space: nowrap;
}

.anima-inventory-goods-groups {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 4px 0 8px;
}

.anima-inventory-goods-btn {
  padding: 2px 10px;
  font-size: 0.8rem;
  border-radius: 12px;
  border: 1px solid var(--border);
  background: transparent;
  color: var(--bs-body-color, var(--ink));
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
}

.anima-inventory-goods-btn:hover {
  border-color: var(--accent);
  color: var(--accent);
}

.anima-inventory-goods-btn.active {
  background: color-mix(in srgb, var(--accent) 15%, transparent);
  border-color: var(--accent);
  color: var(--accent);
  font-weight: 600;
}

.anima-inventory-quantity {
  width: 76px;
}

.anima-inventory-notes {
  min-width: 190px;
}

/* Un plancher de largeur, pour que la colonne ne saute pas d'une ligne à l'autre selon
   la marche sélectionnée — « Normale » est le plus long des sept libellés. */
.anima-inventory-quality {
  min-width: 96px;
}

.anima-inventory-quality-hint {
  color: var(--bs-secondary-color, #adb5bd);
  font-size: 0.8rem;
}

@media (max-width: 991.98px) {
  .anima-inventory-forms {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 575.98px) {
  .anima-inventory-header {
    align-items: stretch;
    flex-direction: column;
  }

  .anima-inventory-wallet-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* Modals — inventory buy / wallet

   Deux règles vivaient ici, `.anima-modal-overlay` et `.anima-modal`, et TOUTES DEUX
   étaient mortes — vérifié à la mesure avant de les retirer, pas déduit :

   — l'overlay redéclarait mot pour mot les SEPT propriétés que components.css pose déjà,
     z-index 1300 compris. Son commentaire expliquait qu'il gagnait la cascade ; c'était
     vrai, et sans effet, puisqu'il gagnait avec la même valeur. Son intention (rester
     >= 1300, au-dessus du tableau blanc et du HUD flottant) est reprise en commentaire
     dans components.css ;

   — la boîte visait les modales d'achat et de bourse de l'inventaire et voulait les
     faire étroites : `width: 90%`, `max-width: 460px`, `padding: 24px`. Aucune de ses
     HUIT déclarations ne survivait — pages/encounter-combat.css, chargé après, les
     redéclarait toutes. Mesuré : la modale de bourse rendait 760 px de large avec 22 px
     de marge, comme n'importe quelle autre modale du projet. L'intention « étroite »
     était perdue depuis que la feuille de combat existe.

   Elles ne sont pas déplacées mais SUPPRIMÉES, et c'est délibéré : les rétablir
   changerait le rendu de ces modales (760 → 460 px), ce qui est une décision de
   maquette, pas un démêlage de cascade. Le jour où on la prend, la surcharge se pose
   ici avec un sélecteur qui NOMME ces modales — les deux fonds d'inventaire sont hors
   de `.anima-inventory-panel` (vérifié : la section se ferme avant eux), il faudra donc
   leur donner une classe de variante, comme `.anima-picker-modal` en a une. */

/* LE `margin-bottom` A ÉTÉ RETIRÉ, et pas déplacé. Il valait 16 px, il était écrit pour
   les modales d'inventaire, et il atteignait les 27 titres de modale du dépôt —
   recensés sur le corpus de tests/browser/modal-corpus.mjs (69 modales, 57 fichiers),
   pas à l'œil :

     22 titres sont des `<span>` DANS un `.anima-modal-header`. Là, la marge ne sépare
        rien : l'en-tête a sa propre marge intérieure et son filet. Elle gonfle un
        bandeau devenu collant, donc prélevé en permanence. Mesuré sur les page-témoins
        du dépôt (modal-desktop-reach, modal-longtail), l'en-tête passe de 76 à 60 px,
        et de 103 à 87 px sur les trois dont le titre tient sur deux lignes à 360 px ;
      5 titres se tiennent SEULS dans `.anima-modal`, sans en-tête pour les séparer de
        leur contenu — c'est là que la marge servait.

   Et sur ces cinq, elle ne servait déjà plus. Quatre sont des `<h4>` : `.anima-modal h4`
   (pages/encounter-combat.css, chargé après celui-ci) leur donne 14 px et l'emporte à
   0,1,1 contre 0,1,0 — mesuré, pas déduit ; l'un d'eux porte en plus `mb-0`. Autrement
   dit la règle n'atteignait AUCUNE des quatre modales d'inventaire pour lesquelles elle
   avait été écrite. Le cinquième est le `<h3>` de forgot-password-modal, qui n'est pas
   une modale d'inventaire. Il est le seul à perdre quelque chose, et il perd peu :
   supprimer la déclaration laisse repasser devant la règle `h1`…`h6` de Bootstrap, soit
   0,5 rem. Relevé sur les quatre enfants de cette modale, qui déclare par ailleurs son
   propre rythme (`gap: 14px` en colonne flex, pages/login.css), l'écart sous le titre
   passe de 30 à 23 px — les deux autres écarts valent 14 px et ne bougent pas. Le titre
   ne se colle donc à rien, et aucune marge n'a été redonnée localement : 23 px reste
   au-dessus du rythme que cette modale s'est choisi.

   Mesurer la suppression exige d'ailleurs de la faire pour de bon : injecter
   `margin-bottom: 0` répond à côté, un zéro explicite battant AUSSI la règle Bootstrap
   que la suppression laisse au contraire ressortir. Cette sonde-là annonçait 14 px.

   Les trois autres déclarations restent à portée large, et c'est délibéré : elles
   redéclarent la `font-size` et la couleur que components.css pose sur la même classe.
   Les restreindre ferait passer les 22 en-têtes de 1 rem à 0,85 rem et de la couleur du
   texte à l'accent — une décision de maquette, pas un démêlage de cascade, exactement
   comme pour la boîte étroite dont il est question au-dessus. */
.anima-modal-title {
  font-size: 1rem;
  font-weight: 600;
  color: var(--bs-body-color, var(--ink));
}

.anima-modal-item-name {
  font-size: 0.9rem;
  color: var(--accent);
  margin-bottom: 12px;
}

.anima-modal-wallet-compare {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
  margin: 12px 0;
  font-size: 0.82rem;
}

.anima-modal-wallet-col-label {
  font-size: 0.8rem;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 6px;
}

.anima-modal-wallet-row {
  display: flex;
  justify-content: space-between;
  padding: 2px 0;
}

.anima-wallet-amount {
  font-weight: 600;
}

.anima-modal-delta-label {
  font-size: 0.8rem;
  text-transform: uppercase;
  color: var(--muted);
  margin: 12px 0 6px;
}

/* ── Artefacts ─────────────────────────────────────────────────────── */

.artifact-section {
  margin-top: 1.5rem;
}

.artifact-section__title {
  font-family: 'Cinzel', Georgia, serif;
  font-size: 1rem;
  font-weight: 600;
  color: var(--ink);
  margin: 0 0 0.75rem;
  border-bottom: 1px solid var(--border);
  padding-bottom: 6px;
}

.artifact-section__gate {
  text-align: center;
  padding: 32px 16px;
  border: 1px dashed var(--border);
  border-radius: 6px;
}

.artifact-section__gate-hint {
  color: var(--muted);
  font-size: 0.9rem;
  margin: 0 0 0.75rem;
}

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

.artifact-card {
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface-2);
  padding: 1rem;
}

.artifact-card__header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
}

.artifact-card__header h4 {
  font-family: 'Cinzel', Georgia, serif;
  font-size: 0.95rem;
  color: var(--ink);
  margin: 0;
}

.artifact-card__book {
  font-size: 0.8rem;
  color: var(--muted);
  white-space: nowrap;
}

.artifact-card__image {
  display: block;
  max-width: 100%;
  border-radius: 4px;
  margin: 0.5rem 0;
}

.artifact-card__description {
  white-space: pre-line;
  font-size: 0.9rem;
  line-height: 1.6;
  color: var(--ink);
  margin: 0.5rem 0 0;
}

.artifact-card__section {
  margin-top: 0.75rem;
}

.artifact-card__section h5 {
  color: var(--accent);
  font-size: 0.8rem;
  font-weight: bold;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin: 0 0 6px;
}

.artifact-level {
  margin: 0.5rem 0;
  padding-top: 0.5rem;
  border-top: 1px dotted var(--border);
}

.artifact-level:first-child {
  padding-top: 0;
  border-top: none;
}

.artifact-requirement {
  font-size: 0.85rem;
  color: var(--ink);
  margin: 2px 0;
}

.artifact-warning {
  color: var(--warning);
  font-size: 0.85rem;
  margin: 2px 0;
}

/* ── Edit Form Sticky Actions Bar ─────────────────────────────────── */
.anima-edit-actions {
  position: sticky;
  bottom: 0;
  z-index: 10;
  background: var(--surface);
  border-top: 1px solid var(--border);
  padding: 12px 0 16px;
  margin-top: 16px;
  display: flex;
  justify-content: flex-end;
  gap: 8px;
}

/* Même cause que le trou au-dessus de .anima-subtab-bar, par l'autre bout : sous
   767,98px la barre d'onglets globale est `fixed` en bas de l'écran (layout.css) et
   couvre les 49,84px du bas. Collée à bottom:0, cette barre d'actions passait donc
   DESSOUS — z-index 10 contre 1045.
   Mesuré sur la page-témoin à 360 et 422px : barre d'actions 622,56→690, barre
   d'onglets 640,16→690, soit 49,84px des 67,44px de haut recouverts. Des 17,60px
   restés visibles, 12 sont le padding du haut : il n'affleurait que 5,60px de
   boutons sur les 39,44 de leur rangée (67,44 moins les 12 et 16 de padding
   ci-dessus). Après correction : bas de la barre à 640,00 pour une barre d'onglets
   qui commence à 640,16 — entièrement dégagée, aux deux largeurs.
   Le dégagement passe par --bottomnav-h, jamais par 50 en dur.
   Ce n'est pas le bug signalé (l'utilisateur a décrit le trou du HAUT) : il est
   sorti de l'inventaire des éléments collants fait à cette occasion. */
@media (max-width: 767.98px) {
  .anima-edit-actions {
    bottom: var(--bottomnav-h);
  }
}

/* ── Inventory carry weight bar ── */
.anima-inventory-carry-weight {
  padding: 0.5rem 0;
}

.anima-carry-weight-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 0.25rem;
}

.anima-carry-weight-value {
  font-size: 0.8rem;
  color: var(--bs-secondary-color, var(--muted));
}

.anima-carry-progress {
  height: 8px;
  border-radius: 4px;
}

/* ── Item picker modal ── */
.anima-picker-overlay {
  align-items: flex-start;
  padding-top: 2rem;
}

.anima-picker-modal {
  width: 100%;
  max-width: 640px;
  max-height: calc(100vh - 4rem);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.anima-picker-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-shrink: 0;
  margin-bottom: 0.75rem;
}

.anima-picker-search {
  flex-shrink: 0;
  margin-bottom: 0.5rem;
}

.anima-picker-tabs {
  display: flex;
  gap: 0.25rem;
  flex-wrap: wrap;
  flex-shrink: 0;
  margin-bottom: 0.5rem;
}

.anima-picker-tab {
  padding: 0.25rem 0.75rem;
  font-size: 0.8rem;
  background: transparent;
  border: 1px solid var(--bs-border-color, var(--border));
  border-radius: 4px;
  color: var(--bs-body-color, var(--ink));
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}

.anima-picker-tab:hover {
  background: var(--surface-2);
}

.anima-picker-tab.active {
  background: var(--bs-primary, var(--accent));
  border-color: var(--bs-primary, var(--accent));
  color: var(--on-accent);
}

.anima-picker-goods-groups {
  flex-shrink: 0;
  margin-bottom: 0.5rem;
}

.anima-picker-body {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
  gap: 0.75rem;
}

/* Item list */
.anima-picker-list {
  list-style: none;
  margin: 0;
  padding: 0;
  overflow-y: auto;
  flex: 1 1 140px;
  min-height: 80px;
  max-height: 240px;
  border: 1px solid var(--bs-border-color, var(--border));
  border-radius: 4px;
}

.anima-picker-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.35rem 0.6rem;
  cursor: pointer;
  font-size: 0.85rem;
  border-bottom: 1px solid var(--border);
  transition: background 0.1s;
}

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

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

.anima-picker-row.selected {
  background: color-mix(in srgb, var(--accent) 20%, transparent);
}

/* Zone de clic d'une rangée du sélecteur : elle occupe toute la rangée, dont la
   `<li>` garde l'habillage et la gouttière. La disposition des deux libellés
   (`space-between`) descend ici avec elle. */
.anima-picker-row-hit {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.4rem;
}

.anima-picker-row-name {
  flex: 1 1 auto;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.anima-picker-row-price {
  flex-shrink: 0;
  color: var(--bs-secondary-color, var(--muted));
  font-size: 0.8rem;
  margin-left: 0.5rem;
}

.anima-picker-empty {
  padding: 1rem;
  text-align: center;
  color: var(--bs-secondary-color, var(--muted));
  font-size: 0.85rem;
}

/* Item detail panel */
.anima-picker-detail {
  flex-shrink: 0;
  background: var(--surface-2);
  border: 1px solid var(--bs-border-color, var(--border));
  border-radius: 4px;
  padding: 0.6rem 0.75rem;
  font-size: 0.82rem;
}

.anima-picker-detail-name {
  font-size: 0.9rem;
  font-weight: 600;
  margin-bottom: 0.4rem;
}

.anima-picker-detail-row {
  display: flex;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.15rem 0;
  border-bottom: 1px solid var(--border);
}

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

.anima-picker-detail-label {
  color: var(--bs-secondary-color, var(--muted));
  flex-shrink: 0;
}

/* Footer */
.anima-picker-footer {
  flex-shrink: 0;
  padding-top: 0.75rem;
  border-top: 1px solid var(--bs-border-color, var(--border));
  margin-top: 0.5rem;
}

.anima-picker-footer-top {
  display: flex;
  align-items: center;
  gap: 1rem;
}

.anima-picker-qty {
  width: 5rem;
}

.anima-picker-buy-section {
  font-size: 0.85rem;
}

/* ── Combat modules read-only view ── */

.anima-module-view-bonuses {
  font-size: 0.88rem;
}

.anima-module-view-bonuses-label {
  color: var(--muted);
  margin-right: 6px;
}

.anima-module-view-row {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  background: none;
  border: none;
  border-bottom: 1px solid var(--border);
  padding: 8px 4px;
  text-align: left;
  cursor: pointer;
  color: inherit;
  transition: background 0.1s;
}

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

.anima-module-view-row:hover {
  background: var(--surface-2);
}

.anima-module-view-info {
  flex: 1 1 0;
  min-width: 0;
}

.anima-module-view-name {
  display: block;
  font-size: 0.92rem;
  font-weight: 600;
  line-height: 1.3;
}

.anima-module-view-param {
  font-size: 0.85rem;
  font-weight: 400;
  color: var(--muted);
}

.anima-module-view-desc {
  display: block;
  font-size: 0.8rem;
  color: var(--muted);
  margin-top: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}

/* ── Combat module detail modal ── */

.anima-module-detail-modal {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 20px 24px;
  width: 90%;
  max-width: 480px;
  max-height: 80vh;
  overflow-y: auto;
}

/* ── En-tête collant : le titre et le × ne partent plus avec le contenu ──────
   Le défaut rapporté à la main : « les titres de modale de description de compétence ne
   réagissent pas de la même manière que les autres — si on scrolle vers le bas le titre
   disparaît, ainsi que le bouton pour fermer la modale ».
   C'est la SEULE modale du dépôt où ça arrive à une largeur de bureau, et le relevé dit
   pourquoi. Sur les 69 modales, 28 portent une rangée titre + ×. Vingt d'entre elles —
   la convention majoritaire — écrivent cette rangée EN DEHORS de leur boîte défilante :
   `.anima-modal-header` est le frère de `.anima-modal-body`, et c'est le corps qui
   défile. Huit n'ont pas de `.anima-modal-body` ; sept d'entre elles s'en passent sans
   dommage, et chacune pour une raison qui se vérifie dans la feuille :
   — deux sont des colonnes flex bornées en `overflow: hidden` dont c'est un ENFANT qui
     défile, donc leur en-tête est déjà épinglé par construction — le sélecteur d'objet
     de l'inventaire et `.anima-char-sheet-modal`, qui pousse déjà la même logique
     jusqu'à une barre d'onglets collante dans son corps ;
   — une est un aperçu d'image plein écran, sans texte à faire défiler ;
   — trois sont des modales de jet (`.anima-roll-modal`) : aucun plafond de hauteur,
     aucun `overflow`, donc aucune boîte défilante d'où l'en-tête pourrait sortir ;
   — la dernière est « mot de passe oublié », dont le × et le titre ne sont même pas dans
     une rangée commune, et dont le contenu — une phrase et un champ, dans une colonne de
     340 px — n'atteint jamais le plafond de 90vh de `.anima-modal`.
   Celle-ci est la huitième : sa rangée d'en-tête est
   DANS la boîte, et la boîte défile (`max-height: 80vh; overflow-y: auto` ci-dessus).
   Mesuré à 1280x800 sur un décalque : le haut de l'en-tête passe de 101 px à −1 143 px,
   le × sort de l'écran ; le décalque de la modale de compétence secondaire, qui suit la
   convention majoritaire, garde le sien à 63 px dans le même geste.
   CORRECTIF CSS ET NON RESTRUCTURATION : la rangée d'en-tête existe déjà comme élément
   propre (`.anima-roll-modal-header`), le titre n'est pas noyé dans le corps. Il n'y a
   donc rien à découper dans le template.
   MÊME VOCABULAIRE QUE LES PIEDS COLLANTS de components.css, à l'envers : `position:
   sticky` avec le bord opposé, fond opaque `var(--surface)` — obligatoire, sans lui le
   contenu défile en transparence dessous — et un filet d'1 px `var(--border)`, ici en
   bas puisque l'en-tête borde le contenu par le bas. Le filet est AJOUTÉ : la règle de
   base de `.anima-roll-modal-header`, plus haut dans ce fichier, n'en porte aucun. Il
   n'est pas décoratif — sans lui, rien ne marque où s'arrête le bandeau opaque et où
   reprend le contenu qui passe dessous.
   LE `z-index` N'EST PAS DÉCORATIF NON PLUS, et c'est la différence avec un pied. Un
   pied collant est le DERNIER enfant : il peint naturellement au-dessus de ses frères.
   Un en-tête est le PREMIER, donc tout ce qui le suit le recouvrirait sans lui.
   LA MARGE BASSE DEVIENT UNE GOUTTIÈRE, et c'est la subtilité du collant. Les 16 px de
   `margin-bottom` de la règle de base sont hors de la boîte peinte : le contenu défilant
   les traverserait, et on verrait une bande de texte glisser entre le titre et le filet.
   Reportés en `padding-bottom`, ils restent dans le fond opaque, et l'écartement au
   repos ne bouge pas — 16 px avant, 16 px plus l'épaisseur du filet après. C'est
   exactement la géométrie du primitif `.anima-modal-header` de components.css, qui pose
   la même gouttière puis le même filet. */
.anima-module-detail-modal > .anima-roll-modal-header {
  position: sticky;
  top: 0;
  z-index: 1;
  margin-bottom: 0;
  padding-bottom: 16px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}

.anima-module-modal-cost {
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--anima-accent, var(--accent));
  margin-bottom: 14px;
}

.anima-module-modal-field {
  margin-bottom: 10px;
}

.anima-module-modal-label {
  font-size: 0.8rem;
  color: var(--muted);
  display: block;
  margin-bottom: 3px;
}

.anima-module-modal-effects {
  font-size: 0.92rem;
  line-height: 1.6;
  color: var(--ink);
  margin-bottom: 14px;
}

.anima-module-modal-warnings {
  margin-top: 12px;
  font-size: 0.82rem;
  color: var(--warning);
}


/* ── Race / Class info cards ── */
.char-info-card {
  padding: 4px 0;
  overflow-y: auto;
  max-height: 60vh;
}

.char-info-card-title-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 10px;
}

.char-info-card-name {
  font-size: 0.9rem;
  font-weight: bold;
  color: var(--accent);
}

.char-info-card-badge {
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  border: 1px solid var(--border);
  border-radius: 10px;
  color: var(--accent);
  font-size: 0.8rem;
  padding: 2px 10px;
}

.char-info-card-lore {
  background: var(--surface-2);
  border-left: 2px solid var(--accent);
  border-radius: 0 3px 3px 0;
  color: var(--muted);
  font-size: 0.85rem;
  line-height: 1.65;
  margin-bottom: 14px;
  padding: 8px 12px;
}

.char-info-card-section-title {
  color: var(--accent);
  font-size: 0.8rem;
  font-weight: bold;
  letter-spacing: 0.8px;
  margin-bottom: 8px;
  margin-top: 14px;
  text-transform: uppercase;
}

.char-info-card-power {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 3px;
  margin-bottom: 5px;
  padding: 7px 10px;
}

.char-info-card-power-name {
  color: var(--accent);
  font-size: 0.8rem;
  font-weight: bold;
  margin-bottom: 2px;
}

.char-info-card-power-desc {
  color: var(--muted);
  font-size: 0.8rem;
  line-height: 1.45;
}

.char-info-card-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  margin-bottom: 4px;
}

.char-info-card-chip {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 2px;
  color: var(--muted);
  font-size: 0.8rem;
  padding: 3px 8px;
}

.char-info-card-costs-table {
  border-collapse: collapse;
  font-size: 0.8rem;
  margin-bottom: 4px;
  width: 100%;
}

.char-info-card-costs-table thead th {
  border-bottom: 1px solid var(--border);
  color: var(--muted);
  font-size: 0.8rem;
  font-weight: normal;
  padding: 4px 6px;
  text-align: left;
}

.char-info-card-costs-table tbody tr:nth-child(even) {
  background: var(--surface-2);
}

.char-info-card-costs-table tbody td {
  color: var(--muted);
  padding: 4px 6px;
}

.char-info-card-costs-table tbody td:last-child {
  color: var(--accent);
  font-weight: bold;
  text-align: center;
  width: 70px;
}

.char-info-card-reduced-note {
  color: var(--muted);
  font-size: 0.8rem;
  font-style: italic;
  margin-top: 8px;
}

.char-info-card-empty {
  color: var(--muted);
  font-size: 0.8rem;
  font-style: italic;
  padding: 20px 0;
  text-align: center;
}

/* ── Barre d'onglets de la fiche de personnage ──────────────────────────────
   Nom propre (.anima-sheet-tabs / .anima-sheet-tab), et règles autonomes.
   Avant, ce bloc redéfinissait .anima-tab-bar / .anima-tab sans les scoper : ces
   classes appartiennent à la barre de navigation du site (layout.css), et comme
   ce fichier est chargé APRÈS layout.css, chaque barre héritait de l'autre.
   La navigation prenait le flex-wrap et le padding de la fiche ; la fiche prenait
   le sticky, le fond et la typo de la navigation — dépendance invisible dont
   dépendaient deux correctifs (le `top: 0` en fiche modale plus bas, et la liste
   d'exceptions de la page qui se tourne dans components.css).
   Les valeurs ci-dessous sont l'exact résultat calculé de cette ancienne fusion :
   le rendu de la fiche est inchangé, mais il ne dépend plus de layout.css. */
.anima-sheet-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 0;
  padding: 0;
  border-bottom: 2px solid var(--bs-border-color, var(--border));
  background: var(--surface);
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); /* one-off hairline, repris de layout.css */
  position: sticky;
  top: var(--topnav-h);
  z-index: 1045;
  isolation: isolate;
}

.anima-sheet-tab {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
  white-space: nowrap;
  padding: 8px 16px;
  margin-bottom: -2px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.8rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--bs-secondary-color, var(--muted));
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  cursor: pointer;
  text-decoration: none;
  transition: color 0.15s, border-color 0.15s;
}

.anima-sheet-tab:hover {
  color: var(--bs-body-color, var(--ink));
  text-decoration: none;
}

.anima-sheet-tab--active {
  color: var(--bs-primary, var(--accent));
  border-bottom-color: var(--bs-primary, var(--accent));
  font-weight: 600;
}

.anima-background-textarea {
  min-height: 9rem;
}

.anima-background-text {
  color: var(--ink);
  line-height: 1.7;
  white-space: pre-wrap;
}

.anima-background-timeline {
  list-style: none;
  margin: 1rem 0 0;
  padding: 0;
  border-left: 1px solid var(--border);
}

.anima-background-timeline li {
  margin-left: 1rem;
  padding: 0 0 1rem 1rem;
  position: relative;
}

.anima-background-timeline li::before {
  background: var(--accent);
  border-radius: 50%;
  content: "";
  height: 0.5rem;
  left: -1.28rem;
  position: absolute;
  top: 0.25rem;
  width: 0.5rem;
}

.anima-background-date {
  color: var(--accent);
  display: block;
  font-size: 0.8rem;
  margin-bottom: 0.2rem;
  text-transform: uppercase;
}

.anima-background-timeline strong {
  color: var(--ink);
}

.anima-background-timeline p {
  color: color-mix(in srgb, var(--ink) 75%, transparent);
  margin: 0.25rem 0 0;
  white-space: pre-wrap;
}

.anima-background-editor-list {
  display: grid;
  gap: 0.75rem;
}

.anima-background-editor-row {
  display: grid;
  gap: 0.5rem;
  grid-template-columns: auto minmax(7rem, 0.8fr) minmax(9rem, 1fr) minmax(12rem, 2fr) auto;
}

.anima-background-panel .anima-drag-handle {
  align-self: start;
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  border: 1px solid var(--border);
  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-background-panel .anima-drag-handle:active {
  cursor: grabbing;
}

.anima-background-editor-row textarea {
  min-height: 2.4rem;
}

@media (max-width: 720px) {
  .anima-background-editor-row {
    grid-template-columns: 1fr;
  }
}

/* ── Ki Form ─────────────────────────────────────────────────────────── */

.ki-dp-max {
  color: color-mix(in srgb, var(--ink) 45%, transparent);
  font-size: 0.8rem;
}

.ki-input {
  background-color: color-mix(in srgb, var(--ink) 7%, transparent) !important;
  border-color: color-mix(in srgb, var(--ink) 20%, transparent) !important;
  color: var(--bs-body-color, var(--ink)) !important;
}

.ki-input:focus {
  background-color: color-mix(in srgb, var(--ink) 12%, transparent) !important;
  border-color: color-mix(in srgb, var(--ink) 40%, transparent) !important;
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--ink) 10%, transparent) !important;
  color: var(--bs-body-color, var(--ink)) !important;
}

.ki-dp-footer {
  background-color: color-mix(in srgb, var(--ink) 4%, transparent);
  border-top-color: color-mix(in srgb, var(--ink) 10%, transparent);
  color: color-mix(in srgb, var(--ink) 50%, transparent);
  font-size: 0.8rem;
}

.ki-dp-footer strong {
  color: var(--bs-body-color, var(--ink));
}

/* Ability list */
.ki-ability-block {
  border-bottom: 1px solid color-mix(in srgb, var(--ink) 7%, transparent);
}

.ki-ability-block:last-child {
  border-bottom: none;
}

.ki-ability-block.ki-ability--owned {
  background-color: color-mix(in srgb, var(--success) 6%, transparent);
}

.ki-ability-block.ki-ability--locked {
  opacity: 0.45;
}

.ki-ability-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 14px;
}

.ki-ability-indent {
  width: 14px;
  flex-shrink: 0;
  color: color-mix(in srgb, var(--ink) 30%, transparent);
  font-size: 0.8rem;
}

.ki-ability-toggle {
  background: none;
  border: 1px solid color-mix(in srgb, var(--ink) 20%, transparent);
  border-radius: 3px;
  padding: 1px 5px;
  color: color-mix(in srgb, var(--ink) 60%, transparent);
  font-size: 0.8rem;
  cursor: pointer;
  flex-shrink: 0;
  line-height: 1.4;
  min-width: 22px;
  text-align: center;
}

.ki-ability-toggle:hover {
  color: var(--bs-body-color, var(--ink));
  border-color: color-mix(in srgb, var(--ink) 50%, transparent);
  background: color-mix(in srgb, var(--ink) 5%, transparent);
}

.ki-ability-name {
  flex: 1;
  font-size: 0.85rem;
  color: var(--bs-body-color, var(--ink));
  line-height: 1.3;
}

.ki-ability-name--clickable {
  cursor: pointer;
}

.ki-ability-name--clickable:hover {
  color: var(--link-hover);
}

.ki-owned-check {
  color: var(--success);
  font-size: 0.8rem;
}

.ki-badge-de {
  display: inline-block;
  padding: 1px 5px;
  border-radius: 3px;
  font-size: 0.8rem;
  background: color-mix(in srgb, var(--zeon) 12%, transparent);
  color: var(--zeon);
  margin-left: 4px;
  vertical-align: middle;
}

.ki-mk-cost {
  font-size: 0.8rem;
  color: color-mix(in srgb, var(--ink) 45%, transparent);
  min-width: 52px;
  text-align: right;
  flex-shrink: 0;
}

/* Ability action buttons */
.ki-btn {
  padding: 3px 12px;
  font-size: 0.8rem;
  border-radius: 4px;
  border: 1px solid;
  cursor: pointer;
  background: transparent;
  white-space: nowrap;
  flex-shrink: 0;
}

.ki-btn--acquire {
  border-color: color-mix(in srgb, var(--ink) 40%, transparent);
  color: var(--bs-body-color, var(--ink));
}

.ki-btn--acquire:hover {
  background-color: color-mix(in srgb, var(--ink) 10%, transparent);
}

.ki-btn--remove {
  border-color: color-mix(in srgb, var(--success) 35%, transparent);
  color: var(--success);
}

.ki-btn--remove:hover {
  background-color: color-mix(in srgb, var(--success) 8%, transparent);
}

.ki-btn--locked {
  border-color: color-mix(in srgb, var(--ink) 12%, transparent);
  color: color-mix(in srgb, var(--ink) 25%, transparent);
  cursor: not-allowed;
}

/* Description accordion */
.ki-ability-desc {
  padding: 10px 16px 14px 52px;
  font-size: 0.8rem;
  line-height: 1.65;
  color: color-mix(in srgb, var(--ink) 70%, transparent);
  border-top: 1px solid color-mix(in srgb, var(--ink) 8%, transparent);
  background-color: rgba(0, 0, 0, 0.12); /* one-off dark wash, no matching token */
}

/* ── Sceaux d'Invocation ─────────────────────────────────────────── */
.ki-seal-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 16px;
  border-bottom: 1px solid color-mix(in srgb, var(--ink) 8%, transparent);
}
.ki-seal-row:last-child {
  border-bottom: none;
}
.ki-seal-element-label {
  min-width: 56px;
  font-size: 0.85rem;
  font-weight: 600;
  color: color-mix(in srgb, var(--ink) 85%, transparent);
}
.ki-seal-tiers {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}
.ki-seal-btn {
  font-size: 0.8rem;
}
.ki-seal-btn--learned {
  background-color: color-mix(in srgb, var(--success) 18%, transparent);
  color: var(--success);
  border-color: color-mix(in srgb, var(--success) 35%, transparent);
}
.ki-seal-btn--learned:hover {
  background-color: color-mix(in srgb, var(--success) 28%, transparent);
}

/* ── KiTechniquesForm ─────────────────────────────────────────────── */
.ki-tech-container { display: flex; flex-direction: column; gap: 0; }

.ki-tech-topbar {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 0 14px;
  border-bottom: 1px solid color-mix(in srgb, var(--ink) 12%, transparent);
  margin-bottom: 16px;
}

.ki-tech-back-btn {
  background: none; border: 1px solid color-mix(in srgb, var(--ink) 20%, transparent);
  border-radius: 4px; padding: 3px 12px; font-size: 0.8rem;
  color: color-mix(in srgb, var(--ink) 60%, transparent); cursor: pointer;
}
.ki-tech-back-btn:hover { color: var(--bs-body-color, var(--ink)); }

.ki-tech-title { font-size: 0.85rem; font-weight: 600; color: var(--bs-body-color, var(--ink)); }

.ki-tech-mk-info { margin-left: auto; font-size: 0.8rem; color: color-mix(in srgb, var(--ink) 50%, transparent); }
.ki-mk-negative { color: var(--hp); }

.ki-tech-body {
  display: flex; gap: 0; min-height: 400px;
  border: 1px solid color-mix(in srgb, var(--ink) 12%, transparent);
  border-radius: 6px; overflow: hidden;
}

.ki-tech-sidebar {
  width: 180px; flex-shrink: 0;
  border-right: 1px solid color-mix(in srgb, var(--ink) 10%, transparent);
  overflow-y: auto; background: rgba(0, 0, 0, 0.1); /* one-off dark wash, no matching token */
}

.ki-tech-tree-item {
  display: flex; align-items: center; justify-content: space-between;
  width: 100%; padding: 8px 12px; background: none; border: none;
  border-left: 3px solid transparent; text-align: left; font-size: 0.8rem;
  color: color-mix(in srgb, var(--ink) 50%, transparent); cursor: pointer;
  font-family: 'JetBrains Mono', monospace;
}
.ki-tech-tree-item:hover { color: var(--bs-body-color, var(--ink)); }
.ki-tech-tree-item--active {
  color: var(--bs-body-color, var(--ink));
  border-left-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 6%, transparent);
}
.ki-tech-tree-name { flex: 1; }
.ki-tech-tree-badge {
  font-size: 0.8rem; color: var(--success);
  padding: 1px 5px; background: color-mix(in srgb, var(--success) 12%, transparent); border-radius: 8px;
}

.ki-tech-panel { flex: 1; overflow-y: auto; padding: 12px; }

.ki-tech-tree-desc {
  font-size: 0.8rem; color: color-mix(in srgb, var(--ink) 50%, transparent); margin-bottom: 12px;
  line-height: 1.5; border-bottom: 1px solid color-mix(in srgb, var(--ink) 7%, transparent); padding-bottom: 10px;
}

.ki-tech-row { border-bottom: 1px solid color-mix(in srgb, var(--ink) 6%, transparent); padding: 6px 0; }
.ki-tech-row--owned { background: color-mix(in srgb, var(--success) 4%, transparent); }
.ki-tech-row--warn  { background: color-mix(in srgb, var(--warning) 4%, transparent); }

.ki-tech-row-header { display: flex; align-items: center; gap: 8px; }

.ki-tech-level-badge {
  display: inline-block; padding: 1px 6px; border-radius: 3px;
  font-size: 0.8rem; font-weight: 700; flex-shrink: 0;
}
.ki-tech-level-badge--1 { background: color-mix(in srgb, var(--success) 15%, transparent); color: var(--success); }
.ki-tech-level-badge--2 { background: color-mix(in srgb, var(--accent) 15%, transparent); color: var(--accent); }
.ki-tech-level-badge--3 { background: color-mix(in srgb, var(--hp) 15%, transparent);  color: var(--hp); }

.ki-tech-name-btn {
  flex: 1; background: none; border: none; text-align: left;
  font-size: 0.8rem; color: var(--bs-body-color, var(--ink)); cursor: pointer;
  display: flex; align-items: center; gap: 6px;
  font-family: 'Roboto', sans-serif;
}
.ki-tech-name-btn:hover { color: var(--link-hover); }

.ki-tech-chevron { font-size: 0.8rem; color: color-mix(in srgb, var(--ink) 40%, transparent); }
.ki-tech-owned-check { color: var(--success); }

.ki-tech-mk {
  font-size: 0.8rem; color: color-mix(in srgb, var(--ink) 40%, transparent);
  min-width: 50px; text-align: right; flex-shrink: 0;
}

.ki-tech-detail {
  padding: 12px 14px 16px 16px;
  border-top: 1px solid color-mix(in srgb, var(--ink) 8%, transparent);
  background: rgba(0, 0, 0, 0.15); /* one-off dark wash, no matching token */
}

/* Description lore */
.ki-tech-desc-text {
  font-size: 0.8rem;
  color: color-mix(in srgb, var(--ink) 75%, transparent);
  line-height: 1.65;
  margin-bottom: 12px;
  font-style: italic;
}

/* Grille effets / avantages / désavantages */
.ki-tech-detail-grid { display: flex; flex-direction: column; gap: 8px; }

.ki-tech-detail-item { display: flex; gap: 10px; align-items: flex-start; }

.ki-tech-detail-label {
  flex-shrink: 0;
  min-width: 90px;
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding-top: 2px;
  color: color-mix(in srgb, var(--ink) 40%, transparent);
}

/* Coût Ki — bleu-violet énergétique */
.ki-tech-detail-label--ki {
  color: var(--psychic);
}
.ki-tech-detail-val--ki {
  font-size: 0.8rem;
  color: var(--psychic);
  font-weight: 700;
  font-family: 'JetBrains Mono', monospace;
  line-height: 1.5;
}

/* Effets — cyan doré vif */
.ki-tech-detail-label--effects {
  color: var(--accent);
}
.ki-tech-detail-val--effects {
  font-size: 0.8rem;
  color: var(--accent);
  font-weight: 600;
  line-height: 1.5;
}

/* Avantages — vert */
.ki-tech-detail-label--pos { color: var(--success); }
.ki-tech-detail-val--pos {
  font-size: 0.8rem;
  color: var(--success);
  line-height: 1.5;
}

/* Désavantages — rouge atténué */
.ki-tech-detail-label--neg { color: var(--hp); }
.ki-tech-detail-val--neg {
  font-size: 0.8rem;
  color: var(--hp);
  line-height: 1.5;
}

/* Valeur générique */
.ki-tech-detail-val {
  font-size: 0.8rem;
  color: color-mix(in srgb, var(--ink) 75%, transparent);
  line-height: 1.5;
}

.ki-tech-compact-row {
  padding: 9px 14px;
  border-bottom: 1px solid color-mix(in srgb, var(--ink) 7%, transparent);
}

.ki-tech-compact-level {
  font-size: 0.8rem;
  padding: 2px 7px;
  flex-shrink: 0;
}

.ki-tech-compact-name {
  flex: 1;
  font-size: 0.85rem;
  color: var(--bs-body-color, var(--ink));
}

.ki-tech-compact-cost {
  font-size: 0.8rem;
  color: color-mix(in srgb, var(--ink) 50%, transparent);
  flex-shrink: 0;
  font-family: 'JetBrains Mono', monospace;
}

.ki-tech-compact-warn {
  font-size: 0.8rem;
  color: var(--warning);
  flex-shrink: 0;
}

.ki-tech-compact-chevron {
  font-size: 0.8rem;
  color: color-mix(in srgb, var(--ink) 35%, transparent);
  flex-shrink: 0;
}

.ki-tech-compact-block {
  border-bottom: 1px solid color-mix(in srgb, var(--ink) 7%, transparent);
}

.ki-tech-compact-block:last-child {
  border-bottom: none;
}

.ki-tech-compact-block .ki-tech-compact-row {
  border-bottom: none;
  cursor: pointer;
}

.ki-tech-compact-block .ki-tech-compact-row:hover .ki-tech-compact-name {
  color: var(--link-hover);
}

.ki-tech-compact-block--open .ki-tech-compact-chevron {
  color: color-mix(in srgb, var(--ink) 70%, transparent);
}

.ki-btn--warn {
  padding: 3px 12px; font-size: 0.8rem; border-radius: 4px;
  border: 1px solid color-mix(in srgb, var(--warning) 35%, transparent); color: var(--warning);
  background: transparent; cursor: pointer;
}

/* ── Secret roll inline button on secondary ability rows ── */
.anima-secret-roll-btn {
  border: none;
  background: transparent;
  cursor: pointer;
  padding: 0 0.15rem;
  font-size: 0.8rem;
  opacity: 0.5;
  line-height: 1;
}
.anima-secret-roll-btn:hover { opacity: 1; }

/* ── Onglet Nemesis (énergie du Vide) ─────────────────────────────── */
/* Structure calquée sur l'onglet Ki (cards + ki-ability-block/row + ki-btn) ;
   la couleur des en-têtes vient désormais du token --nemesis via la recette
   partagée de components.css (.anima-section-tint .card-header), plus besoin
   de code couleur ad-hoc ici. */

/* Capacité possédée : fond froid au lieu du vert de succès du Ki. */
.nemesis-abilities-card .ki-ability-block.ki-ability--owned {
  background-color: rgba(110, 168, 199, 0.1);
}

/* Description toujours visible (pas d'accordéon ici) : on annule le retrait
   gauche du Ki (réservé à l'indentation toggle) pour l'aligner sur la ligne. */
.nemesis-abilities-card .ki-ability-desc {
  padding-left: 16px;
}

/* Encart « Effets passifs actifs » (SP3) : liste sans puces ni retrait. */
.nemesis-passives-list {
  list-style: none;
  padding-left: 0;
  margin: 0;
}

.nemesis-passive-item {
  padding: 0.15rem 0;
}

/* ── Character Sheet Modal (full sheet in adventure context) ── */
.anima-char-sheet-modal {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 2px;
  width: 100%;
  max-width: 1000px;
  max-height: 90vh;
  display: flex;
  flex-direction: column;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6); /* one-off shadow, no matching shadow token */
  position: relative;
  overflow: hidden;
}

.anima-char-sheet-modal-body {
  overflow-y: auto;
  /* Pas de padding-haut : sinon il décale la barre d'onglets sticky vers le bas
     et le contenu remonte dans cet espace. On reporte l'espacement sur l'en-tête. */
  padding: 0 1.5rem 1.2rem;
  flex: 1;
}

.anima-char-sheet-modal-body > .anima-character-sheet-header {
  margin-top: 1.2rem;
}

/* Dans la fiche modale, le conteneur scrollable n'a pas la bannière globale
   (--topnav-h) : la barre d'onglets doit coller tout en haut, sinon le contenu
   remonte au-dessus. */
.anima-char-sheet-modal-body .anima-sheet-tabs {
  top: 0;
}

/* Effets actifs — section sur la fiche de personnage */
.active-effects-panel {
  margin: 1rem 0;
}
.active-effects-panel__title {
  font-size: 1rem;
  margin-bottom: 0.5rem;
}
.active-effects-panel__list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}
.active-effects-panel__item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.35rem 0.6rem;
  border: 1px solid color-mix(in srgb, var(--psychic) 30%, transparent);
  border-radius: 0.4rem;
  background: color-mix(in srgb, var(--psychic) 6%, transparent);
}
.active-effects-panel__label {
  font-size: 0.9rem;
}

.active-effects-panel__detail {
  margin-left: 0.35rem;
  font-size: 0.8rem;
  opacity: 0.75;
}

/* ── Tailles sorties du markup (plancher de police) ──────────────────────────
   Anciennes déclarations `style="font-size:…"` des gabarits de fiche.
   Plancher du projet : 0.8rem (CLAUDE.md). */

/* Message « aucune technique acquise » du corps de carte Ki. */
.anima-ki-empty-note {
  font-size: 0.8rem;
}


/* ── Mises en forme sorties du markup (attribut `style` littéral) ─────────────
   Une valeur écrite dans un attribut `style` n'est atteignable par aucune feuille
   sans `!important`. Ces déclarations ne servent que sur la fiche de personnage.
   Valeurs reprises telles quelles : ce lot déplace, il ne redessine pas. */

/* Champs de l'onglet Ki. Deux largeurs distinctes : le budget de MK est saisi en
   points de développement à quatre chiffres, les colonnes du tableau à deux. Elles
   l'emportent sur `.form-control-sm` par l'ordre des feuilles, à spécificité égale. */
.ki-budget-input {
  width: 70px;
}

.ki-table-input {
  width: 60px;
}

/* Note « aucune technique acquise » de l'onglet Ki. La couleur est celle qui était
   écrite dans le gabarit, en rgba littéral et non en jeton — la reprendre telle
   quelle est ce qui rend le déplacement neutre ; la traduire en `color-mix` sur
   `--ink` serait un changement de rendu déguisé en refactorisation. */
.anima-ki-empty-note {
  color: rgba(220, 201, 154, 0.4);
}

/* Valeur de fatigue des dérivés, cliquable pour ouvrir son éditeur en ligne. */
.anima-derived-editable {
  cursor: pointer;
}

/* Pastille de malus de récupération, isolée de la grille des dérivés. */
.anima-recovery-badge-spaced {
  margin: 8px 0;
}
