/* ==========================================================================
   A.C.A — DESIGN SYSTEM — Phase 1 : socle (tokens, thèmes, cartes, boutons)
   ==========================================================================
   Feuille de style indépendante de bootstrap-3.2.0.min.css et aikido-v2.css.
   Ne redéfinit rien de Bootstrap : tous les composants sont préfixés
   `.aca-` pour ne jamais entrer en collision avec les classes existantes
   (ex. `.btn-primary`, `.card` n'existent pas en Bootstrap 3, mais on
   préfixe quand même par prudence et pour la suite du chantier).

   Structure : voir audit-design-grimoire-vers-ACA.md §2.1
   - Niveau 1 : tokens bruts (une couleur = un nom, par palette de thème)
   - Niveau 2 : alias fonctionnels (--bg, --text, --accent, --border, ...)
     → tous les composants ci-dessous ne lisent QUE les alias, jamais les
       tokens bruts. Changer de thème = redéfinir les alias, rien d'autre.

   Polices : chargées via Google Fonts (<link> dans le <head>), voir §7.1.
   Prochaine étape possible : self-host en .woff2 dans public_html/fonts/.
   ========================================================================== */

/* ==== 1. THÈME PAR DÉFAUT (validé par Corentin le 15 juillet 2026) :
   Terre / Dojo (tatami, bois, ancrage) ==== */
:root {
  /* -- tokens bruts -- */
  --td-tatami: #D9CBA3;
  --td-wood:   #6B4A2E;
  --td-olive:  #5A6B47;
  --td-cream:  #F2EBDA;

  /* -- alias fonctionnels -- */
  --bg:              var(--td-cream);
  --panel:           #FFFFFF;
  --border:          var(--td-tatami);
  --text:            var(--td-wood);
  --muted:           #8A7A5F;
  --accent:          var(--td-olive);
  --accent-contrast: var(--td-cream);
  --danger:          #A63A2E;
  --danger-contrast: #FFFFFF;
  --success:         var(--td-olive);
  --success-contrast:#FFFFFF;
  --radius:          6px;
  --card-shadow:     0 1px 3px rgba(107,74,46,.18), 0 1px 2px rgba(107,74,46,.10);
  --scrim:           rgba(107,74,46,.85);
  --accent-rgb:      90,107,71;
  --bg-rgb:          242,235,218;

  --font-display: 'Sawarabi Mincho', Georgia, serif;
  --font-body:    'Sawarabi Gothic', Arial, sans-serif;

  /* -- Palette admin fixe (2026-08-09, stylisation des tableaux admin,
     validée par Corentin sur la maquette proposition-style-tableaux-admin)
     : indigo/rouge/jade/or, décorrélée des 5 thèmes du site public —
     déclarée UNIQUEMENT ici (jamais redéfinie dans .theme-*), donc reste
     identique quel que soit le thème public actif. Réservée aux écrans
     d'administration (pastilles de statut, zébrage, séparation de groupes
     CMP) — jamais utilisée sur les pages publiques, qui continuent de
     lire --accent/--success/--danger comme avant. */
  --admin-indigo:      #3D4A8C;
  --admin-indigo-rgb:  61,74,140;
  --admin-rouge:       #C0392B;
  --admin-rouge-rgb:   192,57,43;
  --admin-jade:        #2E8B6F;
  --admin-jade-rgb:    46,139,111;
  --admin-or:          #B8892B;
  --admin-or-rgb:      184,137,43;
}

/* Redéfinition explicite (même valeurs que :root) pour que chaque thème
   soit autonome et copiable indépendamment des autres.
   Sélecteur volontairement pas restreint à `body.` : permet d'appliquer
   un thème à un simple conteneur (ex. panneaux de comparaison côte à
   côte), pas seulement à la page entière. */
.theme-terre-dojo {
  --bg: var(--td-cream); --panel: #FFFFFF; --border: var(--td-tatami);
  --text: var(--td-wood); --muted: #8A7A5F;
  --accent: var(--td-olive); --accent-contrast: var(--td-cream);
  --danger: #A63A2E; --danger-contrast: #FFFFFF;
  --success: var(--td-olive); --success-contrast: #FFFFFF;
  --card-shadow: 0 1px 3px rgba(107,74,46,.18), 0 1px 2px rgba(107,74,46,.10);
  --scrim: rgba(107,74,46,.85);
  --accent-rgb: 90,107,71;
  --bg-rgb: 242,235,218;
  --font-display: 'Sawarabi Mincho', Georgia, serif;
  --font-body: 'Sawarabi Gothic', Arial, sans-serif;
}

/* ==== 2. Eau / Harmonie (fluidité, ki) ==== */
.theme-eau-harmonie {
  --eh-navy:      #1F3A5F;
  --eh-blue-gray: #5C7A94;
  --eh-white:     #F0F4F5;
  --eh-blue-light:#A9C4D4;

  --bg: var(--eh-white); --panel: #FFFFFF; --border: var(--eh-blue-light);
  --text: var(--eh-navy); --muted: var(--eh-blue-gray);
  --accent: var(--eh-blue-gray); --accent-contrast: #FFFFFF;
  --danger: #B3261E; --danger-contrast: #FFFFFF;
  --success: #2E6B5C; --success-contrast: #FFFFFF;
  --card-shadow: 0 1px 3px rgba(31,58,95,.16), 0 1px 2px rgba(31,58,95,.08);
  --scrim: rgba(31,58,95,.85);
  --accent-rgb: 92,122,148;
  --bg-rgb: 240,244,245;
  --font-display: 'Spectral', Georgia, serif;
  --font-body: 'Manrope', Arial, sans-serif;
}

/* ==== 3. Feu du combat (énergie, intensité) — seul thème sombre ==== */
.theme-feu-combat {
  --fc-brick:  #A63A2E;
  --fc-orange: #D67B3E;
  --fc-black:  #201C1A;
  --fc-gold:   #E8A94C;

  --bg: var(--fc-black); --panel: #2A2320; --border: var(--fc-orange);
  --text: var(--fc-gold); --muted: #B08A5A;
  --accent: var(--fc-brick); --accent-contrast: #FFFFFF;
  --danger: #E5484D; --danger-contrast: #FFFFFF;
  --success: #6FCF8F; --success-contrast: #1A1A1A;
  --card-shadow: 0 2px 10px rgba(0,0,0,.5);
  --scrim: rgba(232,169,76,.85);
  --accent-rgb: 166,58,46;
  --bg-rgb: 32,28,26;
  --font-display: 'Zen Antique', Georgia, serif;
  --font-body: 'Noto Sans JP', Arial, sans-serif;
}

/* ==== 4. Yin et Yang (équilibre, dualité) ==== */
.theme-yin-yang {
  --yy-black: #1A1A1A;
  --yy-white: #FAFAFA;
  --yy-gray:  #8C8C8C;

  --bg: var(--yy-white); --panel: #FFFFFF; --border: var(--yy-gray);
  --text: var(--yy-black); --muted: var(--yy-gray);
  --accent: var(--yy-black); --accent-contrast: var(--yy-white);
  --danger: #B3261E; --danger-contrast: #FFFFFF;
  --success: #2E6B3E; --success-contrast: #FFFFFF;
  --card-shadow: 0 1px 3px rgba(0,0,0,.14), 0 1px 2px rgba(0,0,0,.08);
  --scrim: rgba(26,26,26,.85);
  --accent-rgb: 26,26,26;
  --bg-rgb: 250,250,250;
  --font-display: 'Marcellus', Georgia, serif;
  --font-body: 'Karla', Arial, sans-serif;
}

/* ==== 5. Zen / Montagne (calme, méditation) ==== */
.theme-zen-montagne {
  --zm-sage:  #8A9A7E;
  --zm-taupe: #6E6B63;
  --zm-cream: #F5F1E8;
  --zm-black: #232320;

  --bg: var(--zm-cream); --panel: #FFFFFF; --border: var(--zm-taupe);
  --text: var(--zm-black); --muted: var(--zm-taupe);
  --accent: var(--zm-sage); --accent-contrast: var(--zm-black);
  --danger: #A63A2E; --danger-contrast: #FFFFFF;
  --success: var(--zm-sage); --success-contrast: #1A1A1A;
  --card-shadow: 0 1px 3px rgba(35,35,32,.14), 0 1px 2px rgba(35,35,32,.08);
  --scrim: rgba(35,35,32,.85);
  --accent-rgb: 138,154,126;
  --bg-rgb: 245,241,232;
  --font-display: 'Zen Old Mincho', Georgia, serif;
  --font-body: 'Sawarabi Gothic', Arial, sans-serif;
}

/* ==== 6. Racine appliquée au body (thème par défaut si aucune classe) ==== */
.aca-ds {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  overflow-x: hidden;
}
/* 2026-07-16 : la navbar (.navbar-fixed-top) n'est plus en position fixe
   (retirée de default.php ET tablesorter.php, sur demande) — ce padding, qui
   compensait uniquement ce comportement fixe, n'a plus lieu d'être. Retiré
   plutôt que mis à 0 pour ne pas laisser une règle sans objet. */
.aca-ds footer {
  padding: 30px 0;
}
/* Séparateur " | " entre liens du pied de page (2026-07-17, refonte Lot 2) :
   posé en CSS sur le lien lui-même plutôt qu'en texte brut entre les <a>,
   pour qu'un glisser-déposer (aca-live-menu-edit.js) ne laisse jamais de
   nœud de texte orphelin à l'ancienne position — combinateur "frère
   adjacent" plutôt que :last-child, qui se tromperait à cause des éléments
   admin (+ Ajouter) / 🐉 placés après les liens dans le DOM. */
.aca-footer-link + .aca-footer-link::before {
  content: " | ";
}

/* ==== 7. ACCESSIBILITÉ (§6 point 7 de l'audit) ==== */
.aca-ds a:focus-visible,
.aca-ds button:focus-visible,
.aca-ds summary:focus-visible,
.aca-ds [tabindex]:focus-visible,
.aca-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  .aca-btn, .aca-card {
    transition: none !important;
  }
}

/* ==========================================================================
   COMPOSANT : Carte (.aca-card) — voir audit §2.3 et §6 point 3
   Brique de base : fond + bordure + ombre légère + radius. Pas de texture
   papier ni de double liseré doré (trop "fantasy" pour A.C.A, voir §7).
   ========================================================================== */
.aca-card {
  background: var(--panel);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--card-shadow);
  padding: 1.25rem;
  margin-bottom: 1.5rem;
  font-family: var(--font-body);
}
.aca-card:last-child {
  margin-bottom: 0;
}
/* 2026-08-08, correctif indépendant du chantier largeur (articles/
   _listeParCategorie.php) : remplace le <p> qui enveloppait auparavant le
   contenu d'un article encadré par un <div> (HTML invalide sinon si
   l'article contient des balises de niveau bloc — voir le commentaire dans
   le partial). Reporte ici le margin-bottom que <p> portait par défaut
   (Bootstrap, `p{margin:0 0 10px}`, bootstrap-3.2.0.min.css) pour ne rien
   changer visuellement aux articles en texte simple. */
.aca-article-liste__contenu {
  margin-bottom: 10px;
}

.aca-card__title {
  font-family: var(--font-display);
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--text);
  margin: 0 0 .75rem;
  padding-bottom: .5rem;
  border-bottom: 2px solid var(--accent);
}

.aca-card__body {
  line-height: 1.6;
}

.aca-card__body :first-child { margin-top: 0; }
.aca-card__body :last-child  { margin-bottom: 0; }

/* .aca-page-title (2026-08-09, retour de Corentin après le diagnostic
   "rendu Horaires/Accès aux dojos/S'inscrire") : aucune page du site n'avait
   jusqu'ici de <h1> de contenu visible à styler (celui d'Accueil est
   .sr-only, celui d'articles/show.php restait nu) — reprend le langage
   visuel de .aca-card__title ci-dessus (même border-bottom en --accent),
   agrandi pour un titre de PAGE plutôt qu'un titre de carte. Utilisée par
   articles/index.php, articles/category.php et pages/afficher.php. */
.aca-page-title {
  font-family: var(--font-display);
  font-size: 1.75rem;
  font-weight: 700;
  color: var(--text);
  margin: 0 0 1.5rem;
  padding-bottom: .5rem;
  border-bottom: 2px solid var(--accent);
}

/* ==========================================================================
   COMPOSANT : Boutons (.aca-btn) — hiérarchie à 3 niveaux, voir audit §2.4
   Primaire (validation) / Secondaire (neutre) / Danger (irréversible).
   Pas de dégradés ni d'ombres internes prononcées (garder ça pour le
   fantasy) — sobre et contemporain, voir §7.
   ========================================================================== */
.aca-btn {
  display: inline-block;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1rem;
  line-height: 1.2;
  padding: .6em 1.4em;
  border-radius: var(--radius);
  border: 2px solid transparent;
  cursor: pointer;
  text-decoration: none;
  text-align: center;
  transition: background-color .15s ease, border-color .15s ease,
              color .15s ease, opacity .15s ease;
}

/* -- Primaire / validation -- */
.aca-btn--primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-contrast);
}
.aca-btn--primary:hover   { opacity: .88; }
.aca-btn--primary:active  { opacity: .78; }

/* -- Secondaire / neutre -- */
.aca-btn--secondary {
  background: transparent;
  border-color: var(--border);
  color: var(--text);
}
.aca-btn--secondary:hover  { background: var(--border); color: var(--panel); }
.aca-btn--secondary:active { opacity: .82; }
/* État "actif" (2026-08-09, bouton "Exporter" en mode sélection — voir
   aca-categories-admin.js) : fond plus foncé, persistant (contrairement à
   :hover) tant que le mode sélection reste ouvert. Générique (pas
   spécifique à --secondary) au cas où réutilisé sur un autre bouton. */
.aca-btn--actif {
  background: var(--border) !important;
  color: var(--panel) !important;
}

/* -- Danger / irréversible -- */
.aca-btn--danger {
  background: var(--danger);
  border-color: var(--danger);
  color: var(--danger-contrast);
}
.aca-btn--danger:hover  { opacity: .88; }
.aca-btn--danger:active { opacity: .78; }

/* -- Succès / création (2026-07-16) : n'existait pas encore, nécessaire pour
   remplacer le vert Bootstrap (btn-success) des boutons "Ajouter" côté admin. -- */
.aca-btn--success {
  background: var(--success);
  border-color: var(--success);
  color: var(--success-contrast);
}
.aca-btn--success:hover  { opacity: .88; }
.aca-btn--success:active { opacity: .78; }

/* -- État désactivé, commun aux 4 niveaux -- */
.aca-btn:disabled,
.aca-btn[aria-disabled="true"] {
  opacity: .5;
  cursor: not-allowed;
}

/* -- Modifier "outline" (2026-07-16, admin) : fond transparent par défaut,
   bordure/texte colorés, remplissage au survol — se combine avec un des
   niveaux ci-dessus (.aca-btn--primary/--danger/--success). Ne modifie pas
   ces classes seules, donc n'affecte aucun bouton public existant (aucun
   n'utilise --outline aujourd'hui, uniquement l'admin). Rayon d'angle et
   transition (150ms) déjà hérités de .aca-btn, rien à redéfinir ici. -- */
.aca-btn--outline {
  background: transparent;
}
.aca-btn--outline.aca-btn--primary  { border-color: var(--accent);  color: var(--accent); }
.aca-btn--outline.aca-btn--danger   { border-color: var(--danger);  color: var(--danger); }
.aca-btn--outline.aca-btn--success  { border-color: var(--success); color: var(--success); }
.aca-btn--outline.aca-btn--primary:hover  { background: var(--accent);  color: var(--accent-contrast); opacity: 1; }
.aca-btn--outline.aca-btn--danger:hover   { background: var(--danger);  color: var(--danger-contrast); opacity: 1; }
.aca-btn--outline.aca-btn--success:hover  { background: var(--success); color: var(--success-contrast); opacity: 1; }

/* -- Discret (2026-08-09, stylisation validée par Corentin — maquette
   proposition-style-tableaux-admin) : neutre au repos, la couleur de
   statut (--accent/--danger) n'apparaît qu'au survol — déjà le
   comportement des règles :hover ci-dessus, seul l'état de repos change
   ici. Pour les actions PAR LIGNE d'un tableau (ex. Modifier/Retirer des
   blocs CMP) plutôt que les boutons d'action principaux d'un bandeau
   (Créer/Ajouter▾...), qui restent pleins pour rester repérables. 3
   classes (au lieu de 2 pour --primary/--danger seuls) : l'emporte sur
   les règles ci-dessus quel que soit l'ordre des règles dans la feuille,
   pas seulement par chance de position. -->
.aca-btn--outline.aca-btn--primary.aca-btn--discret {
  border-color: var(--border);
  color: var(--muted);
}
.aca-btn--outline.aca-btn--danger.aca-btn--discret {
  border-color: var(--border);
  color: var(--muted);
}

/* -- Taille compacte (2026-07-16) : flèches ↑/↓ de réordonnancement
   (admin/articles/index.php), remplace btn-xs de Bootstrap. -- */
.aca-btn--sm {
  padding: .2em .6em;
  font-size: .8rem;
}

/* -- Message d'aide inline (2026-07-23, H1 obligatoire) : à côté d'un
   bouton, ex. avertir que Sauvegarder est grisé tant qu'aucun H1 n'est
   présent (voir web/app/Views/admin/articles/edit.php,
   web/editor-app/src/main.tsx). -- */
.aca-form-hint {
  margin-left: .5rem;
  font-size: .85rem;
}
.aca-form-hint--warning {
  color: var(--danger);
}

/* -- Espacement entre boutons adjacents (2026-07-16, v2 plus directe) :
   .aca-btn n'a aucune marge par défaut, contrairement aux .btn-* Bootstrap
   qu'il remplace en admin — sans ça, "Modifier" et le formulaire
   "Supprimer" se touchent. La 1ère version (combinateur .aca-btn + form)
   était correcte sur le papier mais signalée comme toujours chevauchée en
   conditions réelles (admin/utilisateurs/index.php) — remplacée par une
   marge posée DIRECTEMENT sur les classes de formulaire connues
   (.supprimer, .deplacer), sans dépendre d'un élément précédent ni d'un
   combinateur, pour éliminer toute ambiguïté de correspondance de
   sélecteur. Couvre les 7 tableaux admin partageant ce motif. -- */
