/* ============================================================
   GUIDE DU DÉBUTANT — HORUS HERESY 3e ÉDITION
   Feuille de style principale (thème clair)
   Auteur : Jean · Modifié : 2026-07-14
   Palette : parchemin #f4f1e8, bordeaux #8b0000, or #8a6a2c, gris acier #6b6b85
   ============================================================ */

/* ---------- Polices auto-hébergées ----------
   Cinzel (titres) et Lato (texte) sont servies depuis assets/fonts/
   plutôt que depuis Google Fonts : aucune adresse IP de visiteur
   n'est transmise à un tiers (RGPD / recommandations CNIL), et le
   chargement ne dépend plus d'un domaine externe. Fichiers issus du
   paquet npm @fontsource (sous-ensemble latin, format WOFF2).
   font-display: swap affiche le texte immédiatement avec la police
   système, remplacée sans clignotement une fois la police chargée. */
@font-face {
  font-family: "Cinzel";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("../assets/fonts/cinzel-latin-500-normal.woff2") format("woff2");
}
@font-face {
  font-family: "Cinzel";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../assets/fonts/cinzel-latin-700-normal.woff2") format("woff2");
}
@font-face {
  font-family: "Lato";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../assets/fonts/lato-latin-400-normal.woff2") format("woff2");
}
@font-face {
  font-family: "Lato";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("../assets/fonts/lato-latin-400-italic.woff2") format("woff2");
}
@font-face {
  font-family: "Lato";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../assets/fonts/lato-latin-700-normal.woff2") format("woff2");
}

/* ---------- Variables globales ----------
   Toute la palette et les réglages communs passent par ces
   variables CSS : pour changer une couleur ou un arrondi sur
   tout le site, on modifie une seule ligne ici plutôt que de
   chercher chaque valeur dans le fichier.
   Convention : les variables sont nommées par RÔLE (--fond,
   --accent, --titre...) et non par couleur, pour que les noms
   restent justes si la palette change (ex : futur thème sombre).
   Le suffixe "-clair" (accent, acier) désigne la variante de
   survol ; "-contraste" désigne une déclinaison assombrie pour
   respecter les contrastes WCAG sur petits textes. */
:root {
  --fond: #f4f1e8; /* fond principal (parchemin) */
  --fond-secondaire: #e8e2d0; /* fond nav / footer */
  --accent: #8b0000; /* accent principal (bordeaux) — APLATS de couleur */
  --accent-clair: #a13030;
  /* --accent-texte : le même bordeaux, mais dans son rôle de TEXTE ou de
     LISERÉ sur fond clair. Pourquoi séparer les deux rôles alors que la
     valeur est identique en thème clair ? Parce qu'ils n'ont pas les
     mêmes contraintes de contraste, et que le thème sombre le révèle :
     - en APLAT (`background: var(--accent)`), c'est le texte blanc
       posé dessus qui doit contraster — il monte à 11:1, tout va bien ;
     - en TEXTE (`color: var(--accent)`), c'est l'accent lui-même qui
       doit contraster avec le fond. Sur le fond noir de Nuit Éternelle,
       ce bordeaux tombait à 1,8:1 — soit un texte quasi invisible, très
       loin des 4,5:1 exigés par WCAG 1.4.3 / RGAA 3.2.
     Une seule variable ne pouvait pas satisfaire les deux à la fois. En
     les séparant, le thème sombre n'a plus qu'à redéclarer celle-ci
     (voir « Nuit Éternelle » plus bas), au lieu de rattraper le
     problème règle par règle — ce qui avait déjà commencé pour deux
     composants et aurait dû être répété une vingtaine de fois. */
  --accent-texte: #8b0000;
  /* --titre (or) ≈ 4.3:1 sur --fond : réservé aux titres ≥ 18.66px
     gras (texte large, seuil WCAG 3:1). Pour du texte courant,
     utiliser --titre-contraste (≥ 4.5:1). */
  --titre: #8a6a2c; /* titres, bordures précieuses */
  --titre-contraste: #6b4f1f;
  --acier: #6b6b85; /* bordures, éléments secondaires */
  --acier-clair: #45455f;
  /* --narratif (orange) ≈ 4.6:1 sur --fond/--carte : réservé au
     Détachement Narratif (bordure de carte, bouton d'ajout) pour le
     distinguer nettement de tout le reste de l'organigramme. */
  --narratif: #a35a00;
  --texte: #2c2a24; /* texte courant */
  --texte-doux: #5c584c; /* texte secondaire */
  --carte: #ffffff; /* fond des cartes */
  --carte-hover: #efe9da;
  --fond-nav: rgba(
    248,
    245,
    238,
    0.92
  ); /* fond translucide de la barre de nav */
  --fond-alerte: #fbeae7; /* fond des encadrés d'avertissement */
  --fond-neutre: #ececed; /* fond des puces/boutons neutres (gris clair) */
  --fond-neutre-hover: #dcdcde;
  --radius: 8px;
  --ombre: 0 4px 14px rgba(0, 0, 0, 0.12);
  --transition: 0.25s ease;

  /* ---------- Couleurs SÉMANTIQUES (statuts, réactions, retours) ----------
     Pourquoi des variables ici alors que ces couleurs ne servent qu'à un
     seul composant chacune ? Parce qu'elles étaient jusqu'ici écrites en
     dur dans leur règle (`color: #1f5a96`) : elles ne suivaient donc PAS
     le thème « Nuit Éternelle », qui recolore le site en ne redéfinissant
     que des variables. Résultat : sur fond noir, un titre de statut bleu
     nuit tombait à 2,7:1 de contraste, très en dessous du minimum WCAG
     1.4.3 (4,5:1). En passant par une variable, le thème sombre n'a plus
     qu'à redéclarer la teinte claire correspondante (voir la section
     « Nuit Éternelle » plus bas). Les valeurs ci-dessous sont exactement
     celles d'avant : le thème clair est inchangé au pixel près. */
  --statut-fixe: #8a6a2c;
  --statut-neutralise: #1f5a96;
  --statut-sonne: #7d3fa0;
  --statut-deroute: #a13030;
  --phase-mouvement: #2f7d3a;
  --phase-tir: #1f5a96;
  --phase-assaut: #a8551f;
  --phase-special: #7d3fa0;
  /* Texte volontairement atténué (valeurs « - » des tables) : plus foncé
     que --texte-doux pour rester ≥ 4,5:1 même quand la ligne est
     assombrie par le survol (voir tbody tr:hover td). */
  --texte-attenue: #444444;
  --succes: #2e6b2e;
  --fond-succes: #e6f2e6;
  --texte-succes: #1d4a1d;
  --fond-erreur: #fbeeee;
  --fond-erreur-fort: #f7e6e6;
  --texte-erreur: #6b0000;

  /* Taille minimale d'une cible tactile — voir la note « TAILLE DES
     CIBLES TACTILES » en fin de fichier pour le raisonnement complet.
     1.5rem = 24px avec la taille de police par défaut. */
  --cible-tactile: 1.5rem;
}

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

/* Cache visuellement un élément sans le retirer du DOM : le
   texte reste lisible par les lecteurs d'écran (ex : le label
   de la barre de recherche sur la page Règles spéciales), sans
   prendre de place à l'affichage. Préférer cette classe à un
   style en ligne pour garder toute la présentation dans le CSS.
   `clip` est déprécié mais conservé pour les navigateurs anciens ;
   `clip-path` est son remplaçant standard — les deux cohabitent, le
   navigateur applique celui qu'il connaît. `border`/`padding` à zéro
   parce qu'une bordure ou un rembourrage hérités rendraient visible
   un liseré de 1px de l'élément censé être invisible. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Lien d'évitement (accessibilité, WCAG 2.4.1 / RGAA 12.7) :
   masqué hors écran, il devient visible quand il reçoit le focus
   clavier (Tab en début de page) pour sauter directement au contenu. */
.lien-evitement {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 2000;
  background: var(--accent);
  color: #fff;
  padding: 0.6rem 1rem;
  border-radius: 0 0 var(--radius) 0;
  text-decoration: none;
}
.lien-evitement:focus {
  left: 0;
}

/* Approche MOBILE-FIRST : les styles de base décrivent le petit
   écran (la cible principale du site, consulté en cours de partie),
   et les media queries en min-width ENRICHISSENT pour les grands
   écrans — plutôt que l'inverse. */
html {
  scroll-behavior: smooth;
  /* --nav-height est mesurée en JS (js/main.js) sur la hauteur réelle de
     .nav, car le logo peut passer sur 2 lignes (police système agrandie,
     réglages d'accessibilité...) : une valeur fixe en dur sous-estime
     alors la barre et le bouton burger déborde sur le contenu. La valeur
     en dur ci-dessous ne sert que de repli avant l'exécution du JS. */
  scroll-padding-top: var(--nav-height, 70px);
}

@media (min-width: 761px) {
  html {
    scroll-padding-top: var(--nav-height, 90px);
  }
}

body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  font-family: "Lato", sans-serif;
  background: var(--fond);
  color: var(--texte);
  line-height: 1.7;
  /* Texture subtile en dégradé pour éviter un fond trop plat */
  background-image: radial-gradient(
    circle at 20% 0%,
    #ffffff 0%,
    var(--fond) 60%
  );
}

@media (min-width: 761px) {
  body {
    /* Fige le dégradé au défilement — réservé aux grands écrans :
       iOS Safari l'ignore et Android le paie en repaints continus
       à chaque scroll. Sans lui, le dégradé reste visible, il
       défile simplement avec la page. */
    background-attachment: fixed;
  }
}

h1,
h2,
h3,
h4 {
  font-family: "Cinzel", serif;
  color: var(--titre);
}

a {
  color: var(--titre-contraste);
}

img {
  max-width: 100%;
}

/* ============================================================
   NAVIGATION FIXE
   position: fixed la maintient à l'écran pendant le défilement ;
   le fond semi-transparent + backdrop-filter donne un effet de
   verre dépoli au-dessus du contenu qui défile dessous.
   Le bouton .nav-burger et le repli mobile de .nav-menu sont
   pilotés par js/main.js (section "MENU BURGER").
   ============================================================ */
.nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 1000;
  background: var(--fond-nav);
  backdrop-filter: blur(6px);
  border-bottom: 2px solid var(--accent);
}

.nav-inner {
  position: relative;
  max-width: 1100px;
  margin: 0 auto;
  padding: 0.6rem 1rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.3rem;
}

.nav-logo {
  font-family: "Cinzel", serif;
  font-weight: 700;
  font-size: 0.85rem;
  max-width: calc(100% - 4.5rem); /* laisse la place au bouton burger */
  color: var(--titre);
  text-decoration: none;
  letter-spacing: 1px;
  text-align: center;
}

.nav-logo span {
  color: var(--accent-clair);
}

/* Bouton burger (base mobile : visible) */
.nav-burger {
  display: flex;
  align-items: center;
  justify-content: center;
  /* Cible tactile confortable (~44px) même si le glyphe ☰ est petit */
  min-width: 2.75rem;
  min-height: 2.75rem;
  position: absolute;
  top: 0.5rem;
  right: 1rem;
  background: none;
  border: none;
  border-radius: var(--radius);
  color: var(--titre);
  font-size: 1.4rem;
  padding: 0;
  cursor: pointer;
}

/* Base mobile : menu replié, liens empilés en pleine largeur.
   La classe .ouvert est basculée par le bouton burger (js/main.js). */
.nav-menu {
  display: none;
  width: 100%;
  flex-direction: column;
  list-style: none;
  gap: 0.3rem;
  padding: 0.5rem 0;
  max-height: calc(100dvh - var(--nav-height, 70px) - 1rem);
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}
.nav-menu.ouvert {
  display: flex;
}

.nav-menu a {
  display: block;
  /* Liens empilés en pleine largeur : autant agrandir la zone de tap */
  padding: 0.85rem 1rem;
  color: var(--texte);
  text-decoration: none;
  font-size: 1rem;
  border-radius: var(--radius);
  transition:
    background var(--transition),
    color var(--transition);
}

.nav-menu a:hover {
  background: var(--acier);
  color: #fff;
}

/* Page courante mise en évidence (aria-current="page" posé sur le lien
   de chaque page dans le HTML, pas de classe JS à maintenir) */
.nav-menu a[aria-current="page"] {
  background: var(--accent);
  color: #fff;
  font-weight: 700;
}

/* ---------- Nav bureau : menu toujours déplié, burger masqué ---------- */
@media (min-width: 761px) {
  .nav-burger {
    display: none;
  }
  .nav-logo {
    font-size: 1.1rem;
    max-width: none;
  }
  .nav-menu {
    display: flex;
    flex-direction: row;
    justify-content: center;
    flex-wrap: wrap;
    width: auto;
    padding: 0;
  }
  .nav-menu a {
    padding: 0.5rem 0.9rem;
    font-size: 0.95rem;
  }
}

/* ============================================================
   STRUCTURE GÉNÉRALE
   ============================================================ */
main {
  width: 100%;
  max-width: 1100px;
  margin: 0 auto;
  /* padding-top : voir --nav-height plus haut (mesurée en JS, la barre
     n'a pas une hauteur fixe garantie). */
  padding-top: var(--nav-height, 70px);
  padding-right: 1rem;
  padding-bottom: 3rem;
  padding-left: 1rem;
  /* body est un conteneur flex : les marges auto pour centrer main font
     que son "width: auto" se calcule en shrink-to-fit, borné par la
     largeur minimale de son contenu (ex : une table large) — ça faisait
     déborder toute la page horizontalement au lieu de laisser
     .table-scroll gérer son propre défilement. "width: 100%" fixe une
     largeur définie qui ne peut pas grandir avec le contenu. */
  min-width: 0;
}

@media (min-width: 761px) {
  main {
    padding-top: var(--nav-height, 130px);
  }
}

/* Page d'accueil : centre le hero (donc l'image) verticalement
   entre le trait rouge de la nav et celui du footer. */
main.main-accueil {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

section {
  margin-bottom: 3.5rem;
}

.section-titre {
  font-size: 1.7rem;
  border-bottom: 2px solid var(--accent);
  padding-bottom: 0.4rem;
  margin-bottom: 1.2rem;
  display: flex;
  align-items: center;
  gap: 0.6rem;
}

.section-titre--centre {
  justify-content: center;
}

/* Titre principal des pages intérieures : remplace les anciens
   style="font-size: 2rem" en ligne (la présentation reste dans le CSS). */
.titre-page {
  font-size: 2rem;
}

.sous-titre {
  font-size: 1.2rem;
  color: var(--titre-contraste);
  margin: 1.6rem 0 0.8rem;
}

p {
  margin-bottom: 0.9rem;
}

ul,
ol {
  margin: 0 0 1rem 1.4rem;
}

li {
  margin-bottom: 0.35rem;
}

strong {
  color: var(--titre-contraste);
}

/* Encadré générique */
.encadre {
  background: var(--carte);
  border-left: 4px solid var(--acier);
  border-radius: var(--radius);
  padding: 1rem 1.2rem;
  margin: 1.2rem 0;
}

/* Encadré "attention" */
.encadre-attention {
  background: var(--fond-alerte);
  border-left: 4px solid var(--accent-clair);
  border-radius: var(--radius);
  padding: 1rem 1.2rem;
  margin: 1.2rem 0;
}

/* Le dernier paragraphe d'un encadré ne doit pas creuser le padding :
   remplace les anciens style="margin: 0" posés en ligne dans le HTML. */
.encadre p:last-child,
.encadre-attention p:last-child {
  margin-bottom: 0;
}

/* Lien "Détail de la phase →" en bas des items de la timeline (tour.html) */
.lien-detail {
  margin: 0.6rem 0 0;
}

/* ============================================================
   PAGE ACCUEIL — HERO + CARTES
   ============================================================ */
.hero {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 2.5rem;
  text-align: center;
  padding: 3rem 1rem 2rem;
}

.hero-texte {
  flex: 1 1 260px;
}

.hero h1 {
  font-size: clamp(1.8rem, 5vw, 3rem);
  letter-spacing: 2px;
  margin-bottom: 0.6rem;
  text-shadow: 0 0 18px rgba(139, 0, 0, 0.25);
}

.hero .devise {
  color: var(--texte-doux);
  font-style: italic;
  font-size: 1.1rem;
}

/* Portrait d'ambiance : encadré à la manière d'un blason, avec
   un léger vignettage intérieur pour fondre la photo (sombre et
   contrastée) dans la palette parchemin du site plutôt que de la
   plaquer telle quelle. */
.hero-image {
  flex: 0 1 300px;
  position: relative;
  border-radius: 12px;
  border: 3px solid var(--titre);
  box-shadow: var(--ombre);
  overflow: hidden;
}

.hero-image img {
  display: block;
  width: 100%;
  height: auto;
}

.hero-image::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 9px;
  border: 1px solid var(--accent);
  box-shadow: inset 0 0 40px 12px rgba(0, 0, 0, 0.5);
  pointer-events: none;
}

/* ============================================================
   PAGE ACCUEIL — FRISE « ORDRE DE DÉPLOIEMENT DES FORCES »
   Deux phases reliées par un connecteur en pointillés : empilées
   verticalement sur mobile (lecture naturelle de haut en bas), en
   frise horizontale à partir de 761px.
   ============================================================ */
.frise {
  display: flex;
  /* Mobile d'abord : les phases s'empilent. Le passage en ligne se fait
     dans la media query en fin de section. */
  flex-direction: column;
  gap: 2.4rem;
  list-style: none;
  margin: 0;
  padding: 0;
  /* Filet de sécurité : si une phase venait à contenir un libellé plus
     large que l'écran, on défile horizontalement plutôt que de casser
     la mise en page. padding-bottom réserve la place de la barre de
     défilement pour qu'elle ne recouvre pas les cartes. */
  overflow-x: auto;
  padding-bottom: 0.4rem;
}

.frise-phase {
  position: relative;
  flex: 1 1 0;
  /* isolation: isolate crée un contexte d'empilement local : le voile
     décoratif (::after, z-index: -1) reste DERRIÈRE le texte de sa
     propre phase au lieu de passer derrière le fond de la page, où il
     serait invisible. */
  isolation: isolate;
  border: 1px solid var(--acier);
  border-radius: var(--radius);
  background: var(--carte);
  padding: 1rem 1.1rem;
  margin-bottom: 0;
}

/* Connecteur entre deux phases : un simple trait en pointillés dessiné
   par un pseudo-élément, sans SVG ni image à charger. Vertical dans la
   version empilée (mobile), redessiné horizontalement plus bas. */
.frise-phase + .frise-phase::before {
  content: "";
  position: absolute;
  left: 50%;
  top: -2.4rem;
  height: 2.4rem;
  border-left: 3px dotted var(--acier);
}

.frise-phase-titre {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: center;
  gap: 0.4rem;
  font-size: 1.15rem;
  margin-bottom: 0.7rem;
}

/* L'emoji d'état (✅ / 🔜) est décoratif (aria-hidden dans le HTML) :
   on le fige à la taille du texte courant pour qu'il ne dépasse pas du
   titre, les emojis étant rendus plus grands que la police sur
   certaines plateformes. */
.frise-phase-icone {
  font-size: 1rem;
  line-height: 1;
}

/* L'état est écrit en toutes lettres à côté du titre : c'est lui qui
   porte l'information « disponible / à venir », la couleur ne fait que
   la redoubler (WCAG 1.4.1). */
.frise-phase-etat {
  font-family: "Lato", sans-serif;
  font-size: 0.9rem;
  font-weight: 700;
  letter-spacing: 0.5px;
  text-transform: uppercase;
}

.frise-forces {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

.frise-force {
  position: relative;
  isolation: isolate;
  font-size: 0.92rem;
  border-radius: var(--radius);
  padding: 0.35rem 0.7rem;
  margin-bottom: 0;
}

/* ---------- Phase I : déployée (vert, opacité pleine) ---------- */
.frise-phase--deployee {
  border-left: 5px solid var(--succes);
}

.frise-phase--deployee .frise-phase-titre,
.frise-phase--deployee .frise-phase-etat {
  color: var(--succes);
}

.frise-phase--deployee .frise-force {
  color: var(--texte);
  background: color-mix(in srgb, var(--succes) 14%, var(--carte));
  border: 1px solid color-mix(in srgb, var(--succes) 55%, var(--carte));
}

/* ---------- Phase II : à venir (orange, voilée et floutée) ----------
   Le flou porte sur le FOND des étiquettes, jamais sur leur texte :
   filter: blur(1px) posé sur .frise-force rendrait les noms de Faction
   illisibles, ce qu'aucune règle WCAG ne tolère (1.4.8, et en pratique
   1.4.3 : un texte flou n'a plus de contraste mesurable). On floute
   donc un calque décoratif placé sous le texte — la bordure en
   pointillés s'estompe, l'étiquette semble prise dans la brume, et le
   nom reste net. */
.frise-phase--avenir {
  border-left: 5px solid var(--phase-assaut);
}

.frise-phase--avenir .frise-phase-titre,
.frise-phase--avenir .frise-phase-etat {
  color: var(--phase-assaut);
}

/* Voile semi-transparent sur toute la phase. z-index: -1 le maintient
   sous le texte (voir isolation: isolate plus haut) : le voile teinte
   le fond de la carte sans dégrader le contraste des libellés. */
.frise-phase--avenir::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--phase-assaut) 10%, transparent);
  pointer-events: none;
}

.frise-phase--avenir .frise-force {
  color: var(--texte);
}

.frise-phase--avenir .frise-force::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--phase-assaut) 16%, var(--carte));
  border: 1px dashed color-mix(in srgb, var(--phase-assaut) 65%, var(--carte));
  filter: blur(1px);
}

/* ---------- Frise horizontale (écrans larges) ---------- */
@media (min-width: 761px) {
  .frise {
    flex-direction: row;
    align-items: stretch;
  }

  /* Le connecteur bascule de vertical à horizontal : il occupe
     l'espace du gap (2.4rem) entre deux phases, à hauteur du titre. */
  .frise-phase + .frise-phase::before {
    left: -2.4rem;
    top: 1.6rem;
    height: 0;
    width: 2.4rem;
    border-left: 0;
    border-top: 3px dotted var(--acier);
  }
}

/* ============================================================
   ORGANIGRAMME DE FORCE (page armée)
   ============================================================ */
.organigramme {
  display: grid;
  gap: 1.2rem;
}

.orga-groupe {
  border: 1px dashed var(--acier);
  border-radius: var(--radius);
  padding: 1rem;
}

.orga-groupe > h2 {
  font-size: 0.95rem;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--acier-clair);
  margin-bottom: 0.7rem;
}

.orga-cases {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
}

/* Une "boîte" de détachement avec tooltip au survol */
.orga-boite {
  position: relative;
  background: var(--carte);
  border: 1px solid var(--acier);
  border-radius: var(--radius);
  padding: 0.6rem 0.9rem;
  font-size: 0.9rem;
  cursor: help;
  transition:
    border-color var(--transition),
    background var(--transition);
}

.orga-boite:hover,
.orga-boite:focus-within {
  border-color: var(--titre);
  background: var(--carte-hover);
}

.orga-boite.principal {
  border-color: var(--accent-clair);
  border-width: 2px;
}

/* Tooltip descriptif : caché par défaut (opacity 0 + visibility
   hidden, pas display:none, pour permettre la transition en
   fondu) et révélé uniquement par les sélecteurs :hover/:focus
   ci-dessous. Sur grand écran, sa position (haut/bas + décalage
   horizontal) est calculée par JS au survol/focus (positionnerBulle,
   js/main.js) plutôt qu'en CSS pur : un tableau d'armes est borné à
   la fois horizontalement (.table-scroll, overflow-x:auto) et
   verticalement (le même overflow-x force overflow-y à auto ;
   table{overflow:hidden} pour les coins arrondis fait de même), donc
   une bulle en position:absolute serait rognée dès qu'elle manque de
   place au-dessus ou en dessous de sa ligne dans le tableau — ce qui
   arrive dès qu'un tableau ne compte que deux lignes, cas très
   fréquent ici. En position:fixed avec des coordonnées calculées par
   rapport au viewport, la bulle échappe à ce rognage quelle que soit
   la hauteur du tableau qui la contient.
   Partagé par .orga-boite (organigramme, construction-liste.html), .regle-tag
   (règles spéciales des tables d'armes, armes.html) et .orga-badge
   (badges de Rôles Tactiques du constructeur d'armée, construction-liste.html). */
.orga-boite .tooltip,
.regle-tag .tooltip,
.orga-badge .tooltip {
  visibility: hidden;
  opacity: 0;
  /* Base mobile : la bulle s'affiche en bandeau fixé en bas d'écran,
     là où une bulle flottante serait rognée ou cachée par le doigt. */
  position: fixed;
  left: 1rem;
  right: 1rem;
  bottom: 1rem;
  background: var(--fond-secondaire);
  border: 1px solid var(--titre);
  border-radius: var(--radius);
  padding: 0.7rem 0.9rem;
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--texte);
  z-index: 50;
  transition: opacity var(--transition);
  box-shadow: var(--ombre);
  /* Accessibilité (WCAG 1.4.13) : le tooltip reste survolable pour que
     l'utilisateur puisse amener le pointeur dessus sans le faire disparaître. */
  pointer-events: auto;
}

.orga-boite:hover .tooltip,
.orga-boite:focus .tooltip,
.regle-tag:hover .tooltip,
.regle-tag:focus .tooltip,
.orga-badge:hover .tooltip,
.orga-badge:focus .tooltip {
  visibility: visible;
  opacity: 1;
}

/* Grand écran : la bulle flotte au-dessus ou en dessous de sa case
   (selon la place disponible), centrée. Valeurs de repli avant que JS
   n'ait calculé une position exacte (positionnerBulle, js/main.js) :
   ce cas ne se produit normalement jamais en pratique (l'écouteur est
   posé une fois pour toutes sur document, donc actif dès le premier
   survol/focus), gardé seulement par prudence. */
@media (min-width: 601px) {
  .orga-boite .tooltip,
  .regle-tag .tooltip,
  .orga-badge .tooltip {
    position: fixed;
    bottom: calc(100% + 8px);
    left: 50%;
    right: auto;
    transform: translateX(-50%);
    width: 260px;
  }
}

/* Règle spéciale inline (tables d'armes) avec la même info-bulle que
   .orga-boite, mais habillée pour tenir dans le texte d'une cellule
   de tableau plutôt que comme une boîte à part entière. */
.regle-tag {
  position: relative;
  cursor: help;
  border-bottom: 1px dotted var(--acier-clair);
  transition: color var(--transition);
}

.regle-tag:hover,
.regle-tag:focus-within {
  color: var(--titre);
  border-bottom-color: var(--titre);
}

.orga-fleche {
  text-align: center;
  color: var(--accent-clair);
  font-size: 1.4rem;
}

/* ============================================================
   TABLEAUX (rôles tactiques + tables de référence)
   Les tables de tir.html et assaut.html sont générées par js/tables.js à
   partir de tableaux JS (voir TABLE_CC, TABLE_BLESSURE...) : ce
   fichier ne définit que leur apparence.
   ============================================================ */
.table-scroll {
  /* Empêche un tableau large de casser la mise en page sur
     mobile : lui seul défile horizontalement, jamais la page. */
  overflow-x: auto;
  margin: 1rem 0;
  /* -webkit-overflow-scrolling: touch aide encore certains anciens
     navigateurs mobiles à défiler ce conteneur au doigt sans à-coups. */
  -webkit-overflow-scrolling: touch;
}

/* Accessibilité (WCAG 2.1.1 / 2.4.7, RGAA 7.3 / 10.7) : quand la zone
   déborde, js/main.js (majZoneDefilable) lui pose tabindex="0" pour
   qu'on puisse la faire défiler aux flèches du clavier. Il faut alors
   que la prise de focus SE VOIE — sinon l'utilisateur au clavier reçoit
   le focus sur une zone dont rien n'indique qu'elle est sélectionnée, et
   ne devine pas que les flèches vont maintenant défiler le tableau. */
.table-scroll:focus-visible {
  outline: 3px solid var(--acier-clair);
  outline-offset: 2px;
}

table {
  border-collapse: collapse;
  width: 100%;
  font-size: 0.92rem;
  background: var(--carte);
  border-radius: var(--radius);
  overflow: hidden;
}

/* Grandes matrices (CC, Blessure, CT) : la première colonne (l'en-tête de
   ligne) reste figée au défilement horizontal, pour garder le repère
   (ex : "Attaquant CC 8") visible même après avoir fait défiler la table
   vers les colonnes de droite sur un petit écran. */
.table-matrice {
  /* table{overflow:hidden} (règle générique, pour les coins arrondis)
     crée son propre contexte de clipping entre la case et .table-scroll :
     ça empêche "position: sticky" de fonctionner sur th:first-child
     ci-dessous. On accepte de perdre l'arrondi du coin sur ces tables
     pour que la colonne figée fonctionne réellement au défilement. */
  overflow: visible;
}

.table-matrice th:first-child {
  position: sticky;
  left: 0;
  z-index: 2;
  box-shadow: 2px 0 4px rgba(0, 0, 0, 0.15);
}

/* Les cases de ces tables réagissent au tap (voir js/tables.js) :
   curseur adapté et suppression du flash bleu natif d'iOS/Android
   au profit de notre propre surbrillance .case-active. */