form.supprimer,
form.deplacer {
  margin-left: .5rem;
}
form.deplacer:first-child {
  margin-left: 0;
}

/* ==========================================================================
   RETOUCHE DES COMPOSANTS BOOTSTRAP EXISTANTS (pages publiques uniquement)
   Applique les tokens du thème actif aux vrais boutons/cartes déjà présents
   dans le HTML (`.btn-*`, `.jumbotron`, `.modal-content`, `.panel`,
   `.list-group[-item]`), sans toucher au balisage PHP. Tout est scopé sous
   `.aca-ds` (posé sur <body> par templates/default.php) : n'affecte que les
   pages publiques qui chargent design-system.css, jamais l'admin
   (templates/tablesorter.php, non concerné à ce stade, voir §6 point 10
   de l'audit — tableaux admin traités dans une phase ultérieure).
   ========================================================================== */

/* -- Boutons existants (hiérarchie à 3 niveaux appliquée aux classes déjà en place) -- */
.aca-ds .btn {
  font-family: var(--font-display);
  font-weight: 700;
  border-radius: var(--radius);
  transition: background-color .15s ease, border-color .15s ease,
              color .15s ease, opacity .15s ease;
}
.aca-ds .btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Primaire / validation — le site utilise `.btn-success` pour Connexion/
   Déconnexion et `.btn-primary` pour les formulaires : les deux sont des
   actions de validation, pas des confirmations de succès (ça, c'est
   `.alert-success`, non concerné ici). */
.aca-ds .btn-primary,
.aca-ds .btn-success {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-contrast);
}
.aca-ds .btn-primary:hover,   .aca-ds .btn-primary:focus,
.aca-ds .btn-success:hover,   .aca-ds .btn-success:focus {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-contrast);
  opacity: .88;
}
.aca-ds .btn-primary:active, .aca-ds .btn-success:active { opacity: .78; }

/* Secondaire / neutre */
.aca-ds .btn-default {
  background: transparent;
  border-color: var(--border);
  color: var(--text);
}
.aca-ds .btn-default:hover, .aca-ds .btn-default:focus {
  background: var(--border);
  color: var(--panel);
}

/* Danger / irréversible */
.aca-ds .btn-danger {
  background: var(--danger);
  border-color: var(--danger);
  color: var(--danger-contrast);
}
.aca-ds .btn-danger:hover, .aca-ds .btn-danger:focus { opacity: .88; }
.aca-ds .btn-danger:active { opacity: .78; }

/* -- Cartes existantes : conteneurs déjà utilisés comme des cartes
   (jumbotron d'accueil, encarts logos, panneaux d'article/contact,
   menu latéral) — même traitement que .aca-card : fond, bordure, ombre,
   radius, voir §2.3 et §6 point 3 de l'audit. -- */
.aca-ds .jumbotron,
.aca-ds .modal-content,
.aca-ds .panel {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--card-shadow);
  color: var(--text);
}

.aca-ds .list-group-item {
  background: var(--panel);
  border-color: var(--border);
  color: var(--text);
  font-family: var(--font-body);
}
.aca-ds .list-group-item:hover,
.aca-ds .list-group-item:focus {
  background: var(--border);
  color: var(--panel);
}
.aca-ds .list-group-item.active,
.aca-ds .list-group-item.active:hover,
.aca-ds .list-group-item.active:focus {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-contrast);
}

/* -- Titres et liens existants : Bootstrap ne fixe pas de couleur sur
   h1-h6 mais les pages publiques les passent presque toutes en
   `.text-info` (bleu Bootstrap, #31708f), et tous les liens `<a>` héritent
   du bleu Bootstrap par défaut (#428bca) — aucun des deux n'était couvert
   par la retouche boutons/cartes précédente. `.text-info` est utilisé ici
   comme simple utilitaire de couleur de texte (titres, intro), pas au
   sens sémantique "info" de Bootstrap : on le fait pointer vers --text
   comme le reste du corps de texte ; les liens, eux, gardent une couleur
   distincte (--accent) pour rester repérables comme cliquables. -- */
.aca-ds h1, .aca-ds h2, .aca-ds h3,
.aca-ds h4, .aca-ds h5, .aca-ds h6 {
  color: var(--text);
  font-family: var(--font-display);
}

.aca-ds .text-info {
  color: var(--text);
}

.aca-ds a {
  color: var(--accent);
}
.aca-ds a:hover,
.aca-ds a:focus {
  color: var(--accent);
  opacity: .78;
}

/* Sur Yin et Yang, --accent est identique à --text (palette volontairement
   monochrome, voir §7 de l'audit) : un lien en couleur seule s'y
   confondrait avec le texte courant. On rajoute un soulignement pour les
   liens en contexte de lecture (paragraphes, contenu de carte) — profite
   aussi à Eau/Harmonie où les deux teintes de bleu restent proches, sans
   toucher les liens de nav/menu/boutons qui ont déjà leur propre
   traitement visuel. */
.aca-ds p a,
.aca-ds .aca-card__body a {
  text-decoration: underline;
}

/* ==========================================================================
   CARROUSEL (accueil.index / carousel.php / bloc BlockNote "carousel",
   scopé sur la classe .carousel — 2026-07-25, pas un id fixe, voir
   aikido-v2.css) — lisibilité de la légende et des flèches par-dessus des
   photos au contenu imprévisible (certaines contiennent déjà du texte,
   ex. "Stage Le Vigan 2013").
   ========================================================================== */

/* Légende : bandeau plein en bas plutôt qu'un texte flottant sans fond —
   utilise --scrim (version semi-transparente de --text, donc le contraste
   avec le texte de légende en --bg reste garanti quel que soit le thème,
   indépendamment de la photo affichée derrière). */
.aca-ds .carousel .carousel-caption {
  left: 0;
  right: 0;
  bottom: 0;
  padding: .6rem 1rem;
  background: var(--scrim);
  text-align: left;
  text-shadow: none;
}
.aca-ds .carousel .carousel-caption h2 {
  margin: 0;
  font-size: 1.1rem;
  font-family: var(--font-display);
  color: var(--bg);
}

/* Flèches : fond circulaire sombre fixe, volontairement PAS lié aux tokens
   du thème (contrairement à la légende) — doit rester lisible sur
   n'importe quelle photo, y compris sur Feu du combat où --scrim est clair. */
.aca-ds .carousel .carousel-control {
  opacity: .85;
}
.aca-ds .carousel .carousel-control:hover,
.aca-ds .carousel .carousel-control:focus {
  opacity: 1;
}
.aca-ds .carousel .carousel-control .glyphicon-chevron-left,
.aca-ds .carousel .carousel-control .glyphicon-chevron-right {
  width: 40px;
  height: 40px;
  margin-top: -20px;
  line-height: 40px;
  font-size: 20px;
  text-align: center;
  background: rgba(0,0,0,.45);
  border-radius: 50%;
}
.aca-ds .carousel .carousel-control .glyphicon-chevron-left {
  left: 50%;
  margin-left: -20px;
}
.aca-ds .carousel .carousel-control .glyphicon-chevron-right {
  right: 50%;
  margin-right: -20px;
}

/* ==========================================================================
   PHASE 2 — TABLEAUX ADMIN (voir audit §2.5 et §6 point 10)
   ==========================================================================
   Cible `table.table1` (classe statique déjà présente dans le HTML de
   toutes les vues admin.*.index). Depuis le 2026-07-18, le tri au clic est
   assuré par js/aca-table-sort.js (JS vanilla, remplace jQuery +
   jquery.tablesorter.js/theme.blue.css) : les classes `.aca-th-sortable`/
   `.aca-th-sort--asc`/`.aca-th-sort--desc` sont posées par ce script, le
   CSS ci-dessous se contente de leur donner une apparence (curseur,
   flèche ▲/▼/⇅), sans toucher au JS. ========================================================================== */

.aca-ds table.table1 {
  /* `width: auto` (2026-08-09, retour de Corentin — colonnes trop larges,
     espace gaspillé) : chaque colonne épouse son contenu le plus large au
     lieu d'être étirée pour occuper 100% du conteneur. `table-layout` reste
     `auto` (valeur par défaut, pas posée en dur) : le navigateur continue
     de faire passer le contenu à la ligne dans une colonne si la table
     dépasserait la largeur disponible, comme avant — width:100% forçait
     seulement un étirement quand il y avait de la place EN PLUS, jamais un
     garde-fou contre le débordement.
     Contour/ombre/centrage PAS posés ici (2026-08-09, retour de Corentin —
     ne s'affichait pas correctement sur #aca-table-categories, le seul
     tableau du site avec plusieurs <tbody> : bug connu, border-radius +
     overflow:hidden sur un <table> ne clippe fiablement QUE le 1er
     fragment/tbody dans certains moteurs de rendu, le reste du tableau
     "dépassait" du cadre sans bordure ni ombre visibles au-delà). Portés
     par `.aca-table-card` à la place — voir ce wrapper plus bas, qui
     enveloppe chaque `<table class="table1">` dans les 14 vues admin — un
     <div> classique clippe toujours correctement quelle que soit la
     structure interne du tableau qu'il contient. */
  width: auto;
  max-width: 100%;
  border-collapse: collapse;
  background-color: var(--panel);
  font-family: var(--font-body);
}
/* Carte (2026-08-09, stylisation validée par Corentin — maquette
   proposition-style-tableaux-admin, corrigée le même jour pour le bug
   multi-tbody ci-dessus) : enveloppe chaque `<table class="table1">`.
   `width: fit-content` (pas `auto`, qui prendrait toute la largeur
   disponible) : le cadre épouse la largeur réelle de la table (elle-même
   `width: auto`, cf. ci-dessus) au lieu de s'étirer inutilement à
   `max-width` quand le contenu est plus étroit — nécessaire pour que
   `margin: auto` centre effectivement quelque chose (un bloc `width: auto`
   classique occupe déjà 100% de son parent, `margin: auto` n'aurait alors
   aucun espace à répartir). `overflow-x: auto` (jamais `hidden`, qui
   masquerait le contenu) : si un tableau reste malgré tout plus large que
   1100px (beaucoup de colonnes), défilement horizontal DANS la carte
   plutôt qu'un débordement de la mise en page — `overflow-y: hidden`
   suffit pour clipper les coins arrondis. */
.aca-table-card {
  width: fit-content;
  max-width: min(1100px, 100%);
  margin: 1.5rem auto;
  border: 1px solid var(--border);
  border-radius: 14px;
  overflow-x: auto;
  overflow-y: hidden;
  box-shadow: var(--card-shadow);
}

/* Miniature de la colonne "Aperçu/Détail" de l'écran Contenus (chantier
   fusion admin, Lot 6, 2026-08-14) — même principe que .aca-cmp-thumb
   (hauteur fixe, largeur libre) mais sans le scale() dynamique (pas
   d'iframe ici, juste une <img>). */
.aca-contenus-apercu-miniature {
  max-height: 48px;
  max-width: 80px;
  object-fit: cover;
  border-radius: 4px;
  vertical-align: middle;
}

/* En-têtes : petites capitales, fond légèrement teinté d'accent, bordures
   horizontales seulement. Couvre `th` ET `td` car certaines vues admin
   utilisent `<td>` dans le `<thead>` (markup existant, pas de notre fait). */
.aca-ds table.table1 thead th,
.aca-ds table.table1 thead td {
  background-color: rgba(var(--accent-rgb), .14);
  color: var(--text);
  font-family: var(--font-body);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  font-size: .78rem;
  border: none;
  border-top: 1px solid var(--border);
  border-bottom: 2px solid var(--border);
  padding: .5rem .6rem;
}

/* En-têtes triables (classe posée par aca-table-sort.js sur les cellules
   sans champ de formulaire imbriqué, ex. la case "tout sélectionner" reste
   non triable) : curseur pointeur + flèche ⇅ discrète au repos. */
.aca-ds table.table1 thead th.aca-th-sortable,
.aca-ds table.table1 thead td.aca-th-sortable {
  cursor: pointer;
  user-select: none;
}
.aca-ds table.table1 thead th.aca-th-sortable::after,
.aca-ds table.table1 thead td.aca-th-sortable::after {
  content: "⇅";
  display: inline-block;
  margin-left: .35em;
  opacity: .35;
  font-size: .85em;
}

/* États de tri (classes posées/retirées dynamiquement par
   aca-table-sort.js) : fond légèrement plus accentué que l'en-tête au
   repos + flèche pleine opacité indiquant la direction active. */
.aca-ds table.table1 thead th.aca-th-sort--asc,
.aca-ds table.table1 thead th.aca-th-sort--desc,
.aca-ds table.table1 thead td.aca-th-sort--asc,
.aca-ds table.table1 thead td.aca-th-sort--desc {
  background-color: rgba(var(--accent-rgb), .28);
}
.aca-ds table.table1 thead th.aca-th-sort--asc::after,
.aca-ds table.table1 thead td.aca-th-sort--asc::after {
  content: "▲";
  opacity: 1;
}
.aca-ds table.table1 thead th.aca-th-sort--desc::after,
.aca-ds table.table1 thead td.aca-th-sort--desc::after {
  content: "▼";
  opacity: 1;
}

.aca-ds table.table1 tbody td {
  border: none;
  border-bottom: 1px solid var(--border);
  /* .5rem .6rem -> .85rem 1rem (2026-08-09, stylisation validée par
     Corentin — lignes trop denses). */
  padding: .85rem 1rem;
  color: var(--text);
  background-color: transparent;
  vertical-align: middle;
}

/* Lignes alternées, à peine teintées. Calculées en :nth-child plutôt que
   via une classe .odd/.even posée par du JS (comme avant le passage au
   tri vanilla, 2026-07-18) : le tri au clic déplace les <tr> dans le DOM,
   :nth-child se recalcule donc automatiquement après un tri, sans code JS
   dédié. #aca-table-categories exclue : elle a déjà sa propre règle
   plus bas (plusieurs <tbody> par groupe + lignes de détail bloc/fiche
   Corbeille intercalées entre 2 lignes "réelles" — un simple :nth-child
   compterait aussi ces lignes cachées et décalerait l'alternance de façon
   imprévisible selon l'état déplié/replié ; calculé côté PHP à la place,
   voir admin/cmp/_content.php et admin/corbeille/_content.php).
   Couleur : indigo fixe de la palette admin (2026-08-09) plutôt que
   --accent-rgb (dépendant du thème public actif) — même teinte partout,
   cohérent avec le zébrage CMP ci-dessous. */
.aca-ds table.table1:not(#aca-table-categories):not([id^="aca-table-corbeille-"]) tbody tr:nth-child(even) > td {
  background-color: rgba(var(--admin-indigo-rgb), .035);
}
/* Zébrage calculé côté PHP pour CMP/Corbeille (voir commentaire ci-dessus)
   — même teinte que la règle :nth-child générique, posée directement sur
   la ligne concernée (classe .aca-zebra) plutôt que déduite en CSS. */
.aca-ds table.table1 tbody tr.aca-zebra > td {
  background-color: rgba(var(--admin-indigo-rgb), .035);
}

.aca-ds table.table1 tbody tr:hover > td {
  background-color: rgba(var(--admin-indigo-rgb), .10);
}

/* Renommage en ligne + ouverture au clic (2026-07-31, Spec_SEO.md §2.3,
   voir aca-inline-title.js) : clic simple = ouvre (toute la ligne, y
   compris le titre), double-clic sur le titre = renomme — même curseur
   partout, le title="" natif détaille l'interaction au survol du titre. */
.aca-ds table[data-inline-title] tbody tr[data-open-url] {
  cursor: pointer;
}

.aca-inline-title__input {
  display: inline-block;
  width: auto;
  min-width: 12ch;
  padding: .15rem .3rem;
  height: auto;
  cursor: text;
}

/* Aperçu pré-envoi du formulaire d'import d'images (2026-07-31,
   Spec_SEO.md §2.3, voir aca-images-upload-preview.js) : simple curseur
   texte sur le nom, pas d'ouverture au clic possible ici (rien n'est
   encore enregistré) contrairement aux tableaux [data-inline-title]. */
#aca-images-upload-preview {
  margin-top: 1.5rem;
}

.aca-images-upload-preview__nom {
  cursor: text;
}

/* Formulaire "Ajouter une propriété" schema.org (2026-07-31, Spec_SEO.md
   §2.6, voir admin/schemaOrg/_content.php) : select + valeur + bouton sur
   une ligne plutôt qu'empilés verticalement. */
.aca-schemaorg-ajouter {
  display: flex;
  gap: .5rem;
  align-items: center;
  margin: .5rem 0 2rem;
}

.aca-schemaorg-ajouter select {
  flex: 0 0 auto;
  width: auto;
}

.aca-schemaorg-ajouter input[type="text"] {
  flex: 1 1 auto;
}

/* Code couleur sémantique en bordure gauche de cellule (§2.5), plutôt
   qu'en fond plein — réservé aux colonnes qui reflètent un vrai état
   binaire existant (ex. `certificatMedical` Oui/Non dans admin.utilisateurs,
   présence/absence d'image dans admin.articles) : classes posées côté PHP
   au cas par cas, pas de code couleur inventé sur des colonnes purement
   descriptives (titre, grade, catégorie...). */
/* Jade/rouge fixes (2026-08-09, stylisation validée par Corentin — palette
   admin, voir --admin-* dans :root) plutôt que --success/--danger : ces 2
   tokens varient selon le thème public actif (5 rendus différents pour le
   même statut Oui/Non), la palette admin reste elle identique partout. */
.aca-ds table.table1 td.aca-flag-ok {
  box-shadow: inset 3px 0 0 var(--admin-jade);
}
.aca-ds table.table1 td.aca-flag-danger {
  box-shadow: inset 3px 0 0 var(--admin-rouge);
}

/* Pastille présent/absent (2026-07-17, Faire l'appel + Suivi des
   présences) : remplace le ✓/✗ texte brut, peu lisible sur une grille
   dense. Couleur ET symbole conservés ensemble (accessibilité daltonisme
   — ne pas se fier uniquement à la couleur) ; var(--success)/var(--danger)
   s'adaptent automatiquement aux 5 thèmes du site. */
.aca-presence-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.4em;
  height: 1.4em;
  border-radius: 50%;
  font-weight: 700;
  line-height: 1;
}
.aca-presence-badge--present {
  background: var(--success);
  color: var(--success-contrast);
}
.aca-presence-badge--absent {
  background: var(--danger);
  color: var(--danger-contrast);
}

/* Vue mensuelle de Faire l'appel (2026-07-17) : une colonne étroite par
   jour du mois, table large -> défilement horizontal plutôt que de casser
   la mise en page (cohérent avec les autres tableaux larges du site). */
.aca-appel-mensuel-wrapper {
  overflow-x: auto;
}
.aca-appel-jour {
  text-align: center;
  min-width: 2.4em;
}
/* Bordure d'indication "commentaire présent" — inset comme .aca-flag-ok/
   danger, mais sur --accent pour ne pas se confondre avec le sens
   présent/absent (déjà porté par --success/--danger sur la pastille). */
.aca-appel-jour--commente {
  box-shadow: inset 0 0 0 2px var(--accent);
}
/* Le <details> de chaque jour passé sert de popover cliquable (même
   mécanisme zéro-JS que Présentation/☰/Catégorie dans la navbar) — le
   <summary> ne doit porter aucun style de liste par défaut. */
.aca-appel-popover summary {
  list-style: none;
  cursor: pointer;
}
.aca-appel-popover summary::-webkit-details-marker {
  display: none;
}
.aca-appel-popover__panel {
  position: absolute;
  z-index: 1040;
  margin-top: .25rem;
  padding: .75rem;
  min-width: 220px;
  text-align: left;
}
.aca-appel-vide {
  color: var(--border);
}

/* Largeur commune pour les boutons Modifier/Supprimer de la colonne
   Actions — sans ça, "Modifier" et "Supprimer" ont des largeurs
   différentes d'une ligne à l'autre (texte + police d'emphase en gras),
   ce qui donne un alignement irrégulier. 100px couvre "Supprimer" (le
   plus long des deux) avec un peu de marge, quelle que soit la table.
   Sélecteur corrigé le 2026-07-17 : ciblait `.btn` (classe Bootstrap),
   mais tous les boutons admin utilisent `.aca-btn` (voir plus haut) —
   cette règle ne s'appliquait donc encore nulle part. */
.aca-ds table.table1 td .aca-btn:not(.aca-btn--sm) {
  min-width: 100px;
  text-align: center;
}

/* Empêche "Modifier"/le formulaire "Supprimer" de retomber chacun sur sa
   propre ligne dans la colonne Actions. Généralisée à `td:last-child` sur
   tous les tableaux admin (correctifs round 7, 2026-07-18 : le même
   empilement, initialement corrigé uniquement sur #aca-table-categories
   via `.aca-categories-admin__actions`, existait aussi de façon identique
   sur Administrer les utilisateurs — et par construction sur les 8 autres
   tableaux admin partageant strictement le même motif HTML, Actions
   toujours en dernière colonne : images, vidéos, articles, techniques,
   attaques, formesTravail, nomsTechniques, informationsPersonnelles).
   Exclusion des lignes `.aca-table-section`/`.aca-table-section__vide`
   (catégories) : leur dernière — et unique — cellule est un `<td
   colspan="6">` de titre de section, pas une colonne Actions ; forcer
   nowrap dessus risquerait de la faire déborder sur petit écran. */
.aca-ds table.table1 tbody tr:not(.aca-table-section):not(.aca-table-section__vide) > td:last-child {
  white-space: nowrap;
}
.aca-ds table.table1 tbody tr > td:last-child form {
  margin-left: .5rem;
}

/* Empêche "↑"/"↓" (colonne Réordonner) de retomber chacun sur sa propre
   ligne (correctifs round 6, 2026-07-18) : `min-width: 100px` ci-dessus ne
   visait que Modifier/Supprimer, mais son sélecteur (`.aca-btn` générique)
   s'appliquait aussi par erreur aux petits boutons `.aca-btn--sm` de
   réordonnancement, sans qu'aucun `white-space: nowrap` ne protège cette
   colonne (contrairement à la colonne Actions, protégée ci-dessus) —
   la colonne réelle (~117px) ne pouvant contenir 2 boutons artificiellement
   élargis à 100px chacun, "↓" wrappait sous "↑". Exclusion de `--sm` du
   `min-width` (règle du dessus) + `nowrap` ici : les deux traitent la même
   cause, l'un empêchant l'élargissement artificiel, l'autre empêchant le
   retour à la ligne si jamais la colonne redevient étroite. */
form.deplacer {
  white-space: nowrap;
}

/* ==========================================================================
   Réinitialisation générique de <summary> (triangle natif masqué, curseur
   pointeur, sans puce) — encore utilisée par le <details> du sélecteur de
   thème (.aca-theme-switcher, voir templates/default.php). L'ancien
   composant "bandeau + articles déroulants" qui utilisait aussi ce reset
   (.aca-band, articles repliables) a été abandonné le 2026-07-15 au profit
   d'une grille de cartes-liens, voir plus bas dans ce fichier.
   ========================================================================== */

.aca-ds summary {
  display: block;
  cursor: pointer;
  list-style: none;
}
.aca-ds summary::-webkit-details-marker { display: none; }
.aca-ds summary::marker { display: none; }

/* ==========================================================================
   Alignement d'images dans le contenu d'article (TinyMCE, natif) — classes
   posées par la config `formats` de aca-article-editor.js, jamais présentes
   dans un article existant avant ce chantier : règles ciblées sur des noms
   de classe inédits, zéro risque de régression sur le contenu déjà en base.
   ========================================================================== */
.aca-ds img.aca-img-left,
.aca-ds img.aca-img-right {
  max-width: 45%;
  height: auto;
  margin-bottom: 1rem;
  border-radius: var(--radius);
}
.aca-ds img.aca-img-left {
  float: left;
  margin-right: 1.5rem;
}
.aca-ds img.aca-img-right {
  float: right;
  margin-left: 1.5rem;
}
.aca-ds img.aca-img-center {
  display: block;
  max-width: 100%;
  height: auto;
  margin: 0 auto 1rem;
  border-radius: var(--radius);
}
/* Clearfix sur les conteneurs réels où le contenu brut d'un article
   s'affiche (articles/show.php, seule page à afficher .contenu directement
   dans une .aca-card depuis l'abandon du système <details>/résumé) — évite
   qu'une image flottante déborde de son bloc. Inoffensif si aucune image
   flottante n'est présente. Scopé à .aca-card en général (plutôt qu'un
   sélecteur par page) : ::after vide ne coûte rien sur les .aca-card qui
   n'ont jamais de contenu flottant (thème switcher, club-picker, cartes-liens
   d'articles...). */
.aca-ds .aca-card::after {
  content: "";
  display: table;
  clear: both;
}
@media (max-width: 480px) {
  .aca-ds img.aca-img-left,
  .aca-ds img.aca-img-right {
    float: none;
    max-width: 100%;
    margin: 0 0 1rem;
  }
}

/* ==========================================================================
   COMPOSANT : Encadré d'article (.article-callout) — seul bloc personnalisé
   conservé (le bloc .article-figure "texte/image côte à côte figé" a été
   abandonné au profit de l'alignement d'image natif ci-dessus). Fond en
   `--bg` (pas `--panel`) et pas d'ombre, délibérément : ambiance "fiche
   papier" chaleureuse plutôt qu'une carte web classique, cf. la fiche de
   personnage JDR de l'audit design (§6) donnée en référence par Corentin.
   `--bg` diffère de `--panel` (fond de .aca-card) sur les 5 thèmes, donc
   reste visuellement distinct sans teinte supplémentaire.
   ========================================================================== */
.article-callout {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.25rem 1.5rem;
  margin: 1.5rem 0;
  font-family: var(--font-body);
  color: var(--text);
  clear: both;
  /* Correctif de largeur (2026-08-07, retour de Corentin — correctif ciblé,
     PAS le traitement visuel complet prévu au chantier séparé "Tableaux et
     encadrés"/charte graphique) : un encadré court ("Lundi & Mercredi")
     s'étirait sur toute la largeur du bloc parent (comportement par défaut
     d'un <div> block-level), disproportionné par rapport à son contenu.
     width: fit-content + min-width pour éviter l'inverse (un encadré ridicule
     sur un mot très court) + max-width: 100% pour ne jamais déborder du
     conteneur sur un contenu long (article, ou colonne étroite en mobile).
     .calloutBlock.tsx (éditeur BlockNote) réutilise cette même classe, voir
     son commentaire — ce correctif s'applique donc aussi à l'édition, pas
     seulement au rendu public. */
  width: fit-content;
  min-width: 12rem;
  max-width: 100%;
}
.article-callout > *:first-child { margin-top: 0; }
.article-callout > *:last-child  { margin-bottom: 0; }

/* ==========================================================================
   COMPOSANT : Carte Google Maps (.aca-google-maps) — 2026-08-09, même
   diagnostic que ci-dessus : googleMapsBlock.tsx exportait un <iframe> nu à
   largeur FIXE (600px), débordant d'une carte étroite (ex.
   aca-article-card--w2) au lieu de s'y adapter. max-width:100% + l'iframe
   lui-même passé à width="100%" (voir toExternalHTML) le contraignent à la
   largeur de son conteneur ; border-radius+overflow:hidden lui donnent les
   coins arrondis de .aca-card au lieu du rectangle net par défaut d'un
   <iframe>. display:block évite l'espace blanc sous l'iframe (comportement
   par défaut inline d'un élément remplacé).
   ========================================================================== */
.aca-google-maps {
  max-width: 100%;
  border-radius: var(--radius);
  overflow: hidden;
}
.aca-google-maps iframe {
  display: block;
  width: 100%;
}

/* ==========================================================================
   COMPOSANT : Image de fond avec texte superposé (2026-07-31,
   Spec_reste_backoffice.md §7, point 2.4) — voir
   web/editor-app/src/blocks/imageDeFondBlock.tsx pour le détail de la
   structure (un seul élément porteur, texte en enfants directs). L'image
   vit dans un ::before à z-index négatif ; `isolation: isolate` crée un
   contexte d'empilement propre à ce bloc pour que ce z-index négatif reste
   confiné ici (jamais un effet sur le reste de la page) — dans cet ordre,
   le texte (enfants normaux, z-index:auto) peint naturellement AU-DESSUS
   du ::before sans classe ni z-index supplémentaire à lui poser.
   --img-opacite est un NOMBRE 0-1 (pas un pourcentage CSS) : posé tel quel
   par imageDeFondBlock.tsx sur `opacity`, qui attend cette unité. */
.aca-image-de-fond {
  position: relative;
  isolation: isolate;
  min-height: 200px;
  padding: 2rem;
  border-radius: var(--radius);
  overflow: hidden;
  color: #fff;
  cursor: move;
}
.aca-image-de-fond::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image: var(--img-url);
  background-position: var(--img-position);
  background-size: cover;
  background-repeat: no-repeat;
  opacity: var(--img-opacite);
  background-color: var(--muted);
}
.aca-image-de-fond > * {
  cursor: text;
}
/* Placeholder (avant qu'une image ne soit choisie, voir la prop `render`
   du bloc) — pas de fond/glissement tant qu'aucune image n'est encore là. */
.aca-image-de-fond-placeholder {
  border: 1px dashed var(--border);
  border-radius: var(--radius);
  padding: 1.5rem;
  text-align: center;
}
.aca-image-de-fond__reglages {
  display: flex;
  align-items: center;
  gap: 1rem;
  font-size: .85em;
  margin-top: .5rem;
}

/* ==========================================================================
   PHASE 3 — MENU DE PRÉSENTATION (sélecteur de thème visiteur, voir audit §3)
   ==========================================================================
   Réutilise <details>/<summary> (§2.8) : pas de JS pour l'ouverture/
   fermeture du panneau, seulement pour appliquer le thème choisi et le
   mémoriser (voir public_html/js/aca-theme-switcher.js + le script inline
   dans templates/default.php). Le panneau lui-même reprend .aca-card.
   Le bouton ⚙️ reste dans le habillage sombre existant de la navbar
   (.navbar-inverse, non retouché aux Phases 1-2) : pas de couleur de
   thème forcée dessus, il hérite du blanc de la navbar comme les autres
   liens de nav.
   ========================================================================== */

.aca-theme-switcher {
  position: relative;
}

.aca-theme-switcher__toggle {
  display: block;
  padding: 15px;
}

.aca-theme-switcher__panel {
  position: absolute;
  right: 0;
  top: 100%;
  z-index: 1040;
  min-width: 220px;
  max-width: calc(100vw - 2rem);
}

.aca-theme-switcher__heading {
  margin: 0 0 .5rem;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: .9rem;
  color: var(--text);
}

.aca-theme-switcher__option {
  display: flex;
  align-items: center;
  gap: .5rem;
  padding: .35rem .4rem;
  margin: 0 -0.4rem;
  border-radius: var(--radius);
  font-family: var(--font-body);
  font-weight: 400;
  color: var(--text);
  cursor: pointer;
}
/* Indication du thème actif au-delà du simple point radio coché —
   dégradation gracieuse : sans support de :has(), le point radio coché
   reste l'indicateur, ce qui suffit fonctionnellement. */
.aca-theme-switcher__option:has(input:checked) {
  background: rgba(var(--accent-rgb), .14);
}

.aca-theme-switcher__option input[type="radio"] {
  accent-color: var(--accent);
  margin: 0;
}

.aca-theme-switcher__swatch {
  display: inline-block;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  border: 1px solid rgba(0,0,0,.15);
  flex-shrink: 0;
}

/* Menu "Paramètres" (2026-08-07, Spec_ergonomie_admin_cmp.md, Chantier 5) :
   entrées "Pseudo"/Déconnexion réutilisent .aca-theme-switcher__option
   (déjà flex + gap + padding, voir ci-dessus) — seuls resets nécessaires
   ici, un <a>/<button> n'hérite pas nativement du même style qu'un
   <label>. Icônes SVG même gabarit que .aca-theme-switcher__swatch
   ci-dessus (cohérence visuelle avec les pastilles de couleur des thèmes). */
.aca-parametres-pseudo,
.aca-parametres-deconnexion {
  text-decoration: none;
  background: none;
  border: none;
  width: 100%;
  text-align: left;
  font-size: 1em;
}
.aca-parametres-pseudo:hover,
.aca-parametres-deconnexion:hover {
  background: rgba(var(--accent-rgb), .14);
}
.aca-parametres-pseudo svg,
.aca-parametres-deconnexion svg {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}
.aca-theme-switcher__separateur {
  border: none;
  border-top: 1px solid var(--border);
  margin: .5rem -0.4rem;
}

/* Sous-menu "Thème du site" (2026-08-08, retour ergonomie de Corentin) :
   <details> imbriqué dans le panneau Paramètres (⚙️), replié par défaut —
   même mécanisme natif <details>/<summary> zéro-JS que le panneau
   parent, aucun conflit avec aca-hover-dropdown.js (ce sous-menu ne porte
   pas sa classe, seul le <details> parent en a besoin — voir plus haut).
   Le <summary> réutilise .aca-theme-switcher__heading pour garder le même
   poids visuel que le titre "Paramètres" en tête de panneau. */
.aca-theme-switcher__submenu summary {
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.aca-theme-switcher__submenu summary::after {
  content: '▾';
  font-size: .75em;
  transition: transform .15s ease;
}
.aca-theme-switcher__submenu[open] summary::after {
  transform: rotate(180deg);
}
.aca-theme-switcher__submenu[open] summary {
  margin-bottom: .35rem;
}

/* ==========================================================================
   PHASE 4 — NAV PRINCIPALE (bandeau plein contraste, voir audit §2.3)
   ==========================================================================
   La nav suit maintenant --text (pas --accent) comme couleur de fond,
   avec --bg en contraste pour le texte/liens. Choix délibéré, voir le
   raisonnement ci-dessous — c'est directement la leçon retenue de la
   Phase 1 sur les liens (Yin et Yang / Eau-Harmonie) :
   - --accent seul aurait posé deux problèmes concrets : pour Eau/Harmonie,
     le ratio de contraste blanc-sur-accent tombe autour de 4.5:1 (limite
     AA, pas de marge) ; pour Yin et Yang, --accent EST --text (#1A1A1A) —
     un fond de nav en --accent aurait été identique au token qu'on
     s'apprêtait à utiliser pour le texte, et surtout aurait rendu le
     bouton Connexion (fond --accent) invisible sur la nav (même couleur).
   - --text/--bg est la paire déjà éprouvée sur tout le site pour un
     contraste fort garanti, quel que soit le thème (y compris Feu du
     combat, seul thème où --text est clair et --bg sombre — le sens
     s'inverse mais la paire reste toujours fortement contrastée).
   --bg-rgb sert au survol : un lavis semi-transparent de --bg par-dessus
   un fond --text reste visible quel que soit le thème, y compris Feu du
   combat où --text est déjà clair (un lavis sombre l'assombrit au lieu de
   l'éclaircir, mais reste perceptible dans les deux sens).
   ========================================================================== */

/* 2026-07-16 (3e itération) : les classes Bootstrap .navbar/.navbar-inverse
   sont retirées du HTML (plus de fond/bordure/rayon Bootstrap non désirés,
   et plus aucune règle Bootstrap résiduelle — position, min-height,
   margin-bottom — pouvant interférer avec la largeur). .aca-navbar-row
   porte maintenant seule tout ce qui était nécessaire (fond du thème actif,
   position pour ancrer les panneaux déroulants en absolute). */
.aca-ds .aca-navbar-row {
  background-color: var(--text);
  border: none;
  font-family: var(--font-display);
}

/* refonte simplifiée : les liens principaux (Accueil/Horaires/.../
   catégories) ne sont plus affichés inline dans la nav — ils vivent
   tous dans le panneau ☰ (.aca-nav-overflow__panel, fond clair .aca-card),
   donc plus besoin d'y forcer une couleur claire pensée pour un fond de nav
   sombre : ils héritent simplement de la couleur de lien standard du site
   (.aca-ds a, --accent), lisible sur fond clair. Seul le toggle du
   sélecteur de thème reste concerné ici (bouton directement sur le fond
   sombre de la nav). */
.aca-ds .aca-navbar-row .aca-theme-switcher__toggle {
  color: var(--bg);
  font-family: var(--font-display);
}
.aca-ds .aca-navbar-row .aca-theme-switcher__toggle:hover,
.aca-ds .aca-navbar-row .aca-theme-switcher__toggle:focus {
  color: var(--bg);
  background-color: rgba(var(--bg-rgb), .15);
}

/* Bouton Connexion/nom d'utilisateur : garde son habillage .btn-success
   existant (fond --accent, Phase 1), on ajoute juste une bordure --bg pour
   qu'il reste visible même quand --accent est proche ou identique à --text
   (donc au fond de la nav) — cas de Yin et Yang. */
.aca-ds .aca-navbar-row .btn-success {
  border-color: var(--bg);
}

/* -- Refonte simplifiée de la nav (2026-07-16) --------------------------
   Logo seul à gauche, tout le reste à droite (Présentation icône seule,
   Connexion/Déconnexion, puis ☰ à l'extrémité). Remplace l'ancien découpage
   Bootstrap .navbar-header/.navbar-collapse (float) par un flex simple —
   plus besoin du composant JS de mesure d'espace (aca-nav-overflow.js,
   supprimé) : tous les liens principaux et catégories vivent en permanence
   dans le panneau ☰, sans condition de largeur d'écran. -- */
/* 2026-07-16 (2e itération) : appliqué directement sur .navbar.navbar-inverse
   (plus de <div class="container"> imbriqué à l'intérieur) — la tentative
   précédente neutralisait .container via width:100%/max-width:none, mais
   malgré une spécificité et un ordre de cascade corrects sur le papier
   (vérifiés), le rendu réel restait centré/étroit. Plutôt que de continuer
   à contrer les règles Bootstrap de .container (width fixe par palier
   750/970/1170px + margin:0 auto), le conteneur .container est supprimé du
   HTML : plus aucune classe Bootstrap de largeur à neutraliser.
   3e itération : .navbar/.navbar-inverse retirés du HTML aussi (fond/bordure
   Bootstrap non désirés) — .aca-navbar-row reprend maintenant seule tout ce
   que .navbar fournissait (position pour ancrer les panneaux déroulants en
   absolute, hauteur mini, marge basse), plus aucune classe Bootstrap du
   tout sur cet élément. */
.aca-navbar-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: 0 15px;
  box-sizing: border-box;
  position: relative;
  min-height: 50px;
  margin-bottom: 20px;
}
.aca-navbar-brand {
  display: flex;
  align-items: center;
}
.aca-navbar-right-group {
  display: flex;
  align-items: center;
  gap: .5rem;
}
/* Conteneur des icônes ☰ (2026-08-07, Spec_ergonomie_admin_cmp.md,
   Chantier 3) : nécessaire comme cible de remplacement pour le polling
   temps réel (aca-menu-live-poll.js) — même display/gap que
   .aca-navbar-right-group ci-dessus pour ne rien changer visuellement,
   les icônes ☰ étaient auparavant des enfants directs de ce dernier. */