.table-matrice td {
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

/* Base mobile : cellules plus hautes pour que l'épinglage au doigt
   (voir js/tables.js) approche les 44px recommandés (WCAG 2.5.8). */
.table-matrice th,
.table-matrice td {
  padding: 0.7rem 0.6rem;
}

@media (min-width: 601px) {
  .table-matrice th,
  .table-matrice td {
    /* À la souris, on peut resserrer pour afficher plus de colonnes. */
    padding: 0.45rem 0.6rem;
  }
}

/* Cellule de coin (voir construireMatrice, js/main.js) : le libellé de
   ligne et celui de colonne sur deux lignes séparées plutôt qu'un
   "Attaquant \ Défenseur" à plat, qui se coupait de façon ambiguë sur
   un écran étroit. */
.table-matrice thead th:first-child {
  font-size: 0.78rem;
  line-height: 1.3;
  text-align: left;
  vertical-align: bottom;
}

.matrice-coin-axe {
  display: block;
  white-space: nowrap;
}

/* Légende « ↓ Lignes · → Colonnes » (voir construireLegendeAxes,
   js/main.js) : répète en toutes lettres, hors de la zone de
   défilement horizontal de la table, l'information de la cellule de
   coin ci-dessus — toujours entièrement visible quelle que soit la
   largeur de l'écran. */
.matrice-legende {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 0.7rem;
  margin: 0.5rem 0 0;
  font-size: 0.85rem;
  color: var(--texte-doux);
}

.matrice-legende-axe {
  font-weight: 700;
  color: var(--titre-contraste);
}

caption {
  caption-side: top;
  text-align: left;
  font-family: "Cinzel", serif;
  /* Accessibilité (WCAG 1.4.3 / RGAA 3.2) : --titre #8a6a2c sur --fond
     #f4f1e8 ne donne que 4,45:1. Le caption fait 1.05rem (16,8 px) sans
     graisse : il ne bénéficie donc PAS de l'assouplissement « texte
     large » (≥ 18,66 px gras ou ≥ 24 px), et doit atteindre 4,5:1.
     --titre-contraste #6b4f1f monte à 6,73:1. Même correction, même
     raison, que sur th plus haut. */
  color: var(--titre-contraste);
  font-size: 1.05rem;
  padding: 0.5rem 0;
}

th,
td {
  border: 1px solid var(--acier);
  padding: 0.45rem 0.6rem;
  text-align: center;
}

th {
  background: var(--fond-secondaire);
  /* Accessibilité (WCAG 1.4.3 / RGAA 3.2) : --titre #8a6a2c sur --fond-secondaire
     #e8e2d0 ne donnait que 3.88:1, insuffisant pour ce texte < 18px.
     --titre-contraste #6b4f1f atteint 5.7:1. */
  color: var(--titre-contraste);
  font-family: "Cinzel", serif;
  font-size: 0.85rem;
}

td.gauche,
th.gauche {
  text-align: left;
}

/* Surbrillance au survol d'une case des tables de référence.
   La LIGNE est surlignée en CSS pur (tr:hover ne coûte rien).
   La COLONNE ne peut pas se faire en CSS seul (il n'existe pas
   de sélecteur "même index de colonne que la case survolée") :
   js/tables.js écoute mouseover/mouseout et ajoute/retire les
   classes .colonne-active et .case-active ci-dessous à la main. */
tbody tr:hover td {
  background: rgba(139, 0, 0, 0.25);
}

td.colonne-active,
th.colonne-active {
  background: rgba(201, 168, 76, 0.18);
}

td.case-active {
  background: var(--accent) !important;
  color: #fff;
  font-weight: 700;
}

/* Valeurs impossibles ( - ) grisées. Voir --texte-attenue (:root) :
   le contraste reste ≥ 4.5:1 même quand la ligne est assombrie par le
   survol (tbody tr:hover ci-dessus). */
td.impossible {
  color: var(--texte-attenue);
}

/* ============================================================
   TABLEAU DE BLESSURE FLOTTANT (toutes les pages sauf index.html,
   choix-legion.html et construction-liste.html — voir activerTableauFlottant
   dans js/main.js)
   .table-flottante est le point d'ancrage position: fixed, déplacé en
   JS (left/top en px) une fois que le bouton a été glissé ; tant
   qu'il ne l'a pas été, right/bottom (ci-dessous) suivent seuls le
   viewport. .table-flottante-panneau est positionné en absolute PAR
   RAPPORT à ce point d'ancrage : il ne participe donc pas à la taille
   du conteneur (offsetWidth/Height utilisés pour le glissement du
   bouton restent ceux du bouton seul, panneau ouvert ou non).
   z-index: 1500 > .nav (1000) pour rester au-dessus de la barre de
   navigation, < .lien-evitement (2000, qui n'apparaît qu'au focus).
   ============================================================ */
.table-flottante {
  position: fixed;
  right: 1rem;
  bottom: 1rem;
  z-index: 1500;
}

.table-flottante-bouton {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 3rem;
  height: 3rem;
  border: none;
  border-radius: 50%;
  background: var(--accent);
  color: #fff;
  font-family: "Cinzel", serif;
  font-size: 1.3rem;
  box-shadow: var(--ombre);
  cursor: grab;
  /* Le geste de glissement est entièrement géré en JS (Pointer
     Events) : on empêche le navigateur d'interpréter le même geste
     tactile comme un défilement/zoom de page. */
  touch-action: none;
  user-select: none;
}

.table-flottante-bouton:hover {
  background: var(--accent-clair);
}

.table-flottante-bouton:active {
  cursor: grabbing;
}

.table-flottante-panneau {
  position: absolute;
  right: 0;
  bottom: calc(100% + 0.6rem);
  width: min(92vw, 380px);
  max-height: min(70vh, 480px);
  overflow-y: auto;
  background: var(--carte);
  border: 1px solid var(--acier);
  border-radius: var(--radius);
  box-shadow: var(--ombre);
  padding: 0.7rem;
}

/* Bascules posées en JS (positionnerPanneau, js/main.js) quand la
   place manque autour du bouton, ex. glissé près d'un bord. */
.table-flottante-panneau--bas {
  bottom: auto;
  top: calc(100% + 0.6rem);
}

.table-flottante-panneau--gauche {
  right: auto;
  left: 0;
}

.table-flottante-entete {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  margin-bottom: 0.4rem;
}

.table-flottante-entete h2 {
  font-family: "Cinzel", serif;
  font-size: 1rem;
  color: var(--titre-contraste);
}

.table-flottante-fermer {
  flex-shrink: 0;
  min-width: 2.2rem;
  min-height: 2.2rem;
  border: none;
  background: none;
  color: var(--texte-doux);
  font-size: 1.4rem;
  line-height: 1;
  cursor: pointer;
  border-radius: var(--radius);
}

.table-flottante-fermer:hover {
  background: var(--fond-secondaire);
  color: var(--texte);
}

/* La table injectée (construireMatrice, js/main.js) réutilise déjà
   .table-scroll/.table-matrice ; on resserre juste sa marge par
   défaut (1rem) qui n'a pas lieu d'être dans ce petit panneau. */
.table-flottante-corps .table-scroll {
  margin: 0;
}

.table-flottante-corps caption {
  font-size: 0.95rem;
  padding-top: 0;
}

/* ============================================================
   ACCORDÉON (Cases Principales)
   Le CSS gère uniquement l'apparence ouverte/fermée via la
   classe .ouvert ; c'est js/main.js qui bascule cette classe au
   clic et calcule la hauteur à ouvrir (voir la note sur
   .accordeon-contenu juste en dessous).
   ============================================================ */
.accordeon {
  border: 1px solid var(--acier);
  border-radius: var(--radius);
  overflow: hidden;
}

.accordeon-item + .accordeon-item {
  border-top: 1px solid var(--acier);
}

/* Accessibilité (WCAG 1.3.1 / RGAA 9.1) : le bouton qui déplie une
   section EST le titre de cette section pour l'œil, mais un <button>
   nu n'apparaît nulle part dans le plan du document — un utilisateur
   de lecteur d'écran qui parcourt la page par les titres (touche H
   sous NVDA/JAWS, le mode de navigation le plus utilisé) ne voyait
   donc AUCUNE de ces sections. On enveloppe donc le bouton dans un
   vrai élément de titre, exactement comme le fait déjà
   `<h2 class="section-titre"><button class="section-toggle">` plus bas
   dans ce fichier — c'est le motif recommandé par l'ARIA Authoring
   Practices Guide pour un accordéon.
   L'enveloppe ne doit RIEN peindre : tout le style (police, fond,
   bordure, taille) reste porté par le bouton lui-même, pour que
   l'ajout de la balise ne déplace pas un seul pixel. D'où la remise à
   zéro des valeurs par défaut du navigateur pour un <h2>/<h3>/<h4>. */
.accordeon-entete,
.timeline-entete {
  margin: 0;
  font-size: inherit;
  font-weight: inherit;
  line-height: inherit;
}

.accordeon-titre {
  width: 100%;
  background: var(--carte);
  color: var(--titre-contraste);
  font-family: "Cinzel", serif;
  font-size: 1rem;
  text-align: left;
  padding: 0.9rem 1.1rem;
  border: none;
  cursor: pointer;
  display: flex;
  justify-content: space-between;
  align-items: center;
  transition: background var(--transition);
}

.accordeon-titre:hover {
  background: var(--carte-hover);
}

.accordeon-titre .chevron {
  transition: transform var(--transition);
  color: var(--accent-clair);
}

.accordeon-item.ouvert .accordeon-titre .chevron {
  transform: rotate(90deg);
}

/* Technique d'ouverture animée sans JS de mise en page :
   height:auto ne peut pas être transitionné en CSS, donc on
   anime max-height à la place. Il faut néanmoins connaître une
   valeur en pixels à atteindre : c'est pour ça que main.js lit
   contenu.scrollHeight (la hauteur réelle du contenu) et l'écrit
   directement en style.maxHeight au moment de l'ouverture. */
.accordeon-contenu {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.35s ease;
  background: var(--fond-secondaire);
}

.accordeon-contenu-inner {
  padding: 1rem 1.2rem;
}

.conseil-debutant {
  margin-top: 0.6rem;
  padding: 0.6rem 0.9rem;
  background: rgba(201, 168, 76, 0.08);
  border-left: 3px solid var(--titre);
  border-radius: 0 var(--radius) var(--radius) 0;
  font-size: 0.92rem;
}

/* ============================================================
   TIMELINE VERTICALE (page tour)
   Même principe d'ouverture/fermeture que l'Accordéon ci-dessus
   (classe .ouvert + animation max-height), rejoué ici avec les
   noms .timeline-item/.timeline-titre/.timeline-details : les
   deux composants partagent la même fonction JS dans main.js.
   ============================================================ */
.timeline {
  position: relative;
  padding-left: 2rem;
}

/* La ligne verticale */
.timeline::before {
  content: "";
  position: absolute;
  left: 0.55rem;
  top: 0;
  bottom: 0;
  width: 3px;
  background: linear-gradient(var(--accent), var(--acier));
}

.timeline-item {
  position: relative;
  margin-bottom: 1rem;
}

/* Le point sur la ligne */
.timeline-item::before {
  content: "";
  position: absolute;
  left: -1.98rem;
  top: 0.85rem;
  width: 14px;
  height: 14px;
  background: var(--fond);
  border: 3px solid var(--titre);
  border-radius: 50%;
}

.timeline-titre {
  width: 100%;
  text-align: left;
  background: var(--carte);
  border: 1px solid var(--acier);
  border-radius: var(--radius);
  color: var(--titre);
  font-family: "Cinzel", serif;
  font-size: 1.05rem;
  padding: 0.8rem 1rem;
  cursor: pointer;
  display: flex;
  justify-content: space-between;
  align-items: center;
  transition: border-color var(--transition);
}

.timeline-titre:hover {
  border-color: var(--titre);
}

/* Mise en avant des sections "Réactions adverses" */
.timeline-titre--reactions {
  background: var(--fond-neutre);
  border: 1px solid var(--acier);
  border-left: 4px solid var(--acier);
  color: var(--acier-clair);
}

.timeline-titre--reactions:hover {
  border-color: var(--acier-clair);
}

.timeline-titre .chevron {
  transition: transform var(--transition);
  color: var(--accent-clair);
}

.timeline-titre--reactions .chevron {
  color: var(--acier-clair);
}

.timeline-item.ouvert .timeline-titre .chevron {
  transform: rotate(90deg);
}

.timeline-details {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.35s ease;
}

.timeline-details-inner {
  padding: 0.9rem 1.1rem;
  background: var(--fond-secondaire);
  border: 1px solid var(--acier);
  border-top: none;
  border-radius: 0 0 var(--radius) var(--radius);
  font-size: 0.95rem;
}

/* ============================================================
   SECTIONS REPLIABLES (pages de détail : assaut, mouvement, tir,
   statuts-reactions, tables)
   Même principe que l'Accordéon/la Timeline ci-dessus : fermées
   par défaut (max-height: 0 tant que la section n'a pas la classe
   .ouvert). C'est main.js qui ajoute cette classe et calcule la
   hauteur en pixels au clic, pour permettre l'animation.
   ============================================================ */
.section-toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  width: 100%;
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}

.section-titre--centre .section-toggle {
  width: auto;
  justify-content: center;
}

.section-titre .chevron {
  transition: transform var(--transition);
  color: var(--accent-clair);
  flex-shrink: 0;
}

section.ouvert > .section-titre .chevron {
  transform: rotate(90deg);
}

.section-corps {
  overflow: hidden;
  transition: max-height 0.35s ease;
}

section:not(.ouvert) > .section-corps {
  max-height: 0;
}

/* Étapes numérotées (séquences de tir, de charge, de résolution...)
   On désactive la numérotation native de <ol> (list-style: none)
   pour dessiner nous-mêmes un rond numéroté via ::before, plus
   proche de la maquette. Le numéro vient d'un compteur CSS :
   counter-reset l'initialise à 0 sur le <ol>, et chaque <li>
   l'incrémente puis l'affiche avec content: counter(etape).
   Attention : counter-reset est posé sur la classe .etapes, donc
   CHAQUE <ol class="etapes"> repart de 1 — deux listes d'étapes
   sur une même page ne se suivent jamais automatiquement (l'attribut
   HTML start="4" n'aurait aucun effet ici, puisque l'affichage
   du numéro dépend du compteur CSS et non de l'ordre natif de <li>). */
.etapes {
  list-style: none;
  margin-left: 0;
  counter-reset: etape;
}

.etapes li {
  counter-increment: etape;
  position: relative;
  padding: 0.55rem 0.8rem 0.55rem 3rem;
  background: var(--carte);
  border: 1px solid var(--acier);
  border-radius: var(--radius);
  margin-bottom: 0.45rem;
}

.etapes li::before {
  content: counter(etape);
  position: absolute;
  left: 0.7rem;
  top: 50%;
  transform: translateY(-50%);
  width: 1.7rem;
  height: 1.7rem;
  /* Accessibilité (WCAG 1.4.3 / RGAA 3.2) : #b5726a sur blanc ne donnait
     que 3.76:1 pour ces numéros < 18.66px. #9c4f47 atteint ~4.7:1. */
  background: #9c4f47;
  color: #fff;
  font-family: "Cinzel", serif;
  font-weight: 700;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.9rem;
}

/* ============================================================
   CARTES DE STATUTS TACTIQUES
   ============================================================ */
.grille-statuts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 1rem;
}

.carte-statut {
  border-radius: var(--radius);
  padding: 1.1rem 1.2rem;
  border: 1px solid var(--acier);
  background: var(--carte);
  border-top: 5px solid var(--acier);
}

.carte-statut h3 {
  font-size: 1.1rem;
  margin-bottom: 0.5rem;
}

.carte-statut ul {
  margin-bottom: 0;
  font-size: 0.93rem;
}

/* Couleur par statut. Le liseré supérieur (border-top) est décoratif :
   il double une information déjà portée par le titre de la carte, donc
   il n'a pas à respecter les 3:1 de WCAG 1.4.11. Le TITRE, lui, est du
   texte : il passe par une variable pour suivre le thème sombre (voir
   --statut-* dans :root). */
.statut-fixe {
  border-top-color: #c9a84c;
}
.statut-fixe h3 {
  color: var(--statut-fixe);
}
.statut-neutralise {
  border-top-color: #4a90d9;
}
.statut-neutralise h3 {
  color: var(--statut-neutralise);
}
.statut-sonne {
  border-top-color: #9b59b6;
}
.statut-sonne h3 {
  color: var(--statut-sonne);
}
.statut-deroute {
  border-top-color: #b22222;
}
.statut-deroute h3 {
  color: var(--statut-deroute);
}

/* ============================================================
   RÉACTIONS (page tour)
   ============================================================ */
.reaction {
  margin-bottom: 1rem;
}

.reaction-nom {
  font-family: "Cinzel", serif;
  font-weight: 700;
  font-size: 1.02rem;
}

/* Couleur du nom selon la phase déclenchante (variables --phase-*,
   voir :root : indispensable pour que le thème sombre puisse les
   éclaircir sans réécrire ces quatre règles). */
.reaction-mouvement .reaction-nom {
  color: var(--phase-mouvement);
}
.reaction-tir .reaction-nom {
  color: var(--phase-tir);
}
.reaction-assaut .reaction-nom {
  color: var(--phase-assaut);
}
.reaction-special .reaction-nom {
  color: var(--phase-special);
}

/* Réactions présentées en cartes (page statuts-reactions) */
.grille-reactions {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 1rem;
  margin-bottom: 1.2rem;
}

.carte-statut.reaction-mouvement {
  border-top-color: #2f7d3a;
}
.carte-statut.reaction-tir {
  border-top-color: #1f5a96;
}
.carte-statut.reaction-assaut {
  border-top-color: #a8551f;
}
.carte-statut.reaction-special {
  border-top-color: #7d3fa0;
}

.badge-phase {
  display: inline-block;
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 1px;
  border: 1px solid var(--acier);
  border-radius: 20px;
  padding: 0.05rem 0.6rem;
  margin-left: 0.5rem;
  color: var(--texte-doux);
  vertical-align: middle;
}

/* ============================================================
   RÈGLES SPÉCIALES (page règles) — recherche + liste
   ============================================================ */
.barre-recherche {
  width: 100%;
  padding: 0.8rem 1.1rem;
  font-size: 1rem;
  font-family: "Lato", sans-serif;
  background: var(--carte);
  /* Accessibilité (WCAG 1.4.11 / RGAA 3.3) : --acier #6b6b85 sur blanc
     ne donnait que 2.9:1 pour la bordure du champ ; --acier-clair
     #45455f atteint 8:1, l'unique repère visuel du champ reste perceptible. */
  border: 2px solid var(--acier-clair);
  border-radius: var(--radius);
  color: var(--texte);
  margin-bottom: 1.2rem;
}

/* Accessibilité (WCAG 2.4.7 / 2.4.11 / RGAA 10.7) : indicateur de focus
   net et contrasté. On remplace l'ancien outline: none (qui ne laissait
   qu'un discret changement de couleur de bordure) par un contour visible. */
.barre-recherche:focus,
.barre-recherche:focus-visible {
  outline: 3px solid var(--acier-clair);
  outline-offset: 2px;
  border-color: var(--titre);
}

/* Focus clavier homogène et bien visible sur TOUS les éléments
   interactifs du site (liens, boutons, cases focalisables). */
a:focus-visible,
button:focus-visible,
[tabindex]:focus-visible {
  outline: 3px solid var(--acier-clair);
  outline-offset: 2px;
}

.compteur-resultats {
  color: var(--texte-doux);
  font-size: 0.9rem;
  margin-bottom: 1rem;
}

/* Clin d'œil : portrait d'Erebus en popup, affiché par js/main.js
   (activerClinDoeilErebus) quand on tape son nom dans une barre de
   recherche du site. Fermable au clic en dehors, via Échap ou en
   effaçant le champ. */
.erebus-popup-overlay {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
  background: rgba(0, 0, 0, 0.6);
}

.erebus-popup-overlay[hidden] {
  display: none;
}

.erebus-popup-image {
  max-width: 320px;
  width: 100%;
  max-height: 80vh;
  object-fit: contain;
  border-radius: var(--radius);
  box-shadow: var(--ombre);
}

/* Clin d'œil : bandeau « Magnus did nothing wrong », affiché par
   js/organigramme.js (activerBandeauMagnus) tant que la Légion active
   de l'Armée est les Thousand Sons (XV). pointer-events: none pour ne
   bloquer aucune interaction sous la barre. */
.magnus-banniere {
  position: fixed;
  left: 0;
  bottom: 0;
  width: 100%;
  margin: 0;
  padding: 0.5rem 1rem;
  background: var(--carte);
  border-top: 1px solid var(--titre);
  color: var(--texte-doux);
  font-style: italic;
  font-size: 0.85rem;
  text-align: center;
  box-shadow: var(--ombre);
  opacity: 0;
  transition: opacity 0.3s ease-in-out;
  pointer-events: none;
  z-index: 999;
}

.magnus-banniere.visible {
  opacity: 1;
}

.regle {
  background: var(--carte);
  border: 1px solid var(--acier);
  border-radius: var(--radius);
  padding: 0.9rem 1.1rem;
  margin-bottom: 0.7rem;
}

.regle h3 {
  font-size: 1.02rem;
  margin-bottom: 0.3rem;
  color: var(--titre-contraste);
}

.regle p {
  margin-bottom: 0;
  font-size: 0.95rem;
}

.regle.cachee {
  display: none;
}

/* ============================================================
   ARSENAL — tables d'armes (page armes.html)
   Généré par js/armes.js : une table par catégorie, filtrée ligne
   par ligne (voir tr.cachee) par la même barre de recherche que
   la page Règles spéciales.
   ============================================================ */
.groupe-armes {
  margin-bottom: 2.2rem;
}

.groupe-armes h3 {
  font-size: 1.2rem;
  color: var(--titre-contraste);
  border-bottom: 1px solid var(--acier);
  padding-bottom: 0.3rem;
  margin-bottom: 0.5rem;
}

.arme-note {
  font-size: 0.85rem;
  color: var(--texte-doux);
  font-style: italic;
  margin-top: 0.4rem;
  margin-bottom: 0;
}

.groupe-armes table tr.cachee {
  display: none;
}

.armes-controles {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem 1.2rem;
  margin-bottom: 1.2rem;
}

.armes-filtre-selection {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.95rem;
  cursor: pointer;
}

.armes-filtre-selection input {
  /* Voir la note « TAILLE DES CIBLES TACTILES » en fin de fichier. */
  width: var(--cible-tactile);
  height: var(--cible-tactile);
  cursor: pointer;
}

.armes-bouton-reset {
  font-family: "Lato", sans-serif;
  font-size: 0.88rem;
  background: var(--carte);
  color: var(--texte-doux);
  border: 1px solid var(--acier);
  border-radius: var(--radius);
  padding: 0.4rem 0.9rem;
  cursor: pointer;
  transition:
    border-color var(--transition),
    color var(--transition);
}