.aca-navbar-menus-live {
  display: flex;
  align-items: center;
  gap: .5rem;
}
/* Nom de la page courante (2026-07-25, chantier "logique cible A.C.A",
   point 5), désormais aussi sur mobile (2026-08-09, retour ergonomie —
   masqué jusqu'ici sous 480px, incohérent avec le desktop). color: var(--bg),
   même convention que .aca-nav-overflow__toggle juste en dessous (texte
   lisible sur le fond sombre de la navbar). */
.aca-navbar-page-title {
  margin-left: .75rem;
  font-family: var(--font-display);
  font-weight: 700;
  color: var(--bg);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Flèches de navigation navigateur (Spec_reste_backoffice.md §9) — desktop
   uniquement, à droite du logo. Même famille de bouton que .aca-logout-btn
   (cercle transparent, bordure/couleur var(--bg), lavis au survol). */
.aca-nav-history {
  display: flex;
  align-items: center;
  gap: .25rem;
  margin-left: .5rem;
}
@media (max-width: 480px) {
  .aca-nav-history {
    display: none;
  }
}
.aca-nav-history__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 1px solid var(--bg);
  border-radius: 50%;
  background: transparent;
  color: var(--bg);
  cursor: pointer;
}
.aca-nav-history__btn:hover,
.aca-nav-history__btn:focus {
  background-color: rgba(var(--bg-rgb), .15);
}
.aca-nav-history__btn svg {
  width: 16px;
  height: 16px;
}
/* Sélecteur de club (2026-07-25, chantier "logique cible A.C.A", point 6)
   — mobile uniquement, caché par défaut (desktop garde les 3 cartes
   .aca-club-picker de l'accueil, voir plus bas). 2026-08-09 (retour
   ergonomie) : déplacé dans le cluster ☰ (.aca-navbar-right-group, voir
   templates/default.php) au lieu d'un bouton "▾" isolé dans la barre —
   partage désormais .aca-nav-overflow/.aca-nav-overflow__toggle (même
   famille visuelle que les menus ☰) plutôt que sa propre règle dupliquée à
   l'identique ; .aca-club-switcher ne porte plus que la visibilité
   mobile-only ci-dessous. */
.aca-club-switcher {
  display: none;
}
@media (max-width: 480px) {
  .aca-club-switcher {
    display: block;
  }
}
.aca-club-switcher__panel {
  position: absolute;
  right: 0;
  top: 100%;
  z-index: 1040;
  min-width: 220px;
  max-width: calc(100vw - 2rem);
  display: flex;
  flex-direction: column;
  gap: .5rem;
  padding: .5rem;
}
.aca-club-switcher__option {
  display: flex;
  align-items: center;
  gap: .5rem;
  padding: .4rem;
  border-radius: var(--radius);
  color: var(--text);
  text-decoration: none;
}
.aca-club-switcher__logo {
  width: 40px;
  height: 40px;
  object-fit: contain;
  flex-shrink: 0;
  border-radius: var(--radius);
}

/* ☰ : même mécanisme que .aca-theme-switcher (details/summary natif, pas de
   JS pour ouvrir/fermer — voir §2.8) — remplace l'ancien bouton Bootstrap
   .navbar-toggle (8 barres, jugé trop grand/haut) et son comportement
   conditionné par point de rupture, permanent désormais. */
.aca-nav-overflow {
  position: relative;
}
.aca-nav-overflow__toggle {
  display: block;
  background: transparent;
  border: 2px solid var(--bg);
  border-radius: var(--radius);
  color: var(--bg);
  font-size: 1.1rem;
  line-height: 1;
  padding: .3em .5em;
  cursor: pointer;
}
.aca-nav-overflow__toggle:hover,
.aca-nav-overflow__toggle:focus {
  background-color: rgba(var(--bg-rgb), .15);
}
/* Panneau : même mécanisme que .aca-theme-switcher__panel (dropdown
   position:absolute, masqué/affiché nativement par <details>, pas de
   display:none/is-open à gérer ici), réutilise .aca-card pour fond/bordure/
   ombre — le texte hérite de var(--text)/--accent (couleurs standard du
   site, lisibles sur fond clair). */
.aca-nav-overflow__panel {
  position: absolute;
  right: 0;
  top: 100%;
  z-index: 1040;
  min-width: 220px;
  max-width: calc(100vw - 2rem);
  margin: 0;
  padding: .5rem;
  list-style: none;
}
.aca-nav-overflow__panel > li {
  list-style: none;
}
.aca-nav-overflow__panel > li > a {
  display: block;
  padding: .5rem;
}
/* Séparateur entre les liens principaux et le bloc "Menu" rapatrié
   (2026-07-16, voir templates/default.php). */
.aca-nav-overflow__separator hr {
  margin: .35rem 0;
  border: none;
  border-top: 1px solid var(--border);
}

/* Easter egg (footer, 🐉) : du texte brut dans un <p> hérite du curseur
   "text" (I-beam) du navigateur au survol, comme n'importe quel texte
   sélectionnable — ça trahissait visuellement que l'icône était spéciale.
   Neutralisé explicitement : ni curseur ni sélection, l'icône doit rester
   indiscernable du reste du footer. */
.aca-easter-egg {
  cursor: default;
  user-select: none;
  -webkit-user-select: none;
}

/* Déclencheur SupAdmin (2026-07-30, chantier 9.8) : même bug/correctif que
   .aca-easter-egg ci-dessus — le titre "Administrer" est aussi du texte
   brut dans un <p>, qui hériterait sinon du curseur "text" au survol,
   trahissant visuellement qu'il est spécial. Discrétion demandée = aucun
   changement visuel au survol, cursor par défaut, texte non sélectionnable. */
.aca-supadmin-trigger {
  cursor: default;
  user-select: none;
  -webkit-user-select: none;
}

/* Recherche globale (2026-07-16) : réutilise .aca-theme-switcher/__panel
   (dropdown <details>, même mécanisme que Présentation) — seul le contenu
   du panneau change, un formulaire au lieu d'une liste de thèmes.
   2026-08-08 : le formulaire vit désormais à l'intérieur du panneau
   Paramètres (⚙️) plutôt que dans son propre <details> ☰ 🔍 autonome — la
   classe .aca-search-panel qui portait le min-width dédié n'a plus
   d'élément à styler (le panneau Paramètres a déjà son propre min-width,
   voir .aca-theme-switcher__panel), retirée. */
.aca-search-form {
  display: flex;
  gap: .5rem;
}
.aca-search-form .form-control {
  flex: 1;
  min-width: 0;
}

/* Export "impression/PDF" du bilan de présences (2026-07-16) : masque la nav,
   la sidebar et les contrôles de filtre/impression au moment d'imprimer —
   l'impression navigateur ("Enregistrer en PDF") suffit, pas de dépendance
   PDF ajoutée. .aca-no-print est réutilisable ailleurs si besoin. */
@media print {
  .aca-navbar-row,
  footer,
  .aca-no-print {
    display: none !important;
  }
}

/* Focus clavier : la règle globale (§6 point 7) utilise --accent, invisible
   sur la nav quand --accent == --text (Yin et Yang). On force --bg ici. */
.aca-ds .aca-navbar-row a:focus-visible,
.aca-ds .aca-navbar-row summary:focus-visible,
.aca-ds .aca-navbar-row button:focus-visible {
  outline-color: var(--bg);
}

/* ==========================================================================
   MIGRATION HORS BOOTSTRAP (audit §8) — CSS natif, page par page
   ==========================================================================
   `.aca-native` marque le conteneur d'une page (ou d'une partie de page)
   dont le contenu interne n'utilise plus les classes de grille Bootstrap
   (.col-*), remplacées par grid/flexbox natif appuyé sur les tokens
   .aca-ds. bootstrap-3.2.0.min.css reste chargé globalement tant que
   toutes les pages n'ont pas été traitées — .aca-native ne fait QUE
   marquer/documenter l'avancement, il n'a aucune règle visuelle propre.

   Pages migrées à ce jour, à l'intérieur de leur colonne de contenu — le
   wrapper .row.row-offcanvas et la sidebar (menu.php) restent en
   Bootstrap, partagés par presque toutes les pages donc hors scope d'une
   migration "une page à la fois" :
     - FAQ (app/Views/FAQ/index.php)
     - piedDePages (app/Views/piedDePages/index.php) — Contactez-nous /
       Mentions légales / Liens, sert 3 catégories différentes (id=8/9/10)
     - Archives (app/Views/archives/index.php)
     - accueil (app/Views/accueil/index.php) — page la plus complexe à ce
       jour. Le carrousel (carousel.php, composant JS Bootstrap réel) est
       volontairement INCHANGÉ, hors scope d'une migration de grille/CSS.
     - Contenu principal des pages images/vidéos ci-dessus (dernier
       morceau) : une .aca-card par élément (titre + média), voir
       .aca-gallery-image/.aca-gallery-video. Le carrousel de
       images/index.php et images/category.php (require carousel.php) est
       lui aussi volontairement inchangé, même raison que sur l'accueil.
     - articles/index.php et articles/category.php (2026-08-09) : sidebar
       de filtrage par catégorie (.aca-filter-list, plus utilisée nulle
       part depuis ce jour, retirée du CSS) retirée avec menu.php — grille
       de cartes en pleine largeur directement dans .aca-native, même
       schéma que l'accueil, filtre catégorie relocalisé dans l'icône 🏷️
       de la navbar.
   ========================================================================== */

/* -- .aca-media-item (pattern titre + texte + illustration en 2 colonnes)
   a été retiré (2026-07-15) : la colonne image dédiée par article a été
   supprimée (redondante avec les images insérées directement dans le
   texte via TinyMCE, voir plus bas) sur les 7 pages qui la partageaient
   (FAQ, Horaires, S'inscrire, Accueil, articles/index.php, category.php,
   articles/show.php) — chaque article est maintenant une simple .aca-card
   pleine largeur, plus de grid 2 colonnes ni de breakpoint dédié ici. -- */

/* -- .aca-hero : bandeau club switcher tout en haut de l'accueil,
   remplace .jumbotron. Réutilise .aca-card pour fond/bordure/ombre
   (donc aussi son margin-bottom), ajoute juste la mise en page interne
   et un peu plus de padding vertical pour garder une allure de bandeau
   (le padding par défaut de .aca-card est plus modeste). Tailles de logo
   (100px) reprises à l'identique de l'ancien style inline, pas de
   redesign — seul le mécanisme change. -- */
.aca-hero {
  padding: 2rem 1.25rem;
  text-align: center;
}
.aca-hero__clubs {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 1rem;
}
/* RÉGRESSION CORRIGÉE : width+height fixes sans object-fit forçaient
   l'image à remplir exactement la boîte, l'étirant si son ratio naturel
   ne correspond pas (logoACV.png fait 800×600, pas carré — le cercle
   yin-yang s'affichait en ovale). object-fit:contain garde le ratio
   naturel de l'image à l'intérieur de la même boîte 100×100 — même
   principe déjà utilisé pour le carrousel (aikido-v2.css). */
/* 2026-07-16 : agrandi ×1.5 (100px→150px) sur demande — .aca-hero__clubs a
   déjà flex-wrap:wrap (dégrade en passage à la ligne plutôt qu'un
   débordement), mais repli explicite en dessous de 480px pour revenir à la
   taille d'origine, où l'agrandissement risque le plus de forcer un retour
   à la ligne non désiré (option de repli proposée par Corentin lui-même). */
.aca-hero__logo {
  width: 150px;
  height: 150px;
  object-fit: contain;
  display: block;
  border-radius: var(--radius);
}
.aca-hero__title {
  margin: 0;
  font-size: 2.25rem;
}
@media (max-width: 480px) {
  .aca-hero__logo {
    width: 100px;
    height: 100px;
  }
  .aca-hero__title {
    font-size: 1.5rem;
  }
}

/* -- .aca-club-picker : les 3 cartes de sélection de club (logo + texte
   d'accès : ACV, AMV, ACA depuis le 2026-07-16), remplace les
   .modal-content détournés en boîtes stylées — tailles de logo (200px)
   reprises à l'identique.
   2026-08-08, chantier unification carte, Lot 1 : n'est plus un conteneur
   de grille (display:grid/grid-template-columns retirés) — ClubPickerBloc
   rend désormais ses cartes dans .aca-article-grid.aca-article-grid--cartes
   (même grille 840 colonnes que le reste du site), .aca-club-picker restant
   posée EN PLUS sur le même conteneur comme simple marqueur pour 2 règles
   qui lui sont toujours propres : le masquage mobile ci-dessous
   (@media max-width:480px) et le correctif de margin-bottom descendant
   juste après. -- */
/* Carte active (2026-07-16) : surbrillance légère de l'encadré correspondant
   au club actuellement consulté, même teinte que le sélecteur de thème
   (.aca-theme-switcher__option:has(input:checked)) pour rester cohérent. */
.aca-club-picker__card--active {
  background: rgba(var(--accent-rgb), .14);
}
/* Liens désactivés par aca-club-context.js sur la carte déjà active (voir ce
   fichier, 2026-08-08) : curseur neutre, plus d'invite au clic. */
.aca-club-picker__card--active a {
  cursor: default;
}
/* RÉGRESSION CORRIGÉE : .aca-card porte un margin-bottom de base (pour les
   listes de cartes empilées type Archives/piedDePages) avec un reset
   :last-child pour éviter l'espace en trop en fin de liste. Dans une
   grille à 2 colonnes, seule la carte de DROITE est :last-child — la
   carte de gauche gardait donc son margin-bottom de 1.5rem, invisible en
   soi, mais qui gonflait la hauteur de ligne que align-items:stretch
   utilise pour étirer les deux cartes : la carte de droite (sans marge)
   devait alors étirer sa boîte visible (fond/bordure) plus loin que la
   carte de gauche pour remplir cette même hauteur de ligne — d'où
   l'impression qu'elle était plus haute. Le gap de la grille gère déjà
   l'espacement, le margin-bottom individuel n'a pas lieu d'être ici. */
.aca-club-picker > .aca-card,
.aca-club-picker .aca-card {
  /* Descendant (pas seulement enfant direct) depuis le 2026-07-25, point
     8.4 : les cartes rendues par ClubPickerBloc/_listeParCategorie.php sont
     désormais enveloppées dans un <div id="aca-article-liste-X"> par
     article — .aca-card n'est donc plus toujours un enfant DIRECT de
     .aca-club-picker, contrairement à l'ancien HTML codé en dur qu'il
     remplace. Sélecteur élargi pour continuer à couvrir ce cas, l'ancien
     ne devenant qu'un sous-ensemble redondant (gardé pour ne rien casser
     ailleurs si jamais un .aca-card redevenait un jour un enfant direct). */
  margin-bottom: 0;
}

/* ==========================================================================
   COMPOSANT : grille de cartes-liens d'articles (2026-07-15, v5) — remplace
   l'ancien système <details>/<summary> + résumé HTML clippé en CSS
   (.aca-band, .aca-article__summary/__preview/__body), abandonné après
   plusieurs bugs d'affichage non résolus (carte vide selon le contenu,
   fiabilité de -webkit-line-clamp et du masquage natif de <details> — voir
   l'historique dans le git log si besoin). Nouveau pattern volontairement
   plus simple et standard du web (Medium/BBC/dev.to) : une carte non
   interactive, un seul vrai lien (le titre), le reste de la carte cliquable
   via une astuce CSS "stretched link" plutôt qu'un <a> unique enveloppant
   tout le contenu (celui-ci créerait un lien géant peu accessible : nom
   accessible pollué par l'alt de l'image, impossible de distinguer titre et
   texte au clavier/lecteur d'écran).
   ========================================================================== */