.armes-bouton-reset:hover,
.armes-bouton-reset:focus-visible {
  border-color: var(--titre);
  color: var(--titre-contraste);
}

.col-selection {
  width: 2.2rem;
  text-align: center;
}

.col-selection input[type="checkbox"] {
  /* Voir la note « TAILLE DES CIBLES TACTILES » en fin de fichier. */
  width: var(--cible-tactile);
  height: var(--cible-tactile);
  cursor: pointer;
}

/* ============================================================
   TÉLÉCHARGEMENTS — fiches téléchargeables (page telechargement.html)
   ============================================================ */
.grille-telechargements {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 1rem;
  margin-bottom: 1.2rem;
}

.carte-telechargement {
  display: flex;
  flex-direction: column;
  border-radius: var(--radius);
  padding: 1.1rem 1.2rem;
  border: 1px solid var(--acier);
  background: var(--carte);
  border-top: 5px solid var(--titre);
}

.carte-telechargement h3 {
  font-size: 1.05rem;
  margin-bottom: 0.4rem;
}

.carte-telechargement p {
  font-size: 0.93rem;
  color: var(--texte-doux);
  margin-bottom: 0.9rem;
  flex-grow: 1;
}

.bouton-telecharger {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  background: var(--fond-neutre);
  color: var(--acier-clair);
  font-family: "Lato", sans-serif;
  font-weight: 700;
  font-size: 0.92rem;
  text-decoration: none;
  border-radius: var(--radius);
  padding: 0.55rem 1rem;
  transition: background var(--transition);
}

.bouton-telecharger:hover,
.bouton-telecharger:focus {
  background: var(--fond-neutre-hover);
}

.bouton-telecharger .taille {
  font-weight: 400;
  opacity: 0.85;
}

/* ============================================================
   PIED DE PAGE
   ============================================================ */
footer {
  background: var(--fond-secondaire);
  border-top: 2px solid var(--accent);
  text-align: center;
  padding: 1.4rem 1rem;
  color: var(--texte-doux);
  font-size: 0.85rem;
}

footer p {
  margin: 0.2rem 0;
}

/* ============================================================
   FICHES D'UNITÉS — configurateur (page construction-liste.html)
   Générées par js/unites.js à partir de js/unites-data.js :
   une carte par unité ajoutée (formulaire d'options + fiche
   récap), total général recalculé en direct, et impression
   possible (voir le bloc @media print en fin de section).
   ============================================================ */
.unites-selection {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem 1rem;
  margin-bottom: 1rem;
}

.unites-selection label {
  font-weight: 700;
}

/* Case « Afficher les unités Legacies » (voir initialiserChoixUnite,
   js/unites.js) : même motif que .armes-filtre-selection
   (pages/armes.html), y compris la cible tactile agrandie de la case
   (voir la note « TAILLE DES CIBLES TACTILES » en fin de fichier). Le
   sélecteur .unites-selection label ci-dessus mettrait sinon aussi ce
   libellé en gras comme "Unité à ajouter" : neutralisé ici pour rester
   au poids normal, cohérent avec le filtre de l'Arsenal.
   */
.unites-filtre-legacy {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.95rem;
  font-weight: 400;
  cursor: pointer;
}

.unites-filtre-legacy input {
  width: var(--cible-tactile);
  height: var(--cible-tactile);
  cursor: pointer;
}

/* Combobox « Unité à ajouter » (champ de recherche + liste
   déroulante filtrée, voir initialiserChoixUnite dans js/unites.js) :
   remplace un <select> à <optgroup>, dont le contenu texte n'est pas
   filtrable au clavier. */
.unite-combobox {
  position: relative;
  flex: 1 1 260px;
  max-width: 100%;
}

.unite-combobox-champ {
  width: 100%;
  padding: 0.55rem 2.2rem 0.55rem 0.7rem;
  font-family: "Lato", sans-serif;
  font-size: 0.95rem;
  background: var(--carte);
  color: var(--texte);
  border: 2px solid var(--acier-clair);
  border-radius: var(--radius);
}

.unite-combobox-champ:focus,
.unite-combobox-champ:focus-visible {
  outline: 3px solid var(--acier-clair);
  outline-offset: 2px;
  border-color: var(--titre);
}

/* Tant qu'aucune Légion n'est choisie dans les paramètres de la partie :
   voir actualiserVerrouLegion dans js/unites.js. */
.unite-combobox-champ:disabled,
.unite-combobox-bouton:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

/* Bouton « flèche » : rouvre la liste complète en un clic (ex : après
   un Échap), voir initialiserChoixUnite dans js/unites.js. Le champ
   reste utilisable sans lui (focus, clic, ou simplement taper). */
.unite-combobox-bouton {
  position: absolute;
  top: 2px;
  right: 2px;
  bottom: 2px;
  width: 2.1rem;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: none;
  border-radius: var(--radius);
  color: var(--texte-doux);
  font-size: 1rem;
  cursor: pointer;
}

.unite-combobox-bouton:hover {
  color: var(--titre);
  background: var(--carte-hover);
}

.unite-combobox-liste {
  position: absolute;
  top: calc(100% + 0.3rem);
  left: 0;
  right: 0;
  z-index: 40;
  max-height: 320px;
  overflow-y: auto;
  margin: 0;
  padding: 0.3rem 0;
  list-style: none;
  background: var(--carte);
  border: 1px solid var(--acier);
  border-radius: var(--radius);
  box-shadow: var(--ombre);
}

.unite-combobox-liste[hidden] {
  display: none;
}

/* En-tête de catégorie (Troupe, Élite, Soutien...) : collé en haut de
   la liste pendant le défilement (position: sticky) pour rester lisible
   même au milieu d'une longue catégorie. Repris des couleurs de skin de
   Légion (--accent, --titre) : voir « Skins de Légion » plus bas — sans
   Légion choisie, --accent/--titre gardent leurs teintes par défaut. */
.unite-combobox-groupe {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--fond-secondaire);
  border-left: 3px solid var(--accent);
  border-bottom: 1px solid var(--titre);
}

/* En-tête de catégorie plié/déplié (voir initialiserChoixUnite,
   js/unites.js) : un <button> plutôt qu'un simple <li>, pour rester
   focalisable au clavier (Tab) et déclencher Entrée/Espace nativement.
   Réinitialise entièrement l'apparence par défaut d'un <button> pour
   reprendre exactement la typographie de l'ancien <li>. */
.unite-combobox-groupe-bouton {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  width: 100%;
  padding: 0.45rem 0.9rem;
  border: none;
  background: none;
  font-family: "Cinzel", serif;
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 1.3px;
  color: var(--titre-contraste);
  text-align: left;
  cursor: pointer;
}

.unite-combobox-groupe-bouton:hover,
.unite-combobox-groupe-bouton:focus-visible {
  background: var(--carte-hover);
}

.unite-combobox-groupe-chevron {
  flex: none;
  width: 1em;
  font-size: 0.9em;
  text-align: center;
}

.unite-combobox-option {
  padding: 0.5rem 0.9rem 0.5rem 1.1rem;
  border-left: 3px solid transparent;
  font-size: 0.92rem;
  cursor: pointer;
}

.unite-combobox-option:hover,
.unite-combobox-option.unite-combobox-actif {
  background: var(--carte-hover);
}

/* Unité propre à la Légion actuelle (voir initialiserChoixUnite, qui
   les fait déjà remonter en tête de leur catégorie) : liseré et texte
   dans la couleur de skin de la Légion, pour les repérer d'un coup
   d'œil parmi les unités génériques. */
.unite-combobox-option--legion {
  border-left-color: var(--accent-texte);
  color: var(--titre-contraste);
  font-weight: 700;
}

/* Unité d'une autre Faction que celle de l'Armée (ex : Titans Legio
   Titanicus proposés dans une Armée Legio Astartes, cf. l'exception
   de uniteAccessible dans js/unites.js) : léger fond distinctif pour
   la repérer parmi les unités de la Faction en cours, et son nom de
   Faction affiché en gris à sa suite. */
.unite-combobox-option--autre-faction {
  background: var(--fond-secondaire);
}

.unite-combobox-option--autre-faction:hover,
.unite-combobox-option--autre-faction.unite-combobox-actif {
  background: var(--carte-hover);
}

/* Teinte spécifique à la Légion propriétaire de l'unité (couleur
   d'accent SKINS_LEGION, js/organigramme.js), posée en style inline sur
   `--tinte-legion` par rendre() dans js/unites.js — remplace le fond
   gris neutre ci-dessus pour les unités Legio Astartes d'un Détachement
   Allié. color-mix() dégrade proprement sur les navigateurs qui ne le
   supportent pas : la déclaration entière est alors ignorée et le fond
   gris neutre de --autre-faction (règle précédente) s'applique. */
.unite-combobox-option--teinte-legion {
  background: color-mix(in srgb, var(--tinte-legion) 16%, var(--carte));
  border-left-color: var(--tinte-legion);
}

.unite-combobox-option--teinte-legion:hover,
.unite-combobox-option--teinte-legion.unite-combobox-actif {
  background: color-mix(in srgb, var(--tinte-legion) 30%, var(--carte));
}

.unite-combobox-option-faction {
  margin-left: 0.35rem;
  color: var(--texte-doux);
  font-size: 0.85em;
  font-weight: 400;
}

/* Unité par ailleurs accessible (Faction/Légion/Allégeance) mais sans
   Case libre dans un détachement déjà présent dans l'Armée (voir
   uniteDisponiblePourCases, js/unites.js) : visible pour indiquer que
   l'unité existe, mais non sélectionnable — l'explication (quel
   détachement ajouter) est portée par l'attribut title (info-bulle
   native), sur le même principe que les autres info-bulles ponctuelles
   de ce fichier (ex : bonus d'Avantage sur la fiche récap). */
.unite-combobox-option--indisponible {
  color: var(--texte-doux);
  font-style: italic;
  cursor: not-allowed;
}

.unite-combobox-option--indisponible:hover,
.unite-combobox-option--indisponible.unite-combobox-actif {
  background: transparent;
}

.unite-combobox-vide {
  padding: 0.5rem 0.9rem;
  font-size: 0.9rem;
  color: var(--texte-doux);
}

/* Boutons d'action de la page (ajout, impression, vidage). */
.bouton-principal,
.bouton-secondaire {
  font-family: "Lato", sans-serif;
  font-weight: 700;
  font-size: 0.92rem;
  border-radius: var(--radius);
  padding: 0.55rem 1.1rem;
  cursor: pointer;
  transition:
    background var(--transition),
    border-color var(--transition),
    color var(--transition);
}

.bouton-principal:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

.bouton-principal {
  background: var(--accent);
  color: #fff;
  border: 2px solid var(--accent);
}

.bouton-principal:hover,
.bouton-principal:focus-visible {
  background: var(--accent-clair);
  border-color: var(--accent-clair);
}

.bouton-secondaire {
  background: var(--carte);
  color: var(--texte-doux);
  border: 1px solid var(--acier);
}

.bouton-secondaire:hover,
.bouton-secondaire:focus-visible {
  border-color: var(--titre);
  color: var(--titre-contraste);
}

/* Barre « total + actions » : le total reste lisible d'un coup
   d'œil pendant que l'on configure les unités. */
.unites-barre {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem 1.2rem;
  background: var(--fond-secondaire);
  border: 1px solid var(--acier);
  border-radius: var(--radius);
  padding: 0.7rem 1rem;
  margin-bottom: 1.4rem;
}

.unites-barre p {
  margin: 0;
  font-weight: 700;
  color: var(--titre-contraste);
}

.unites-barre-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
}

/* Petit menu déroulant (Téléchargement PDF/Word, Export/Import) : même
   principe d'ouverture/fermeture que .unite-combobox-liste (bouton qui
   bascule un <ul> masqué par [hidden]), mais en popup ancrée sous un
   bouton plutôt qu'en liste de recherche. */
.menu-deroulant {
  position: relative;
}

.menu-deroulant-bouton {
  font-family: inherit;
}

.menu-deroulant-liste {
  position: absolute;
  z-index: 20;
  top: calc(100% + 0.3rem);
  left: 0;
  min-width: 100%;
  margin: 0;
  padding: 0.3rem;
  list-style: none;
  background: var(--carte);
  border: 1px solid var(--acier);
  border-radius: var(--radius);
  box-shadow: 0 6px 16px rgb(0 0 0 / 0.18);
}

.menu-deroulant-liste[hidden] {
  display: none;
}

.menu-deroulant-option {
  display: block;
  width: 100%;
  padding: 0.45rem 0.9rem;
  border: none;
  border-radius: var(--radius);
  background: none;
  color: var(--texte-doux);
  font-family: "Lato", sans-serif;
  font-weight: 700;
  font-size: 0.92rem;
  text-align: left;
  white-space: nowrap;
  cursor: pointer;
}

.menu-deroulant-option:hover,
.menu-deroulant-option:focus-visible {
  background: var(--fond-secondaire);
  color: var(--titre-contraste);
}

/* ---------- Carte d'unité ---------- */
.unite-carte {
  background: var(--carte);
  border: 1px solid var(--acier);
  border-top: 5px solid var(--titre);
  border-radius: var(--radius);
  padding: 1.1rem 1.2rem;
  margin-bottom: 1.4rem;
  box-shadow: var(--ombre);
}

.unite-carte-entete {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 1rem;
  margin-bottom: 0.3rem;
}

.unite-carte-entete h3 {
  font-size: 1.25rem;
  color: var(--titre-contraste);
  flex-grow: 1;
}

/* Badge de coût : mis à jour en direct par js/unites.js. */
.unite-points {
  background: var(--accent);
  color: #fff;
  font-weight: 700;
  font-size: 0.95rem;
  border-radius: var(--radius);
  padding: 0.25rem 0.75rem;
  white-space: nowrap;
}

.unite-retirer {
  font-family: "Lato", sans-serif;
  font-size: 0.85rem;
  background: var(--carte);
  color: var(--texte-doux);
  border: 1px solid var(--acier);
  border-radius: var(--radius);
  padding: 0.3rem 0.8rem;
  cursor: pointer;
  transition:
    border-color var(--transition),
    color var(--transition);
}

.unite-retirer:hover,
.unite-retirer:focus-visible {
  border-color: var(--accent-texte);
  color: var(--accent-texte);
}

/* Repli/dépli d'une fiche (voir construireCarte dans js/unites.js) :
   même gabarit que .unite-retirer, mais colorée comme un bouton
   secondaire pour signaler une action de confort plutôt que de
   suppression. */
.unite-bascule {
  font-family: "Lato", sans-serif;
  font-size: 0.85rem;
  font-weight: 700;
  background: var(--carte);
  color: var(--titre-contraste);
  border: 1px solid var(--acier);
  border-radius: var(--radius);
  padding: 0.3rem 0.8rem;
  cursor: pointer;
  transition:
    border-color var(--transition),
    color var(--transition);
}

.unite-bascule:hover,
.unite-bascule:focus-visible {
  border-color: var(--accent-texte);
  color: var(--accent-texte);
}

/* Fiche repliée : seul l'en-tête (nom, coût, boutons) reste visible
   à l'écran. Toujours dépliée à l'impression (voir @media print
   plus bas), où la fiche récap est le contenu recherché. */
.unite-carte--repliee .unite-composition,
.unite-carte--repliee .unite-affectation,
.unite-carte--repliee .unite-config,
.unite-carte--repliee .unite-fiche {
  display: none;
}

.unite-composition {
  font-size: 0.88rem;
  color: var(--texte-doux);
  font-style: italic;
  margin-bottom: 0.8rem;
}

/* ---------- Formulaire de configuration ---------- */
.unite-config fieldset {
  border: 1px dashed var(--acier);
  border-radius: var(--radius);
  padding: 0.7rem 0.9rem;
  margin-bottom: 0.9rem;
}

.unite-config legend {
  font-weight: 700;
  color: var(--titre-contraste);
  padding: 0 0.4rem;
}

.option-ligne {
  display: block;
  margin: 0.45rem 0;
  font-size: 0.93rem;
}

.option-ligne label {
  display: block;
  margin-bottom: 0.2rem;
}

.option-ligne select {
  width: 100%;
  max-width: 34rem;
  padding: 0.4rem 0.6rem;
  font-family: "Lato", sans-serif;
  font-size: 0.9rem;
  background: var(--carte);
  color: var(--texte);
  border: 1px solid var(--acier-clair);
  border-radius: var(--radius);
}

/* Champ grisé = option impossible dans la configuration actuelle
   (ex : baïonnette alors que le bolter a été remplacé). */
.unite-config select:disabled,
.unite-config input:disabled,
.unite-config input:disabled + * {
  opacity: 0.45;
  cursor: not-allowed;
}

.option-multi-titre {
  font-weight: 700;
  margin-bottom: 0.2rem;
}

.option-multi-case {
  display: block;
  margin: 0.25rem 0 0.25rem 1rem;
}

/* Champs numériques (effectif d'escouade, échanges « par tranche
   de cinq figurines ») : compacts, alignés sous leur libellé. */
.unite-config input[type="number"] {
  width: 5.5rem;
  padding: 0.35rem 0.5rem;
  font-family: "Lato", sans-serif;
  font-size: 0.9rem;
  background: var(--carte);
  color: var(--texte);
  border: 1px solid var(--acier-clair);
  border-radius: var(--radius);
}