/* Largeur par carte configurable, 1/1 à 1/8 (2026-07-18, chantier accueil
   éditable — voir ArticleEntity::getClasseLargeur()), sur une vraie grille
   CSS Grid (2026-07-18, révision Phase 4 "deux versions petite/normale") :
   840 colonnes = PPCM(1..8), le plus petit nombre de pistes qui donne un
   span ENTIER exact pour chaque fraction 1/1 à 1/8 (y compris 1/5 et 1/7,
   qui ne divisent pas un compte de colonnes plus "rond" comme 24) — un
   nombre de pistes élevé mais sans coût réel de performance à l'échelle
   d'une grille de quelques dizaines de cartes. Remplace le flexbox
   utilisé jusqu'ici : une carte "normale" (voir plus bas) doit pouvoir
   s'étirer sur PLUSIEURS lignes de grille (grid-row: span N, N calculé en
   JS selon la hauteur réelle de son contenu, aca-article-versions.js) SANS
   étirer la hauteur des autres cartes de sa ligne d'origine — impossible
   avec flexbox (une carte plus haute étire tout le monde via
   align-items:stretch), possible avec CSS Grid car chaque carte occupe des
   cellules distinctes d'une grille à hauteur de ligne FIXE
   (grid-auto-rows), pas une hauteur déduite du contenu. */
/* column-gap (2026-07-18, correctif) : `gap` CSS Grid ajoute un espace à
   CHAQUE frontière entre pistes déclarées par grid-template-columns, pas
   seulement entre cartes réellement visibles — avec 840 pistes, ça ferait
   839 espaces de 1.5rem (~20000px), largement plus que la largeur de tout
   conteneur réaliste, et le calc() qui en tiendrait compte donnerait une
   taille de piste négative (839 espaces ne tiennent tout simplement pas
   dans ~1400px). column-gap doit rester à 0 ; l'espacement horizontal est
   recréé "à la Bootstrap" (déjà utilisé ailleurs sur ce site) via
   padding-right sur chaque carte + margin-right négatif équivalent sur la
   grille pour annuler le padding de trop en bout de ligne — voir
   .aca-article-card/.aca-article-normale plus bas. row-gap n'a pas ce
   problème (peu de lignes réelles, pas des centaines de pistes). */
.aca-article-grid {
  display: grid;
  grid-template-columns: repeat(840, 1fr);
  column-gap: 0;
  row-gap: 1.5rem;
  margin-right: -1.5rem;
  /* Largeur minimale par carte (2026-07-24, demande de Corentin) : conteneur
     nommé pour les @container émises par ArticleEntity::getStyleLargeurMin()/
     getStyleLargeurMinPetite() — force une carte en pleine largeur si ce
     conteneur devient plus étroit que son largeurMinPx × N. Approche CSS
     pure (Container Queries), pas de JS. */
  container-type: inline-size;
  container-name: aca-article-grid;
}
/* 2026-08-08 : généralise à TOUTE `.aca-article-grid` le correctif déjà posé
   pour `.aca-club-picker` (voir plus haut, "RÉGRESSION CORRIGÉE") — même
   cause exacte, ailleurs. `.aca-card` porte un margin-bottom de base pour
   les listes EMPILÉES (Archives/PiedDePages, hors grille), avec un reset
   `:last-child` pour éviter l'espace en trop en fin de liste. Dans une
   grille à plusieurs colonnes, seule la DERNIÈRE carte du DOM (2e position
   sur une ligne de 2) est `:last-child` — elle perd sa marge basse, pas les
   précédentes. Avec `align-items: stretch` (CSS Grid, non contredit ici),
   la hauteur de ligne est fixée par le max "boîte + marge" de chaque
   carte : la carte SANS marge doit alors étirer sa boîte visible plus loin
   pour combler cette même hauteur de ligne — écart constant, INDÉPENDANT du
   contenu réel des cartes (repéré sur Horaires ET Accès aux dojos, même
   écart dans les deux cas malgré un contenu différent). `row-gap: 1.5rem`
   ci-dessus fournit déjà l'espacement entre lignes de la grille : le
   margin-bottom individuel des cartes n'a plus lieu d'être ici. */
.aca-article-grid > .aca-card,
.aca-article-grid .aca-card {
  margin-bottom: 0;
}
/* Hauteur de ligne FIXE (2026-08-08, chantier unification carte, Lot 1) :
   sortie de la règle de base ci-dessus — pensée pour des cartes courtes
   uniformes (grille Actualités, articles/category.php, articles/index.php,
   ClubPickerBloc), mais .aca-article-grid sert aussi de conteneur à
   ArticlesBloc générique (bandeau/carrousel/texte de présentation d'Accueil,
   voir AccueilController::show()), qui a besoin d'une hauteur de ligne
   automatique basée sur son contenu réel — pas d'une piste figée à 370px qui
   les tronquerait. Modificateur explicite plutôt qu'une valeur par défaut
   qui conviendrait à un seul des deux usages. */
.aca-article-grid--cartes {
  grid-auto-rows: 370px;
}
.aca-article-card--w1 { grid-column: span 840; }
.aca-article-card--w2 { grid-column: span 420; }
.aca-article-card--w3 { grid-column: span 280; }
.aca-article-card--w4 { grid-column: span 210; }
.aca-article-card--w5 { grid-column: span 168; }
.aca-article-card--w6 { grid-column: span 140; }
.aca-article-card--w7 { grid-column: span 120; }
.aca-article-card--w8 { grid-column: span 105; }
/* Marge horizontale entre cellules (2026-08-09, retour de Corentin —
   harmonisation des grilles Horaires/Accès aux dojos/S'inscrire/cartes club
   sur Actualités) : portée ici plutôt que sur .aca-article-card ci-dessous,
   qui ne couvre que les cartes-teaser (branche $carteLien de
   _listeParCategorie.php). getClasseLargeur()/getClasseLargeurPetite()
   posent TOUJOURS l'une de ces 8 classes sur CHAQUE élément de grille, quel
   que soit son rendu (teaser, contenu complet "else", sansCadre) — les
   porter ici couvre tous les cas d'un coup, contrairement à des correctifs
   ciblés par composant (ex. l'ancien correctif :has(.aca-club-picker__card),
   retiré, devenu redondant). Le margin-right:-1.5rem du conteneur
   (.aca-article-grid ci-dessus) annule déjà la marge de trop en fin de
   ligne, quel que soit le nombre de cellules qui la partagent. */
.aca-article-card--w1,
.aca-article-card--w2,
.aca-article-card--w3,
.aca-article-card--w4,
.aca-article-card--w5,
.aca-article-card--w6,
.aca-article-card--w7,
.aca-article-card--w8 {
  margin-right: 1.5rem;
}
/* En dessous de 480px, toujours 1/1 quelle que soit la largeur configurée
   (même seuil que .aca-club-picker ci-dessous) — 1/6-1/8 y serait
   illisible. */
@media (max-width: 480px) {
  .aca-article-card--w1,
  .aca-article-card--w2,
  .aca-article-card--w3,
  .aca-article-card--w4,
  .aca-article-card--w5,
  .aca-article-card--w6,
  .aca-article-card--w7,
  .aca-article-card--w8 {
    grid-column: span 840;
  }
}

/* Hauteur du bloc carrousel (2026-07-25, chantier Hauteur) : contrairement
   à Largeur ci-dessus (fraction de la largeur RESPONSIVE de
   .aca-article-grid via grid-column), il n'existe aucune grille de
   hauteur équivalente — 1/N est une fraction d'une hauteur de référence
   FIXE (1680px, voir ArticleEntity::HAUTEUR_REFERENCE_PX), pas une valeur
   responsive. Cible spécifiquement le carrousel À L'INTÉRIEUR du wrapper
   (sélecteur descendant), pas le wrapper lui-même : contrairement à
   Largeur, la hauteur ne concerne que l'espace réservé au média, pas la
   carte entière. 4 sélecteurs de classe ici > les 3 de la règle de base
   (.carousel .carousel-inner .item, aikido-v2.css) : gagne sans
   !important. h4 = 420px = valeur de repli actuelle (voir
   ArticleEntity::nHauteurDepuis(), repli sur 4 si non réglé). */
.aca-article-hauteur--h1 .carousel .carousel-inner .item { height: 1680px; }
.aca-article-hauteur--h2 .carousel .carousel-inner .item { height: 840px; }
.aca-article-hauteur--h3 .carousel .carousel-inner .item { height: 560px; }
.aca-article-hauteur--h4 .carousel .carousel-inner .item { height: 420px; }
.aca-article-hauteur--h5 .carousel .carousel-inner .item { height: 336px; }
.aca-article-hauteur--h6 .carousel .carousel-inner .item { height: 280px; }
.aca-article-hauteur--h7 .carousel .carousel-inner .item { height: 240px; }
.aca-article-hauteur--h8 .carousel .carousel-inner .item { height: 210px; }

/* padding:0 + overflow:hidden : l'image (si présente) touche les 4 bords de
   la carte, le padding vit uniquement dans .aca-article-card__body. Le
   overflow:hidden clippe aussi les coins de l'image au border-radius de la
   carte. Hauteur non fixée ici : align-items:stretch (défaut de CSS Grid,
   comme du flexbox) l'étire automatiquement à la hauteur de ligne fixe
   (grid-auto-rows ci-dessus) — voir __image/__body pour comment cette
   hauteur fixe se répartit à l'intérieur (image à hauteur fixe, corps en
   flex:1 qui absorbe le reste). */
.aca-article-card {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 0;
  overflow: hidden;
  margin-bottom: 0;
  /* margin-right (pas padding, pas de column-gap de grille) : voir le
     commentaire sur .aca-article-card--w1..w8 plus haut, qui porte
     désormais cette marge — reste appliquée ici aussi via ces classes de
     largeur, toujours présentes sur une carte-teaser. */
}
/* Hauteur FIXE (2026-07-18, révision Phase 4) plutôt qu'aspect-ratio:16/9 :
   une image à ratio fixe serait ~5× plus haute en pixels sur une carte 1/1
   que sur une carte 1/8 (même ratio, largeur très différente), rendant la
   hauteur totale de carte incompatible d'une largeur à l'autre — alors que
   la règle de non-régression Phase 4 exige une hauteur de carte pleinement
   fixe, y compris entre cartes voisines de largeurs différentes. object-fit
   cover + une hauteur en px assure ça au prix d'un recadrage un peu plus
   présent sur les cartes larges qu'avant. object-position:top (2026-07-16,
   inchangé) : ancre l'image en haut plutôt qu'au centre, le sujet principal
   d'une photo de dojo/stage étant en général cadré vers le haut. */
.aca-article-card__image {
  width: 100%;
  height: 180px;
  flex-shrink: 0;
  object-fit: cover;
  object-position: top;
  display: block;
}
/* flex:1 (dans le flex-column de .aca-article-card ci-dessus) : occupe tout
   l'espace restant sous l'image fixe (180px) jusqu'à la hauteur de ligne
   fixe de la grille (370px) — 190px de contenu, sans calcul en dur ici,
   juste "ce qui reste". overflow:hidden + min-height:0 (nécessaire pour
   qu'un enfant flex en colonne accepte de se faire clipper plutôt que de
   pousser la carte plus haut) : sécurité si un titre/résumé venait à
   dépasser malgré le -webkit-line-clamp de .aca-article-card__resume
   ci-dessous. */