.unite-config input[type="checkbox"],
.unite-config input[type="radio"] {
  /* Voir la note « TAILLE DES CIBLES TACTILES » en fin de fichier. */
  width: var(--cible-tactile);
  height: var(--cible-tactile);
  cursor: pointer;
  /* Recalé sur la ligne de base du texte du libellé : la case ayant
     grandi, l'ancien -0.15rem la faisait flotter au-dessus du mot. */
  vertical-align: -0.35rem;
}

/* ---------- Fiche récap ---------- */
.unite-fiche {
  border-top: 1px solid var(--acier);
  padding-top: 0.7rem;
}

.unite-fiche .table-scroll {
  margin: 0.4rem 0 0.4rem;
}

/* Indice de défilement horizontal (voir construireIndiceDefilement,
   js/unites.js) : signale qu'il reste des colonnes à droite (ex : la
   colonne « Règles spéciales ») quand la table déborde de l'écran, la
   barre de défilement native étant invisible sur mobile tant qu'on ne
   touche pas l'écran. Masqué dès qu'il y a la place de tout afficher
   sans défiler. */
.table-scroll-indice {
  margin: -0.15rem 0 0.8rem;
  font-size: 0.75rem;
  color: var(--texte-doux);
  text-align: right;
}

@media (min-width: 601px) {
  .table-scroll-indice {
    display: none;
  }
}

.table-profil th,
.table-profil td {
  padding: 0.45rem 0.55rem;
  text-align: center;
  border: 1px solid var(--fond-secondaire);
}

.table-profil th {
  background: var(--fond-secondaire);
  color: var(--titre-contraste);
}

/* Caractéristique modifiée par un Avantage Principal (Maître-sergent,
   Vétérans de Combat, Parangon de Bataille — voir js/unites.js). */
.table-profil td.profil-bonus {
  font-weight: 700;
  color: var(--accent-clair);
}

.fiche-ligne {
  font-size: 0.93rem;
  margin-bottom: 0.35rem;
}

/* Bloc « Définitions » : reprend en texte visible la définition de
   chaque règle spéciale / trait de la fiche (voir construireDefinitions
   dans js/unites.js). Masqué à l'écran, où l'info-bulle (.regle-tag /
   .tooltip) suffit ; réservé à l'impression, qui ne peut pas montrer
   un contenu révélé au survol — voir @media print ci-dessous. */
.unite-fiche-definitions {
  display: none;
  margin-top: 0.6rem;
  padding-top: 0.5rem;
  border-top: 1px dashed var(--acier);
}

.unite-definitions-titre {
  font-weight: 700;
  font-size: 0.85rem;
  margin-bottom: 0.3rem;
}

.unite-fiche-definitions ul {
  margin: 0;
  padding-left: 1.1rem;
}

.unite-fiche-definitions li {
  font-size: 0.82rem;
  line-height: 1.4;
  margin-bottom: 0.25rem;
}

/* ---------- Impression de la fiche récap ----------
   À l'impression (bouton « Imprimer » ou Ctrl+P), on ne garde
   que l'essentiel : les fiches et le total. La navigation, les
   formulaires de configuration et les boutons disparaissent. */
@media print {
  .nav,
  footer,
  .encadre,
  .lien-evitement,
  .unites-selection,
  .unites-barre-actions,
  .unite-config,
  .unite-retirer,
  .unite-bascule,
  .fiche-ligne--notes {
    display: none !important;
  }

  body {
    background: #fff;
  }

  .unites-barre {
    border: none;
    padding: 0;
  }

  .unite-carte {
    box-shadow: none;
    border: 1px solid #000;
    break-inside: avoid;
    margin-bottom: 0.8rem;
  }

  /* Une fiche repliée à l'écran reste entièrement visible sur
     l'impression : c'est justement le contenu recherché. */
  .unite-carte--repliee .unite-composition,
  .unite-carte--repliee .unite-fiche {
    display: block;
  }

  .unite-fiche-definitions {
    display: block;
  }
}

/* ============================================================
   ASSISTANT DE SÉLECTION D'ARMÉE (page construction-liste.html)
   Organigramme de Force, badges de Rôles Tactiques, jauge de
   points, validation et résumé — voir js/organigramme.js.
   ============================================================ */

/* ---------- Paramètres de la partie ---------- */
.orga-parametres {
  display: flex;
  flex-wrap: wrap;
  gap: 0.8rem 2rem;
  align-items: center;
  background: var(--carte);
  border: 1px solid var(--acier);
  border-radius: var(--radius);
  padding: 0.8rem 1rem;
  margin-bottom: 1rem;
}

/* Empilé (label au-dessus du champ) par défaut sur mobile : un <select>
   flex-item posé À CÔTÉ de son label ne se rétrécit jamais de façon
   fiable sous la largeur de sa plus longue option une fois le label
   lui-même réduit à son mot le plus long (vécu avec « Désignation de
   Legiones Auxilia », dont les options dépassent 35 caractères — le
   label se compressait mot par mot mais le <select> gardait sa largeur
   intrinsèque et débordait du cadre/de l'écran). Empiler élimine le
   partage de largeur entre label et champ : le champ reçoit toute la
   largeur disponible de la carte pour se rétrécir. Repasse en ligne
   (label + champ côte à côte) à partir de 601px, où la carte est assez
   large pour ne plus poser ce problème. */
.orga-parametre {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.3rem;
  width: 100%;
  min-width: 0;
  max-width: 100%;
}

.orga-parametres label {
  font-weight: 700;
}

.orga-parametres input,
.orga-parametres select {
  padding: 0.3rem 0.5rem;
  border: 1px solid var(--acier);
  border-radius: var(--radius);
  background: var(--fond);
  color: var(--texte);
  font: inherit;
  min-width: 0;
  max-width: 100%;
  width: 100%;
}

.orga-parametres input {
  width: 6.5rem;
}

@media (min-width: 601px) {
  .orga-parametre {
    flex-direction: row;
    align-items: center;
    width: auto;
  }

  .orga-parametres select {
    width: auto;
  }
}

/* ---------- Bandeau de contexte historique (skin de Légion) ---------- */
.legion-banniere {
  margin: -0.4rem 0 1rem;
  padding: 0.6rem 1rem;
  border: 1px solid var(--titre);
  border-left: 6px solid var(--accent);
  border-radius: var(--radius);
  background: var(--carte);
  color: var(--texte-doux);
  font-size: 0.95rem;
}

.legion-banniere strong {
  font-family: "Cinzel", serif;
  color: var(--accent-texte);
}

.legion-banniere em {
  display: block;
  margin-top: 0.25rem;
  font-style: italic;
  color: var(--texte-doux);
}

/* ---------- Skins de Légion ----------
   Posés sur <body> par js/organigramme.js (construireParametres) selon
   la Légion choisie dans les paramètres de la partie. Chaque skin
   recolore les variables CSS déjà utilisées partout (--accent,
   --accent-clair, --fond-secondaire, --carte-hover) : boutons,
   bordures, badges, jauge… s'adaptent sans règle par composant. Les
   règles partagées ci-dessous (double filet, liserés…) s'appliquent à
   N'IMPORTE QUEL skin-legion-* posé sur <body>, pour ne pas dupliquer
   la mise en forme à chaque nouvelle Légion.
   --titre/--titre-contraste (or) restent VOLONTAIREMENT inchangés
   pour toutes les Légions : leur contraste WCAG (~4.3:1 / ~7:1 sur
   --fond) est calibré pour le thème par défaut, et l'or sert de
   liseré héraldique commun à toutes les livrées. */

/* Blason de Légion : <img> posé par js/organigramme.js
   (creerIconeLegion), pointant vers assets/logo_legions/*.png (une
   bannière héraldique déjà en couleur par Légion — contrairement à
   l'ancien sprite ligne, elle ne suit pas --accent). Bannière haute et
   étroite (ratio ~0.53) : on fixe la hauteur et on laisse la largeur
   s'adapter, plutôt qu'un carré fixe. */
.legion-icon {
  height: 1.8rem;
  width: auto;
  flex: 0 0 auto;
}

/* Version agrandie posée devant le titre de page (h1.titre-page). */
.legion-icon--titre {
  height: 2.2em;
  width: auto;
  margin-right: 0.5rem;
  vertical-align: -0.6em;
  filter: drop-shadow(0 0 3px rgba(0, 0, 0, 0.35));
}

/* Second blason Legio Titanicus, posé APRÈS le titre plutôt qu'avant
   (voir construireParametres dans js/organigramme.js — seule cette
   Faction en pose deux, faute d'un sélecteur de Légion Titanicus). */
.legion-icon--titre-droite {
  margin-right: 0;
  margin-left: 0.5rem;
}

/* Bandeau de contexte : blason + nom de Légion alignés (voir
   .legion-banniere strong dans js/organigramme.js). */
.legion-item {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  vertical-align: middle;
}

/* Double filet (accent + or) sous les titres de section : évoque les
   liserés d'héraldique de Légion plutôt qu'un simple trait plein. */
body[class*="skin-legion-"] .section-titre {
  border-bottom: 3px solid var(--accent);
  box-shadow: 0 3px 0 0 var(--titre);
  margin-bottom: 1.4rem;
}

/* Cartes et encadrés : liseré d'or en tête, dans l'esprit d'une
   bordure d'autel ou d'un parchemin de croisade illuminé (.unite-carte
   porte déjà ce liseré par défaut, voir plus bas). */
body[class*="skin-legion-"] .orga-parametres,
body[class*="skin-legion-"] .orga-resume {
  border-top: 3px solid var(--titre);
}

body[class*="skin-legion-"] .encadre {
  border-left-color: var(--accent-texte);
}

/* Badges de Rôles Tactiques : liseré d'or plutôt que gris-acier. */
body[class*="skin-legion-"] .orga-badge {
  border-color: var(--titre);
}

/* Bouton principal : corps de la couleur de Légion, liseré d'or (au
   lieu du même ton en double), comme une pièce d'armure héraldique. */
body[class*="skin-legion-"] .bouton-principal {
  border-color: var(--titre);
}

body[class*="skin-legion-"] .bouton-principal:hover,
body[class*="skin-legion-"] .bouton-principal:focus-visible {
  border-color: var(--titre-contraste);
}

/* IX — Blood Angels (Primarque Sanguinius, monde natal Baal) : rouge
   sang à liserés d'or, vignette évoquant les soleils jumeaux de Baal. */