.aca-article-card__body {
  padding: 1.25rem;
  flex: 1;
  min-height: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
/* Astuce "stretched link" : le lien réel reste le titre (.aca-card__title
   a, classe déjà utilisée ailleurs pour un simple titre non cliquable en
   entier — archives/piedDePages — donc le ::after ci-dessous est scopé à
   .aca-article-card pour ne rien changer à ces autres usages), son ::after
   couvre toute la carte (position:relative ci-dessus) pour capter le clic
   n'importe où sur la carte. */
.aca-article-card .aca-card__title a {
  text-decoration: none;
  color: inherit;
}
.aca-article-card .aca-card__title a::after {
  content: "";
  position: absolute;
  inset: 0;
}
.aca-article-card__categorie {
  margin: 0 0 .5rem;
  font-size: .85rem;
  color: var(--muted);
  text-transform: uppercase;
}
/* -webkit-line-clamp:3 (2026-07-18, révision Phase 4) : tronque avec "…"
   plutôt que de déborder d'une hauteur de carte désormais fixe (voir
   .aca-article-card__body ci-dessus) — surtout utile sur une carte étroite
   (1/6-1/8), où le résumé (déjà plafonné à 200 caractères, voir
   ArticleEntity::getResumeAffiche()) peut occuper plus de 3 lignes une fois
   redistribué sur une largeur réduite. */
.aca-article-card__resume {
  margin: 0;
  flex: 1;
  font-family: var(--font-body);
  line-height: 1.5;
  color: var(--text);
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* ==========================================================================
   COMPOSANT : deux versions "petite"/"normale" (2026-07-18, chantier accueil
   éditable — révision du concept plié/déplié initial, abandonné avant tout
   déploiement pour cause de fragilité pressentie)
   ==========================================================================
   Utilisé seulement quand articles.aDeuxVersions=1 (voir ArticleEntity::
   getTitrePetiteAffiche()/getResumeAffichePetite()/getPremiereImagePetite()/
   getClasseLargeurPetite() et les vues accueil/articles.index/category.php).
   PAS un <details>/<summary> (accordéon qui empile le contenu ouvert
   au-dessus/en-dessous d'un résumé qui reste visible) : .aca-article-petite
   et .aca-article-normale sont deux <div> SŒURS indépendantes dans
   .aca-article-grid (même article, jamais montées en même temps — une
   seule visible à la fois, l'autre display:none), permutées par
   aca-article-versions.js au clic. Zéro résidu possible par construction
   (deux éléments distincts, pas un contenu partiellement masqué). Largeur :
   chaque version garde sa PROPRE classe .aca-article-card--wN (grid-column).
   Hauteur (2026-07-18, révision Phase 4 — CSS Grid remplace le flexbox
   d'origine pour cette raison précise) : .aca-article-normale n'a PAS de
   hauteur fixe comme .aca-article-card (elle affiche l'intégralité du
   texte, pas question de le clipper) — aca-article-versions.js lui
   applique un grid-row:span N calculé dynamiquement depuis sa hauteur de
   contenu réelle (scrollHeight), pour qu'elle occupe N lignes de la grille
   SANS étirer la hauteur des cartes qui partageaient sa ligne d'origine
   (impossible avec le flexbox + align-items:stretch utilisé jusqu'ici). */
.aca-article-petite {
  cursor: pointer;
}
/* Image collée directement dans le HTML riche (contenuPetite/contenu via
   TinyMCE), pas seulement l'image de repli (getPremiereImage[Petite]()) —
   sans ça une image insérée en pleine résolution casse la largeur de carte
   (1/1 à 1/8, voir .aca-article-card--wN). */
.aca-article-normale__corps img {
  max-width: 100%;
  height: auto;
}

/* -- Bloc image "habillage" gauche/droite (2026-08-08, éditeur BlockNote,
   voir editor-app/src/blocks/imageHabillageBlock.tsx) : DISTINCT de
   l'alignement natif BlockNote (`textAlignment`, jamais exporté vers le
   HTML public — vérifié dans le code source de BlockNote, ImageToExternalHTML
   ne porte que url/caption/largeur, jamais l'alignement). Le texte
   s'enroule via `float`, uniquement au rendu "normal" d'un article (cette
   classe n'apparaît jamais dans le rendu "petite", qui n'affiche qu'un
   résumé texte + une image de repli séparée — pas le HTML riche de
   l'article, voir _listeParCategorie.php). Pas de migration des anciens
   articles (habillage de l'ancien éditeur pré-BlockNote, ~6 articles,
   corrigés au cas par cas s'ils sont rouverts). */
.aca-image-habillage {
  max-width: 100%;
}
.aca-image-habillage--gauche {
  float: left;
  margin: 0 1.25rem .75rem 0;
}
.aca-image-habillage--droite {
  float: right;
  margin: 0 0 .75rem 1.25rem;
}
.aca-image-habillage img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radius);
}
/* Image cliquable (2026-08-08, prop "lien" du même bloc image, voir
   imageHabillageBlock.tsx/AvecLienOptionnel) : `<a>` autour du `<img>`
   SEUL, aussi bien en rendu "aucun" (dans .aca-article-normale__corps) qu'en
   habillage gauche/droite (dans .aca-image-habillage) — `display:block`
   évite le petit espace parasite sous l'image (l'<a> est inline par défaut
   autour d'un contenu qui, lui, est déjà en `display:block`), pas de
   soulignement (aucun texte dans le lien, juste l'image). */
.aca-image-lien {
  display: block;
  text-decoration: none;
}
.aca-image-habillage__legende {
  font-size: .85rem;
  color: var(--muted);
  margin: .25rem 0 0;
}
/* Empêche un bloc STRUCTUREL (pas du texte courant) de remonter à côté de
   la fin de l'image si le texte qui l'accompagne est plus court qu'elle :
   une autre image/habillage, un callout, un tableau, une vidéo, un
   carousel... redescendent sous l'image plutôt que de coller à son flanc.
   Ajusté le 2026-08-08 (retour de Corentin après vérification visuelle) :
   les titres (h1-h6) sont volontairement RETIRÉS de cette liste — ils
   peuvent continuer à habiller l'image exactement comme p/ul/ol, seuls les
   blocs non-texte doivent "repartir à zéro". */
.aca-image-habillage ~ :not(p):not(ul):not(ol):not(h1):not(h2):not(h3):not(h4):not(h5):not(h6) {
  clear: both;
}
/* Filet de sécurité pour la hauteur du conteneur : sans ça, une image
   habillée plus haute que tout le texte qui l'accompagne "sort" visuellement
   du cadre (les flottants ne comptent pas dans la hauteur auto d'un bloc
   qui n'établit pas son propre contexte de formatage). Scopé aux deux
   conteneurs de contenu riche concernés (_listeParCategorie.php) plutôt
   qu'à .aca-card en général — évite tout changement de comportement de
   marges (collapsing) sur les nombreux autres usages de .aca-card
   (panneaux, cartes teaser...) qui n'affichent jamais de HTML riche
   d'article. flow-root se comporte comme block pour tout conteneur sans
   image habillée (aucun changement visuel dans ce cas). */
.aca-article-liste__contenu,
.aca-article-normale__corps {
  display: flow-root;
}
@media (max-width: 480px) {
  /* Repli mobile (spec) : pleine largeur empilée, plus d'habillage. */
  .aca-image-habillage {
    float: none !important;
    width: 100% !important;
    margin: 0 0 .75rem;
  }
}

.aca-article-normale {
  position: relative;
  display: flex;
  flex-direction: column;
  margin-bottom: 0;
  margin-right: 1.5rem;
  padding: 1.25rem;
  overflow: visible;
}
.aca-article-normale__reduire {
  align-self: flex-start;
  margin: 0 0 .75rem;
  padding: 0;
  border: 0;
  background: none;
  font-family: var(--font-body);
  font-size: .85rem;
  color: var(--muted);
  cursor: pointer;
}
.aca-article-normale__corps {
  font-family: var(--font-body);
  line-height: 1.6;
  color: var(--text);
}

@media (max-width: 480px) {
  /* 2026-07-25, chantier "logique cible A.C.A", point 6 : remplacées en
     mobile par le menu déroulant .aca-club-switcher de l'en-tête (voir
     templates/default.php) — desktop garde ces 3 cartes intactes (seul
     moyen actuel d'y changer de club, décision explicite de Corentin). Le
     repli 1 colonne devient sans objet, la règle est donc remplacée par un
     masquage complet plutôt qu'ajoutée en plus. */
  .aca-club-picker {
    display: none;
  }
}
.aca-club-picker__card {
  text-align: center;
  min-width: 0;
}
/* RÉGRESSION CORRIGÉE : même cause qu'.aca-hero__logo juste au-dessus —
   width+height fixes sans object-fit étiraient logoACV.png (800×600) et,
   dans une moindre mesure, logoAMV.jpg (1417×1276, presque carré mais pas
   tout à fait) puisqu'aucun des deux logos n'est réellement carré. */
.aca-club-picker__logo {
  width: 200px;
  height: 200px;
  max-width: 100%;
  object-fit: contain;
  display: block;
  margin: 0 auto .75rem;
  border-radius: var(--radius);
}

/* -- Galerie images/vidéos (images/index.php, images/category.php,
   videos/index.php, videos/category.php) : chaque élément = une
   .aca-card (titre + média), plus de .img-responsive/dimensions figées
   en HTML — juste du CSS natif responsive. -- */
/* .aca-gallery-lightbox/__image supprimées au chantier "visionneuse média",
   Lot I (2026-08-14, dernier lot) : leur seul consommateur (aca-gallery-
   lightbox.js) est retiré, remplacé par la page dédiée medias.voir.
   .aca-gallery-image (ci-dessous), seul contexte restant : bloc CMP
   "Images" (app/Blocs/ImagesBloc.php + app/Views/images/_content.php) —
   sa vignette est rebranchée vers medias.voir en suite de chantier
   (2026-08-14), `cursor: zoom-in` donc restauré (redevient une promesse
   tenue). */
.aca-gallery-image {
  display: block;
  max-width: 100%;
  height: auto;
  border-radius: var(--radius);
  cursor: zoom-in;
}
.aca-gallery-video {
  display: block;
  max-width: 100%;
  height: auto;
  border-radius: var(--radius);
}

/* ==========================================================================
   PARTIALS PARTAGÉS (audit §8, dernière étape) — menu.php, wrapper
   .container et .row.row-offcanvas de templates/default.php.
   ==========================================================================
   Contrairement aux pages précédentes, ces classes sont utilisées sur
   QUASIMENT TOUTES les pages publiques à la fois : le risque d'une
   régression silencieuse est plus élevé, d'où un luxe de vérifications
   après ce changement (voir le suivi des tests).

   Trouvaille en creusant .row-offcanvas/.sidebar-offcanvas avant de les
   remplacer : le mécanisme "off-canvas" (panneau qui glisse sur mobile)
   ne fonctionne pas et n'a probablement jamais fonctionné — offcanvas.js
   n'écoute que les clics sur [data-toggle="offcanvas"], attribut qui
   n'existe nulle part dans le code. offcanvas.css/offcanvas.js sont
   donc retirés de templates/default.php avec ce changement (plus aucune
   page ne référence .row-offcanvas/.sidebar-offcanvas après migration).
   ========================================================================== */

/* -- .aca-container : remplace .container (contenu principal + pied de
   page uniquement — la nav garde son .container Bootstrap pour
   l'instant, sa structure interne n'est pas dans le scope de cette
   migration, seule sa couleur a été retouchée). Largeur fluide avec un
   seul max-width plutôt que les 4 paliers fixes de Bootstrap — plus
   simple, cohérent avec "peu de breakpoints" (§6 point 8 de l'audit). -- */
.aca-container {
  box-sizing: border-box;
  max-width: 1170px;
  margin-left: auto;
  margin-right: auto;
  padding-left: 15px;
  padding-right: 15px;
}
/* -- .aca-container--full (2026-07-15) : variante pleine largeur, appliquée
   uniquement sur l'accueil (Core\Controller\Controller::$containerClass, voir
   AccueilController::show()). max-width:none suffit : box-sizing:border-box +
   padding déjà présents ci-dessus restent utiles pour ne pas coller le
   contenu aux bords de l'écran. -- */
.aca-container--full {
  max-width: none;
}

/* -- .aca-page-layout : remplace .row.row-offcanvas.row-offcanvas-right,
   la structure contenu+sidebar de presque toutes les pages publiques.
   Flexbox avec wrap : le sidebar passe sous le contenu dès que la place
   manque, sans media query dédiée (contrairement aux 4 paliers Bootstrap
   qu'utilisait .row/.col-*). -- */
.aca-page-layout {
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem;
  align-items: flex-start;
}
.aca-page-layout__content {
  flex: 3 1 480px;
  min-width: 0;
}
.aca-page-layout__sidebar {
  flex: 1 1 220px;
}
/* .aca-container--full s'applique à TOUT le site depuis le 2026-07-25 (plus
   seulement l'accueil, voir App\Controller\AppController) : la sidebar garde
   sa largeur actuelle au lieu de grossir avec l'espace libéré par le
   conteneur pleine largeur — .aca-page-layout__content (flex-grow:3
   ci-dessus) absorbe alors tout cet espace, ce qui pousse mécaniquement la
   sidebar contre le bord droit du conteneur élargi, sans avoir besoin de la
   positionner explicitement. */
.aca-container--full .aca-page-layout__sidebar {
  flex-grow: 0;
}
/* Sidebar sans contenu réel (2026-07-25, retour de Corentin : "grand vide à
   droite" sur la quasi-totalité des pages) : <aside class="aca-page-layout__
   sidebar"> n'inclut le plus souvent que menu.php, qui ne produit plus
   AUCUNE sortie pour un club sans widget météo (voir menu.php) — sans cette
   règle, cet <aside> réservait quand même 220px de flex-basis pour rien.
   `:not(:has(*))` plutôt que `:empty` (vérifié en conditions réelles,
   Chromium) : `:empty` échoue dès qu'un nœud de texte blanc traîne entre
   <aside> et le <?php require ?> dans la page appelante (indentation du
   template, inévitable et non concerné par ce correctif) — `:has(*)` ne
   regarde que les éléments enfants réels, ignore les nœuds de texte.
   Ne s'applique jamais aux pages où l'aside contient AUSSI un vrai filtre de
   catégorie (.aca-filter-list, ex. articles/index.php) : cet <aside>-là a
   un vrai enfant élément, sa largeur reste inchangée. display:none (pas
   visibility:hidden) : l'élément doit sortir du flux flex pour que
   .aca-page-layout__content reprenne l'espace libéré. */
.aca-page-layout__sidebar:not(:has(*)) {
  display: none;
}

/* -- Menu latéral (menu.php) : réutilise .aca-filter-list pour les deux
   listes de liens (menu principal + sous-menu admin), espacement entre
   blocs successifs (listes, puis widget météo). -- */
.aca-filter-list + .aca-filter-list,
.aca-page-layout__sidebar > .aca-filter-list + * {
  margin-top: 1rem;
}

/* ==========================================================================
   Administrer > Catégories — page fusionnée avec l'ancienne page Menus
   (refonte Lot 2, chantier visibilité par rôle, 2026-07-17).
   ========================================================================== */

.aca-categories-admin__ajouter {
  margin-bottom: 1rem;
  padding: .75rem 1rem;
  /* Correctif de largeur (2026-08-07, retour de Corentin, même correctif
     ciblé que .article-callout plus haut — PAS le traitement visuel complet
     du futur chantier "Tableaux et encadrés") : ce panneau (contenu court —
     2-3 champs) s'étirait sur toute la largeur de la colonne de contenu
     (comportement par défaut d'un <div> block-level), disproportionné une
     fois replié par défaut derrière "Ajouter ▾" (Chantier 1). */
  width: fit-content;
  min-width: 22rem;
  max-width: 100%;
}
.aca-categories-admin__ajouter-form {
  margin-top: .75rem;
}

/* Menu "Ajouter ▾" + panneaux repliables (2026-08-07,
   Spec_ergonomie_admin_cmp.md, Chantier 1) : remplace les 4 boutons
   "Créer un CMP"/"Importer un CMP sur cette page"/"Créer une page"/
   "+ Nouveau menu" auparavant tous visibles en permanence. Le menu
   réutilise .aca-roles-cell-popover (voir plus bas, popovers "Rôles ▾"/
   "SEO ▾") ; seul le contenu de la liste et le repli des panneaux sont
   propres à cet écran. */
.aca-cmp-ajouter-menu-ligne {
  display: flex;
  align-items: center;
  gap: .5rem;
  margin-bottom: 1rem;
}
.aca-cmp-ajouter-menu__contenu {
  flex-direction: column;
  align-items: stretch;
  gap: .1rem;
}
.aca-cmp-ajouter-menu__item {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  padding: .4rem .6rem;
  border-radius: var(--radius);
  cursor: pointer;
  white-space: nowrap;
  font: inherit;
  color: var(--text);
}
.aca-cmp-ajouter-menu__item:hover,
.aca-cmp-ajouter-menu__item:focus-visible {
  background: rgba(var(--accent-rgb), .12);
}
.aca-cmp-ajout-panel {
  display: none;
}
.aca-cmp-ajout-panel.is-ouvert {
  display: block;
}
#aca-cmp-nouveau-menu-details.is-ouvert {
  display: flex;
  align-items: flex-start;
  gap: .5rem;
  /* Même correctif de largeur que .aca-categories-admin__ajouter ci-dessus
     (2026-08-07) : ce wrapper flex reste block-level malgré display:flex,
     s'étirait donc lui aussi sur toute la largeur disponible. */
  width: fit-content;
  max-width: 100%;
}
#aca-cmp-creer-panel {
  width: fit-content;
  min-width: 22rem;
  max-width: 100%;
}

/* Ligne de filtre/recherche (2026-08-07, Spec_ergonomie_admin_cmp.md,
   Chantier 2A) : label "Rechercher :" + menu "Filtre ▾" regroupant les 2
   selects groupe/page jusque-là côte à côte à plat. */
.aca-cmp-filtre-ligne {
  display: flex;
  align-items: center;
  gap: .5rem;
  flex-wrap: wrap;
}
.aca-cmp-filtre-label {
  font-weight: 600;
  white-space: nowrap;
}
.aca-cmp-filtre-menu__contenu {
  flex-direction: column;
  align-items: stretch;
  gap: .6rem;
}
.aca-cmp-filtre-menu__contenu label {
  display: flex;
  flex-direction: column;
  gap: .2rem;
  font-weight: 400;
  white-space: nowrap;
}
/* Correctif de largeur (2026-08-07, retour de Corentin) : .form-control
   (Bootstrap) impose width:100%, étirant ces 2 selects à la largeur du
   popover (320px, .aca-cmp-popover__contenu) plutôt qu'à leur contenu. */
.aca-cmp-filtre-menu__contenu select {
  width: auto;
  min-width: 10rem;
  max-width: 100%;
}

/* Ajout rapide en ligne (2026-07-24, backlog Groupe 6, admin/categories/
   index.php uniquement — admin/pages/index.php garde son <details> classique
   ci-dessus, pas concerné). Toujours visible, pas de mécanisme de repli à
   déplier. */
.aca-categories-admin__ajout-rapide {
  display: flex;
  gap: .5rem;
  align-items: center;
  flex-wrap: wrap;
}
.aca-categories-admin__ajout-rapide input[type="text"] {
  flex: 1 1 220px;
}
.aca-categories-admin__ajout-rapide select {
  flex: 0 1 260px;
}

/* Titre de catégorie éditable en ligne (2026-08-07, Spec_ergonomie_admin_cmp.md,
   Chantier 2D §6) : remplace l'ancien <input> toujours visible par le même
   mécanisme clic/double-clic que Articles/Images (aca-inline-title.js) —
   voir aussi .aca-ds table[data-inline-title] tbody tr[data-open-url] plus
   haut pour le curseur pointer de toute la ligne. */
.aca-cmp-titre-inline {
  display: inline-block;
  padding: .2em .4em;
  border-radius: var(--radius);
}
.aca-cmp-titre-inline:hover {
  background: rgba(var(--accent-rgb), .10);
}

/* Champ "Filtrer..." des pages Catégories (2026-07-18) et Articles
   (2026-08-13, Chantier 2 sous-lot 2A — sans ce plafond, le `width:100%`
   Bootstrap fait déborder .aca-cmp-filtre-ligne et "Filtre ▾" retombe à la
   ligne) : plafonné à 350px au lieu de s'étirer sur toute la largeur
   (comportement par défaut hérité de Bootstrap .form-control). Ciblé par
   data-table (une page à la fois) plutôt qu'en élargissant
   .aca-table-filter globalement — les autres tableaux admin partagent la
   même classe et n'ont pas demandé ce changement. */
input.aca-table-filter[data-table="#aca-table-categories"],
input.aca-table-filter[data-table="#aca-table-pages"],
input.aca-table-filter[data-table="#aca-table-articles"] {
  width: 350px;
  max-width: 100%;
}

/* Catégories/pages "admin" dans Administrer les pages (2026-07-19) : celles
   qui portent une entrée du menu Administrer (Catégories/Les pages/
   Articles/Images/Vidéo... — voir ElementMenuTable::idsCategoriesAdmin())
   plutôt que du contenu public, distinguées en rouge dans le <select>
   "Ajouter" et dans les tableaux — `color` reste l'une des rares propriétés
   stylables sur un <option>. Rouge fixe de la palette admin (2026-08-09,
   stylisation validée par Corentin) plutôt que --danger (variait selon le
   thème public actif). Deux sélecteurs : le premier pour un <option> (hors
   tableau), le second pour une cellule de #aca-table-pages — nécessaire
   pour battre en spécificité la règle générique
   `.aca-ds table.table1 tbody td { color: var(--text) }` ci-dessus (2
   classes + 3 éléments), sinon le texte resterait dans la couleur par
   défaut malgré la classe posée sur le <td>. */
.aca-pages-admin__entree,
.aca-ds table.table1 tbody td.aca-pages-admin__entree {
  color: var(--admin-rouge);
}

/* Popovers compacts "Rôles ▾"/"SEO ▾" du tableau CMP (2026-07-29,
   unification CMP — redesign suite au retour de Corentin). Avant cette
   date, "Rôles autorisés" affichait 9 cases à plat sur la ligne au-dessus
   de 1024px et ne devenait un popover cliquable que sous cette largeur ; le
   popover SEO (ajouté le même jour) réutilisait le bouton déclencheur mais
   pas la classe qui pilote l'affichage/masquage, restant donc toujours
   visible en 3 lignes empilées — un bug d'intégration, pas juste
   d'ergonomie. Toujours un popover désormais, à toute largeur d'écran :
   `.aca-cmp-popover__contenu` généralise l'affichage/masquage à N popovers
   de ce type (Rôles, SEO, un futur autre), chacun gardant son propre style
   de contenu via sa classe spécifique (`.aca-roles-cell`/`.aca-cmp-seo-fields`
   ci-dessous). Piloté par `.is-collapsed` (JS aca-categories-admin.js,
   replié par défaut) plutôt que <details>/[open] : Chrome masque le
   contenu d'un <details> fermé via `content-visibility: hidden` sur un
   pseudo-élément interne (::details-content), jamais surmontable depuis un
   descendant en CSS pur (bug constaté en vérification CDP avant tout
   affichage à Corentin). */
.aca-roles-cell-popover {
  position: relative;
  display: inline-block;
}
.aca-roles-cell-popover.is-collapsed .aca-cmp-popover__contenu {
  display: none;
}
.aca-roles-cell-popover:not(.is-collapsed) .aca-cmp-popover__contenu {
  display: flex;
  flex-wrap: wrap;
  position: absolute;
  z-index: 1040;
  top: 100%;
  left: 0;
  margin-top: .25rem;
  width: max-content;
  max-width: 320px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: .6rem .75rem;
  box-shadow: 0 2px 10px rgba(0, 0, 0, .18);
}
/* Contenu du popover "Rôles ▾" : 9 cases + "Tous les rôles", repliées sur
   plusieurs lignes si besoin (max-width ci-dessus) plutôt qu'en une seule
   ligne forcée (n'a plus besoin de tenir dans la largeur d'une cellule de
   tableau maintenant que c'est un popover flottant). */
.aca-roles-cell {
  gap: .2rem .6rem;
  font-size: .85rem;
}
.aca-roles-cell label {
  white-space: nowrap;
  font-weight: 400;
}
.aca-roles-cell__tous {
  width: 100%;
  border-right: none;
  border-bottom: 1px solid var(--border);
  padding-bottom: .3rem;
  margin-bottom: .2rem;
}
/* Contenu du popover "SEO ▾" (2026-07-29, Spec_SEO.md §2.1) : Title SEO et
   Meta-description côte à côte sur une seule ligne (demande explicite de
   Corentin), chaque champ empilant son étiquette au-dessus pour rester
   lisible malgré la largeur réduite. `max-width` élargi par rapport au
   popover générique (320px, pensé pour les rôles) : les 2 champs à 15rem
   chacun + l'écart ne tiendraient pas dedans et repasseraient sur 2 lignes
   via le flex-wrap hérité de `.aca-cmp-popover__contenu`, exactement le
   défaut signalé par Corentin. */
.aca-roles-cell-popover:not(.is-collapsed) .aca-cmp-seo-fields {
  max-width: none;
  width: 34rem;
}
.aca-cmp-seo-fields {
  flex-direction: row;
  align-items: flex-start;
  gap: .75rem;
  /* 16px (2026-08-13, audit taille de police, demande de Corentin) :
     champs de saisie, pas une info secondaire — remplace .85rem. */
  font-size: 1rem;
}
.aca-cmp-seo-fields label {
  display: flex;
  flex-direction: column;
  gap: .2rem;
  font-weight: 400;
  white-space: nowrap;
}
.aca-cmp-seo-fields input,
.aca-cmp-seo-fields textarea {
  width: 15rem;
  font-size: 1rem;
}
.aca-cmp-seo-fields textarea {
  resize: vertical;
  min-height: 2.4rem;
}
/* Les deux popovers ("Rôles ▾"/"SEO ▾") à côté du titre du CMP, dans la
   même cellule (2026-07-29) — remplace l'ancien bouton isolé qui flottait
   seul sous le champ de titre. display:inline-flex (2026-08-12, sous-lot
   1E, demande de Corentin — "mise sur une ligne" de toute la ligne CMP) :
   display:flex seul est un bloc, forçait ce <span> sur SA PROPRE ligne
   sous le titre malgré le commentaire "côté à côte" ci-dessus (vrai
   seulement entre Rôles/SEO l'un par rapport à l'autre, pas par rapport au
   titre) — inline-flex garde Rôles/SEO alignés horizontalement entre eux
   ET sur la même ligne que le titre/la pastille/le badge Bloc qui précèdent
   dans cette cellule. margin-top retiré (redondant avec l'alignement
   inline), gap conservé. */
.aca-cmp-popovers {
  display: inline-flex;
  gap: .4rem;
  vertical-align: middle;
}

/* Sections groupées par menu (2026-07-17, retour de Corentin sur la 1ère
   version de cette page — voir Admin\CategoriesController::index()).
   #aca-table-categories est le seul tableau du site avec plusieurs
   <tbody> et est exclu du tri au clic générique (voir js/aca-table-sort.js) :
   son ordre est fixe. Zébrage : ancienne règle :nth-child(even) retirée le
   2026-08-09 (stylisation validée par Corentin) — remplacée par la classe
   .aca-zebra calculée côté PHP (voir le commentaire dans
   admin/cmp/_content.php et la règle générique `tr.aca-zebra > td`
   ci-dessus), plus fiable que :nth-child face aux lignes de détail
   (blocs de page) intercalées entre 2 catégories. */
/* Bordure indigo + espace vertical accru (2026-08-09, stylisation validée
   par Corentin — maquette proposition-style-tableaux-admin) : la couleur
   ET l'espace marquent la coupure entre 2 groupes, pas l'espace seul comme
   avant (`border-top: 2px solid var(--border)`, neutre). Dégradé plutôt
   qu'un fond plat : la teinte s'estompe vers la droite, laisse le compteur
   "· N entrées" lisible sans y superposer un aplat uniforme. */
.aca-ds table.table1#aca-table-categories tr.aca-table-section td {
  background: linear-gradient(90deg, rgba(var(--admin-indigo-rgb), .16), transparent 85%);
  color: var(--admin-indigo);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .03em;
  /* 16px (2026-08-13, audit taille de police, demande de Corentin) :
     libellé principal (pastille + Nom(N) + chevron), pas une info
     secondaire — remplace .8rem. */
  font-size: 1rem;
  border-top: 3px solid var(--admin-indigo);
  padding-top: 1.15rem;
  padding-bottom: 1.15rem;
}
.aca-table-section__compte {
  font-weight: 400;
  text-transform: none;
  letter-spacing: normal;
  opacity: .75;
}
.aca-table-section__vide td {
  color: var(--border);
  font-style: italic;
}

/* Écran CMP fusionné en accordéon (2026-08-01, Spec_fusion_CMP.md, Lot 2) :
   en-tête de groupe (flèches + pastille couleur + chevron), chevron par
   catégorie, badge "Bloc (n)", et le mini-tableau de blocs imbriqué sous
   chaque catégorie dépliée. */
.aca-cmp-groupe-entete {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
}
.aca-cmp-groupe-toggle {
  background: none;
  border: none;
  color: inherit;
  font: inherit;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .03em;
  cursor: pointer;
  padding: 0;
}
/* .aca-cmp-groupe-etat ("(Replié)") retirée (2026-08-13, correctif de
   Corentin) : plus aucun usage, l'icône chevron seule (rotation ci-dessous)
   suffit à indiquer l'état déplié/replié. */
.aca-cmp-chevron {
  display: inline-block;
  transition: transform .15s ease;
}
.aca-cmp-groupe-toggle[aria-expanded="false"] .aca-cmp-chevron {
  transform: rotate(-90deg);
}
/* Pastille couleur : <input type="color"> natif habillé en petit rond
   cliquable (plutôt qu'un sélecteur de couleur maison) — ouvre directement
   le sélecteur du système au clic, sauvegarde immédiate au changement (voir
   aca-categories-admin.js). */
.aca-cmp-pastille {
  display: inline-flex;
  width: 1.1rem;
  height: 1.1rem;
  border-radius: 50%;
  border: 1px solid var(--border);
  overflow: hidden;
  cursor: pointer;
  flex: none;
}
.aca-cmp-pastille input[type="color"] {
  width: 100%;
  height: 100%;
  padding: 0;
  border: none;
  cursor: pointer;
  opacity: 0; /* le fond de .aca-cmp-pastille porte la couleur visible, l'input reste cliquable par-dessus */
}
/* Or fixe (2026-08-09, stylisation validée par Corentin — palette admin,
   symbolique kintsugi "précieux/protégé") au lieu de var(--border) gris
   neutre, pour les groupes verrouillés (Administrer/Paramètres/Pied de
   page/Catégories sans rattachement). */
.aca-cmp-pastille--verrouille {
  background-color: var(--admin-or);
  cursor: default;
}
/* .aca-cmp-pastille-lecture-seule et la règle de .aca-cmp-detail-row
   (2026-08-12, uniformisation Menu > Entrée de menu > CMP > Bloc) retirées
   (2026-08-13, retour en arrière sur le sous-lot B, demande de Corentin) :
   la scission Entrée de menu/CMP en 2 lignes a été annulée, remis sur une
   seule ligne — plus de pastille de couleur ni de ligne détail séparée à
   ce niveau. */
/* Zone de clic généreuse + fond visible au survol/focus (2026-08-01,
   retour de Corentin après Lot 2 : le chevron par catégorie passait
   inaperçu, difficile à distinguer d'une simple puce de texte à
   `padding: 0 .3rem 0 0` — corrigé en un vrai petit bouton carré, même
   esprit que .aca-cmp-groupe-toggle mais à l'échelle d'une ligne). */
.aca-cmp-chevron-cat {
  background: none;
  border: 1px solid transparent;
  border-radius: 3px;
  color: inherit;
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
  padding: .2rem .35rem;
  margin-left: .3rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.6rem;
  min-height: 1.6rem;
  transition: transform .15s ease, background-color .15s ease, border-color .15s ease;
}
.aca-cmp-chevron-cat:hover,
.aca-cmp-chevron-cat:focus-visible {
  background-color: rgba(var(--accent-rgb), .15);
  border-color: var(--border);
}
.aca-cmp-chevron-cat[aria-expanded="true"] {
  transform: rotate(90deg);
}
/* margin-left retiré (2026-08-13, correctif de Corentin) : héritage de
   l'ancien badge "Bloc (N)" séparé du nom par un espace visuel — le format
   "Nom(N)" (ex. "Accueil(9)") doit être collé, ce margin recréait un espace
   même sans caractère espace dans le HTML source. */
.aca-cmp-badge-bloc {
  font-size: .75rem;
  opacity: .75;
}

/* Flèches ↑/↓/chevron agrandies x2 sur la ligne CMP (2026-08-12, sous-lot
   1E, demande de Corentin) : x2 par rapport à .aca-btn--sm (.8rem → 1.6rem)
   et .aca-cmp-chevron-cat (1rem/1.6rem → 2rem/3.2rem) — scopé à
   .aca-cmp-fleches-larges (posée uniquement sur cette cellule précise,
   admin/cmp/_content.php) plutôt que sur les classes de base, réutilisées
   telles quelles par d'autres tableaux admin (ex. Articles/Images) qui
   n'ont pas demandé cet agrandissement. */
.aca-cmp-fleches-larges .aca-btn--sm {
  font-size: 1.6rem;
  padding: .3em .8em;
}
.aca-cmp-fleches-larges .aca-cmp-chevron-cat {
  font-size: 2rem;
  min-width: 3.2rem;
  min-height: 3.2rem;
}

/* Nombre d'articles "en petit" à côté du chevron ▸ de la ligne CMP
   (2026-08-12, sous-lot 1F, correction de Corentin — remplace un 1er essai
   à 2 niveaux ici, revenu à un seul : ce chevron reste le SEUL toggle du
   sous-tableau de blocs, ce texte est purement informatif, pas cliquable). */
.aca-cmp-blocs-compte {
  font-size: .75rem;
  color: var(--muted);
  margin-left: .3rem;
}

/* Code couleur Menu/Article/bloc-CMP (2026-08-07, Spec_ergonomie_admin_cmp.md,
   Chantier 2E, confirmé par Corentin) : pastille + texte normal, pas de
   fond/gras (garde le tableau déjà dense lisible). "Menu" (en-tête de
   groupe) est déjà distinct par son fond teinté + majuscules
   (.aca-table-section, voir plus bas) — pas de nouvelle pastille pour lui,
   seuls les 2 niveaux encore visuellement identiques (catégorie/CMP, bloc)
   en reçoivent une. Rouge explicitement exclu, réservé aux alertes.
   Jade/indigo fixes (2026-08-09, stylisation validée par Corentin — palette
   admin) au lieu de --success/--accent : ces 2 tokens variaient selon le
   thème public actif (5 rendus différents pour la même pastille), la
   palette admin reste identique partout. */
.aca-cmp-type-pastille {
  display: inline-block;
  width: .55rem;
  height: .55rem;
  border-radius: 50%;
  margin-right: .4rem;
  vertical-align: middle;
}
.aca-cmp-type-pastille--article {
  background-color: var(--admin-jade);
}
/* .aca-cmp-type-pastille--bloc retirée (2026-08-13, correctif de Corentin,
   audit hiérarchie CMP) : plus aucun usage — confirmé qu'aucune pastille
   n'est voulue au niveau Bloc de CMP. */
/* Miniature de page publique (2026-08-09, idée de Corentin ; repositionnée
   2 fois puis rendue responsive le même jour après retours successifs —
   voir le commentaire dans admin/cmp/_content.php pour l'historique) : un
   <iframe> vers la vraie page, réduit par transform:scale plutôt qu'une
   capture d'écran serveur (aucune nouvelle dépendance). pointer-events:
   none — pure prévisualisation, jamais interactive (la page réelle reste
   à un clic sur la ligne, data-open-url déjà en place). Cellule dédiée à
   gauche du sous-tableau des blocs (seule occupante de cette <td>,
   jusqu'ici vide — voir .aca-cmp-blocs-row__thumb).
   Occupe toute la cellule, y compris au redimensionnement de colonne
   (2026-08-09, retour de Corentin — restait figée à 72×48px) :
   `width: 100%` + `aspect-ratio: 3 / 2` (mêmes proportions que l'iframe
   intrinsèque 1200×800) au lieu d'une taille fixe. L'iframe elle-même
   reste à sa résolution "desktop" plausible (1200×800, pour un rendu
   fidèle à la vraie mise en page plutôt qu'un reflow mobile à une largeur
   minuscule) ; son `transform: scale()` ne peut pas être une simple valeur
   CSS fixe puisque la largeur du conteneur varie désormais (dépend de la
   colonne) — recalculé en JS via ResizeObserver à chaque changement de
   taille du conteneur, voir le bloc "Miniature CMP" dans
   aca-categories-admin.js. La valeur `scale(.06)` ci-dessous n'est qu'un
   repli avant le premier calcul JS (ou si ResizeObserver est indisponible). */
.aca-cmp-blocs-row__thumb {
  vertical-align: top;
  padding-top: 1rem;
}
.aca-cmp-thumb {
  display: block;
  width: 100%;
  /* min-width (2026-08-09) : cette cellule est la seule du tableau visible
     dans la colonne 1 hors mode sélection (l'en-tête et les cases à cocher
     des autres lignes restent masqués, voir .aca-bulk-checkbox) — sans
     largeur minimale, `width: 100%` n'aurait aucune base solide en layout
     de tableau auto et la colonne s'effondrerait à une largeur quasi
     nulle. Le redimensionnement manuel (poignée sur l'en-tête, visible en
     mode sélection) reste libre de l'agrandir au-delà. */
  min-width: 120px;
  aspect-ratio: 3 / 2;
  overflow: hidden;
  border-radius: 4px;
  border: 1px solid var(--border);
  background: var(--bg);
  position: relative;
}
.aca-cmp-thumb iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: 1200px;
  height: 800px;
  border: 0;
  transform: scale(.06);
  transform-origin: top left;
  pointer-events: none;
}
.aca-cmp-verrouilles-separateur td {
  padding-top: 1rem;
  text-align: center;
  font-style: italic;
  opacity: .6;
  border-top: 1px dashed var(--border);
}
/* Sous-tableau des blocs d'une catégorie dépliée : légèrement en retrait
   et sur un fond distinct du reste de la ligne, pour rester visuellement
   subordonné à sa catégorie (réordonnancement propre au bloc, distinct de
   celui de la catégorie — spec §2). */