body.skin-legion-ix {
  --accent: #7a0c0c;
  --accent-clair: #b3281c;
  --fond-secondaire: #ecd9c9;
  --carte-hover: #f5e6da;
  background-image:
    radial-gradient(circle at 20% 0%, #ffffff 0%, var(--fond) 60%),
    radial-gradient(
      circle at 100% 100%,
      rgba(122, 12, 12, 0.1) 0%,
      transparent 55%
    ),
    radial-gradient(
      circle at 0% 100%,
      rgba(184, 150, 47, 0.08) 0%,
      transparent 50%
    );
}

/* IV — Iron Warriors (Primarque Perturabo, monde natal Olympia) :
   gris fer, blason en double chevron (marques de siège). */
body.skin-legion-iv {
  --accent: #4a4a4a;
  --accent-clair: #5f5f5f;
  --fond-secondaire: #e6e2d8;
  --carte-hover: #efece4;
  background-image:
    radial-gradient(circle at 20% 0%, #ffffff 0%, var(--fond) 60%),
    radial-gradient(
      circle at 100% 100%,
      rgba(74, 74, 74, 0.12) 0%,
      transparent 55%
    ),
    radial-gradient(
      circle at 0% 100%,
      rgba(184, 150, 47, 0.08) 0%,
      transparent 50%
    );
}

/* VIII — Night Lords (Primarque Konrad Curze, monde natal Nostramo) :
   noir nocturne, blason à la silhouette anguleuse (terreur nocturne). */
body.skin-legion-viii {
  --accent: #10151f;
  --accent-clair: #2b3550;
  --fond-secondaire: #dfe1e8;
  --carte-hover: #eceef2;
  background-image:
    radial-gradient(circle at 20% 0%, #ffffff 0%, var(--fond) 60%),
    radial-gradient(
      circle at 100% 100%,
      rgba(16, 21, 31, 0.14) 0%,
      transparent 55%
    ),
    radial-gradient(
      circle at 0% 100%,
      rgba(138, 143, 156, 0.1) 0%,
      transparent 50%
    );
}

/* V — White Scars (Primarque Jaghatai Khan, monde natal Chogoris) :
   rouge vermillon, blason en éclair (vitesse, charge à moto). */
body.skin-legion-v {
  --accent: #a3341c;
  --accent-clair: #b8481f;
  --fond-secondaire: #f0e9df;
  --carte-hover: #f7f1e7;
  background-image:
    radial-gradient(circle at 20% 0%, #ffffff 0%, var(--fond) 60%),
    radial-gradient(
      circle at 100% 100%,
      rgba(163, 52, 28, 0.1) 0%,
      transparent 55%
    ),
    radial-gradient(
      circle at 0% 100%,
      rgba(184, 150, 47, 0.08) 0%,
      transparent 50%
    );
}

/* XII — World Eaters (Primarque Angron) : brun-rouille et bronze,
   blason en masque de rage (Clous du Boucher, fureur au combat). */
body.skin-legion-xii {
  --accent: #8a3a12;
  --accent-clair: #a04a19;
  --fond-secondaire: #ecdfd0;
  --carte-hover: #f3e8da;
  background-image:
    radial-gradient(circle at 20% 0%, #ffffff 0%, var(--fond) 60%),
    radial-gradient(
      circle at 100% 100%,
      rgba(138, 58, 18, 0.12) 0%,
      transparent 55%
    ),
    radial-gradient(
      circle at 0% 100%,
      rgba(184, 150, 47, 0.08) 0%,
      transparent 50%
    );
}

/* XIX — Raven Guard (Primarque Corvus Corax, monde natal Deliverance) :
   noir mat, blason en silhouette ailée (guerre furtive et embuscades). */
body.skin-legion-xix {
  --accent: #1c1c22;
  --accent-clair: #3a3a46;
  --fond-secondaire: #e2e2e6;
  --carte-hover: #ececef;
  background-image:
    radial-gradient(circle at 20% 0%, #ffffff 0%, var(--fond) 60%),
    radial-gradient(
      circle at 100% 100%,
      rgba(28, 28, 34, 0.12) 0%,
      transparent 55%
    ),
    radial-gradient(
      circle at 0% 100%,
      rgba(184, 150, 47, 0.08) 0%,
      transparent 50%
    );
}

/* I — Dark Angels (Primarque Lion El'Jonson, monde natal Caliban) :
   vert forêt, blason en épée stylisée (ordres chevaleresques, secrets). */
body.skin-legion-i {
  --accent: #1f3a24;
  --accent-clair: #2f5a38;
  --fond-secondaire: #dde5dc;
  --carte-hover: #e8eee7;
  background-image:
    radial-gradient(circle at 20% 0%, #ffffff 0%, var(--fond) 60%),
    radial-gradient(
      circle at 100% 100%,
      rgba(31, 58, 36, 0.12) 0%,
      transparent 55%
    ),
    radial-gradient(
      circle at 0% 100%,
      rgba(184, 150, 47, 0.08) 0%,
      transparent 50%
    );
}

/* III — Emperor's Children (Primarque Fulgrim, monde natal Chemos) :
   pourpre profond, blason en triade géométrique (quête de perfection). */
body.skin-legion-iii {
  --accent: #4a1a5c;
  --accent-clair: #6b2b82;
  --fond-secondaire: #e8dfe8;
  --carte-hover: #f0e9f0;
  background-image:
    radial-gradient(circle at 20% 0%, #ffffff 0%, var(--fond) 60%),
    radial-gradient(
      circle at 100% 100%,
      rgba(74, 26, 92, 0.1) 0%,
      transparent 55%
    ),
    radial-gradient(
      circle at 0% 100%,
      rgba(184, 150, 47, 0.08) 0%,
      transparent 50%
    );
}

/* VI — Space Wolves (Primarque Leman Russ, monde natal Fenris) :
   gris-bleu acier, blason en tête de loup stylisée (chasse en meute). */
body.skin-legion-vi {
  --accent: #33454e;
  --accent-clair: #4a626e;
  --fond-secondaire: #dde6ea;
  --carte-hover: #e8eff2;
  background-image:
    radial-gradient(circle at 20% 0%, #ffffff 0%, var(--fond) 60%),
    radial-gradient(
      circle at 100% 100%,
      rgba(51, 69, 78, 0.12) 0%,
      transparent 55%
    ),
    radial-gradient(
      circle at 0% 100%,
      rgba(184, 150, 47, 0.08) 0%,
      transparent 50%
    );
}

/* VII — Imperial Fists (Primarque Rogal Dorn, monde natal Terra/Inwit) :
   teinte calée sur le jaune du blason (assets/logo_legions/imperial_fists.png,
   dominante #e9ac2d, ~40° de teinte) déclinée en plus foncé pour --accent
   (texte blanc de .bouton-principal, ~5.5:1) et plus clair pour
   --accent-clair (survol, ~3.7:1), blason en muraille crénelée
   (défense inébranlable). */
body.skin-legion-vii {
  --accent: #76520a;
  --accent-clair: #97690c;
  --fond-secondaire: #eee0c4;
  --carte-hover: #f4ead7;
  background-image:
    radial-gradient(circle at 20% 0%, #ffffff 0%, var(--fond) 60%),
    radial-gradient(
      circle at 100% 100%,
      rgba(118, 82, 10, 0.12) 0%,
      transparent 55%
    ),
    radial-gradient(
      circle at 0% 100%,
      rgba(233, 172, 45, 0.1) 0%,
      transparent 50%
    );
}

/* X — Iron Hands (Primarque Ferrus Manus, monde natal Medusa) :
   noir-rouille, blason en rouage mécanique (culte de la Machine). */
body.skin-legion-x {
  --accent: #2a1414;
  --accent-clair: #4a2020;
  --fond-secondaire: #e0dcdc;
  --carte-hover: #e8e4e4;
  background-image:
    radial-gradient(circle at 20% 0%, #ffffff 0%, var(--fond) 60%),
    radial-gradient(
      circle at 100% 100%,
      rgba(42, 20, 20, 0.12) 0%,
      transparent 55%
    ),
    radial-gradient(
      circle at 0% 100%,
      rgba(184, 150, 47, 0.08) 0%,
      transparent 50%
    );
}

/* XIII — Ultramarines (Primarque Roboute Guilliman, monde natal
   Macragge) : bleu roi, blason en arc stylisé (discipline, Codex Astartes). */
body.skin-legion-xiii {
  --accent: #1c3a6e;
  --accent-clair: #2f5490;
  --fond-secondaire: #dde3ee;
  --carte-hover: #e8ecf4;
  background-image:
    radial-gradient(circle at 20% 0%, #ffffff 0%, var(--fond) 60%),
    radial-gradient(
      circle at 100% 100%,
      rgba(28, 58, 110, 0.1) 0%,
      transparent 55%
    ),
    radial-gradient(
      circle at 0% 100%,
      rgba(184, 150, 47, 0.08) 0%,
      transparent 50%
    );
}

/* XIV — Death Guard (Primarque Mortarion, monde natal Barbarus) :
   vert marécage, blason en cloche stylisée (endurance et longue patience). */
body.skin-legion-xiv {
  --accent: #3a4a2e;
  --accent-clair: #52683f;
  --fond-secondaire: #e2e6d8;
  --carte-hover: #eaeee2;
  background-image:
    radial-gradient(circle at 20% 0%, #ffffff 0%, var(--fond) 60%),
    radial-gradient(
      circle at 100% 100%,
      rgba(58, 74, 46, 0.12) 0%,
      transparent 55%
    ),
    radial-gradient(
      circle at 0% 100%,
      rgba(184, 150, 47, 0.08) 0%,
      transparent 50%
    );
}

/* XV — Thousand Sons (Primarque Magnus le Rouge, monde natal
   Prospero) : bleu cobalt, blason en œil (sorcellerie et savoir). */
body.skin-legion-xv {
  --accent: #1c2f5c;
  --accent-clair: #2f4a82;
  --fond-secondaire: #e0dfee;
  --carte-hover: #e8e7f4;
  background-image:
    radial-gradient(circle at 20% 0%, #ffffff 0%, var(--fond) 60%),
    radial-gradient(
      circle at 100% 100%,
      rgba(28, 47, 92, 0.12) 0%,
      transparent 55%
    ),
    radial-gradient(
      circle at 0% 100%,
      rgba(184, 150, 47, 0.08) 0%,
      transparent 50%
    );
}

/* XVI — Sons of Horus (Primarque Horus Lupercal, monde natal
   Cthonia) : bronze sombre, blason en œil stylisé (le Warmaster). */
body.skin-legion-xvi {
  --accent: #3a3020;
  --accent-clair: #5c4c30;
  --fond-secondaire: #e6ddc9;
  --carte-hover: #efe8d8;
  background-image:
    radial-gradient(circle at 20% 0%, #ffffff 0%, var(--fond) 60%),
    radial-gradient(
      circle at 100% 100%,
      rgba(58, 48, 32, 0.12) 0%,
      transparent 55%
    ),
    radial-gradient(
      circle at 0% 100%,
      rgba(184, 150, 47, 0.08) 0%,
      transparent 50%
    );
}

/* XVII — Word Bearers (Primarque Lorgar, monde natal Colchis) :
   marron profond, blason en livre ouvert (Écritures de Colchis, zèle). */
body.skin-legion-xvii {
  --accent: #4a1c1c;
  --accent-clair: #6b2e2e;
  --fond-secondaire: #ecdcd6;
  --carte-hover: #f2e6e1;
  background-image:
    radial-gradient(circle at 20% 0%, #ffffff 0%, var(--fond) 60%),
    radial-gradient(
      circle at 100% 100%,
      rgba(74, 28, 28, 0.12) 0%,
      transparent 55%
    ),
    radial-gradient(
      circle at 0% 100%,
      rgba(184, 150, 47, 0.08) 0%,
      transparent 50%
    );
}

/* XVIII — Salamanders (Primarque Vulkan, monde natal Nocturne) :
   vert bronze, blason en flamme stylisée (forge de Nocturne). */
body.skin-legion-xviii {
  --accent: #2a3a24;
  --accent-clair: #435c37;
  --fond-secondaire: #e6e0cf;
  --carte-hover: #efe9dc;
  background-image:
    radial-gradient(circle at 20% 0%, #ffffff 0%, var(--fond) 60%),
    radial-gradient(
      circle at 100% 100%,
      rgba(42, 58, 36, 0.12) 0%,
      transparent 55%
    ),
    radial-gradient(
      circle at 0% 100%,
      rgba(184, 150, 47, 0.08) 0%,
      transparent 50%
    );
}

/* XX — Alpha Legion (Primarques Alpharius et Omegon, monde natal
   inconnu) : sarcelle sombre, blason en « A » stylisé (infiltration, ruse). */
body.skin-legion-xx {
  --accent: #123a3c;
  --accent-clair: #1f5a5c;
  --fond-secondaire: #d8e6e6;
  --carte-hover: #e2eeee;
  background-image:
    radial-gradient(circle at 20% 0%, #ffffff 0%, var(--fond) 60%),
    radial-gradient(
      circle at 100% 100%,
      rgba(18, 58, 60, 0.12) 0%,
      transparent 55%
    ),
    radial-gradient(
      circle at 0% 100%,
      rgba(184, 150, 47, 0.08) 0%,
      transparent 50%
    );
}

/* Legio Titanicus (Faction, livre d'armée Legio Titanicus) : skin
   commun à toute la Faction plutôt qu'à une Légion précise (voir
   SKIN_TITANICUS dans js/organigramme.js — pas de subdivision en
   Légions Titanicus dans ce site) — dans l'esprit héraldique « Legio
   Ignatum » (rouge sombre et or, quasi-noir plutôt que le bronze
   rustique des skins de Légion), sans jamais quitter le fond clair
   parchemin partagé par tout le site (--fond/--carte/--titre restent
   volontairement inchangés, comme pour toute Légion — voir plus haut).
   Le très léger quadrillage diagonal du background-image (dernière
   couche, 1.5 % d'opacité) évoque le métal brossé/les damiers de
   blindage sans jamais concurrencer le texte. Le bandeau de contexte
   (.legion-banniere ci-dessus) reçoit en plus un liseré gauche à
   bandes obliques rouge/noir façon marquage de danger — voir plus bas. */
body.skin-legion-titanicus {
  --accent: #6e1410;
  --accent-clair: #93211a;
  --fond-secondaire: #f0e1d5;
  --carte-hover: #f7ece4;
  background-image:
    radial-gradient(circle at 20% 0%, #ffffff 0%, var(--fond) 60%),
    radial-gradient(
      circle at 100% 100%,
      rgba(110, 20, 16, 0.12) 0%,
      transparent 55%
    ),
    radial-gradient(
      circle at 0% 100%,
      rgba(184, 150, 47, 0.08) 0%,
      transparent 50%
    ),
    repeating-linear-gradient(
      135deg,
      rgba(0, 0, 0, 0.015) 0 12px,
      transparent 12px 24px
    );
}

/* Liseré à bandes obliques rouge/noir (marquage de danger, cf. les
   bandes jaune/noir des blindages Titanicus) remplaçant, pour ce skin
   uniquement, le liseré plein de .legion-banniere : la bordure gauche
   est mise à blanc (elle sert juste à réserver l'espace) et un ::before
   à fond rayé vient se caler dedans, rogné par overflow: hidden pour
   suivre l'arrondi de la carte. */
body.skin-legion-titanicus .legion-banniere {
  position: relative;
  overflow: hidden;
  border-left-width: 10px;
  border-left-color: transparent;
}

body.skin-legion-titanicus .legion-banniere::before {
  content: "";
  position: absolute;
  top: -1px;
  bottom: -1px;
  left: -1px;
  width: 10px;
  background: repeating-linear-gradient(
    -45deg,
    var(--accent) 0 7px,
    #1c1a16 7px 14px
  );
}

/* Petit rouage décoratif à la suite du nom de Faction dans le bandeau
   (voir construireParametres dans js/organigramme.js — partagé par les
   skins Legio Titanicus et Mechanicum, chacun avec ses deux blasons
   propres) : posé en aria-hidden côté JS, comme toute icône purement
   décorative de ce site. */
.legion-titan-cog {
  margin-left: 0.4rem;
  color: var(--titre);
}

/* Maisonnées Questoris (Faction Chevaliers Questoris, livre d'armée
   Chevaliers Questoris) : même mécanique que les skins de Légion
   ci-dessus (voir SKINS_MAISONNEE dans js/organigramme.js), rattachée
   à etat.maisonnee plutôt qu'à etat.legion. Trois teintes distinctes
   des Légions et de Legio Titanicus déjà utilisées : or antique
   (Imperialis, héraldique impériale), rouille du Mechanicum
   (Mechanicum, Monde-Forge) et gris-brun passé (Mendicus, Maisonnées
   errantes sans couleurs propres). */
body.skin-legion-questoris-imperialis {
  --accent: #8a6a2c;
  /* Accessibilité (WCAG 1.4.3 / RGAA 3.2) : l'ancien #b08f3f ne donnait
     que 3,07:1 avec le texte blanc de .bouton-principal au survol —
     le bouton devenait le point le moins lisible de la page au moment
     précis où l'utilisateur le vise. #8f7128 garde l'or antique de la
     Maisonnée Imperialis en atteignant 4,6:1. */
  --accent-clair: #8f7128;
  --fond-secondaire: #eee6d5;
  --carte-hover: #f5efe0;
  background-image:
    radial-gradient(circle at 20% 0%, #ffffff 0%, var(--fond) 60%),
    radial-gradient(
      circle at 100% 100%,
      rgba(138, 106, 44, 0.12) 0%,
      transparent 55%
    ),
    radial-gradient(
      circle at 0% 100%,
      rgba(184, 150, 47, 0.08) 0%,
      transparent 50%
    );
}

body.skin-legion-questoris-mechanicum {
  --accent: #8a2a1a;
  --accent-clair: #b5432a;
  --fond-secondaire: #ecdbd5;
  --carte-hover: #f3e6e1;
  background-image:
    radial-gradient(circle at 20% 0%, #ffffff 0%, var(--fond) 60%),
    radial-gradient(
      circle at 100% 100%,
      rgba(138, 42, 26, 0.12) 0%,
      transparent 55%
    ),
    radial-gradient(
      circle at 0% 100%,
      rgba(184, 150, 47, 0.08) 0%,
      transparent 50%
    );
}

body.skin-legion-questoris-mendicus {
  --accent: #5a5548;
  /* Même correction que la Maisonnée Imperialis ci-dessus : #7d7768
     plafonnait à 4,46:1 sous le texte blanc du bouton au survol, juste
     sous le seuil. #6e685b atteint 5,53:1 sans changer la teinte. */
  --accent-clair: #6e685b;
  --fond-secondaire: #e6e3da;
  --carte-hover: #efece5;
  background-image:
    radial-gradient(circle at 20% 0%, #ffffff 0%, var(--fond) 60%),
    radial-gradient(
      circle at 100% 100%,
      rgba(90, 85, 72, 0.12) 0%,
      transparent 55%
    ),
    radial-gradient(
      circle at 0% 100%,
      rgba(184, 150, 47, 0.08) 0%,
      transparent 50%
    );
}

/* Mechanicum (Faction, livre d'armée Mechanicum) : skin de Faction sans
   subdivision (comme Legio Titanicus ci-dessus, voir SKIN_MECHANICUM
   dans js/organigramme.js) — terre cuite/rouille d'un Monde-Forge,
   distincte du rouge des Maisonnées Questoris Mechanicum ci-dessus.
   Pas de blason dédié (aucun asset fourni) : contrairement aux autres
   skins, aucune image n'est posée sur le titre de page. */
body.skin-legion-mechanicum {
  --accent: #7a3418;
  --accent-clair: #a8501f;
  --fond-secondaire: #ecdccb;
  --carte-hover: #f4ebe0;
  background-image:
    radial-gradient(circle at 20% 0%, #ffffff 0%, var(--fond) 60%),
    radial-gradient(
      circle at 100% 100%,
      rgba(122, 52, 24, 0.12) 0%,
      transparent 55%
    ),
    radial-gradient(
      circle at 0% 100%,
      rgba(184, 150, 47, 0.08) 0%,
      transparent 50%
    );
}

/* Désignations de Legiones Auxilia (Faction Solar Auxilia, livre
   Legiones Auxilia intégré au Liber Auxilia p. 50-84) : remplace les
   anciens skins de Doctrine de Cohorte (retirés — six teintes
   génériques sans rapport avec le fluff réel des Cohortes) par un skin
   par Désignation (voir SKINS_DESIGNATION_AUXILIA dans
   js/organigramme.js), rattachée à etat.designationAuxilia plutôt qu'à
   etat.doctrineCohorte. Chaque Désignation sert une Légion Astartes
   précise (DESIGNATIONS_LEGIONES_AUXILIA, js/organigramme-data.js) :
   la palette reprend donc à l'identique celle de la Légion de tutelle
   (body.skin-legion-<légion> ci-dessus), le repère thématique le plus
   naturel en l'absence de couleurs propres à chaque régiment auxiliaire.
   Blason posé à gauche du titre, un par Désignation (assets/
   logo_solar_auxilia/*.png, voir LOGOS_DESIGNATION_AUXILIA dans
   js/organigramme.js pour la correspondance id → nom de fichier). */
body.skin-legion-solar-chasseurs-calibanites {
  /* Dark Angels */
  --accent: #1f3a24;
  --accent-clair: #2f5a38;
  --fond-secondaire: #dde5dc;
  --carte-hover: #e8eee7;
  background-image:
    radial-gradient(circle at 20% 0%, #ffffff 0%, var(--fond) 60%),
    radial-gradient(
      circle at 100% 100%,
      rgba(31, 58, 36, 0.12) 0%,
      transparent 55%
    ),
    radial-gradient(
      circle at 0% 100%,
      rgba(184, 150, 47, 0.08) 0%,
      transparent 50%
    );
}

body.skin-legion-solar-palatins-archites {
  /* Emperor's Children */
  --accent: #4a1a5c;
  --accent-clair: #6b2b82;
  --fond-secondaire: #e8dfe8;
  --carte-hover: #f0e9f0;
  background-image:
    radial-gradient(circle at 20% 0%, #ffffff 0%, var(--fond) 60%),
    radial-gradient(
      circle at 100% 100%,
      rgba(74, 26, 92, 0.1) 0%,
      transparent 55%
    ),
    radial-gradient(
      circle at 0% 100%,
      rgba(184, 150, 47, 0.08) 0%,
      transparent 50%
    );
}

body.skin-legion-solar-thorakites-selucides {
  /* Iron Warriors */
  --accent: #4a4a4a;
  --accent-clair: #5f5f5f;
  --fond-secondaire: #e6e2d8;
  --carte-hover: #efece4;
  background-image:
    radial-gradient(circle at 20% 0%, #ffffff 0%, var(--fond) 60%),
    radial-gradient(
      circle at 100% 100%,
      rgba(74, 74, 74, 0.12) 0%,
      transparent 55%
    ),
    radial-gradient(
      circle at 0% 100%,
      rgba(184, 150, 47, 0.08) 0%,
      transparent 50%
    );
}

body.skin-legion-solar-limitanei-chogoriens {
  /* White Scars */
  --accent: #a3341c;
  --accent-clair: #b8481f;
  --fond-secondaire: #f0e9df;
  --carte-hover: #f7f1e7;
  background-image:
    radial-gradient(circle at 20% 0%, #ffffff 0%, var(--fond) 60%),
    radial-gradient(
      circle at 100% 100%,
      rgba(163, 52, 28, 0.1) 0%,
      transparent 55%
    ),
    radial-gradient(
      circle at 0% 100%,
      rgba(184, 150, 47, 0.08) 0%,
      transparent 50%
    );
}

body.skin-legion-solar-kaerls-fenrissiens {
  /* Space Wolves */
  --accent: #33454e;
  --accent-clair: #4a626e;
  --fond-secondaire: #dde6ea;
  --carte-hover: #e8eff2;
  background-image:
    radial-gradient(circle at 20% 0%, #ffffff 0%, var(--fond) 60%),
    radial-gradient(
      circle at 100% 100%,
      rgba(51, 69, 78, 0.12) 0%,
      transparent 55%
    ),
    radial-gradient(
      circle at 0% 100%,
      rgba(184, 150, 47, 0.08) 0%,
      transparent 50%
    );
}

body.skin-legion-solar-phalangites-dinwit {
  /* Imperial Fists */
  --accent: #76520a;
  --accent-clair: #97690c;
  --fond-secondaire: #eee0c4;
  --carte-hover: #f4ead7;
  background-image:
    radial-gradient(circle at 20% 0%, #ffffff 0%, var(--fond) 60%),
    radial-gradient(
      circle at 100% 100%,
      rgba(118, 82, 10, 0.12) 0%,
      transparent 55%
    ),
    radial-gradient(
      circle at 0% 100%,
      rgba(233, 172, 45, 0.1) 0%,
      transparent 50%
    );
}

body.skin-legion-solar-damnatii-nostramiens {
  /* Night Lords */
  --accent: #10151f;
  --accent-clair: #2b3550;
  --fond-secondaire: #dfe1e8;
  --carte-hover: #eceef2;
  background-image:
    radial-gradient(circle at 20% 0%, #ffffff 0%, var(--fond) 60%),
    radial-gradient(
      circle at 100% 100%,
      rgba(16, 21, 31, 0.14) 0%,
      transparent 55%
    ),
    radial-gradient(
      circle at 0% 100%,
      rgba(138, 143, 156, 0.1) 0%,
      transparent 50%
    );
}

body.skin-legion-solar-elevatii-saiphains {
  /* Blood Angels */
  --accent: #7a0c0c;
  --accent-clair: #b3281c;
  --fond-secondaire: #ecd9c9;
  --carte-hover: #f5e6da;
  background-image:
    radial-gradient(circle at 20% 0%, #ffffff 0%, var(--fond) 60%),
    radial-gradient(
      circle at 100% 100%,
      rgba(122, 12, 12, 0.1) 0%,
      transparent 55%
    ),
    radial-gradient(
      circle at 0% 100%,
      rgba(184, 150, 47, 0.08) 0%,
      transparent 50%
    );
}

body.skin-legion-solar-suaire-de-chaines-medusien {
  /* Iron Hands */
  --accent: #2a1414;
  --accent-clair: #4a2020;
  --fond-secondaire: #e0dcdc;
  --carte-hover: #e8e4e4;
  background-image:
    radial-gradient(circle at 20% 0%, #ffffff 0%, var(--fond) 60%),
    radial-gradient(
      circle at 100% 100%,
      rgba(42, 20, 20, 0.12) 0%,
      transparent 55%
    ),
    radial-gradient(
      circle at 0% 100%,
      rgba(184, 150, 47, 0.08) 0%,
      transparent 50%
    );
}

body.skin-legion-solar-thraexii-nagrakals {
  /* World Eaters */
  --accent: #8a3a12;
  --accent-clair: #a04a19;
  --fond-secondaire: #ecdfd0;
  --carte-hover: #f3e8da;
  background-image:
    radial-gradient(circle at 20% 0%, #ffffff 0%, var(--fond) 60%),
    radial-gradient(
      circle at 100% 100%,
      rgba(138, 58, 18, 0.12) 0%,
      transparent 55%
    ),
    radial-gradient(
      circle at 0% 100%,
      rgba(184, 150, 47, 0.08) 0%,
      transparent 50%
    );
}

body.skin-legion-solar-haute-garde-dultramar {
  /* Ultramarines */
  --accent: #1c3a6e;
  --accent-clair: #2f5490;
  --fond-secondaire: #dde3ee;
  --carte-hover: #e8ecf4;
  background-image:
    radial-gradient(circle at 20% 0%, #ffffff 0%, var(--fond) 60%),
    radial-gradient(
      circle at 100% 100%,
      rgba(28, 58, 110, 0.1) 0%,
      transparent 55%
    ),
    radial-gradient(
      circle at 0% 100%,
      rgba(184, 150, 47, 0.08) 0%,
      transparent 50%
    );
}

body.skin-legion-solar-ambaxtoi-de-barbarus {
  /* Death Guard */
  --accent: #3a4a2e;
  --accent-clair: #52683f;
  --fond-secondaire: #e2e6d8;
  --carte-hover: #eaeee2;
  background-image:
    radial-gradient(circle at 20% 0%, #ffffff 0%, var(--fond) 60%),
    radial-gradient(
      circle at 100% 100%,
      rgba(58, 74, 46, 0.12) 0%,
      transparent 55%
    ),
    radial-gradient(
      circle at 0% 100%,
      rgba(184, 150, 47, 0.08) 0%,
      transparent 50%
    );
}

body.skin-legion-solar-gardespire-prosperienne {
  /* Thousand Sons */
  --accent: #1c2f5c;
  --accent-clair: #2f4a82;
  --fond-secondaire: #e0dfee;
  --carte-hover: #e8e7f4;
  background-image:
    radial-gradient(circle at 20% 0%, #ffffff 0%, var(--fond) 60%),
    radial-gradient(
      circle at 100% 100%,
      rgba(28, 47, 92, 0.12) 0%,
      transparent 55%
    ),
    radial-gradient(
      circle at 0% 100%,
      rgba(184, 150, 47, 0.08) 0%,
      transparent 50%
    );
}

body.skin-legion-solar-chasseurs-de-tetes-cthoniens {
  /* Sons of Horus */
  --accent: #3a3020;
  --accent-clair: #5c4c30;
  --fond-secondaire: #e6ddc9;
  --carte-hover: #efe8d8;
  background-image:
    radial-gradient(circle at 20% 0%, #ffffff 0%, var(--fond) 60%),
    radial-gradient(
      circle at 100% 100%,
      rgba(58, 48, 32, 0.12) 0%,
      transparent 55%
    ),
    radial-gradient(
      circle at 0% 100%,
      rgba(184, 150, 47, 0.08) 0%,
      transparent 50%
    );
}

body.skin-legion-solar-velites-de-therion {
  /* Raven Guard */
  --accent: #1c1c22;
  --accent-clair: #3a3a46;
  --fond-secondaire: #e2e2e6;
  --carte-hover: #ececef;
  background-image:
    radial-gradient(circle at 20% 0%, #ffffff 0%, var(--fond) 60%),
    radial-gradient(
      circle at 100% 100%,
      rgba(28, 28, 34, 0.12) 0%,
      transparent 55%
    ),
    radial-gradient(
      circle at 0% 100%,
      rgba(184, 150, 47, 0.08) 0%,
      transparent 50%
    );
}

body.skin-legion-solar-vindictaires-sparatoi {
  /* Alpha Legion */
  --accent: #123a3c;
  --accent-clair: #1f5a5c;
  --fond-secondaire: #d8e6e6;
  --carte-hover: #e2eeee;
  background-image:
    radial-gradient(circle at 20% 0%, #ffffff 0%, var(--fond) 60%),
    radial-gradient(
      circle at 100% 100%,
      rgba(18, 58, 60, 0.12) 0%,
      transparent 55%
    ),
    radial-gradient(
      circle at 0% 100%,
      rgba(184, 150, 47, 0.08) 0%,
      transparent 50%
    );
}

/* ---------- Nuit Éternelle (clin d'œil, Konrad Curze) ----------
   Bascule par js/main.js (activerNuitEternelle) en tapant "night" au
   clavier. Recolore les mêmes variables de rôle que les Skins de
   Légion ci-dessus (--fond, --texte, --carte...) plutôt que d'ajouter
   des propriétés en dur composant par composant : tout le site (nav,
   cartes, organigramme...) suit sans règle supplémentaire. */
body.nuit-eternelle {
  --fond: #08080a;
  --fond-secondaire: #101014;
  --accent: #7a0c0c;
  --accent-clair: #a13030;
  /* Bordeaux ÉCLAIRCI pour le rôle texte/liseré (voir --accent-texte
     dans :root) : 6,7:1 sur --fond et 6,4:1 sur --carte, contre 1,8:1
     pour --accent brut. C'est ce qui rend de nouveau lisibles, en thème
     sombre, les liens de case d'organigramme, les états de survol des
     boutons de fiche et les bordures de champ en erreur. */
  --accent-texte: #d97b73;
  --titre: #b3924f;
  --titre-contraste: #d4b56a;
  /* Accessibilité (WCAG 1.4.11 / RGAA 3.3) : --acier sert de bordure aux
     champs de saisie et aux <select> (paramètres de la partie, cases de
     l'organigramme). Or cette bordure est l'UNIQUE repère visuel qui
     délimite le champ : elle doit atteindre 3:1. #4a4a58 n'en donnait
     que 2,18 sur le fond noir de ce thème ; #63637a atteint 3,25. */
  --acier: #63637a;
  --acier-clair: #6b6b85;
  --texte: #d9d5c8;
  --texte-doux: #948f80;
  --carte: #101013;
  --carte-hover: #1a1a1f;
  --fond-nav: rgba(8, 8, 10, 0.88);
  --fond-alerte: rgba(122, 12, 12, 0.28);
  --fond-neutre: #1c1c21;
  --fond-neutre-hover: #26262c;
  --ombre: 0 4px 20px rgba(0, 0, 0, 0.75);
  /* Couleurs sémantiques (voir :root) : les teintes du thème clair sont
     des tons SOMBRES, conçus pour être lus sur du blanc. Reposées telles
     quelles sur le fond #08080a de ce thème, elles tombaient entre 1,8:1
     et 3,7:1 — bien en dessous des 4,5:1 de WCAG 1.4.3 / RGAA 3.2 (un
     titre de statut bleu nuit sur noir est illisible). On redéclare donc
     ici, et ici seulement, la variante CLAIRE de chaque teinte : la même
     identité de couleur (or, bleu, violet, rouge, vert, orange), juste
     inversée en luminosité. Tous les composants qui les consomment
     suivent sans une règle de plus. */
  --statut-fixe: #e0a06a;
  --statut-neutralise: #79b0e8;
  --statut-sonne: #c091d8;
  --statut-deroute: #e06b5f;
  --phase-mouvement: #7fb98a;
  --phase-tir: #79b0e8;
  --phase-assaut: #e0a06a;
  --phase-special: #c091d8;
  --texte-attenue: #948f80;
  --succes: #7fb98a;
  --fond-succes: #142014;
  --texte-succes: #a8d8a8;
  --fond-erreur: #26100f;
  --fond-erreur-fort: #2e1211;
  --texte-erreur: #e8a09a;
  background-image: none;
  transition:
    background-color 1s ease,
    color 1s ease;
}

/* ---------- Jauge de points + compteurs ---------- */
.orga-total {
  font-weight: 700;
  margin-bottom: 0.4rem;
}

.orga-jauge {
  height: 0.8rem;
  background: var(--fond-secondaire);
  border: 1px solid var(--acier);
  border-radius: var(--radius);
  overflow: hidden;
  margin-bottom: 0.8rem;
}

.orga-jauge-remplissage {
  height: 100%;
  background: var(--titre);
  transition: width var(--transition);
}

/* Alerte visuelle : la jauge vire à l'accent (bordeaux) quand la
   Limite de Points est dépassée. */
.orga-jauge--depassement {
  background: var(--accent);
}

/* ---------- Messages de validation ---------- */
.orga-erreurs {
  border: 2px solid var(--accent);
  border-radius: var(--radius);
  background: var(--fond-erreur);
  padding: 0.7rem 1rem;
  margin-bottom: 1rem;
}

.orga-erreurs-titre {
  font-weight: 700;
  color: var(--accent-texte);
  margin-bottom: 0.3rem;
}

/* Accessibilité (WCAG 1.4.3 / RGAA 3.2) : même cas que .orga-case-unite
   plus bas — --accent est un bordeaux sombre, illisible (2,56:1) sur le
   fond d'alerte sombre du thème Nuit Éternelle. Or c'est précisément le
   titre qui annonce à l'utilisateur que sa liste d'armée est invalide :
   c'est le dernier texte du site qu'on peut se permettre de rendre
   illisible. --texte-erreur remonte à 8,20:1. */
body.nuit-eternelle .orga-erreurs-titre {
  color: var(--texte-erreur);
}

.orga-erreurs ul {
  margin: 0;
  padding-left: 1.2rem;
}

.orga-erreurs li {
  margin-bottom: 0.25rem;
}

.orga-valide {
  color: var(--succes);
  font-weight: 700;
  margin-bottom: 1rem;
}

/* ---------- Cartes de détachements (arbre) ---------- */
.orga-detachement {
  background: var(--carte);
  border: 1px solid var(--acier);
  /* le liseré gauche code la famille du détachement (voir plus bas) */
  border-left: 5px solid var(--acier);
  border-radius: var(--radius);
  box-shadow: var(--ombre);
  padding: 0.8rem 1rem;
  margin-bottom: 0.9rem;
}

.orga-detachement--principal {
  border-left-color: var(--accent-texte);
}

.orga-detachement--apex {
  border-left-color: var(--titre);
}

.orga-detachement--additionnel {
  border-left-color: var(--acier-clair);
}

.orga-detachement--narratif {
  border-left-color: var(--narratif);
  border-left-width: 6px;
  background: color-mix(in srgb, var(--narratif) 6%, var(--carte));
}

.orga-detachement-entete {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1rem;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 0.6rem;
}

.orga-detachement-entete h3 {
  color: var(--titre-contraste);
}

/* Menu « Faction Alliée » (toute Armée — voir
   construireSelectFactionAlliee dans js/organigramme.js) et menus de
   sous-identité alliée (Légion/Maisonnée/Doctrine de Cohorte, affichés
   selon la Faction Alliée choisie — voir construireSelectLegionAlliee/
   MaisonneeAlliee/DoctrineAlliee). */
.orga-detachement-faction,
.orga-detachement-legion,
.orga-detachement-maisonnee,
.orga-detachement-doctrine {
  margin: -0.3rem 0 0.6rem;
  font-size: 0.85rem;
}

/* max-width: 100% — options longues (« ... (Faction du Détachement
   Principal) », « ... (Légion du Détachement Principal) »…) : sans ça,
   ces <select> (éléments inline « atomiques ») gardent leur largeur
   intrinsèque et débordent du cadre sur mobile au lieu de passer à la
   ligne sous leur label, même problème que .orga-parametre plus haut. */
.orga-detachement-faction select,
.orga-detachement-legion select,
.orga-detachement-maisonnee select,
.orga-detachement-doctrine select {
  margin-left: 0.4rem;
  padding: 0.2rem 0.4rem;
  max-width: 100%;
  vertical-align: middle;
}

/* ---------- Cases d'un détachement ---------- */
.orga-cases-liste {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 0.5rem;
}

.orga-case {
  display: flex;
  gap: 0.6rem;
  align-items: flex-start;
  border: 1px dashed var(--acier);
  border-radius: var(--radius);
  padding: 0.5rem 0.6rem;
  background: var(--fond);
}

.orga-case--occupee {
  border-style: solid;
  background: var(--carte-hover);
}

.orga-case-contenu {
  flex: 1;
  min-width: 0;
}

.orga-case-role {
  font-size: 0.8rem;
  color: var(--texte-doux);
  margin-bottom: 0.15rem;
}

.orga-case-unite a {
  color: var(--accent-texte);
  font-weight: 700;
  text-decoration: none;
}

/* Accessibilité (WCAG 1.4.3 / RGAA 3.2) : --accent est un bordeaux
   sombre (#7a0c0c en Nuit Éternelle) et .orga-case a le fond le plus
   noir du site (--fond, #08080a) — le nom de l'unité tombait à 1,80:1,
   soit un texte rouge quasiment invisible sur du noir. On garde
   l'identité « rouge de Légion » en passant à sa déclinaison claire
   (6,13:1). Cette règle est volontairement rangée à côté de celle
   qu'elle corrige plutôt que dans le bloc body.nuit-eternelle : c'est
   ici qu'on la cherchera si la couleur du lien change un jour. */
body.nuit-eternelle .orga-case-unite a {
  color: var(--statut-deroute);
}

.orga-case-unite a:hover,
.orga-case-unite a:focus {
  text-decoration: underline;
}

.orga-case-libre {
  color: var(--texte-doux);
  font-style: italic;
}

.orga-case-avantage-label {
  display: block;
  font-size: 0.82rem;
  margin-top: 0.3rem;
}

.orga-case-avantage-label select {
  display: block;
  width: 100%;
  margin-top: 0.15rem;
  padding: 0.25rem 0.4rem;
  border: 1px solid var(--acier);
  border-radius: var(--radius);
  background: var(--carte);
  color: var(--texte);
  font: inherit;
  font-size: 0.82rem;
}

.orga-case-role-select {
  display: block;
  width: 100%;
  box-sizing: border-box;
  margin-top: 0.15rem;
  padding: 0.25rem 0.4rem;
  border: 1px solid var(--acier);
  border-radius: var(--radius);
  background: var(--carte);
  color: var(--texte);
  font: inherit;
  font-size: 0.82rem;
}

.orga-case-avantage-texte {
  font-size: 0.78rem;
  color: var(--texte-doux);
  margin-top: 0.25rem;
}

/* ---------- Badges de Rôles Tactiques ----------
   Équivalents textuels des icônes du livre (p. 285) : cercle
   uni pour une case normale, liseré étoilé (pointillés + ✶)
   pour une Case Principale (p. 283). */
.orga-badge {
  position: relative;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.1rem;
  height: 2.1rem;
  border: 2px solid var(--acier-clair);
  border-radius: 50%;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--texte);
  background: var(--carte);
  cursor: help;
}

.orga-badge--principale {
  border-style: dotted;
  border-color: var(--accent-texte);
  color: var(--accent-texte);
}

.orga-badge--principale::after {
  content: "✶";
  position: absolute;
  top: -0.55rem;
  right: -0.35rem;
  font-size: 0.7rem;
  color: var(--accent-texte);
}

/* ---------- Panneau « Ajouter un détachement » ---------- */
.orga-ajout-titre {
  margin: 0.8rem 0 0.4rem;
  color: var(--titre-contraste);
}

.orga-ajout-groupe {
  margin-bottom: 0.7rem;
}

.orga-ajout-groupe summary {
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--texte-doux);
  margin-bottom: 0.3rem;
}

/* Seul ce texte (et non toute la largeur du <summary>, voir
   construireAjoutDetachements dans js/organigramme.js) déclenche le
   pli/dépli : curseur et survol restreints à lui pour ne pas laisser
   croire que le reste de la ligne est cliquable. */
.orga-ajout-titre-texte {
  cursor: pointer;
  user-select: none;
}

.orga-ajout-titre-texte:hover,
.orga-ajout-groupe summary:focus-visible .orga-ajout-titre-texte {
  color: var(--accent-texte);
}

/* Titre du groupe « Détachement Narratif » : en rouge en permanence
   (pas seulement au survol) pour rester bien visible dans le panneau
   « Ajouter un détachement », comme sa carte et son bouton d'ajout. */
.orga-ajout-groupe[data-famille="narratif"] summary {
  color: var(--accent-texte);
}

.orga-ajout-groupe .orga-ajout-boutons {
  margin-top: 0.3rem;
}

.orga-ajout-boutons {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}

/* Bouton d'ajout du Détachement Narratif : coloré en orange pour
   rester bien visible parmi les autres Détachements additionnels
   (voir construireAjoutDetachements, js/organigramme.js). */
.orga-ajout-bouton--narratif {
  color: var(--narratif);
  border-color: var(--narratif);
  font-weight: 700;
}

.orga-ajout-bouton--narratif:hover,
.orga-ajout-bouton--narratif:focus-visible {
  background: color-mix(in srgb, var(--narratif) 12%, var(--carte));
  border-color: var(--narratif);
  color: var(--narratif);
}

.orga-ajout-bouton:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

/* Enveloppe d'un bouton grisé : porte l'info-bulle expliquant
   pourquoi la règle interdit ce détachement (le title d'un bouton
   disabled n'est pas accessible au clavier ni au tactile). */
.orga-ajout-grise {
  border-bottom: none;
  display: inline-block;
}

.orga-ajout-message {
  margin-top: 0.5rem;
  padding: 0.5rem 0.8rem;
  border: 1px solid var(--titre);
  border-radius: var(--radius);
  background: var(--fond-secondaire);
}

/* ---------- Carte d'unité : affectation à une case ---------- */
.unite-affectation {
  padding: 0.4rem 1rem;
  background: var(--fond-secondaire);
  font-size: 0.9rem;
}

.unite-affectation label {
  font-weight: 700;
}

.unite-case-select {
  margin-left: 0.4rem;
  max-width: 100%;
  padding: 0.25rem 0.4rem;
  border: 1px solid var(--acier);
  border-radius: var(--radius);
  background: var(--carte);
  color: var(--texte);
  font: inherit;
  font-size: 0.85rem;
}

/* Unité sans case (ancienne liste, détachement supprimé) : liste
   non conforme aux règles → alerte visuelle sur la carte. */
.unite-carte--sans-case {
  border: 2px solid var(--accent);
}

.unite-carte--sans-case .unite-affectation {
  background: var(--fond-erreur);
  color: var(--accent-texte);
}

/* ---------- Résumé de la liste ---------- */
.orga-resume {
  background: var(--carte);
  border: 1px solid var(--acier);
  border-radius: var(--radius);
  padding: 0.8rem 1rem;
  margin: 1rem 0;
}

.orga-resume-entete {
  font-weight: 700;
  margin-bottom: 0.5rem;
}

.orga-resume-detachement {
  margin-bottom: 0.6rem;
}

.orga-resume-detachement h3 {
  font-size: 0.95rem;
  color: var(--titre-contraste);
}

.orga-resume-detachement ul {
  margin: 0.2rem 0 0;
  padding-left: 1.2rem;
  font-size: 0.88rem;
}

/* ---------- Impression ----------
   La fiche imprimée s'ouvre sur le résumé de la structure d'armée
   (détachements, cases, avantages, points) suivi des fiches
   d'unités ; l'éditeur d'organigramme, les paramètres et les
   sélecteurs disparaissent. */
@media print {
  #orga-parametres,
  #orga-barre,
  #orga-arbre,
  #orga-ajout,
  .orga-ajout-titre,
  .orga-ajout-message,
  .unite-affectation,
  section[aria-label="Organigramme de Force de Croisade"] {
    display: none !important;
  }

  .orga-resume {
    border: 1px solid #000;
    box-shadow: none;
    break-inside: avoid;
  }

  .unite-carte--sans-case {
    border: 2px dashed #000; /* signale aussi à l'impression */
  }
}

/* ============================================================
   FORMULAIRE DE SIGNALEMENT (page contact.html)
   ============================================================ */
.formulaire {
  max-width: 700px;
  margin: 0 auto 2rem;
  background: var(--carte);
  border: 1px solid var(--acier);
  border-radius: var(--radius);
  box-shadow: var(--ombre);
  padding: 1.4rem;
}

/* Un « champ » = un libellé + son contrôle + son aide éventuelle.
   display: flex en colonne : le label se place TOUJOURS au-dessus,
   sans avoir à gérer des marges au cas par cas. */
.champ {
  display: flex;
  flex-direction: column;
  margin-bottom: 1.2rem;
}

.champ label {
  font-family: "Cinzel", serif;
  font-weight: 500;
  color: var(--titre-contraste);
  margin-bottom: 0.4rem;
}

.champ-option {
  font-family: "Lato", sans-serif;
  font-weight: 400;
  color: var(--texte-doux);
  font-size: 0.85rem;
}

.champ-aide {
  font-size: 0.82rem;
  color: var(--texte-doux);
  margin-top: 0.35rem;
}

/* Bordure --acier-clair (et non --acier) : 8:1 sur blanc, alors que
   --acier ne donnait que 2.9:1 — or le contour est l'unique repère
   visuel qui délimite le champ (WCAG 1.4.11 / RGAA 3.3).
   font: inherit — les navigateurs imposent par défaut leur propre
   police aux input/textarea/select ; sans cette ligne, les champs
   ne reprennent PAS la police du site. */
.champ input,
.champ select,
.champ textarea {
  font: inherit;
  font-size: 1rem;
  width: 100%;
  padding: 0.7rem 0.9rem;
  background: var(--fond);
  border: 2px solid var(--acier-clair);
  border-radius: var(--radius);
  color: var(--texte);
}

/* resize: vertical — l'utilisateur peut agrandir la zone de texte en
   hauteur (utile pour un long message) mais pas en largeur, ce qui
   casserait la mise en page. */
.champ textarea {
  resize: vertical;
  min-height: 8rem;
}

.champ input:focus-visible,
.champ select:focus-visible,
.champ textarea:focus-visible {
  outline: 3px solid var(--acier-clair);
  outline-offset: 2px;
  border-color: var(--titre);
}

/* Champ invalide APRÈS saisie : :user-invalid (et non :invalid) ne se
   déclenche qu'une fois le champ quitté ou le formulaire soumis. Avec
   :invalid, un champ « required » encore vide serait signalé en rouge
   dès l'ouverture de la page — on gronde l'utilisateur avant qu'il
   ait tapé quoi que ce soit. */
.champ input:user-invalid,
.champ textarea:user-invalid {
  border-color: var(--accent-texte);
}

/* PIÈGE À ROBOTS : invisible pour l'humain, présent dans le DOM pour
   le robot. On n'utilise NI display:none NI visibility:hidden, que
   les robots un peu sérieux savent détecter — le champ est simplement
   envoyé hors de l'écran. Voir le commentaire du champ _gotcha dans
   pages/contact.html. */
.honeypot {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.bouton-envoyer {
  display: block;
  margin: 0 auto;
  font-family: "Cinzel", serif;
  font-size: 1rem;
  font-weight: 700;
  padding: 0.8rem 2rem;
  background: var(--accent);
  color: #fff;
  border: none;
  border-radius: var(--radius);
  cursor: pointer;
  transition: background var(--transition);
}

.bouton-envoyer:hover {
  background: var(--accent-clair);
}

/* Pendant l'envoi (bouton désactivé par js/contact.js) : l'aspect
   grisé + le curseur « interdit » signalent qu'un clic de plus ne
   servira à rien. */
.bouton-envoyer:disabled {
  background: var(--acier);
  cursor: not-allowed;
}

.form-retour {
  margin-top: 1rem;
  padding: 0;
  font-weight: 700;
}

/* :empty — tant que JavaScript n'a rien écrit dans la zone de retour,
   aucun cadre vide ne s'affiche. Les deux états portent une couleur
   ET un préfixe textuel (✔ / ✖) : l'information ne repose jamais sur
   la seule couleur (WCAG 1.4.1 / RGAA 3.1). */
.form-retour:not(:empty) {
  padding: 0.8rem 1rem;
  border-radius: var(--radius);
  border-left: 4px solid;
}

.form-retour--succes {
  background: var(--fond-succes);
  border-left-color: var(--succes);
  color: var(--texte-succes);
}

.form-retour--succes::before {
  content: "✔ ";
}

.form-retour--erreur {
  background: var(--fond-erreur-fort);
  border-left-color: var(--accent-texte);
  color: var(--texte-erreur);
}

.form-retour--erreur::before {
  content: "✖ ";
}

/* Lien « Signaler une erreur » présent dans le pied de page de
   toutes les pages du site. */
.footer-signalement {
  margin-bottom: 0.8rem !important;
  font-size: 0.95rem;
}

.footer-signalement a {
  color: var(--accent-texte);
  font-weight: 700;
}

/* Pages légales (mentions légales, déclaration d'accessibilité), posées
   dans le pied de page de TOUTES les pages par construirePiedDePage
   (js/main.js). Discrètes mais lisibles : le RGAA impose leur présence
   et leur accessibilité, pas leur mise en avant.
   --texte-doux tient les 4,5:1 requis sur --fond-secondaire dans les
   deux thèmes ; le soulignement permanent (et non au seul survol)
   satisfait WCAG 1.4.1 « Utilisation de la couleur » : la nature de
   lien ne doit pas reposer sur la seule teinte. */
.footer-legal {
  margin-bottom: 0.8rem !important;
  font-size: 0.9rem;
}

.footer-legal a {
  color: var(--texte-doux);
  text-decoration: underline;
}

.footer-legal a:hover,
.footer-legal a:focus-visible {
  color: var(--accent-texte);
}

@media (min-width: 700px) {
  .formulaire {
    padding: 2rem;
  }
}

/* ============================================================
   TEXTE INDICATIF DES CHAMPS (placeholder)
   Sans cette règle, chaque navigateur applique SA couleur système au
   texte indicatif — une couleur figée, qui ne connaît ni notre palette
   ni le thème Nuit Éternelle. Sur Chromium, ce gris sombre posé sur le
   fond #08080a du thème sombre devient quasiment illisible. On le
   rattache donc à --texte-doux, qui suit les deux thèmes et respecte
   les 4,5:1 de WCAG 1.4.3 / RGAA 3.2 dans les deux cas.
   opacity: 1 — Firefox applique par défaut une opacité de 0.54 aux
   placeholders, ce qui abaisserait le contraste qu'on vient de calculer.
   ============================================================ */
.champ input::placeholder,
.champ textarea::placeholder,
.barre-recherche::placeholder,
.unite-combobox-champ::placeholder {
  color: var(--texte-doux);
  opacity: 1;
}

/* ============================================================
   TAILLE DES CIBLES TACTILES
   Référence : WCAG 2.2, critère 2.5.8 « Taille de la cible (minimum) »,
   niveau AA — 24 × 24 px au minimum pour tout contrôle actionnable.
   (Attention en cours : ce critère n'existe PAS dans WCAG 2.1, et le
   RGAA 4.1 étant aligné sur 2.1, il ne le teste pas encore. Ce n'est
   donc pas une obligation légale française aujourd'hui, mais ce sera
   le cas à la prochaine révision du RGAA — autant le faire maintenant.)

   POURQUOI 24 px et pas moins : c'est le seuil sous lequel une personne
   dont la motricité fine est réduite — tremblement essentiel, arthrose,
   maladie de Parkinson, mais aussi n'importe qui qui joue debout autour
   d'une table en tenant son téléphone d'une main — rate sa cible de
   façon répétée. Sur l'Arsenal, rater la case « Jouée » d'une arme
   signifie cocher la ligne voisine, donc fausser sa propre liste sans
   s'en apercevoir.

   POURQUOI UNE VARIABLE plutôt que d'écrire 1.5rem trois fois : les
   trois familles de cases (filtre de l'Arsenal, colonne « Jouée »,
   options d'unité) répondaient au même besoin avec trois valeurs
   différentes (1.1, 1.05 et 1.05 rem) — signe qu'elles avaient été
   réglées à l'œil, séparément. Une seule variable rend la contrainte
   explicite et empêche la dérive de revenir.

   POURQUOI rem ET PAS px : si l'utilisateur agrandit la taille de
   police par défaut de son navigateur (réglage d'accessibilité très
   courant), les cases grandissent avec le texte. En px, elles
   resteraient minuscules à côté d'un libellé devenu deux fois plus
   grand.

   NOTE SUR 44 px : le critère 2.5.5 (niveau AAA) demande 44 × 44 px.
   Impossible ici sans casser les lignes de tableau de l'Arsenal, où
   chaque case partage sa ligne avec sept colonnes de statistiques.
   Le niveau AA visé par la loi française est atteint.
   ============================================================ */

/* ============================================================
   ARCHIVES SOUS SCELLEMENT (clin d'œil — voir activerArchivesScellees
   et afficherMessageArchives dans js/main.js)
   Habillage "terminal" : fond noir, texte vert phosphorescent,
   scanlines + léger tremblement pour évoquer un vieux moniteur qui
   grésille en affichant un message classifié.
   z-index: 1800, au-dessus de .table-flottante (1500) et de .nav
   (1000), sous .lien-evitement (2000, qui n'apparaît qu'au focus).
   ============================================================ */
.archives-fond {
  position: fixed;
  inset: 0;
  z-index: 1800;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
  background: rgba(0, 0, 0, 0.85);
}

.archives-terminal {
  position: relative;
  width: 100%;
  max-width: 32rem;
  padding: 1.75rem 1.5rem;
  border: 2px solid #00ff66;
  border-radius: 4px;
  background: #020403;
  color: #00ff66;
  font-family: "Courier New", ui-monospace, monospace;
  text-shadow: 0 0 4px rgba(0, 255, 102, 0.8);
  box-shadow:
    0 0 30px rgba(0, 255, 102, 0.35),
    inset 0 0 40px rgba(0, 255, 102, 0.08);
  overflow: hidden;
  animation: archives-tremblement 0.15s steps(2) infinite;
}

/* Scanlines : bandes horizontales fines, superposées au texte. */
.archives-terminal::before {
  content: "";
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(
    to bottom,
    rgba(0, 255, 102, 0.07) 0,
    rgba(0, 255, 102, 0.07) 1px,
    transparent 1px,
    transparent 3px
  );
  mix-blend-mode: screen;
  pointer-events: none;
}

/* Bruit/grésillement : opacité clignotante par à-coups (steps). */
.archives-terminal::after {
  content: "";
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(
    45deg,
    rgba(0, 255, 102, 0.05) 0,
    transparent 2px
  );
  animation: archives-bruit 0.5s steps(4) infinite;
  pointer-events: none;
}

.archives-titre {
  margin: 0 0 1rem;
  font-family: inherit;
  font-size: 1rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #00ff66;
}

.archives-texte {
  margin: 0 0 1.5rem;
  font-size: 1rem;
  line-height: 1.6;
}

.archives-fermer {
  display: block;
  margin-left: auto;
  padding: 0.4rem 1rem;
  border: 1px solid #00ff66;
  border-radius: 2px;
  background: transparent;
  color: #00ff66;
  font-family: inherit;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  cursor: pointer;
}

.archives-fermer:hover,
.archives-fermer:focus-visible {
  background: rgba(0, 255, 102, 0.15);
}

@keyframes archives-tremblement {
  0% {
    transform: translate(0, 0);
  }
  50% {
    transform: translate(0.5px, -0.5px);
  }
  100% {
    transform: translate(-0.5px, 0.5px);
  }
}

@keyframes archives-bruit {
  0%,
  100% {
    opacity: 0.4;
  }
  50% {
    opacity: 0.85;
  }
}

/* ============================================================
   MOUVEMENT RÉDUIT (prefers-reduced-motion)
   Certaines personnes déclenchent nausées, vertiges ou migraines à la
   vue d'une animation ; d'autres perdent simplement le fil. Le système
   d'exploitation permet de le signaler (Windows : « Afficher les
   animations » ; iOS/macOS : « Réduire les animations »), et le
   navigateur transmet ce réglage via cette media query. On neutralise
   alors TOUTES les animations du site d'un coup — accordéons, bascule
   de thème, jauge de points, défilement fluide — plutôt qu'au cas par
   cas : une transition oubliée est un utilisateur mis en difficulté.
   0.01ms plutôt que 0s : les événements `transitionend` continuent de
   se déclencher, ce dont dépend le recalcul de hauteur des panneaux
   dépliables imbriqués (voir activerPanneauxDepliables, js/main.js).
   Mettre 0s casserait l'ouverture des accordéons.
   Ce bloc existait déjà dans pages/choix-legion.html, qui a sa propre
   feuille de style en ligne : il manquait simplement à la feuille
   partagée par les quinze autres pages.
   Référence : WCAG 2.3.3 (AAA) et bonne pratique RGAA 13.8.
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