.aca-cmp-blocs-row > td {
  background-color: rgba(var(--accent-rgb), .03);
  padding-left: 1.5rem;
}
/* Carte, comme le tableau parent (2026-08-09, retour de Corentin — n'avait
   pas hérité du style appliqué au tableau externe, classe différente
   `.aca-cmp-blocs-table` ≠ `.table1`, jamais ciblée par ces règles-là).
   Même technique que `.aca-ds table.table1` (border-collapse: separate +
   border-spacing: 0, nécessaires pour que border-radius/overflow:hidden
   clippent proprement), rayon plus modeste (10px contre 14px) et pas de
   max-width/centrage : ce tableau reste toujours pleine largeur de sa
   cellule, jamais isolé au milieu d'un espace vide comme le tableau
   parent peut l'être. */
.aca-cmp-blocs-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
  box-shadow: var(--card-shadow);
  margin: .25rem 0 .5rem;
}
.aca-cmp-blocs-table tbody tr:not(:last-child) > td {
  border-bottom: 1px dashed var(--border);
}
.aca-cmp-blocs-table__vide td {
  color: var(--border);
  font-style: italic;
}
/* En-tête discret (2026-08-09, stylisation validée par Corentin) : petites
   capitales, même esprit que l'en-tête du tableau parent (.table1 thead)
   mais plus sobre, ce sous-tableau restant visuellement subordonné à sa
   catégorie. Colonnes étroites (Titre caché/Ordre/Actions) : largeur 1%
   (le minimum pour tenir leur contenu) + nowrap, "Bloc" récupère tout
   l'espace restant — corrige "Cacher le titre" qui semblait collé au nom
   du bloc faute de colonnes délimitées. */
.aca-cmp-blocs-table thead th {
  text-align: left;
  font-size: .68rem;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--muted);
  font-weight: 700;
  padding: .3rem .75rem .5rem 0;
  border-bottom: 1px solid var(--border);
}
.aca-cmp-blocs-table__col-etroite {
  width: 1%;
  white-space: nowrap;
}
/* Séparateur visuel de menu (correctifs post-test, point 6 ; généralisé au
   ☰ public au round 2) : ligne pointillée, pour rester visuellement
   distinct d'une vraie entrée. Règle de base scopée à `li`/`span`
   (contextes ☰/pied de page, éléments bruts hors tableau) ; `td` ciblé
   séparément en plus pour la page dédiée (tableau), `.aca-admin-live-panel`
   en plus pour le panneau Administrer (moins de padding, pas de bordure
   haute) — voir plus bas dans ce fichier.
   Sélecteur volontairement scopé à `li`/`span` (pas de classe nue,
   correctifs round 6, 2026-07-18) : appliqué tel quel à la `<tr>` du
   tableau Catégories, `display: block` sortait la ligne du modèle de mise
   en page tableau — ses `<td>` (restés `display: table-cell`) ne
   participaient plus à la grille de colonnes réelle, d'où un texte décalé
   à gauche et wrappé caractère par caractère au lieu de s'aligner sous
   "Titre". Sans cette règle sur la `<tr>`, elle garde son
   `display: table-row` natif. */
li.aca-categories-admin__separateur,
span.aca-categories-admin__separateur {
  display: block;
  text-align: center;
  font-style: italic;
  opacity: .75;
  padding: .35rem 0;
  border-top: 1px dashed var(--border);
  border-bottom: 1px dashed var(--border);
}
/* Alignée à gauche (pas centrée) pour matcher l'alignement par défaut des
   `<td>` normaux de ce tableau (round 6) : les flèches ↑/↓ ont été
   déplacées dans cette même cellule (voir admin/categories/index.php), la
   règle couvre donc aussi leur espacement avec le texte du titre. */
.aca-categories-admin__separateur td {
  border-top: 1px dashed var(--border);
  border-bottom: 1px dashed var(--border);
  text-align: left;
  font-style: italic;
  opacity: .75;
}
.aca-categories-admin__separateur form.deplacer {
  margin-right: .5rem;
}

/* ==========================================================================
   Édition en direct des menus sur le site réel (point 3, refonte Lot 2,
   2026-07-17). Le HTML des poignées/+ ajouter n'existe que pour un
   visiteur ayant le rôle admin (rendu côté PHP), toujours visible pour lui
   — pas de bouton "Mode édition" (retiré le même jour, correctifs
   post-test : il n'avait aucun effet réel, le glisser-déposer marchait déjà
   qu'il soit activé ou non). Poignée ⁝⁝ retirée visuellement (correctifs
   round 2) : `draggable` était déjà posé sur la ligne entière, jamais sur
   la poignée elle-même — la retirer du HTML ne change rien au mécanisme,
   seul l'indice visuel (curseur "grab") se déplace ici sur la ligne.
   ========================================================================== */
.aca-live-edit__draggable {
  cursor: grab;
}
.aca-live-edit__draggable:active {
  cursor: grabbing;
}
[data-live-menu] [data-element-id] {
  transition: opacity .1s ease;
}
[data-live-menu] [data-element-id][draggable="true"]:active {
  opacity: .6;
}

.aca-live-edit-modale {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 1050;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, .5);
}
.aca-live-edit-modale__panneau {
  max-width: 360px;
  margin: 1rem;
}
.aca-live-edit-modale__texte {
  margin-bottom: 1rem;
}

/* 2e icône ☰ dédiée au menu Administrer (point 6, correctifs post-test) :
   couleur distincte de la 1ère icône ☰ pour que les deux ne se confondent
   jamais au premier coup d'œil, sur --danger plutôt qu'une teinte inventée
   (déjà un token existant, lisible sur le fond sombre de la nav comme
   --bg l'est pour l'icône ☰ normale). */
.aca-admin-live-toggle__icon {
  border-color: var(--danger);
  color: var(--danger);
}
.aca-admin-live-toggle__icon:hover,
.aca-admin-live-toggle__icon:focus {
  background-color: var(--danger);
  color: var(--danger-contrast);
}
/* Icône ☰ à couleur dynamique (2026-08-01, Spec_fusion_CMP.md, Lot 4) :
   remplace .aca-enseignant-live-toggle__icon (couleur bleue fixe, retirée)
   — --icone-couleur posée en style inline par menuLiveEditPanel.php depuis
   `menus.couleur` (pastille de l'admin CMP). Contraste au survol toujours
   blanc (comme --danger-contrast dans les 5 thèmes) : pas de calcul de
   luminance par couleur, limitation connue et acceptée si une couleur très
   claire est choisie. */
.aca-menu-live-toggle__icon {
  border-color: var(--icone-couleur);
  color: var(--icone-couleur);
}
.aca-menu-live-toggle__icon:hover,
.aca-menu-live-toggle__icon:focus {
  background-color: var(--icone-couleur);
  color: #FFFFFF;
}
.aca-admin-live-panel {
  min-width: 260px;
  max-height: 70vh;
  overflow-y: auto;
}
/* Titre uniformisé (2026-08-12, Chantier 5 "menus déroulants admin") :
   même classe pour les 4 panneaux MENU/ENSEIGNANT/ADMINISTRER/PARAMÈTRE
   (menuLiveEditPanel.php + parametresPanel.php) — même taille/majuscules/
   centrage garantis par construction plutôt que par 2 règles dupliquées. */
.aca-admin-live-panel__titre {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .35em;
  margin: 0 0 .5rem;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: .9rem;
  text-align: center;
  text-transform: uppercase;
  letter-spacing: .04em;
}
/* Icône répétée à gauche du titre (même glyphe/couleur que le <summary> de
   l'icône ☰/⚙️ du panneau) — .aca-menu-live-toggle__icon/
   .aca-admin-live-toggle__icon ne fournissent ici que leur `color`, la
   `border-color` ne s'applique pas (span sans bordure). */
.aca-admin-live-panel__titre-icone {
  font-size: 1rem;
  line-height: 1;
}
.aca-admin-live-panel ul[data-live-menu] {
  list-style: none;
  margin: 0;
  padding: 0;
}
.aca-admin-live-panel li[data-element-id] {
  padding: .35rem .25rem;
  border-bottom: 1px solid var(--border);
}
.aca-admin-live-panel .aca-categories-admin__separateur {
  padding: .35rem .25rem;
  border-top: none;
  border-bottom: 1px dashed var(--border);
}

/* ==========================================================================
   ERGONOMIE MOBILE DES MENUS ☰ (2026-07-31, Spec_reste_backoffice.md §6,
   Option A déjà tranchée avec Corentin) — placé APRÈS .aca-admin-live-panel
   ci-dessus délibérément : même spécificité de sélecteur, seul l'ordre dans
   la feuille de style départage lequel gagne à ces largeurs, sans ce bloc
   plus bas .aca-admin-live-panel (min-width/max-height fixes) l'emporterait
   sur le plein écran voulu ici pour les icônes secondaires. Cible
   .aca-nav-overflow__panel : classe commune au ☰ public ET à toute icône
   générée par menuLiveEditPanel.php (généralisé au Lot 4 de
   Spec_fusion_CMP.md, un nouveau menu créé en base hérite automatiquement
   de cette ergonomie, aucune modification de markup nécessaire pour lui).
   ========================================================================== */
/* Bouton de fermeture explicite (croix), ajouté en 1er enfant de chaque
   panneau — voir templates/default.php/menuLiveEditPanel.php. Masqué par
   défaut (desktop, où le
   panneau reste un petit dropdown ancré sur l'icône ☰ — un re-tap dessus
   suffit à le refermer, ce bouton n'a de sens qu'en plein écran). Cette
   règle de base DOIT rester avant le bloc @media ci-dessous (même
   spécificité de sélecteur : la dernière règle du fichier l'emporte,
   media query ou pas — un piège déjà trouvé et corrigé une fois ici avant
   même un premier test). */
.aca-nav-overflow__fermer {
  display: none;
  position: absolute;
  top: .5rem;
  right: .5rem;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  border: 1px solid var(--border);
  border-radius: 50%;
  background: var(--panel);
  color: var(--text);
  font-size: 1.2rem;
  cursor: pointer;
}
@media (max-width: 480px) {
  .aca-nav-overflow__panel {
    position: fixed;
    inset: 0;
    width: 100%;
    max-width: 100%;
    height: 100vh;
    max-height: 100vh;
    margin: 0;
    padding: 3.5rem 1rem 1.5rem;
    border-radius: 0;
    overflow-y: auto;
    z-index: 2000;
  }
  /* Zones de tap agrandies (spec : "actuellement probablement trop
     petites pour le doigt") — remplace le padding desktop (.5rem). */
  .aca-nav-overflow__panel > li > a,
  .aca-admin-live-panel li[data-element-id] a {
    padding: 1rem .5rem;
    font-size: 1.05rem;
  }
  .aca-admin-live-panel li[data-element-id] {
    padding: 0;
  }
  .aca-nav-overflow__fermer {
    display: flex;
  }
}
/* Accordéon des sections (2026-07-31, spec : "un tap sur un groupe déplie
   ses sous-éléments") — chaque séparateur devient le déclencheur du groupe
   qui le suit (jusqu'au séparateur suivant ou la fin de liste), voir
   aca-menu-mobile.js pour la logique de repli/dépli. N'affecte QUE le
   rendu mobile : desktop garde les séparateurs purement visuels
   d'aujourd'hui, aucune classe .aca-menu-section-repliee n'y est jamais
   posée (le JS vérifie la largeur d'écran avant d'agir). */
@media (max-width: 480px) {
  .aca-menu-section-repliee {
    display: none;
  }
  .aca-categories-admin__separateur.aca-menu-section-toggle {
    cursor: pointer;
  }
  .aca-categories-admin__separateur.aca-menu-section-toggle::after {
    content: ' ▸';
  }
  .aca-categories-admin__separateur.aca-menu-section-toggle[aria-expanded="true"]::after {
    content: ' ▾';
  }
}
/* Verrou de scroll du corps de page pendant qu'un des 3 menus est ouvert
   en plein écran mobile (spec : "le reste de la page ne doit pas défiler
   derrière") — classe posée/retirée par aca-menu-mobile.js sur l'event
   natif "toggle" des <details>. */
body.aca-menu-mobile-ouvert {
  overflow: hidden;
}

/* .aca-enseignant-live-toggle__icon (couleur bleue #2C5F8A fixe) retirée
   (2026-08-01, Spec_fusion_CMP.md, Lot 4) : remplacée par
   .aca-menu-live-toggle__icon (couleur dynamique via --icone-couleur,
   voir plus haut) — le menu 'enseignant' porte désormais cette même
   couleur #2C5F8A en base (table `menus`, voir migration_table_menus.sql),
   apparence strictement identique. */

/* ==========================================================================
   REFONTE ÉDITEUR D'ARTICLE — Groupe A (2026-07-22)
   Options regroupées en haut de admin/articles/edit.php (catégorie,
   largeur, visibilité, version petite) + affichage des rôles autorisés.
   ========================================================================== */
.aca-article-options {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1rem 1.25rem;
  margin-bottom: 1.5rem;
}
.aca-roles-autorises {
  display: inline-block;
  margin-left: .75rem;
  font-size: .85rem;
  color: var(--muted);
}
/* Droits par article (Groupe A, 2026-07-23) : liste de cases à cocher,
   scrollable si longue (utilisateurs notamment). */
.aca-droits-liste {
  max-height: 160px;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: .5rem .75rem;
  margin-bottom: 1rem;
  background: var(--bg);
}
.aca-droits-liste__item {
  display: block;
  font-weight: 400;
  padding: .15rem 0;
}
/* Menus déroulants (2026-07-23, retour de Corentin) : les 2 listes de
   droits ci-dessus repliées par défaut dans un <details>/<summary> — même
   mécanisme zéro-JS que .aca-categories-admin__ajouter (marker natif
   masqué, <summary> stylé comme un bouton). .aca-droits-liste (ci-dessus)
   garde son style inchangé, affichée seulement une fois le <details>
   ouvert. */
.aca-droits-details {
  margin-bottom: 1rem;
}
.aca-droits-details summary {
  list-style: none;
  cursor: pointer;
}
.aca-droits-details summary::-webkit-details-marker {
  display: none;
}
.aca-droits-details summary.aca-btn {
  display: inline-block;
}
.aca-droits-details[open] summary {
  margin-bottom: .5rem;
}
/* Éditeur + son propre aperçu, côte à côte (2026-07-25, précision de
   Corentin sur le Groupe 2 : chaque aperçu doit être à côté de SON éditeur,
   pas regroupé avec l'autre aperçu en bas de page). flex + flex-wrap, même
   technique que .aca-page-layout (voir plus haut) : retombe sur
   l'empilement vertical dès que la largeur manque pour les deux colonnes,
   sans media query dédiée. */
.aca-editeur-avec-apercu {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 1.5rem;
  margin-bottom: 1rem;
}
.aca-editeur-avec-apercu__editeur {
  flex: 3 1 480px;
  min-width: 0;
}
.aca-editeur-avec-apercu__apercu {
  flex: 1 1 280px;
  min-width: 0;
}
/* Aperçu live (2026-07-24, demande de Corentin) : encadré en pointillés
   pour signaler visuellement "ceci est un aperçu approximatif", pas la
   page publique réelle (voir editor-app/src/apercuArticle.ts). La carte
   occupe 100% de cette colonne (plus de .aca-article-grid l'entourant
   depuis le 2026-07-25 : la fraction de largeur --wN n'a de sens que dans
   la grille PUBLIQUE, à côté d'autres cartes — ici la carte est seule dans
   sa propre colonne, grid-column est un no-op hors d'un conteneur grid). */
.aca-apercu-grid {
  border: 1px dashed var(--border);
  border-radius: var(--radius);
  padding: 1rem;
}

/* Bouton "Quitter" (2026-07-22) : état visuel du bouton Sauvegarder selon
   qu'il y a ou non des modifications non enregistrées, voir
   web/editor-app/src/main.tsx. */
#btn-sauvegarder.aca-btn--non-enregistre {
  background: var(--danger);
  border-color: var(--danger);
  color: var(--danger-contrast);
}
/* Corbeille générique (2026-07-23, voir App\Corbeille\ + aca-corbeille.js).
   Icône en haut à droite de chaque tableau admin migré (Techniques,
   Attaques, Catégories pour l'instant). */
.aca-corbeille-icone {
  display: inline-block;
  /* x1.5 (2026-08-09, retour de Corentin) : taille ET fanion (padding)
     agrandis dans les mêmes proportions, la cible cliquable grandit avec
     l'icône plutôt que de rester collée à un texte plus gros. */
  font-size: 1.95rem;
  line-height: 1;
  padding: .45rem .825rem;
  border-radius: var(--radius);
  text-decoration: none;
  /* 100px après le dernier bouton du bandeau d'actions (2026-08-09, corrigé
     le même jour — retour de Corentin : correct seulement sur CMP, plaquée
     à l'extrême droite de l'écran sur Articles/Images/etc.). Cause : l'
     ancien `float: right` sortait l'icône du flux normal, où elle se
     positionne par rapport aux AUTRES flottants du conteneur (aucun ici),
     pas par rapport à ses frères .aca-btn (inline-block, pas flottants) —
     le margin-left ne comptait donc que depuis le bord du conteneur, pas
     depuis le dernier bouton réel. Sans float, l'icône reste dans le flux
     normal juste après le dernier bouton (déjà son ordre dans le HTML),
     et margin-left crée bien l'écart demandé avec CE bouton précis, quel
     que soit leur nombre. */
  margin-left: 100px;
  transition: background .15s, color .15s;
}
.aca-corbeille-icone:hover {
  background: var(--border);
}
.aca-corbeille-icone--survol-glisser {
  background: var(--danger);
  color: var(--danger-contrast);
}
/* Cases à cocher masquées par défaut (2026-08-09, retour de Corentin) :
   révélées par double-clic sur l'icône 🗑️ associée (aca-corbeille.js pose
   .aca-bulk-mode sur la <table>) — colonne autrement inutile la plupart du
   temps depuis le retrait de la colonne Actions. :has() déjà utilisé
   ailleurs sur ce site (.aca-theme-switcher__option), même palier de
   support navigateur. */
.aca-ds table.table1 th:has(> input.aca-select-all),
.aca-ds table.table1 td:has(> input.aca-bulk-checkbox) {
  display: none;
}
.aca-ds table.table1.aca-bulk-mode th:has(> input.aca-select-all),
.aca-ds table.table1.aca-bulk-mode td:has(> input.aca-bulk-checkbox) {
  display: table-cell;
}
/* Colonnes redimensionnables à la souris (2026-08-09, retour de Corentin
   — voir aca-table-column-resize.js). Poignée fine sur le bord droit de
   chaque <th>, visible seulement au survol pour ne pas alourdir
   visuellement l'en-tête en permanence. */
.aca-ds table.table1 th.aca-col-resizable {
  position: relative;
}
.aca-col-resize-handle {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 6px;
  cursor: col-resize;
  user-select: none;
  z-index: 2;
}
.aca-col-resize-handle:hover {
  background: rgba(var(--accent-rgb), .45);
}
body.aca-col-resizing {
  cursor: col-resize;
  user-select: none;
}
body.aca-col-resizing .aca-col-resize-handle {
  background: rgba(var(--accent-rgb), .45);
}
/* Lien "→" sur le titre de chaque section Corbeille (2026-08-07,
   Spec_ergonomie_admin_cmp.md, Chantier 4) : ramène à l'écran admin de
   gestion normale de ce type, en plus de l'ancre de navigation déjà en
   place — pour voir le contexte avant de restaurer/purger. Discret (taille
   réduite, opacité) pour ne pas rivaliser visuellement avec le titre H1
   lui-même. */
.aca-corbeille-lien-categorie {
  font-size: 1rem;
  opacity: .6;
  text-decoration: none;
}
.aca-corbeille-lien-categorie:hover {
  opacity: 1;
}
/* Fiche au clic sur une ligne Corbeille (2026-08-09, retour de Corentin) :
   images/vidéos/fichiers/articles seulement — voir admin/corbeille/
   _content.php/aca-corbeille.js. */
.aca-ds table.table1 tbody tr.aca-corbeille-ligne-cliquable {
  cursor: pointer;
}
.aca-ds table.table1 tbody tr.aca-corbeille-fiche:hover > td {
  background-color: transparent;
}
/* Survol de section pendant un glisser-déposer entre groupes (2026-07-29,
   unification CMP — voir aca-categories-admin.js) : même principe que
   .aca-corbeille-icone--survol-glisser ci-dessus mais moins appuyé (une
   section entière, pas une petite icône), sur l'en-tête .aca-table-section
   pour rester visible même avec beaucoup de lignes en dessous. */
.aca-table-section--survol-glisser .aca-table-section {
  background: var(--border);
}
/* Survol d'une ligne CMP pendant le glisser-déposer d'un bloc-CMP
   (2026-08-07, Spec_ergonomie_admin_cmp.md, Chantier 2F — voir
   aca-categories-admin.js) : même principe que .aca-table-section--survol-glisser
   ci-dessus, sur la ligne CMP cible plutôt que sur tout un groupe. */
.aca-cmp-categorie--survol-glisser > td {
  background: var(--border);
}
/* Modale de confirmation "Quitter" (2026-07-22, voir unsavedChangesGuard.ts) */
.aca-modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, .45);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 2000;
}
.aca-modal-panneau {
  max-width: 420px;
  padding: 1.5rem;
}
.aca-modal-panneau__titre {
  margin: 0 0 .5rem;
  font-family: var(--font-display);
  font-weight: 700;
}
.aca-modal-panneau__actions {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
  margin-top: 1rem;
}
/* Surbrillance temporaire après un deep-link "Voir" depuis une liste de
   dépendances bloquantes (2026-08-06, généralisation du système de
   dépendances bloquantes — voir aca-highlight-anchor.js et
   App\Corbeille\DependanceBloquante). --accent-rgb est déjà défini par
   chacun des 5 thèmes : le fondu reste cohérent partout sans code
   supplémentaire par thème. */
@keyframes aca-surbrillance-fondu {
  from { background-color: rgba(var(--accent-rgb), .35); }
  to   { background-color: transparent; }
}
.aca-surbrillance-cible {
  animation: aca-surbrillance-fondu 2.5s ease-out;
}
