/* =========================================================================
   BACKEND.CSS - feuille pilote du back-office
   -------------------------------------------------------------------------
   Feuille unique de l'interface : jetons, base, mise en page, surcouche
   Bootstrap, SweetAlert2, utilitaires et compatibilité navigateurs.
   Une seule déclaration par couple sélecteur + propriété : aucune règle
   n'en écrase une autre du même fichier.

   Ordre de chargement
     bootstrap.css   → base du framework
     all.min.css     → police d'icônes (Phosphor duotone)
     backend.css     → CE FICHIER : jetons + interface
     tools.css       → composants maison (tableau, éditeur, calendrier à venir)

   Les jetons définis en section 01 (couleurs dérivées, échelle typographique,
   tailles de bouton, rayons) pilotent aussi tools.css : ne pas les déplacer.

   Sommaire
     01. Jetons                couleurs, typographie, tailles, rayons
     02. Base                  reset léger, typographie de fond, animations
     03. Mise en page          navbar, bandeau, menus, barres latérales
     04. Composants Bootstrap  cartes, modales, formulaires, boutons, onglets
     05. Utilitaires           texte, icônes, compatibilité, impression
   ========================================================================= */

/* =========================================================================
   POLICE - Open Sans, servie par le projet (remplace Lato)
   -------------------------------------------------------------------------
   Auparavant un @import vers fonts.googleapis.com. Placé en tête de feuille,
   un @import BLOQUE le rendu de tout le reste tant que le serveur distant n'a
   pas répondu : sur un poste hors ligne ou derrière un DNS lent, la page
   attendait le délai d'expiration à chaque chargement.

   Seules les graisses employées par le projet sont embarquées - 300, 400, 700
   et 900, plus l'italique 400 pour <em>. Les graisses 500 et 600 que Bootstrap
   demande n'existent pas chez Open Sans : le navigateur les approche depuis
   400 et 700, comme il le faisait déjà avec Lato. Open Sans elle-même ne va
   que jusqu'à 800 (ExtraBold) - la graisse 900 embarquée ici EST ce 800,
   sous cette étiquette, pour ne rien changer au reste de la feuille.

   woff2 seul : tous les navigateurs qui font tourner cet ERP le lisent.
   ========================================================================= */

@font-face {
   font-family: 'Open Sans';
   font-style: normal;
   font-weight: 300;
   font-display: swap;
   src: url('../font/opensans-300-normal.woff2') format('woff2');
}

@font-face {
   font-family: 'Open Sans';
   font-style: normal;
   font-weight: 400;
   font-display: swap;
   src: url('../font/opensans-400-normal.woff2') format('woff2');
}

@font-face {
   font-family: 'Open Sans';
   font-style: italic;
   font-weight: 400;
   font-display: swap;
   src: url('../font/opensans-400-italic.woff2') format('woff2');
}

@font-face {
   font-family: 'Open Sans';
   font-style: normal;
   font-weight: 700;
   font-display: swap;
   src: url('../font/opensans-700-normal.woff2') format('woff2');
}

@font-face {
   font-family: 'Open Sans';
   font-style: normal;
   font-weight: 900;
   font-display: swap;
   src: url('../font/opensans-900-normal.woff2') format('woff2');
}

/* KFGQPC HAFS - texte arabe, tout l'ERP (abdAllah, 30/09 : remplace Noto
   Sans Arabic). KFGQPC WARSH - déclarée pour la lecture Warsh (futur module
   Qour'an) ; le navigateur ne la télécharge que si un élément l'emploie.
   Polices du Complexe Roi Fahd (fonts.qurancomplex.gov.sa), auto-hébergées
   comme Open Sans. LICENCE (lire font/LICENCE-KFGQPC.txt) : usage, copie et
   distribution gratuits ; ni vente, ni modification - fichiers laissés tels
   que fournis, jamais sous-ensemblés ni convertis.
   Une seule graisse (400) : le gras éventuel est simulé par le navigateur.
   S'applique automatiquement à tout texte marqué dir="rtl" ou lang="ar",
   sans toucher à Open Sans pour le reste de l'interface ; ces polices n'ont
   pas de latin, le repli passe à la police suivante. */
@font-face {
   font-family: 'KFGQPC Hafs';
   font-style: normal;
   font-weight: 400;
   font-display: swap;
   src: url('../font/kfgqpc-hafs-v18.woff2') format('woff2');
}

@font-face {
   font-family: 'KFGQPC Warsh';
   font-style: normal;
   font-weight: 400;
   font-display: swap;
   src: url('../font/kfgqpc-warsh-v10.woff2') format('woff2');
}

/* 1.35rem (abdAllah, 30/09) : l'œil de Hafs est petit, à 1.1rem l'arabe
   paraissait plus petit que le français voisin. */
[dir="rtl"], [lang="ar"] {
   font-family: 'KFGQPC Hafs', 'Open Sans', sans-serif;
   font-size: 1.35rem;
}

/* Les champs de saisie : `.form-control` fixe sa propre taille plus loin
   (--fs-sm) ; le sélecteur qualifié par la balise passe devant. */
input.form-control[dir="rtl"], textarea.form-control[dir="rtl"],
input.form-control[lang="ar"], textarea.form-control[lang="ar"] {
   font-size: 1.35rem;
}

/* ========================================================================
   01. JETONS - couleurs, typographie, tailles, rayons
   ======================================================================== */

:root {
   --dominante-color: #065d89;
   --dominante-rgb: 6, 93, 137;

   /* Hauteur de la navbar. Elle était recopiée à quatre endroits - la navbar
      elle-même, le haut de la barre latérale et sa hauteur, le haut de
      l'en-tête de page - auxquels s'ajoutent les notifications, qui doivent se
      poser dessous. La changer imposait de retrouver chaque copie. */
   --navbar-h: 60px;

   /* Couleurs d'état : succès, erreur, avertissement. Seul endroit du projet
      où elles sont écrites ; dialogues, validation et Bootstrap y renvoient. */
   --state-success: #249934;
   --state-error: #d64545;
   --state-warning: #e8a33d;

   /* Teintes claires des mêmes états, pour les fonds d'alerte. Écrites en
      dur : ce sont les seules couleurs du projet qui ne dérivent pas de la
      dominante, leurs déclinaisons non plus. */
   --state-success-bg: #e9f6eb;
   --state-success-line: #bfe3c5;
   --state-error-bg: #fbeaea;
   --state-error-line: #f2c4c4;
   --state-warning-bg: #fdf3e5;
   --state-warning-line: #f6ddb5;
   --dominante-color-hover: #0786c5;
   --body-bg-light: #f7f7f7;
   --menu-bg-light: #f2f2f2;
   --menu-bg-dark: #2c2c2c;
   --text-color: #111;
   --transition-speed: 0.4s;
   --font-ui: "Open Sans", system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
   --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
   --fs-2xs: 0.75rem;
   --fs-xs: 0.8125rem;
   --fs-sm: 0.9rem;
   --fs-base: 0.9rem;
   /* Surcharge de la variable Bootstrap pour que .form-control,
      .form-select, etc. suivent automatiquement notre taille. */
   --bs-body-font-size: 0.9rem;
   --fs-md: 1.0625rem;
   --fs-lg: 1.25rem;
   --fs-xl: 1.5rem;
   --fs-2xl: 1.875rem;
   --fs-title: 1.375rem;
   --fs-clock: 1.375rem;
   --lh-tight: 1.15;
   --lh-snug: 1.35;
   --lh-normal: 1.55;
   --lh-loose: 1.7;
   --fw-light: 300;
   --fw-regular: 400;
   --fw-bold: 700;
   --fw-black: 900;
   --ls-caps: .05em;
   --ls-title: -.01em;
   --panel: #ffffff;
   --panel-soft: #eef0f4;
   --line: #e1e4ea;
   --slate: #5b6174;
   --slate-dim: #9198aa;
   --radius-panel: 0;
   --radius-field: 5px;
   --btn-h-sm: 28px;
   --btn-h-md: 34px;
   --btn-h-lg: 42px;
   --btn-px-sm: .6rem;
   --btn-px-md: .8rem;
   --btn-px-lg: 1.15rem;
   --btn-fs-sm: var(--fs-xs);
   --btn-fs-md: var(--fs-sm);
   --btn-fs-lg: var(--fs-base);
   --shadow-panel: 0 1px 3px rgba(20, 23, 31, .08);
   --fs-panel-title: 0.97rem;
   --fs-panel-sub: 0.75rem;
}

[data-theme="dark"] {
   /* LE JETON DE TEXTE BASCULE ICI, et c'est le correctif le plus important
      de ce thème. body pose `color: var(--text-color)`, donc TOUT le texte de
      l'application en hérite. Tant que --text-color valait #111 dans les deux
      thèmes, chaque élément qui ne redéfinissait pas sa couleur - options des
      listes déroulantes, paragraphes d'introduction, contenu des onglets -
      s'affichait en noir sur l'anthracite, donc invisible. Les règles sombres
      écrites jusqu'ici ne faisaient que rattraper des cas particuliers.

      Le basculement est sans danger : les cinq usages du jeton sont tous des
      avant-plans posés sur des surfaces qui basculent elles aussi, et aucun
      fond clair du thème sombre ne compte sur un texte foncé hérité. */
   --text-color: #f3f4f7;

   /* Bootstrap a ses PROPRES jetons de couleur, que le projet ne remappe que
      partiellement. --bs-secondary-color vaut rgba(33,37,41,.75) - un gris
      presque noir - et sert de couleur à .form-text, .text-muted, caption et
      .figure-caption. Les blocs d'aide au-dessus des arbres étaient donc
      illisibles, sans qu'aucune règle du projet soit en cause.

      La valeur reprise est celle du thème sombre de Bootstrap lui-même. On ne
      touche PAS à --bs-body-color : les champs de saisie gardent le fond blanc
      de Bootstrap en mode sombre, et un texte clair y deviendrait invisible. */
   --bs-secondary-color: rgba(222, 226, 230, .75);
   --bs-secondary-color-rgb: 222, 226, 230;

   --panel: #1a1e29;
   --panel-soft: #20242f;
   --line: #2b303d;
   --slate: #8a91a6;
   --slate-dim: #5b6174;
   --shadow-panel: 0 1px 2px rgba(0, 0, 0, .2);
}

@supports (font-size:clamp(1rem,1vw,2rem)) {
   :root {
      --fs-title: clamp(1.375rem, 1.15rem + 1.05vw, 1.875rem);
      --fs-clock: clamp(1.375rem, 1.15rem + 1.05vw, 1.75rem);
   }

}

@keyframes spin {
   0% {
      transform: rotate(0deg);
   }

   100% {
      transform: rotate(360deg);
   }
}

/* ========================================================================
   02. BASE - reset léger, typographie de fond, animations
   ======================================================================== */

hr {
   border: none;
   height: 1px;
   width: 100%;
   margin: 1rem auto;
   background: var(--dominante-color);
}

html {
   font-size: 100%;
   -webkit-text-size-adjust: 100%;
   text-size-adjust: 100%;
}

body {
   background: var(--body-bg-light);
   color: var(--text-color);
   transition: background var(--transition-speed), color var(--transition-speed);
   margin-bottom: 100px;
   font-family: var(--font-ui);
   font-size: var(--fs-base);
   font-weight: var(--fw-regular);
   line-height: var(--lh-normal);
   -webkit-font-smoothing: antialiased;
   -moz-osx-font-smoothing: grayscale;
}

h1,
h2,
h3,
h4,
h5,
h6,
.h1,
.h2,
.h3,
.h4,
.h5,
.h6 {
   margin-top: 0;
   margin-bottom: .5em;
   font-family: var(--font-ui);
   font-weight: var(--fw-bold);
   line-height: var(--lh-tight);
   letter-spacing: var(--ls-title);
}

h1,
.h1 {
   font-size: var(--fs-title);
   font-weight: var(--fw-black);
}

h2,
.h2 {
   font-size: var(--fs-xl);
}

h3,
.h3 {
   font-size: var(--fs-lg);
}

h4,
.h4 {
   font-size: var(--fs-md);
}

h5,
.h5,
h6,
.h6 {
   font-size: var(--fs-base);
   letter-spacing: 0;
}

h6,
.h6 {
   text-transform: uppercase;
   letter-spacing: var(--ls-caps);
   color: var(--dc-50-777777, #3f6a80);
}

p {
   margin-bottom: .75rem;
   line-height: var(--lh-normal);
}

strong,
b {
   font-weight: var(--fw-bold);
}

code,
kbd,
pre,
samp {
   font-family: var(--font-mono);
   font-size: .9375em;
}

@media (max-width:767.98px) {
   body {
      line-height: var(--lh-snug);
   }

}

@media print {
   body {
      font-size: 11pt;
      line-height: 1.4;
      /* Le fond du body (--body-bg-light, gris très clair) n'était
         jamais annulé à l'impression - universel : toute page imprimée
         du projet en souffrait. Blanc pur à l'impression, quelle que
         soit la page. */
      background: #fff;
   }

}

@media (min-width:1400px) {
   body {
      line-height: var(--lh-loose);
   }

}

/* ========================================================================
   03. MISE EN PAGE - navbar, bandeau, menus, barres latérales, chargement
   ======================================================================== */

/* LE TEXTE SUIT LE FOND (abdAllah, 01/10) : la couleur DOMINANTE sur le fond
   clair, le texte clair du thème sur le fond foncé du thème sombre.
   `!important` : certains en-têtes posent en ligne la couleur de texte de
   leur filière (composition des classes), blanche sur une filière foncée,
   donc illisible sur ce fond clair. */
.grady-light {
   background: linear-gradient(#fff, #ddd) !important;
   color: var(--dominante-color, #065d89) !important;
}

[data-theme="dark"] .grady-light {
   background: linear-gradient(var(--dc-60-333333, #184c67), var(--dc-60-k, #043852)) !important;
   color: var(--text-color, #f3f4f7) !important;
}

/* LE DÉGRADÉ FONCÉ DE LA CHARTE (abdAllah, 06/10) : la couleur DOMINANTE en bas, une teinte
   légèrement plus claire en haut, texte blanc. Le pendant de `.grady-light`. Il habille tous
   les <thead> de la charte (`.table-mc-entete`, tools.css) et le survol des menus déroulants ;
   la classe sert aussi seule, sur n'importe quel bloc. La 1re ligne est le repli des
   navigateurs sans `color-mix`. */
.grady-dark {
   background: var(--dominante-color, #065d89) !important;
   background: linear-gradient(color-mix(in srgb, var(--dominante-color, #065d89) 72%, #fff), var(--dominante-color, #065d89)) !important;
   color: #fff !important;
}

.page-header {
   top: var(--navbar-h);
   z-index: 5;
   border-left: 10px solid var(--dc-50-333333, #1d485e);
   border-right: 10px solid var(--dc-50-333333, #1d485e);
   display: flex;
   justify-content: space-between;
   flex-wrap: wrap;
   gap: .5rem;
}

#scrollTopBtn {
   position: fixed;
   bottom: 25px;
   right: 25px;
   width: 43px;
   height: 43px;
   border: none;
   border-radius: 50%;
   background: var(--dominante-color);
   color: #fff;
   font-size: 1.2rem;
   display: none;
   align-items: center;
   justify-content: center;
   box-shadow: 0 4px 8px rgba(0, 0, 0, 0.521);
   transition: transform 0.3s ease;
   z-index: 1055;
   filter: opacity(.7);
}

#scrollTopBtn:hover {
   background: var(--dc-80-k, #054a6e);
   transform: scale(1.1);
   filter: opacity(1);
}

[data-theme="dark"] #scrollTopBtn {
   background: var(--dc-30-w, #b4cedc);
   color: var(--dominante-color);
   filter: opacity(1);
}

[data-theme="dark"] #scrollTopBtn:hover {
   background: var(--dc-80-k, #054a6e);
   color: #fff;
}

.navbar {
   top: 0;
   background: var(--dc-95-k, #065882);
   z-index: 1030;
   box-shadow: 0 4px 8px rgba(0, 0, 0, .6);
   transition: background var(--transition-speed);
   height: var(--navbar-h);
}

.btn-square,
.search-group .btn,
#dropdownColor {
   background: rgba(255, 255, 255, .15);
   color: #fff;
}

.btn-square:hover,
.search-group .btn:hover,
#dropdownColor:hover {
   transform: translateY(-2px) scale(1.02);
   color: #222;
   background-color: var(--dc-50-w, #83aec4);
   box-shadow: 0 0 5px 0 #000;
}

.btn-square .ph-duotone,
.darkmode-btn .ph-duotone,
.menu-link .ph-duotone,
.menu-link .triangle {
   transition: color .3s;
}

#selectSkin {
   width: 90px;
   background-color: var(--dc-10-w, #e6eff3);
}

[data-theme="dark"] #selectSkin {
   background: var(--dc-20-3a3a3a, #30414a);
   border-color: #777;
}

.search-group {
   display: flex;
   align-items: center;
   /* Hauteur fixée EXPLICITEMENT : sans elle, un parent flex plus haut (la
      navbar fait 60px, ce groupe 42px comme ses enfants) l'étire par
      défaut (align-items: stretch, jamais annoncé nulle part mais bien la
      valeur initiale de tout conteneur flex) - l'icône et le bouton, eux,
      restent à 42px, laissant un vide visible au-dessus et en-dessous. */
   height: var(--btn-h-lg);
   flex-shrink: 0;
   margin-left: 1rem;
   /* Un contour, sans quoi le champ ne se distingue pas du fond qui le porte :
      blanc sur le panneau clair du menu, l'écart n'est que de 1,12 : 1. Le
      contour, lui, tient au-dessus de 5,9 : 1 sur toutes les dominantes.

      overflow masqué : les extrémités du groupe portent leurs propres arrondis,
      qui déborderaient du contour sans cela. */
   border: 1px solid var(--dc-80-k, #0a2a3c);
   border-radius: var(--radius-field);
   overflow: hidden;
}

/* Le focus du champ est reporté sur le GROUPE. overflow: hidden découpe le halo
   que .form-control:focus dessine autour de lui : il resterait invisible, et le
   champ ne montrerait plus qu'il a la main. Porté par le conteneur, le halo se
   déploie à l'extérieur du découpage. */
.search-group:focus-within {
   border-color: var(--dominante-color);
   box-shadow: 0 0 5px 2px var(--dc-30-t, rgba(6, 93, 137, .3));
}

.search-group .form-control:focus {
   box-shadow: none;
}

/* Affixe d'icône, comme sur les champs de formulaire */
.search-group .input-group-text {
   /* Même carré que le bouton de soumission, à l'autre bout du groupe.
      `flex: 0 0` : sur un écran étroit, un élément flexible se comprime,
      les deux extrémités doivent garder leur taille. */
   flex: 0 0 var(--btn-h-lg);
   width: var(--btn-h-lg);
   height: var(--btn-h-lg);
   padding: 0;
   justify-content: center;
   border: none;
   /* Aucun arrondi sur les enfants : c'est le conteneur .search-group qui
      arrondit et découpe (overflow masqué). Deux rayons pour un même coin ne
      peuvent pas coïncider - le bord intérieur du conteneur est décalé de
      l'épaisseur de sa bordure, et l'écart se voit. */
   border-radius: 0;
   background: var(--dc-25-w, #b6d0dd);
   /* --dc-20-k et non --dc-90-k : ce dernier reste très proche de la dominante
      et ne tenait que 3,58 : 1 sur son propre affixe avec une couleur claire
      (cyan). Celui-ci garde un soupçon de teinte tout en restant lisible -
      12,4 : 1 au pire. */
   color: var(--dc-20-k, #01131b);
}

.search-group .form-control::placeholder {
   color: rgba(17, 17, 17, .65);
}

select.sessionSelect,
#mobile-search-select select.sessionSelect {
   margin: 0 1rem;
   height: 42px;
   min-width: 130px;
   max-width: 200px;
   border-radius: 5px;
   border: none;
   font-size: 1.3rem;
   text-align: center;
   padding: .4rem .9rem;
   background: var(--dc-10-w, #e6eff3);
   color: var(--text-color);
   transition: background var(--transition-speed), color var(--transition-speed);
}

[data-theme="dark"] .sessionSelect,
[data-theme="dark"] #mobile-search-select .sessionSelect {
   background: var(--dc-20-3c3c3c, #31434b);
   color: #fff;
}

[data-theme="dark"] .search-group .form-control {
   background: var(--dc-15-3c3c3c, #344148);
   color: #fff;
}

[data-theme="dark"] .search-group .form-control::placeholder {
   color: rgba(255, 255, 255, .65);
}

#dropdown-menu {
   position: fixed;
   top: var(--navbar-h);
   left: 0;
   width: 280px;
   height: calc(100vh - var(--navbar-h));
   background: var(--menu-bg-light);
   overflow-y: auto;
   transform: translateX(-100%);
   transition: transform .4s ease, opacity .4s ease;
   z-index: 1025;
   display: flex;
   flex-direction: column;
   box-shadow: 3px 0 8px rgba(0, 0, 0, .2);
}

#dropdown-menu.show {
   transform: translateX(0);
}

.menu-items {
   flex: 1;
}

.menu-header {
   display: flex;
   flex-direction: column;
   align-items: center;
   padding: .7rem;
   border-bottom: 1px solid var(--dc-45-w, #8fb6ca);
   box-shadow: 0 2px 6px rgba(0, 0, 0, .1);
}

.menu-header .menu-main {
   display: flex;
   align-items: center;
   width: 100%;
}

.menu-header img.avatar {
   width: 60px;
   height: 60px;
   border-radius: 50%;
   margin-right: 1rem;
   flex-shrink: 0;
   border: 1px solid #c2c2c2;
   padding: 3px;
   background: #fff;
}

.menu-header .user-info {
   display: flex;
   flex-direction: column;
   flex: 1;
}

[data-theme="dark"] .menu-header .user-info {
   color: #fff;
}

.menu-header .user-info div {
   margin-bottom: .2rem;
   color: inherit;
}

/* Bouton "Mon profil", positionné en bas à droite de .menu-main
   (nav-menu.php) - lien nu, sans fond de bouton, juste une icône qui
   réagit au survol. */
.mc-profil-lien {
   color: var(--bs-secondary);
   font-size: 2rem;
   line-height: 1;
   transition: color .15s ease, transform .15s ease;
}

.mc-profil-lien:hover {
   color: var(--dominante-color);
   transform: scale(1.1);
}

[data-theme="dark"] #dropdown-menu {
   background: var(--dc-10-2c2c2c, #283135);
}

[data-theme="dark"] .menu-header {
   background: var(--dc-30-1c1c1c, #15303d);
}

[data-theme="dark"] .menu-header .menu-title {
   color: #fff;
}

#mobile-search-select {
   display: none;
   flex-direction: column;
   gap: 0;
   width: 100%;
}

#mobile-search-select select.sessionSelect,
#mobile-search-select .search-group {
   width: 100%;
   margin: 0;
   box-sizing: border-box;
}

#mobile-search-select .search-group {
   display: flex;
}

/* La règle partagée (background: rgba(255,255,255,.15)) se lit foncée sur
   le fond sombre de la navbar, mais claire sur le panneau clair du menu
   mobile - même règle, deux résultats opposés. Un fond opaque assure ici
   le même résultat visuel foncé, indépendamment du fond sous-jacent. */
#mobile-search-select .search-group .btn {
   background: var(--dominante-color);
   color: #fff;
}

#mobile-search-select .search-group .btn:hover {
   background-color: var(--dc-80-k, #054a6e);
   color: #fff;
}

.menu-link::before {
   content: "";
   position: absolute;
   left: 0;
   top: 0;
   bottom: 0;
   width: 0;
   background: none;
   transition: all .35s ease;
   z-index: 0;
}

.menu-link:hover::before {
   width: 9px;
   background: var(--dominante-color);
   clip-path: polygon(0 0, 0 100%, 100% 50%);
}

.menu-link:hover>i {
   transition: all .6s ease;
   transform: rotateX(360deg);
   margin-left: 15px;
}

.menu-link:hover .ph-duotone,
.menu-link:hover .triangle {
   color: var(--dominante-color);
}

.menu-link[aria-expanded="true"] .triangle {
   transform: rotate(180deg);
   color: var(--dc-60-w, #6a9eb8);
}

.sub-menu {
   display: flex;
   flex-direction: column;
   padding-left: 1rem;
   overflow: hidden;
   max-height: 0;
   opacity: 0;
   transition: max-height .6s ease, opacity .6s ease;
}

.sub-menu.open {
   /* 1200px et non 500 (abdAllah, 25/08) : `Profils` porte neuf entrées PLUS
      le sous-menu « Traitements » déplié - 570px au total. À 500, le menu
      était rogné et ses dernières entrées écrasées.
      La valeur ne sert qu'à animer l'ouverture : elle doit dépasser le contenu
      le plus long, sans quoi celui-ci est coupé. */
   max-height: 1200px;
   opacity: 1;
}

[data-theme="dark"] .menu-link[aria-expanded="true"] .triangle {
   color: var(--dc-90-w, #1f6d95);
}

[data-theme="dark"] .menu-link {
   color: #ccc;
   border-left-color: var(--dc-80-w, #387da1);
}

[data-theme="dark"] .menu-link .ph-duotone,
[data-theme="dark"] .menu-link .triangle {
   color: #ccc;
}

[data-theme="dark"] .menu-link:hover {
   background: var(--dc-25-k, #021722);
   color: var(--dc-40-w, #9bbed0);
   border-left-color: var(--dc-30-w, #b4cedc);
}

[data-theme="dark"] .menu-link:hover .ph-duotone,
[data-theme="dark"] .menu-link:hover .triangle {
   color: var(--dc-40-w, #9bbed0);
}

.menu-logo-etablissement {
   padding: 1rem 0;
   text-align: center;
   background: var(--panel, #fff);
}

.menu-logo-etablissement img {
   max-width: 60%;
   max-height: 90px;
}

.menu-footer {
   padding: 1.5rem 0;
   text-align: center;
   background: linear-gradient(var(--dc-10-w, #e6eff3), var(--dc-50-w, #83aec4));
   margin: 5px auto 100px;
   box-shadow: 0 5px 10px #a3a3a3;
}

.menu-footer img {
   height: 55px;
}

[data-theme="dark"] .menu-footer {
   background: linear-gradient(var(--dc-30-5f5f5f, #445e6c), var(--dc-30-1c1c1c, #15303d));
   box-shadow: 0 3px 10px #494949;
}

[data-theme="dark"] .menu-footer img {
   filter: invert(95%);
}

#horizontal-sidebar.show {
   transform: translateY(0);
   opacity: 1;
   pointer-events: auto;
}

#horizontal-sidebar.d-none {
   display: none;
}

.sidebar-link:hover {
   background: var(--dc-70-w, #518eac);
   color: #fff;
   transform: translateY(-2px) scale(1.05);
   border-color: #fff;
}

[data-theme="dark"] #horizontal-sidebar {
   background: var(--dc-30-1e1e1e, #17313e);
}

[data-theme="dark"] .sidebar-link {
   color: #ccc;
   background: var(--dc-10-1e1e1e, #1c2429);
   border-color: var(--dc-70-w, #518eac);
}

[data-theme="dark"] .sidebar-link:hover {
   background: var(--dominante-color);
   color: #fff;
   border-color: #fff;
}

.dropdown-menu {
   border-color: var(--dominante-color) !important;
   color: var(--dominante-color) !important;
   background: var(--dc-7-w, #eef4f7) !important;
   box-shadow: 0 0 5px 2px var(--dc-30-t, rgba(6, 93, 137, 0.3)) !important;
   transition: all 0.25s ease;
}

[data-theme="dark"] .dropdown-menu {
   background-color: #444 !important;
   border-color: var(--dc-40-w, #9bbed0) !important;
   box-shadow: 0 0 0.3rem #aaa !important;
}

#pageLoader {
   position: fixed;
   inset: 0;
   background: var(--bs-body-bg, #fff);
   display: flex;
   justify-content: center;
   align-items: center;
   z-index: 2000;
   transition: opacity 0.4s ease, visibility 0.4s ease;
}

#pageLoader.hidden {
   opacity: 0;
   visibility: hidden;
}

[data-theme="dark"] #pageLoader {
   background: #121212;
}

.loader-content {
   text-align: center;
   display: flex;
   flex-direction: column;
   align-items: center;
}

.spinner-wrapper {
   position: relative;
   width: 110px;
   height: 110px;
   display: flex;
   justify-content: center;
   align-items: center;
}

/* L'EMBLÈME COLORÉ (images/spinner.png, abdAllah, 12/10), en clair comme en sombre, au centre de
   l'anneau (110 px). */
.loader-img {
   width: 64px;
   height: 64px;
   object-fit: contain;
   position: absolute;
   z-index: 3;
}

.spinner-ring {
   position: absolute;
   width: 110px;
   height: 110px;
   border-radius: 50%;
   border: 0.19rem solid var(--dc-20-w, #cddfe7);
   z-index: 1;
}

.spinner-arc {
   position: absolute;
   width: 110px;
   height: 110px;
   border-radius: 50%;
   border: 0.17rem solid transparent;
   border-top-color: var(--dominante-color);
   z-index: 2;
   animation: spin 1s linear infinite;
}

[data-theme="dark"] .loader-text {
   color: var(--dc-30-w, #b4cedc);
}

.page-header,
.navbar,
table.mc-table thead th,
.mc-editor-toolbar {
   position: sticky;
}

#pageLoader,
.mc-loading,
.mc-dialog-backdrop,
.mc-editor.mc-fullscreen {
   top: 0;
   right: 0;
   bottom: 0;
   left: 0;
}

.mc-table-scroll,
.mc-editor-content,
.mc-menu,
#dropdown-menu,
#horizontal-sidebar {
   -webkit-overflow-scrolling: touch;
}

.mc-menu-holder {
   position: relative;
}

.mc-menu-end {
   left: auto;
   right: 0;
}

.mc-menu-item:hover,
.mc-menu-item:focus-visible {
   background: var(--mc-surface-alt);
   color: var(--mc-accent);
   border-left-color: var(--mc-accent);
   border-right-color: var(--mc-accent);
}

/* La case de coche ne réserve sa place que là où il y a quelque chose à
   cocher. Le menu des exports n'a pas d'état - seul celui des colonnes marque
   aria-checked - et son gabarit vide décalait les icônes vers la droite sans
   rien annoncer. */
.mc-menu-item:not([aria-checked]) .mc-check {
   display: none;
}

.mc-menu-item .mc-check {
   flex: 0 0 auto;
   width: 1rem;
   text-align: center;
   color: var(--mc-accent);

   /* En gras : c'est un simple caractère ✓, et à la graisse du libellé il se
      distinguait mal de la ponctuation environnante. */
   font-weight: var(--fw-bold);

   visibility: hidden;
}

.mc-menu-item[aria-checked="true"] .mc-check {
   visibility: visible;
}

.mc-spinner {
   width: 34px;
   height: 34px;
   border: 3px solid var(--mc-border);
   border-top-color: var(--mc-accent);
   border-radius: 50%;
   -webkit-animation: mc-spin .8s linear infinite;
   animation: mc-spin .8s linear infinite;
}

#current-time,
.mc-info,
.mc-page-btn,
.mc-editor-count,
.mc-textarea-counter,
td[data-label="Montant"] {
   font-variant-numeric: tabular-nums;
   -moz-font-feature-settings: "tnum";
   -webkit-font-feature-settings: "tnum";
   font-feature-settings: "tnum";
}

.navbar .btn-square {
   font-size: var(--fs-base);
}

.menu-header .menu-title {
   font-size: var(--fs-lg);
   font-weight: var(--fw-black);
   color: var(--dominante-color);
   margin: 1rem 0 .5rem;
   text-align: center;
   line-height: var(--lh-tight);
   letter-spacing: var(--ls-caps);
   text-transform: uppercase;
}

.menu-main .user-info {
   line-height: var(--lh-snug);
}

#user-firstname,
#user-lastname {
   font-size: var(--fs-base);
}

#user-id {
   font-weight: var(--fw-bold);
}

.menu-link {
   position: relative;
   display: flex;
   align-items: center;
   width: 100%;
   padding: .75rem 1rem;
   /* --dc-80-k et non --dc-60-w : ce dernier ne tenait que 2,2 à 3,0 : 1 sur le
      panneau #f2f2f2 selon la dominante - très en dessous du seuil de 4,5 : 1
      exigé pour du texte, et d'autant plus bas que la couleur est claire.
      La teinte reste celle de la charte, seule sa profondeur change. */
   color: var(--dc-80-k, #0a2a3c);
   text-decoration: none;
   border-bottom: 1px solid rgba(0, 0, 0, .1);
   border-left: 7px solid var(--dc-40-w, #9bbed0);
   transition: background .3s, border-left-color .3s, color .3s, transform .25s;
   overflow: hidden;
   font-size: var(--fs-base);
   line-height: var(--lh-snug);
}

/* Compteur à droite d'un lien de menu (nav-menu.php) - la couleur dominante
   de la charte, pas le gris générique Bootstrap. ms-auto pousse le badge à
   droite dans le .menu-link déjà flex. */
.mc-menu-compteur {
   margin-left: auto;
   min-width: 1.2rem;
   padding: .1rem .4rem;
   border-radius: 999px;
   background: var(--dominante-color, #065d89);
   color: #fff;
   font-size: .7rem;
   font-weight: var(--fw-bold);
   line-height: 1.25;
   text-align: center;
}

.sub-menu .menu-link {
   font-size: var(--fs-sm);
}

.menu-link:hover {
   background: rgba(0, 0, 0, .05);
   color: var(--dominante-color);
   font-weight: var(--fw-bold);
   border-left-color: var(--dominante-color);
}

.menu-link .triangle {
   margin-left: auto;
   transition: transform .3s, color .3s;
   font-size: var(--fs-2xs);
}

.loader-text {
   margin-top: 1rem;
   font-size: var(--fs-md);
   color: var(--dominante-color);
   letter-spacing: var(--ls-caps);
}

.mc-btn,
.mc-menu-item,
.mc-page-btn,
.mc-select {
   font-size: 1rem;
}

.btn .ph-duotone+span,
.menu-link .ph-duotone,
.mc-menu-item .ph-duotone {
   margin-right: 0;
}

/* Les icônes suivaient la taille du texte (.85rem) : trop petites pour se lire
   d'un coup d'œil dans une liste où elles distinguent les formats. */
.mc-menu-item .ph-duotone {
   font-size: 1.15rem;
   flex: 0 0 auto;

   /* Les icônes suivent la dominante. Phosphor dessine ses duotone en DEUX
      couches - un fond à 20 % d'opacité et un tracé plein - qui héritent
      toutes deux de color : une seule déclaration les tient donc ensemble, et
      le dégradé propre à la charte se fait tout seul. */
   color: var(--dominante-color);
}

/* Icônes de navigation : une seule déclaration pour les deux barres */
.menu-link .ph-duotone,
.sidebar-link .ph-duotone {
   font-size: 1.4rem;
}

.page-header {
   padding: .9rem 1.25rem;
   border: 0;
   border-bottom: 1px solid var(--line);
   background: var(--panel);
   box-shadow: none;
   color: inherit;
   margin-bottom: 1.25rem;
   align-items: flex-end;
}

/* Icône à gauche, titre et sous-titre empilés à droite. */
.page-title-group {
   display: flex;
   align-items: center;
   gap: .75rem;
}

.page-title-icone {
   flex: 0 0 auto;
   font-size: 2.5rem;
   color: var(--dominante-color);
}

/* Une image à la place de l'icône du bandeau (`$page['image']`) : un peu plus haute que
   l'icône, sans agrandir la bande. */
.page-title-image {
   flex: 0 0 auto;
   width: 3.4rem;
   height: 3.4rem;
   margin: -.45rem 0;
   object-fit: contain;
}

.page-header .page-title {
   font-size: 1.4375rem;
   font-weight: var(--fw-bold);
   color: inherit;
   line-height: var(--lh-tight);
   letter-spacing: -.015em;
}

/* Le libellé du dépliant qui contient la page - un onglet virtuel s'il y en a
   un, sinon le module lui-même. Plus discret que le titre : c'est un repère
   de position, pas une information nouvelle. */
.page-header .page-subtitle {
   font-size: .8rem;
   color: var(--slate);
   line-height: var(--lh-tight);
   margin-top: .1rem;
}

.page-header .date-time {
   color: var(--slate);
   font-size: .84rem;
   line-height: 1.3;
   text-transform: capitalize;
}

#current-time {
   font-size: 1.25rem;
   color: inherit;
   margin-top: .1rem;
   font-weight: var(--fw-regular);
   line-height: var(--lh-tight);
   font-family: var(--font-mono);
   letter-spacing: -.03em;
}

/* Icônes de bouton */
.btn .ph-duotone,
.mc-btn .ph-duotone {
   font-size: 1.2rem;
}

/* Les icônes des boutons d'outils - Colonnes, Exporter - suivent la dominante.
   Elles héritaient de --mc-text, la couleur du libellé, et restaient donc
   grises quelle que soit la charte.

   Ce sélecteur ne vise QUE .mc-btn, employé par le seul mc-table.js pour la
   barre d'outils du tableau : ces boutons ont un fond clair. On ne touche pas
   à .btn, dont les variantes pleines portent des icônes sur aplat coloré, où
   la dominante les rendrait illisibles. */
.mc-btn .ph-duotone {
   color: var(--dominante-color);
}

/* Bascule de thème : elle n'est pas un .btn, sa taille se déclare à part.
   EN BLANC (08/10) : l'icône prenait le gris des icônes de menu déroulant,
   illisible sur le fond dominante du bouton. */
.darkmode-btn .ph-duotone {
   font-size: 1.3rem;
}
/* Par l'identifiant : la règle générale des icônes de menu déroulant
   (`.dropdown-item .ph-duotone`, plus bas, en !important) l'emporterait sinon. */
#darkModeToggle .ph-duotone {
   color: #fff !important;
}

/* box-sizing/min-height/max-height en plus de height, ici et sur le bouton
   ci-dessous : le champ et le bouton se lisaient à des hauteurs visuelle-
   ment différentes malgré la même height:var(--btn-h-lg) déjà posée sur les
   deux - verrouillé explicitement pour ne plus dépendre de la hauteur
   intrinsèque propre à chaque type d'élément (<input> vs <button>). */
.search-group .form-control {
   flex: 1 1 auto;
   min-width: 0;
   box-sizing: border-box;
   height: var(--btn-h-lg);
   min-height: var(--btn-h-lg);
   max-height: var(--btn-h-lg);
   border-radius: 0;
   border: none;
   padding: .4rem .9rem;
   /* Un aplat blanc, non teinté. La version précédente prenait --dc-10-w, qui
      ne se détachait du panneau du menu que de 1,02 : 1 - le champ disparaissait
      purement et simplement. Le blanc tient quelle que soit la dominante, sur le
      panneau clair du menu comme sur la navbar sombre. */
   background: var(--panel, #fff);
   color: var(--text-color);
   transition: background var(--transition-speed), color var(--transition-speed);
}

#horizontal-sidebar {
   position: fixed;
   top: var(--navbar-h);
   left: 0;
   width: 100%;
   background: var(--dc-20-w, #cddfe7);
   overflow: hidden;
   z-index: 1000;
   box-shadow: 0 4px 8px rgba(0, 0, 0, 0.425);
   padding: 0.2rem 0;
   white-space: nowrap;
   border-bottom: 1px solid var(--dc-50-w, #83aec4);
   transform: translateY(-20px);
   opacity: 0;
   pointer-events: none;
   transition: transform 0.4s ease, opacity 0.4s ease;
   max-height: 84px;
}

#horizontal-sidebar .sidebar-items {
   display: flex;
   /* nowrap + overflow-x : le nombre de raccourcis n'est pas plafonné, la
      barre défile. Elle portait overflow-Y, ce qui ne défilait rien sur une
      rangée horizontale et coupait les tuiles au-delà de la largeur. */
   flex-wrap: nowrap;
   gap: 0.25rem;
   padding: .4rem .75rem;
   overflow-x: auto;
   overflow-y: hidden;
   scrollbar-width: thin;
   scrollbar-color: var(--dc-40-w, #9bbed0) transparent;
}

/* Séparateur : un simple trait vertical entre deux groupes de raccourcis.
   flex-shrink: 0 est nécessaire - sans lui, il serait le premier écrasé quand
   la barre se remplit, et disparaîtrait au moment où il sert le plus. */
.sidebar-separateur {
   flex: 0 0 auto;
   align-self: stretch;
   width: 1px;
   margin: .35rem .3rem;
   background: currentColor;
   opacity: .35;
}

/* Le bouton de réglage n'est pas un raccourci : il ne mène pas à un contenu,
   il mène à la page qui compose cette barre. Fond plein de la dominante, là où
   les raccourcis sont des tuiles claires - la différence doit se voir avant
   d'avoir lu le libellé.
   Il reste en tête et ne défile pas : c'est la seule issue quand la barre est
   vide, et une barre neuve EST vide.

   Le sélecteur est préfixé par #horizontal-sidebar À DESSEIN. Sans l'identifiant,
   .sidebar-link-fixe et .sidebar-link ont la même spécificité, et .sidebar-link
   est déclarée plus bas : c'est elle qui l'emportait, le bouton se confondait
   avec les autres et cette règle ne servait à rien. */
#horizontal-sidebar .sidebar-link-fixe {
   position: sticky;
   left: 0;
   z-index: 1;
   border-color: var(--dominante-color, #065d89);
   /* Fond OPAQUE obligatoire : c'est le seul élément sous lequel les autres
      tuiles défilent. Une transparence les laisserait apparaître au travers. */
   background: var(--dominante-color, #065d89);
   color: #fff;
   /* L'ombre à droite donne à voir que quelque chose passe dessous. */
   box-shadow: 6px 0 6px -4px rgba(0, 0, 0, .25);
}

#horizontal-sidebar .sidebar-link-fixe:hover {
   border-color: var(--dc-80-k, #022537);
   background: var(--dc-80-k, #022537);
   color: #fff;
   /* Les tuiles se soulèvent au survol ; un bouton ancré, non - il glisserait
      sous celles qui défilent. */
   transform: none;
}

.sidebar-link {
   display: inline-flex;
   flex-direction: column;
   align-items: center;
   justify-content: center;
   /* Largeur au contenu : un libellé long (« Notifications », « Déconnexion »)
      débordait de la tuile à largeur fixe. */
   min-width: 62px;
   height: 55px;
   text-align: center;
   padding: .3rem .55rem;
   border-radius: 5px;
   border: 1px solid var(--dc-70-w, #518eac);
   white-space: nowrap;
   background: var(--dc-10-w, #e6eff3);
   color: var(--dc-70-k, #044160);
   text-decoration: none;
   transition: all 0.25s ease;
   font-size: var(--fs-2xs);
   box-sizing: border-box;
   flex-shrink: 0;
   line-height: var(--lh-snug);
}

.sidebar-link .ph-duotone {
   margin-bottom: .1rem;
   transition: color 0.25s ease;
}

.menu-link .ph-duotone {
   margin-right: 10px;
   color: var(--dc-60-w, #6a9eb8);
}

.btn-square,
.darkmode-btn,
.search-group .btn,
#dropdownColor {
   width: var(--btn-h-lg);
   height: var(--btn-h-lg);
   border-radius: var(--radius-field);
   border: none;
   display: flex;
   align-items: center;
   justify-content: center;
   transition: all .25s ease;
   padding: 0;
   min-height: var(--btn-h-lg);
}

/* #dropdownColor un peu plus large que les 3 autres boutons carrés avec
   qui il partage la règle ci-dessus - hauteur inchangée, largeur seule. */
#dropdownColor {
   width: calc(var(--btn-h-lg) + 8px);
}
/* Après la règle ci-dessus, de même spécificité : dans le groupe de recherche,
   le bouton ferme le côté droit. Il n'arrondit rien lui-même - voir l'affixe
   plus haut, c'est le conteneur qui s'en charge. */
.search-group .btn {
   flex: 0 0 var(--btn-h-lg);
   border-radius: 0;
   box-sizing: border-box;
   height: 100vh;
}

[data-theme="dark"] .card-header p {
   color: var(--slate);
}

[data-theme="dark"] .page-header {
   background: var(--panel);
   border-bottom: 1px solid var(--line);
   color: #f3f4f7;
}

[data-theme="dark"] .page-header .page-title,
[data-theme="dark"] #current-time {
   color: #f3f4f7;
}

.mc-menu-item {
   display: flex;
   align-items: center;
   gap: .5rem;
   width: 100%;
   padding: .45rem .6rem;

   /* Les bords latéraux sont RÉSERVÉS dès maintenant, en transparent : ajoutés
      seulement au survol, ils élargiraient l'élément de 8px et feraient sauter
      le libellé au passage de la souris. */
   border: 0 solid transparent;
   border-left-width: 4px;
   border-right-width: 4px;
   border-radius: 7px;
   background: none;
   color: var(--mc-text);
   font-size: .85rem;
   text-align: left;
   cursor: pointer;
}

@media (max-width:768px) {
   .page-header {
      /* Le bandeau reste sur une rangée : titre à gauche, date et heure en
         haut à droite. Le titre passe à la ligne si besoin, la date non. */
      flex-direction: row;
      /* Le bandeau autorise le retour à la ligne (`flex-wrap: wrap` en base) :
         sur écran étroit, le titre et la date ne tenaient pas côte à côte et
         la date basculait sous le titre. */
      flex-wrap: nowrap;
      align-items: flex-start;
      justify-content: space-between;
      gap: .75rem;
      text-align: left;
      padding: .8rem 1rem;
   }

   /* C'est CE conteneur, pas le <h1> lui-même, qui est l'enfant flexible
      direct de .page-header depuis que l'icône s'y est ajoutée : le
      min-width:0 doit donc porter ici, sinon le groupe icône+texte refuse de
      rétrécir sous sa largeur de contenu et repousse la date hors du cadre. */
   .page-title-group {
      min-width: 0;
      flex: 1 1 auto;
   }

   .page-header .page-title {
      overflow-wrap: anywhere;
      font-size: 1.3rem;
   }

   .page-header .date-time {
      flex: 0 0 auto;
      text-align: right;
      white-space: nowrap;
      font-size: .9rem;
   }

   #horizontal-sidebar {
      max-height: 100px;
   }

   .sidebar-link {
      min-width: 58px;
      height: 58px;
      font-size: 0.8rem;
      padding: 0.4rem;
   }

   .sidebar-link .ph-duotone {
      font-size: 1.25rem;
      margin-bottom: 0.2rem;
   }

}

@media (max-width:992px) {
   #scrollTopBtn {
      width: 42px;
      height: 42px;
      /* 90px auparavant, pour dégager la barre du bas mobile. Celle-ci
         supprimée, le bouton reprend une marge ordinaire. */
      bottom: 15px;
      right: 10px;
      font-size: 1rem;
   }

}

@media (max-width:480px) {

   .sidebar-link {
      min-width: 52px;
      height: 52px;
      font-size: 0.75rem;
      padding: 0.3rem;
   }

   .sidebar-link .ph-duotone {
      font-size: 1.1rem;
      margin-bottom: 0.15rem;
   }

}

/* ENTRE 800 ET 1024 PX (abdAllah, 09/10) : la recherche, la session et les quatre boutons de
   droite ne tenaient plus sur une ligne - ces derniers passaient dessous, coupés par la hauteur
   fixe de la barre et cachés derrière l'en-tête de page. Le champ de recherche et les marges de
   la session se resserrent ; sous 800 px, les deux passent dans la bande mobile (plus bas). */
@media (min-width:800.02px) and (max-width:1023.98px) {
   .navbar .search-group { margin-left: .5rem; }
   .navbar .search-group .form-control { width: 7rem; }
   .navbar select.sessionSelect { margin: 0 .5rem; min-width: 0; max-width: 150px; font-size: 1.1rem; }
}

/* TÉLÉPHONES ÉTROITS (abdAllah, 12/10) : sous 420 px, les sept boutons de la barre ne tenaient
   plus sur une ligne - les quatre de droite (tâches, notifications, réglages, déconnexion) passaient
   dessous, coupés par la hauteur fixe de la barre et cachés derrière la page. La barre ne passe
   plus à la ligne ; ses boutons et leurs marges se resserrent. */
@media (max-width:420px) {
   .navbar { flex-wrap: nowrap; padding-left: .5rem !important; padding-right: .5rem !important; }
   .navbar > div { flex-wrap: nowrap; min-width: 0; }
   .navbar .btn-square,
   .navbar #dropdownColor { width: 36px; height: 36px; min-height: 36px; }
   .navbar #dropdownColor { width: 44px; }
   .navbar .mx-1 { margin-left: 2px !important; margin-right: 2px !important; }
   .navbar .mx-2 { margin-left: 3px !important; margin-right: 3px !important; }
}

@media (max-width:800px) {
   .navbar .search-group,
   .navbar .sessionSelect {
      display: none;
   }

   #mobile-search-select {
      display: flex;
      align-items: stretch;
      gap: .4rem;
      padding: .6rem .4rem;
      background-color: var(--dc-20-w, #cddfe7);
      border-bottom: 1px solid var(--dc-45-w, #8fb6ca);
   }

   [data-theme="dark"] #mobile-search-select {
      background-color: var(--dc-50-k, #032f45);
   }

   /* Le sélecteur de session et la recherche occupent la même boîte : la
      largeur mini et maxi héritées de .sessionSelect sont neutralisées.
      select.sessionSelect (spécificité élément + classe, voir plus haut)
      exige le même préfixe ici, sans quoi cette règle - moins spécifique -
      ne l'emporterait plus. Bordure identique à .search-group : les deux
      occupent la même boîte, ils doivent se lire comme un seul ensemble
      cohérent, pas deux styles différents côte à côte. */
   #mobile-search-select .search-group,
   #mobile-search-select select.sessionSelect {
      width: 100%;
      min-width: 0;
      max-width: none;
      border: 1px solid var(--dc-80-k, #0a2a3c);
      /* !important : neutralise un éventuel utilitaire mx-* resté dans le
         balisage, les classes d'espacement de Bootstrap étant elles-mêmes
         déclarées en !important. */
      margin: 0 !important;
   }

}

@supports not (gap:1px) {
   .page-header>*,
   #horizontal-sidebar .sidebar-items>*,
   .mc-toolbar>*,
   .mc-toolbar-group>*,
   .mc-pagination>*,
   .mc-editor-toolbar>*,
   .mc-footer>* {
      margin: .25rem;
   }

}

@supports not selector(:focus-visible) {
   .mc-btn:focus,
   .mc-tool:focus,
   .mc-page-btn:focus,
   .mc-menu-item:focus,
   .btn:focus {
      outline: 2px solid var(--dominante-color, #065d89);
      outline-offset: 1px;
   }

}

@media (max-width:767.98px) {
   .page-title-icone {
      font-size: 1.3rem;
   }

   .page-header .page-title {
      font-size: var(--fs-lg);
   }

   .page-header .date-time {
      font-size: var(--fs-xs);
   }

}

@media (prefers-reduced-motion:reduce) {
   .mc-btn,
   .mc-spinner {
      transition: none;
      -webkit-animation: none;
      animation: none;
   }

}

/* ========================================================================
   BOOTSTRAP - NEUTRALISATION DES COULEURS NATIVES
   ========================================================================
   Bootstrap peint ses variantes, ses états de focus et ses composants actifs
   en #0d6efd. On remappe ses variables plutôt que de repeindre chaque règle :
   une seule source de vérité, la dominante, qui suit le sélecteur de couleur.
   ======================================================================== */

:root {
   --bs-blue: var(--dominante-color);
   --bs-primary: var(--dominante-color);
   --bs-primary-rgb: var(--dominante-rgb);
   --bs-primary-text-emphasis: var(--dc-80-k, #054a6e);
   --bs-primary-bg-subtle: var(--dc-12-w, #e0ecf1);
   --bs-primary-border-subtle: var(--dc-30-w, #b6d0dd);
   --bs-link-color: var(--dominante-color);
   --bs-link-color-rgb: var(--dominante-rgb);
   --bs-link-hover-color: var(--dominante-color-hover);
   --bs-focus-ring-color: var(--dc-30-t, rgba(6, 93, 137, .3));
   /* Aucun soulignement dans le projet : le survol se marque par le fond. */
   --bs-link-decoration: none;
   --bs-danger: var(--state-error);
   --bs-success: var(--state-success);
   --bs-warning: var(--state-warning);
   --bs-form-valid-color: var(--state-success);
   --bs-form-valid-border-color: var(--state-success);
   --bs-form-invalid-color: var(--state-error);
   --bs-form-invalid-border-color: var(--state-error);
}

.btn-primary {
   /* color/bg/border-color de base + hover retirés : toujours écrasés plus
      loin dans ce fichier par une 2e règle .btn-primary/.btn-primary:hover
      en couleurs directes (background/border-color/color, pas via ces
      variables Bootstrap) - ces 6 propriétés n'étaient jamais effectives.
      disabled-* et focus-shadow-rgb restent, eux : aucune règle
      .btn-primary:disabled ni :focus ne les retouche, ils sont bien
      consommés par .btn de base (bootstrap.css).
      active-bg/active-border-color/active-color : PAS dans le même cas -
      piège vécu, .btn-primary:active de ce fichier (plus bas) ne suffit
      PAS à les rendre inertes. Bootstrap a sa propre règle pour l'état actif
      (`:not(.btn-check)+.btn:active`, bootstrap.css) dont la spécificité
      CSS (0,3,0) dépasse celle de `.btn-primary:active` (0,2,0) - elle
      l'emporte donc MALGRÉ l'ordre de chargement des fichiers, et
      consommait ces 3 variables restées à leurs valeurs Bootstrap par
      défaut (bleu natif) : le bouton clignotait bleu au clic avant d'être
      surchargé ci-dessous. */
   --bs-btn-disabled-bg: var(--dc-40-w, #9bbed0);
   --bs-btn-disabled-border-color: var(--dc-40-w, #9bbed0);
   --bs-btn-focus-shadow-rgb: var(--dominante-rgb);
   --bs-btn-active-bg: var(--dc-40-w, #9bbed0);
   --bs-btn-active-border-color: var(--dc-60-k, #043852);
   --bs-btn-active-color: var(--dc-40-k, #022537);
}

.btn-secondary {
   --bs-btn-color: var(--dominante-color);
   --bs-btn-bg: var(--dc-12-t, rgba(6, 93, 137, .12));
   --bs-btn-border-color: var(--line);
   --bs-btn-hover-color: var(--dominante-color-hover);
   --bs-btn-hover-bg: var(--dc-25-t, rgba(6, 93, 137, .25));
   --bs-btn-hover-border-color: var(--line);
   --bs-btn-active-color: var(--dominante-color-hover);
   --bs-btn-active-bg: var(--dc-30-t, rgba(6, 93, 137, .3));
   --bs-btn-active-border-color: var(--line);
   --bs-btn-focus-shadow-rgb: var(--dominante-rgb);
}

.btn-outline-primary {
   --bs-btn-color: var(--dominante-color);
   --bs-btn-border-color: var(--dominante-color);
   --bs-btn-hover-color: var(--dominante-contrast);
   --bs-btn-hover-bg: var(--dominante-color);
   --bs-btn-hover-border-color: var(--dominante-color);
   --bs-btn-active-color: var(--dominante-contrast);
   --bs-btn-active-bg: var(--dominante-color);
   --bs-btn-active-border-color: var(--dominante-color);
   --bs-btn-disabled-color: var(--dc-45-w, #8fb6ca);
   --bs-btn-disabled-border-color: var(--dc-45-w, #8fb6ca);
   --bs-btn-focus-shadow-rgb: var(--dominante-rgb);
}

.dropdown-menu {
   --bs-dropdown-link-active-bg: var(--dominante-color);
}

.pagination {
   --bs-pagination-active-bg: var(--dominante-color);
   --bs-pagination-active-border-color: var(--dominante-color);
   --bs-pagination-focus-box-shadow: 0 0 0 .25rem var(--dc-25-t, rgba(6, 93, 137, .25));
   --bs-pagination-hover-color: var(--dominante-color-hover);
   --bs-pagination-color: var(--dominante-color);
}

.accordion {
   --bs-accordion-btn-focus-box-shadow: 0 0 0 .25rem var(--dc-25-t, rgba(6, 93, 137, .25));
   --bs-accordion-active-color: var(--dominante-color);
   --bs-accordion-active-bg: var(--dc-10-w, #e6eff3);
}

.progress {
   --bs-progress-bar-bg: var(--dominante-color);
}

.list-group {
   --bs-list-group-active-bg: var(--dominante-color);
   --bs-list-group-active-border-color: var(--dominante-color);
}

.btn-close {
   --bs-btn-close-focus-shadow: 0 0 0 .25rem var(--dc-25-t, rgba(6, 93, 137, .25));
}

.nav-link:focus-visible {
   box-shadow: 0 0 0 .25rem var(--dc-25-t, rgba(6, 93, 137, .25));
}

/* Aucun lien souligné, nulle part : Bootstrap le pose en dur sur <a>. */
a,
a:hover,
a:focus {
   text-decoration: none;
}

/* Type 1 (liens standards, la grande majorité) : suivent la charte
   dominante (couleur par défaut déjà pilotée par --bs-link-color) et se
   marquent au survol par un rouge d'état (jeton déjà établi, pas une
   couleur inventée). Voir plus bas pour le Type 2 (liens Id de membre),
   qui est une exception délibérée à cette même charte. */
a:hover {
   color: var(--state-error);
}

/* Exception à la charte ci-dessus (Type 1 juste au-dessus), posée à la
   demande d'abdAllah - pas la couleur "dominante" habituelle des liens, un
   bleu/rouge classique de lien web précis, pour les rendre reconnaissables
   comme tels (ex. renduColonneId(), shared/membres.php). Valeurs EN DUR,
   PAS de variable CSS : ce fichier remappe délibérément --bs-blue vers
   var(--dominante-color) plus haut ("NEUTRALISATION DES COULEURS NATIVES"
   - une seule source de vérité, la dominante) - une couleur qui suivrait
   la dominante manquerait justement le but de cette exception.

   Plus de <a> imbriqué (1er essai, .linkUrl posée dessus) - abdAllah a
   demandé plus simple : onclick directement sur le <td> lui-même (toute
   la cellule cliquable, pas seulement le texte), .linkUrl-cellule porte
   donc maintenant AUSSI le style de texte (avant : .linkUrl séparée).

   `!important` sur color, ajouté ensuite : nécessaire quand ce <td> se
   trouve dans un <table> qui porte AUSSI la classe .table de Bootstrap
   (ex. composition-des-classes.php) - sa règle .table> :not(caption)>*>*
   a une spécificité plus élevée (0,1,1, le :not(caption) comptant comme
   un sélecteur de type) que .linkUrl-cellule seule (0,1,0), et l'emporte
   sinon silencieusement. Sans effet sur les pages en mc-datatable (pas
   la classe .table), où cette règle Bootstrap ne s'applique jamais. */
.linkUrl-cellule {
   color: #3674ce !important;
   cursor: pointer;
}

/* Effet "survol de bouton" sur toute la cellule, pas seulement le texte
   de l'id. `!important` nécessaire : le <td> a déjà un background-color
   inline (genre_couleur()), plus spécifique que n'importe quelle règle
   CSS externe sans lui.

   1er essai (fond bleu, dérivé de #3674ce) : abdAllah a demandé du gris à
   la place - #6c757d, gris Bootstrap standard (--bs-gray) en dur, même
   prudence que pour le bleu/rouge plus haut (pas var(--bs-gray), au cas
   où ce jeton serait un jour remappé comme --bs-blue l'est déjà).
   Le texte, lui, reste rouge au survol (#b40303) - jamais bleu, inchangé
   par cette demande. 1er essai du fond (opacité 12% seule) : appliqué
   mais invisible sur le pastel très clair de genre_couleur() - opacité
   nettement relevée + box-shadow inset (contour visible quelle que soit
   la couleur de fond sous-jacente, contrairement à un aplat seul).

   Plus simple encore (abdAllah) que scoper cette règle à `td` : le `<th>`
   de la colonne Id (renduEnteteColonnesMembre() et les 3 autres pages qui
   construisent leur propre en-tête) ne porte tout simplement plus la
   classe `.linkUrl-cellule` du tout - il n'est jamais cliquable, cette
   classe entière (couleur, gras, curseur, survol) n'a donc pas sa place
   dessus. Seul le `<td>` la porte désormais. */
.linkUrl-cellule:hover {
   color: #b40303 !important;
   background-color: rgb(182 185 187 / 53%) !important;
   box-shadow: inset 0 0 0 1px #6c757d;
   transition: background-color .15s ease, box-shadow .15s ease, color .15s ease;
}

/* Alertes : Bootstrap les peint avec ses propres verts et rouges. On remappe
   ses variables sur les jetons d'état - l'information reste lisible (vert =
   réussi, rouge = échec) tout en restant dans la palette du projet. */
.alert-success {
   --bs-alert-color: var(--state-success);
   --bs-alert-bg: var(--state-success-bg);
   --bs-alert-border-color: var(--state-success-line);
}

.alert-danger {
   --bs-alert-color: var(--state-error);
   --bs-alert-bg: var(--state-error-bg);
   --bs-alert-border-color: var(--state-error-line);
}

.alert-warning {
   --bs-alert-color: var(--state-warning);
   --bs-alert-bg: var(--state-warning-bg);
   --bs-alert-border-color: var(--state-warning-line);
}

/* Valeurs écrites en dur dans Bootstrap : aucune variable ne les couvre */
.form-select:focus,
.form-check-input:focus {
   border-color: var(--dominante-color);
   box-shadow: 0 0 0 .25rem var(--dc-25-t, rgba(6, 93, 137, .25));
}

.form-check-input:checked,
.form-check-input[type="checkbox"]:indeterminate {
   border-color: var(--dominante-color);
}

.form-range::-webkit-slider-thumb {
   background-color: var(--dominante-color);
}

.form-range::-moz-range-thumb {
   background-color: var(--dominante-color);
}

.form-range:focus::-webkit-slider-thumb {
   box-shadow: 0 0 0 1px #fff, 0 0 0 .25rem var(--dc-25-t, rgba(6, 93, 137, .25));
}

.form-range:focus::-moz-range-thumb {
   box-shadow: 0 0 0 1px #fff, 0 0 0 .25rem var(--dc-25-t, rgba(6, 93, 137, .25));
}

/* Le chevron de l'accordéon et la pastille de l'interrupteur sont des images
   SVG encodées, couleur comprise : impossible à repeindre par une variable.
   On les traite en masque, l'aplat vient donc de la charte. */
.accordion-button::after {
   background-color: var(--slate);
   background-image: none;
   -webkit-mask: var(--bs-accordion-btn-icon) center / contain no-repeat;
   mask: var(--bs-accordion-btn-icon) center / contain no-repeat;
}

.accordion-button:not(.collapsed)::after {
   background-color: var(--dominante-color);
   background-image: none;
}

.form-check.form-switch .form-check-input:focus {
   --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e");
}

/* ========================================================================
   04. COMPOSANTS BOOTSTRAP - cartes, modales, formulaires, boutons, onglets
   ======================================================================== */

input[type="color"]:focus {
   outline: none;
}

[data-theme="dark"] hr {
   background: var(--dc-50-w, #83aec4);
}

.form-control:focus {
   outline: none;
   border-color: var(--dominante-color);
   color: var(--dominante-color);
   background: var(--dc-7-w, #eef4f7);
   box-shadow: 0 0 5px 2px var(--dc-30-t, rgba(6, 93, 137, 0.3));
   transition: border-color 0.3s ease, box-shadow 0.3s ease;
}

.form-label,
.form-check-label {
   color: var(--dominante-color);
   font-weight: var(--fw-regular);
   vertical-align: middle;
}

/* Homogénéisation des tailles de police : aligner les formulaires sur
   0.9rem comme les tableaux. On monte à la même spécificité que Bootstrap
   (.input-group > .form-control = 0-2-0) pour ne pas être écrasé. */
.form-control,
.form-label,
.form-check-label,
.form-select,
.input-group-text,
.input-group > .form-control,
.input-group > .form-select,
.input-group > .form-floating > .form-control,
.input-group > .form-floating > .form-select {
   font-size: var(--fs-sm);
}

.form-check-label,
.form-select {
   cursor: pointer;
}

input::placeholder,
textarea::placeholder,
select::placeholder {
   color: #777;
   opacity: 1;
}

[data-theme="dark"] input:focus,
[data-theme="dark"] select:focus,
[data-theme="dark"] textarea:focus,
[data-theme="dark"] button:focus {
   outline: none;
   border-color: var(--dc-20-w, #cddfe7);
   box-shadow: 0 0 5px 2px var(--dc-50-k, #032f45);
   transition: border-color 0.3s ease, box-shadow 0.3s ease;
}

[data-theme="dark"] .form-control,
[data-theme="dark"] .form-select {
   transition: background var(--transition-speed), color var(--transition-speed);
}

[data-theme="dark"] input::placeholder,
[data-theme="dark"] textarea::placeholder,
[data-theme="dark"] select::placeholder {
   color: #bbb;
   opacity: 1;
}

.darkmode-btn {
   background: var(--dominante-color) !important;
   color: #fff !important;
   transition: all .4s ease;
   padding: 4px 32px;
}

.darkmode-btn:hover {
   transform: scale(.95);
   background-color: var(--dc-80-k, #054a6e) !important;
}

#colorPickerBody {
   height: 44px;
}

/* Le sélecteur occupe toute la largeur du menu. Sa largeur de 100 % ne
   suffisait pas : .menu-header est une colonne flex centrée, le <form> qui
   porte le sélecteur s'y réduisait donc à son contenu, et « 100 % » ne valait
   que 100 % de ce contenu. C'est le formulaire qu'il fallait étirer. */
#formStatut,
.statut-unique {
   width: 100%;
}

/* Badge du statut affiché quand un membre n'en a qu'un seul (pas de vrai
   sélecteur dans ce cas, juste ce libellé) - même habillage. */
.statut-unique {
   border-radius: var(--bs-border-radius);
   background-color: var(--bs-white);
   text-align: center;
   padding-top: .25rem;
   padding-bottom: .25rem;
   margin-top: 1rem;
   font-size: .9rem;
}

/* Champ identifiant mis en avant - même format PARTOUT où ce numéro
   apparaît (installation-superviseur.php, mon-profil.php, modal-adulte.php,
   mbr_add-adulte.php, formulaire-enfant.php…) : un seul format, jamais deux
   pages qui divergent sur le même champ. */
.mc-identifiant-accent {
   width: 130px;
   font-size: 1.3rem !important;
   font-weight: 700;
   letter-spacing: 1.5px;
   padding: 0 !important;
}

/* Le sélecteur de statut est un CHAMP COMME LES AUTRES : icône dans un
   input-group-text, liste à côté, exactement comme le champ Pays du gabarit.
   C'est là toute la raison d'être de ce gabarit - une seule manière de
   composer un champ, ici comme dans les formulaires.

   Il portait auparavant son propre habillage : pleine largeur, bordure
   effacée, fond teinté. Autant de règles qui le faisaient diverger, et qui
   contrariaient de surcroît le groupe - .input-group > .mc-combo lui donne
   flex: 1 1 auto, qu'un width: 100 % aurait défait. */
#formStatut .input-group {
   margin: 1rem 0 .5rem;
}

/* La flèche part à droite, la valeur prend ce qui reste. */
.mc-combo[data-select="selectStatut"] .mc-combo-field {
   justify-content: space-between;
}

/* La couleur des options sélectionnées.

   DEUX CAS À NE PAS CONFONDRE.

   Un select SIMPLE ouvre un menu surgissant, dessiné par le système : sous
   Windows et macOS, aucune de ces déclarations ne l'atteint. C'est précisément
   pourquoi MCSelect existe. La règle ne sert donc que Firefox et Chrome sous
   Linux - on la garde à ce titre, mais elle ne garantit rien.

   Une liste MULTIPLE, ou dotée d'un size, est tout autre chose : ce n'est pas
   un menu mais une boîte de liste posée dans la page, et le CSS l'atteint.

   Reste que Chrome écrase background-color sur une option sélectionnée. Un
   DÉGRADÉ passe, lui : c'est une image de fond, traitée par un autre chemin.
   D'où linear-gradient d'une seule couleur - un aplat déguisé, seule façon
   connue d'imposer la dominante à la place du bleu système. */
.form-select option:hover,
.form-select option:checked,
.form-select option:focus {
   background-color: var(--dominante-color) !important;
   color: #fff !important;
}

select[multiple] option:checked,
select[size]:not([size="1"]) option:checked {
   background: linear-gradient(0deg,
      var(--dominante-color) 0%, var(--dominante-color) 100%) !important;
   color: #fff !important;
}

/* Une liste multiple qui n'a plus le focus grise sa sélection dans certains
   navigateurs : la dominante y perdrait sa lisibilité. On la maintient. */
select[multiple]:not(:focus) option:checked,
select[size]:not([size="1"]):not(:focus) option:checked {
   background: linear-gradient(0deg,
      var(--dc-60-w, #4a90b8) 0%, var(--dc-60-w, #4a90b8) 100%) !important;
   color: #fff !important;
}

.btn-primary {
   background: var(--dc-80-w, #387da1);
   border-color: var(--dc-70-555555, #1e5b79);
   color: #fff;
}
.btn-primary:hover {
   background: var(--dc-85-k, #054f74);
   border-color: var(--dc-80-w, #387da1);
}

.btn-primary:active,
.btn-primary:focus {
   background: var(--dc-40-w, #9bbed0);
   border-color: var(--dc-60-k, #043852);
   color: var(--dc-40-k, #022537);
}

/* Même piège que :active/:focus ci-dessus (voir le commentaire du bloc de
   variables plus haut) - les 3 variables --bs-btn-disabled-* réassignées
   ne suffisent pas à elles seules à empêcher le bleu natif Bootstrap le
   temps où le bouton est disabled (spinner de soumission, mc-soumission.js) :
   règle directe nécessaire, même motif exact. */
.btn-primary:disabled {
   background: var(--dc-40-w, #9bbed0);
   border-color: var(--dc-40-w, #9bbed0);
   color: var(--dc-40-k, #022537);
}

[data-theme="dark"] .btn-primary:hover,
[data-theme="dark"] .btn-primary:focus {
   background: var(--dc-85-k, #054f74);
   border-color: #fff;
}

.accordion-button {
   border-radius: 0;
   background: var(--dc-3-w, #f8fafb);
   color: var(--dominante-color);
}

.accordion-button:not(.collapsed) {
   background: var(--dc-7-w, #eef4f7);
   color: var(--dominante-color);
}

[data-theme="dark"] .accordion-button {
   background: var(--dc-50-999999, #507b91);
   color: var(--dc-3-w, #f8fafb);
}

[data-theme="dark"] .accordion-body {
   background: #444;
   color: #fff;
}

.dropdown .btn.dropdown-toggle {
   background-color: var(--dc-80-w, #387da1);
   border-color: var(--dominante-color);
   color: #fff;
   transition: all 0.25s ease;
}

.dropdown .btn.dropdown-toggle:hover,
.dropdown .btn.dropdown-toggle:focus {
   background-color: var(--dominante-color);
   border-color: var(--dominante-color);
   color: #fff;
   box-shadow: 0 0 0 0.15rem var(--dc-40-t, rgba(6, 93, 137, 0.4));
}

.dropdown-item {
   /* LE TEXTE EN DOMINANTE, L'ICÔNE EN NEUTRE (abdAllah, 06/10) : on distingue l'une de
      l'autre. Avant, les deux étaient du même bleu. */
   color: var(--dominante-color, #065d89);
   padding: 0.5rem 1rem;
   transition: background-color 0.2s, color 0.2s;
}

/* Icône d'un dropdown-item : trop petite par défaut (héritée de la taille du
   texte), et collée au libellé sans espace. Convention générale - tout menu
   déroulant Bootstrap du projet en profite, pas seulement celui-ci. */
.dropdown-item .ph-duotone {
   /* 1.2rem et CALÉE sur le milieu du texte (abdAllah, 06/10) : plus grande que lui, elle
      descendait sous la ligne. `line-height: 1` empêche l'icône de grandir la ligne. */
   /* `!important` : la règle vaut pour TOUT le projet (abdAllah, 06/10), or beaucoup d'entrées
      portent leur taille en ligne (`style="font-size:1.3rem;"` - menus de la barre, menu d'un
      membre…), qui l'emporterait sinon. */
   font-size: 1.2rem !important;
   line-height: 1;
   vertical-align: middle;
   position: relative;
   top: -.06em;
   /* Le gris secondaire de Bootstrap (abdAllah, 06/10). */
   color: var(--bs-secondary-color) !important;
   transition: color 0.2s;
}

/* Une entrée COLORÉE (text-danger sur « Supprimer »…) garde son icône de la même couleur. */
.dropdown-item[class*="text-"] .ph-duotone {
   color: inherit !important;
}

.dropdown-item:hover,
.dropdown-item:focus {
   /* Le dégradé `.grady-dark` (abdAllah, 06/10), à la place de la teinte unie --dc-70-w. */
   background: var(--dominante-color, #065d89) !important;
   background: linear-gradient(color-mix(in srgb, var(--dominante-color, #065d89) 72%, #fff), var(--dominante-color, #065d89)) !important;

   /* `!important` ET L'ICÔNE (abdAllah, 09/09) : `text-danger` de Bootstrap
      pesait plus lourd, et « Annuler ce dépôt » restait rouge sur le fond
      teinté - illisible. */
   color: #fff !important;
}

/* AU SURVOL, les couleurs NE SONT PAS inversées (abdAllah, 06/10) : le texte en blanc
   (ci-dessus), l'icône en teinte claire de la dominante - les deux restent distincts.
   La 1re ligne est le repli des navigateurs sans `color-mix`. */
.dropdown-item:hover i,
.dropdown-item:focus i {
   color: #fff !important;
   color: color-mix(in srgb, var(--dominante-color, #065d89) 30%, #fff) !important;
}

.dropdown-item.active,
.dropdown-item:active {
   background-color: var(--dominante-color) !important;
   color: #fff !important;
}

/* Thème sombre : la dominante pure serait trop sombre sur le fond du menu. */
[data-theme="dark"] .dropdown-item {
   color: #ddd;
   color: color-mix(in srgb, var(--dominante-color, #065d89) 45%, #fff);
}

/* `--bs-secondary-color` ne suit pas le thème sombre du projet (`data-theme`, et non le
   `data-bs-theme` de Bootstrap) : il resterait foncé sur le fond foncé du menu. */
[data-theme="dark"] .dropdown-item .ph-duotone {
   color: #ddd !important;
}

[data-theme="dark"] .dropdown-item[class*="text-"] .ph-duotone {
   color: inherit !important;
}

[data-theme="dark"] .dropdown-item:hover,
[data-theme="dark"] .dropdown-item:focus {
   background-color: var(--dc-20-333333, #2a3b44);
   color: #fff;
}

[data-theme="dark"] .dropdown-item.active,
[data-theme="dark"] .dropdown-item:active {
   background-color: var(--dominante-color) !important;
   color: #fff !important;
}

/* LE SURVOL ANIMÉ (abdAllah, 06/10) - menu latéral, barre des raccourcis, tous les menus
   déroulants. Deux effets, portés par le MÊME `::after` (`::before` est déjà pris par la
   flèche du menu latéral et du menu d'un membre), en deux couches de fond :
     1. LE SOULIGNÉ PROGRESSIF : un trait part de la gauche et court vers la droite ;
     2. LE REFLET (« glossy ») : une bande claire, en biais, traverse l'entrée de gauche à droite.
   Au repos le reflet attend hors champ à gauche ; il y revient d'un coup (transition à 0 s),
   pour ne pas repasser à l'envers quand la souris s'en va. Aussi au focus : le clavier y a droit. */
.dropdown-item,
.sidebar-link {
   position: relative;
   overflow: hidden;   /* le reflet et le trait ne dépassent pas, coins arrondis compris */
}

.menu-link::after,
.sidebar-link::after,
.dropdown-item::after {
   content: "";
   position: absolute;
   inset: 0;
   pointer-events: none;
   background-image:
      linear-gradient(var(--mc-trait, #fff), var(--mc-trait, #fff)),
      linear-gradient(128deg, transparent 30%, var(--mc-reflet, rgba(255, 255, 255, .45)) 50%, transparent 70%);
   background-repeat: no-repeat;
   background-size: 0 2px, 60% 100%;
   background-position: 0 100%, -150% 0;
   transition: background-size .35s ease, background-position 0s;
}

.menu-link:hover::after,
.menu-link:focus-visible::after,
.sidebar-link:hover::after,
.sidebar-link:focus-visible::after,
.dropdown-item:hover::after,
.dropdown-item:focus::after {
   background-size: 100% 2px, 60% 100%;
   background-position: 0 100%, 250% 0;
   transition: background-size .35s ease, background-position 1s ease;
}

/* LES COULEURS. Fond devenu FONCÉ au survol (menus déroulants, raccourcis) : trait clair,
   reflet blanc. Menu latéral, qui reste clair : trait en teinte moyenne de la dominante, reflet blanc plus franc. */
.sidebar-link,
.dropdown-item {
   --mc-trait: rgba(255, 255, 255, .9);
   --mc-reflet: rgba(255, 255, 255, .4);
}

.menu-link {
   /* Le trait en teinte MOYENNE de la dominante (abdAllah, 06/10) : la dominante pure était
      trop sombre, sans aller jusqu'à une teinte claire. */
   --mc-trait: var(--dc-50-w, #83aec4);
   --mc-reflet: rgba(255, 255, 255, .85);
}

[data-theme="dark"] .menu-link {
   --mc-trait: color-mix(in srgb, var(--dominante-color, #065d89) 45%, #fff);
   --mc-reflet: rgba(255, 255, 255, .18);
}

/* Animations réduites demandées au système : le trait apparaît d'un coup, pas de reflet. */
@media (prefers-reduced-motion: reduce) {
   .menu-link::after,
   .sidebar-link::after,
   .dropdown-item::after {
      transition: none !important;
      background-image: linear-gradient(var(--mc-trait, #fff), var(--mc-trait, #fff));
   }
}

/* Titre de la carte d'inscription - jamais de retour à la ligne (le
   card-header est en flex avec le dropdown d'actions à droite, un titre
   long le pousserait hors de la carte) ; tronqué avec des points de
   suspension au besoin. min-width:0 nécessaire pour qu'un enfant flex
   accepte de rétrécir sous sa largeur naturelle. */
.mc-inscription-titre {
   min-width: 0;
   overflow: hidden;
   white-space: nowrap;
   text-overflow: ellipsis;
}

/* Dropdown d'actions de la carte d'inscription : bouton "trois
   points" sans fond propre (le fond de la carte suffit) ni caret Bootstrap
   natif (::after, ajouté automatiquement par .dropdown-toggle). Écart
   icône/texte élargi UNIQUEMENT dans ce dropdown précis - les autres
   dropdown-item du projet gardent leur espacement existant. */
.mc-dropdown-inscription-toggle {
   background: none !important;
   border: none !important;
   border-radius: .375rem;
   padding: .25rem .5rem;
   transition: background-color .15s ease;
}

.mc-dropdown-inscription-toggle:hover {
   background-color: rgba(0, 0, 0, .08) !important;
}

.mc-dropdown-inscription-toggle::after {
   display: none;
}

.mc-dropdown-menu-inscription .dropdown-item .ph-duotone {
   margin-right: .6rem;
}

/* Carte "Coordonnées" (informations-classes.php) - même bouton/dropdown
   déjà établi pour les actions d'inscription (.mc-dropdown-inscription-
   toggle, gestion-des-inscriptions.php), contenu différent : identité +
   adresse (fond pâle, bordure gauche colorée selon le genre - voir
   genre_couleur(), posée en style inline côté PHP) puis email/mobile
   (fond blanc normal, section séparée), calqués sur le modèle fourni par
   abdAllah. */
.mc-dropdown-coordonnees {
   width: 320px;
}

.mc-coordonnees-identite {
   padding: .75rem 1rem;
   background: var(--dc-8-t, rgba(6, 93, 137, .08));
   border-radius: var(--radius-field) var(--radius-field) 0 0;
}

.mc-coordonnees-identite .mc-coordonnees-adresse {
   margin-top: .35rem;
   font-size: var(--fs-sm);
   color: var(--mc-muted);
}

.mc-coordonnees-contact {
   padding: .75rem 1rem;
}

.mc-coordonnees-contact div {
   font-size: var(--fs-sm);
}

.mc-coordonnees-contact div + div {
   margin-top: .5rem;
}

.mc-coordonnees-identite .ph-duotone,
.mc-coordonnees-contact .ph-duotone {
   margin-right: .5rem;
   color: var(--dominante-color);
   font-size: 1.2rem;
   vertical-align: middle;
}

/* Libellé discret devant une valeur (ex. "Inscrite le", "Saisie effectuée
   par") - classe générique, pas spécifique aux inscriptions malgré son
   1er usage ici. */
.mc-label-dominante {
   font-size: 9pt;
   color: var(--dominante-color) !important;
   vertical-align: middle;
}

.ribbon {
   --f: .5em;
   font-size: 15px;
   font-weight: bold;
   color: #fff;
   position: absolute;
   top: 0;
   left: 0;
   line-height: 1.9;
   padding-inline: 1.5lh;
   padding-bottom: var(--f);
   border-image: conic-gradient(#0008 0 0) 51% / var(--f);
   clip-path: polygon(100% calc(100% - var(--f)), 100% 100%, calc(100% - var(--f)) calc(100% - var(--f)), var(--f) calc(100% - var(--f)), 0 100%, 0 calc(100% - var(--f)), 999px calc(100% - var(--f) - 999px), calc(100% - 999px) calc(100% - var(--f) - 999px));
   transform: translate(calc((cos(45deg) - 1) * 100%), -100%) rotate(-45deg);
   transform-origin: 100% 100%;
   background-color: #c20000;
}

/* Ruban « Désistée » d'une inscription, espaces membres (abdAllah, 25/08) :
   le bloc est petit, 15px y débordait largement. */
.mc-carte-inscription > .ribbon {
   font-size: 10px;
}

/* Le ruban sort en haut à gauche de son bloc : celui-ci passe devant ses
   voisins, sinon le ruban serait recouvert par le bloc du dessus. */
.mc-carte-inscription:has(> .ribbon) {
   z-index: 1;
}

/* Variante utilisée sur #headerMembre et les cartes cliquables de la
   colonne PROFILS (carte-membre-lien.php) - pas sur le ribbon "Désistée"
   des inscriptions, non concerné par cette demande. */
.ribbon-membre {
   line-height: 1.7;
   font-size: 13px;
}

.accordion-button:focus,
.accordion-button:not(.collapsed) {
   box-shadow: 0 0 3px 0.15rem var(--dc-50-w, #83aec4);
   outline: none;
}

.tab-content {
   background: #fff;
   color: var(--text-color);
   border: 1px solid var(--dc-30-w, #b4cedc);
   border-radius: 0;
   padding: .75rem;
}

[data-theme="dark"] .tab-content {
   background: #414040;
   color: #fff;
}

.nav-tabs .nav-link {
   color: var(--dominante-color);
   background: var(--dc-7-w, #eef4f7) !important;
   border: 1px solid #e6e6e6;
   margin: 2px 2px -1px 0;
   transition: all .3s ease;
}

.nav-tabs .nav-link:hover:not(.active) {
   color: var(--dc-15-k, #010e15) !important;
   background: var(--dc-15-w, #dae7ed) !important;
   border: 1px solid var(--dominante-color);
   transform: translateY(-3px) scale(.97);
   box-shadow: 0 0 2px var(--dc-15-k, #010e15) !important;
}

.nav-tabs .nav-link.active,
.nav-tabs .nav-link:focus {
   border-color: var(--dominante-color) !important;
   color: #fff !important;
   background: var(--dc-50-w, #83aec4) !important;
   box-shadow: 0 0 5px 2px var(--dc-30-t, rgba(6, 93, 137, 0.3)) !important;
}

[data-theme="dark"] .nav-tabs .nav-link {
   background: var(--dc-50-999999, #507b91) !important;
   color: var(--dc-3-w, #f8fafb) !important;
   border-color: var(--dc-50-w, #83aec4) !important;
}

[data-theme="dark"] .nav-tabs .nav-link:hover {
   background: var(--dc-40-w, #9bbed0) !important;
   border-color: var(--dc-50-w, #83aec4) !important;
}

[data-theme="dark"] .nav-tabs .nav-link.active {
   border-color: var(--dominante-color) !important;
   color: #fff !important;
   background: var(--dc-50-w, #83aec4) !important;
   box-shadow: 0 0 3px 1px var(--dc-20-w, #cddfe7) !important;
}

input[type="checkbox"].form-check-input {
   -webkit-appearance: none;
   -moz-appearance: none;
   appearance: none;
   vertical-align: middle;
   width: 22px;
   height: 22px;
   border: 2px solid var(--dominante-color);
   border-radius: 4px;
   background-color: transparent;
   position: relative;
   cursor: pointer;
   transition: all 0.25s ease;
}

[data-theme="dark"] input[type="checkbox"].form-check-input,
[data-theme="dark"] .form-check-input[type="radio"] {
   border: 2px solid var(--dc-70-w, #518eac);
}

input[type="checkbox"].form-check-input:hover {
   box-shadow: 0 0 0 0.15rem var(--dc-20-t, rgba(6, 93, 137, 0.2));
}

input[type="checkbox"].form-check-input::after {
   content: "";
   position: absolute;
   /* Coche contenue dans la case : les dimensions sont celles du trait,
      pas celles de la case. */
   top: 2px;
   left: 6px;
   width: 6px;
   height: 12px;
   border: solid var(--dc-50-777777, #3f6a80);
   border-width: 0 3px 3px 0;
   transform: rotate(40deg);
   opacity: 0;
   pointer-events: none;
   transition: opacity 0.2s ease-in-out;
}

[data-theme="dark"] input[type="checkbox"].form-check-input::after {
   border: solid var(--dc-1-w, #fdfdfe);
   border-width: 0 3px 3px 0;
}

input[type="checkbox"].form-check-input:checked::after {
   opacity: 1;
}

input[type="checkbox"].form-check-input:checked {
   background-color: var(--dc-40-w, #9bbed0);
   border-color: var(--dominante-color);
}

.form-check-input[type="radio"] {
   cursor: pointer;
   width: 22px;
   height: 22px;
   border: 2px solid var(--dominante-color);
   background-color: transparent;
   position: relative;
   -moz-appearance: none;
   transition: all 0.25s ease;
}

.form-check-input[type="radio"]:hover {
   box-shadow: 0 0 0 0.15rem var(--dc-20-t, rgba(6, 93, 137, 0.2));
}

.form-check-input[type="radio"]::after {
   content: "";
   position: absolute;
   top: 50%;
   left: 50%;
   width: 12px;
   height: 12px;
   background-color: var(--dc-50-aaaaaa, #58849a);
   border-radius: 50%;
   transform: translate(-50%, -50%) scale(0);
   transition: transform 0.25s ease;
}

.form-check-input[type="radio"]:checked::after {
   transform: translate(-50%, -50%) scale(1);
}

.form-check.form-switch .form-check-input {
   width: 2.6rem;
   height: 1.4rem;
   border-radius: 2rem;
   background-color: #ddd;
   border: none;
   transition: background-color 0.25s, background-position 0.25s;
}

.form-check.form-switch .form-check-input:checked {
   background-color: var(--dominante-color);
   background-position: right center;
}

[data-theme="dark"] .form-check.form-switch .form-check-input:checked {
   background-color: var(--dc-80-999999, #23698c);
   background-position: right center;
}

.form-check.form-switch .form-check-input::after {
   display: none;
}

.form-check.form-switch .form-check-input:hover {
   filter: brightness(1.1);
}

.form-check-input:focus {
   outline: none;
   box-shadow: 0 0 0 0.2rem var(--dc-30-t, rgba(6, 93, 137, 0.3));
}

/* ÉTAT VALIDE DES CASES, BOUTONS RADIO ET INTERRUPTEURS : LE CONTRÔLE GARDE
   LA DOMINANTE.

   Bootstrap fait verdir le contrôle en même temps que son libellé. Ici, seul le
   TEXTE verdit ; la case, la pastille et l'interrupteur restent à la charte.

   Rien à écrire pour cela : le projet redessine déjà ces contrôles avec des
   sélecteurs plus spécifiques que ceux de Bootstrap -

      input[type="checkbox"].form-check-input   (0,2,1)
      .was-validated .form-check-input:valid    (0,2,0)

   - et l'emporte donc naturellement. C'est cette même mécanique qui pourrait
   passer pour un défaut : le libellé verdit, le contrôle non. C'est voulu.

   La règle de Bootstrap qui colore le LIBELLÉ n'a, elle, pas de concurrente
   dans le projet : elle s'applique, et c'est ce qu'on veut. */

/* Une exception, POUR L'ÉTAT COCHÉ. Bootstrap y ajoute une pseudo-classe, et
   passe alors devant :

      .was-validated .form-check-input:valid:checked    (0,4,0)  ← l'emportait
      input[type="checkbox"].form-check-input:checked   (0,3,1)
      .form-check-input[type="radio"]                   (0,2,0)

   Le fond de la case et du bouton radio repassait donc au vert une fois coché,
   alors même que la bordure gardait la dominante. On rétablit la charte avec le
   poids qu'il faut.

   L'interrupteur, lui, n'a rien demandé : sa règle atteint (0,4,0) et l'emporte
   par l'ordre de chargement, backend.css venant après bootstrap.css. */
.was-validated input[type="checkbox"].form-check-input:valid:checked {
   background-color: var(--dc-40-w, #9bbed0);
}

/* L'INTERRUPTEUR NE SUIT PAS LA CASE (abdAllah, 09/10) : la règle ci-dessus, de poids (0,4,1),
   repeignait aussi l'interrupteur coché en bleu pâle dès qu'un envoi avait été refusé (modale
   d'un événement). Il garde la dominante. */
.was-validated .form-check.form-switch input[type="checkbox"].form-check-input:valid:checked {
   background-color: var(--dominante-color);
}

[data-theme="dark"] .was-validated .form-check.form-switch input[type="checkbox"].form-check-input:valid:checked {
   background-color: var(--dc-80-999999, #23698c);
}

.was-validated .form-check-input[type="radio"]:valid:checked {
   background-color: transparent;
}

/* La BORDURE du bouton radio, seconde règle de Bootstrap et second duel perdu :

      .was-validated .form-check-input:valid   (0,3,0)  ← l'emportait
      .form-check-input[type="radio"]          (0,2,0)

   Le projet n'a pas de variante :checked pour le radio - contrairement à la
   case -, si bien que l'anneau restait vert dans les DEUX états, et sur les
   deux boutons du groupe dès qu'il devient valide. */
.was-validated .form-check-input[type="radio"]:valid {
   border-color: var(--dominante-color);
}

[data-theme="dark"] .was-validated .form-check-input[type="radio"]:valid {
   border-color: var(--dc-70-w, #518eac);
}

input[type="range"] {
   cursor: pointer;
   background: transparent;
}

input[type="range"]::-webkit-slider-runnable-track {
   height: 6px;
   border-radius: 3px;
   background: var(--dc-30-cccccc, #91abb8);
}

input[type="range"]::-webkit-slider-thumb {
   -webkit-appearance: none;
   width: 18px;
   height: 18px;
   border-radius: 50%;
   background: var(--dominante-color);
   margin-top: -6px;
}

[data-theme="dark"] input[type="range"]::-webkit-slider-thumb {
   border: 1px solid #fff;
   background-color: var(--dc-80-999999, #23698c);
}

input[type="range"]::-moz-range-track {
   height: 6px;
   border-radius: 3px;
   background: var(--dc-30-cccccc, #91abb8);
}

input[type="range"]::-moz-range-thumb {
   width: 18px;
   height: 18px;
   border-radius: 50%;
   background: var(--dominante-color);
}

::-webkit-scrollbar {
   width: 5px;
   height: 5px;
}

::-webkit-scrollbar-track {
   box-shadow: inset 0 0 3px #999;
   background: #f8f8f8;
}

::-webkit-scrollbar-thumb {
   background: var(--dc-80-w, #387da1);
}

::-webkit-scrollbar-thumb:hover {
   background: var(--dc-40-w, #9bbed0);
   cursor: grab;
}

input[type="color"] {
   outline: none;
   width: 30px;
   height: 30px;
   padding: 0;
   margin: 0;
   -moz-appearance: none;
   border: 1px solid rgba(0, 0, 0, .2);
   border-radius: .35rem;
   background: none;
}

input[type="color"]::-webkit-color-swatch-wrapper {
   padding: 2px;
}

input[type="color"]::-webkit-color-swatch {
   border: none;
   border-radius: .2rem;
}

input[type="color"]::-moz-color-swatch {
   border: none;
   border-radius: .2rem;
}

.card-body p,
.accordion-body,
.tab-content p,
.modal-body p {
   max-width: 72ch;
}

.form-check-label {
   font-size: .9rem;
   line-height: var(--lh-snug);
}

.invalid-feedback {
   font-size: 9pt;
   font-weight: 600;
}

.btn {
   font-weight: var(--fw-bold);
   letter-spacing: .01em;
   margin-bottom: 3px;
}

.btn-xs {
   font-size: 9pt !important;
   padding: 2px 8px !important;
   line-height: 1 !important;
   min-height: 0 !important;
}

.dropdown-item,
.nav-tabs .nav-link,
.accordion-button {
   font-size: var(--fs-sm);
}

.accordion-button,
.nav-tabs .nav-link.active {
   font-weight: var(--fw-bold);
}

.mc-barre-filtres {
   display: flex;
   flex-wrap: wrap;
   align-items: center;
   gap: .5rem;
   border-bottom: 1px solid var(--line);
   padding-bottom: .5rem;
   margin-bottom: .75rem;
}

@media (max-width: 767.98px) {
   .mc-barre-filtres {
      flex-direction: column;
      align-items: stretch;
   }
   .mc-barre-filtres > .input-group {
      width: 100% !important;
      flex-shrink: 0 !important;
   }
   .mc-ligne-break {
      display: none;
   }
}

.table {
   font-size: var(--fs-sm);
}

/* mc-select dans un input-group-sm : aligner la taille sur les form-control sm.
   tools.css pose font-size:1rem sur .mc-combo - on surcharge ici. */
.input-group-sm .mc-combo {
   font-size: var(--fs-sm);
   min-height: var(--btn-h-sm);
   padding-top: .15rem;
   padding-bottom: .15rem;
}

/* Ligne du planning du jour - effet survol */
.mc-planning-ligne:hover td {
   background: var(--dominante-hover, rgba(var(--dominante-rgb, 6, 93, 137), .08));
}
.mc-planning-ligne {
   transition: border var(--transition-speed, .15s) ease;
}
.mc-planning-ligne:hover {
   border-left: 3px solid var(--dominante-color) !important;
   border-right: 3px solid var(--dominante-color) !important;
}

/* Filtres de liste : largeur minimum pour éviter le rétrécissement
   au changement d'option. Limité à mc-barre-filtres pour ne pas
   casser les selects dans des conteneurs étroits (ex. configurations). */
/* Selects natifs : la font-size de l'élément s'applique aussi aux options.
   Bootstrap pose 1rem sur .form-select - on aligne sur la variable projet. */
.form-select,
.form-select option {
   font-size: var(--fs-base, 1rem);
}
.input-group-sm .form-select,
.input-group-sm .form-select option {
   font-size: var(--fs-sm);
}

/* mc-multi : hérite la taille du contexte au lieu d'être figé */
.mc-multi {
   font-size: inherit;
}

.mc-barre-filtres .mc-combo {
   min-width: 150px;
}

/* Sens de lecture arabe : aligner le texte à droite quand dir="rtl" est posé
   par l'import PDF ou l'éditeur. Sans ça le paragraphe se lit correctement
   mais reste collé à gauche, là où l'œil arabe commence sa ligne. */
[dir="rtl"] {
   text-align: right;
}

/* Sections de salle - liste et formulaire d'ajout inline dans la carte */
.mc-salle-sections {
   padding: .25rem 0;
   display: flex;
   flex-direction: column;
   gap: .2rem;
}
.mc-salle-section {
   display: flex;
   align-items: center;
   gap: .4rem;
   font-size: var(--fs-sm);
   opacity: .9;
}
.mc-salle-section-libelle { flex: 1; font-weight: 500; }
.mc-salle-section-places  { white-space: nowrap; }

/* Form d'ajout de section - pleine largeur, même ligne */
.mc-salle-section-form {
   display: flex;
   align-items: center;
   gap: .3rem;
   padding: .4rem 0;
   border-top: 1px solid rgba(255,255,255,.2);
}
.mc-salle-section-input {
   border: 1px solid var(--line);
   border-radius: var(--radius-field);
   padding: .15rem .4rem;
   font-size: var(--fs-sm);
   min-width: 0;
   flex: 1;
   background: #fff;
   color: #000;
}
.mc-salle-section-places-input { flex: 0 0 5rem; }

/* Aligner mc-filiere-actions avec la form section */
.mc-filiere-court,
.mc-salle-section-form,
.mc-filiere-actions {
   width: 100%;
   box-sizing: border-box;
}
.mc-filiere-actions {
   padding: .25rem 0;
   border-top: 1px solid rgba(255,255,255,.2);
}

.table thead th {
   font-weight: var(--fw-bold);
   letter-spacing: .01em;
}

[data-theme="dark"] body {
   background: #12141c;
}

.card,
.modal-content {
   background: var(--panel);
   border: 1px solid var(--line);
   color: inherit;
   border-radius: 0;
   box-shadow: var(--shadow-panel);
   /* Pas de `overflow: hidden` : il rognait les menus déroulants ouverts
      depuis une carte. Les angles étant vifs, il n'avait plus d'utilité. */
}

.card-header p {
   margin: .15rem 0 0;
   color: var(--slate-dim);
   font-size: var(--fs-panel-sub);
   font-weight: var(--fw-regular);
   letter-spacing: 0;
}

/* Grosse icône décorative à droite d'un card-header - purement illustrative,
   d'où aria-hidden côté HTML : le titre et le sous-titre suffisent à
   identifier la carte pour un lecteur d'écran. */
.mc-carte-icone {
   font-size: 1.85rem;
   color: var(--dominante-color);
   flex-shrink: 0;
}

/* Convention commune à TOUT tableau ou liste vide du projet - voir
   LE-SOCLE.md, « L'état vide ». */
.mc-etat-vide {
   display: flex;
   flex-direction: column;
   align-items: center;
   gap: .4rem;
   padding: 1.5rem 1rem;
   color: var(--slate);
   text-align: center;
}

.mc-etat-vide .ph-duotone {
   font-size: 2rem;
}

/* Carte d'un événement d'agenda (backend/planifications/agenda.php) - le
   bloc de date en haut, pleine largeur, sans marge ; le corps en dessous ;
   le pied regroupe la progression et les actions, toujours visibles. */
.mc-agenda-carte {
   display: flex;
   flex-direction: row;
   align-items: stretch;
   width: 21rem;
   background: var(--panel-soft, #f4f6f8);
   border: 1px solid var(--line, #dee2e6);
   border-radius: var(--radius-field, .5rem);
   overflow: hidden;
   box-shadow: rgb(0 0 0 / 47%) 0px 2px 3px;
}

/* Le bloc de date colle aux bords de la carte, sans marge ni padding
   autour - juste la hauteur qu'il faut pour ses trois lignes de texte. */
.mc-agenda-bloc-date {
   flex: 0 0 6rem;
   display: flex;
   flex-direction: column;
   align-items: center;
   justify-content: center;
   gap: .1rem;
   padding: .6rem .3rem;
   background: var(--dc-12-t, rgba(6, 93, 137, .12));
   border-right: 3px solid var(--dc-20-t, rgba(6, 93, 137, .2));
   text-align: center;
}

.mc-agenda-jour {
   font-family: 'Open Sans', sans-serif;
   font-size: var(--fs-xs, .8125rem);
   font-weight: 400;
   color: var(--dominante-color, #065d89);
   text-transform: uppercase;
}

.mc-agenda-quantieme {
   font-family: 'Open Sans', sans-serif;
   font-size: 1.3rem;
   font-weight: 700;
   line-height: 1;
   color: var(--dominante-color, #065d89);
}

.mc-agenda-mois {
   font-family: 'Open Sans', sans-serif;
   font-size: var(--fs-xs, .8125rem);
   font-weight: 500;
   color: #b3261e;
   text-transform: uppercase;
}

.mc-agenda-corps {
   flex: 1 1 auto;
   display: flex;
   flex-direction: column;
   padding: .85rem 1rem;
}

.mc-agenda-entete-carte {
   display: flex;
   align-items: baseline;
   justify-content: space-between;
   gap: .4rem;
   cursor: pointer;
   margin-bottom: .3rem;
}

.mc-agenda-titre {
   font-weight: var(--fw-bold);
}

.mc-agenda-chevron {
   flex-shrink: 0;
   color: var(--slate);
   transition: transform .2s ease;
}

.mc-agenda-ouverte .mc-agenda-chevron {
   transform: rotate(180deg);
}

.mc-agenda-pliable {
   max-height: 0;
   overflow: hidden;
   transition: max-height .25s ease;
}

.mc-agenda-ouverte .mc-agenda-pliable {
   max-height: 60rem;
}

.mc-agenda-info {
   font-size: var(--fs-sm);
   color: var(--slate-dim, #5b6174);
   margin: 0 0 .5rem;
}

.mc-agenda-jusquau {
   font-size: var(--fs-xs, .8125rem);
   color: var(--slate);
   margin-bottom: 0;
}

.mc-agenda-destinataires {
   font-size: var(--fs-xs, .8125rem);
   color: var(--dominante-color, #065d89);
   font-style: italic;
   margin-bottom: .5rem;
}

/* Pousse la progression + les actions en bas de carte, même quand une
   carte voisine a un texte plus long - sans ça, le pied de chaque carte
   flotterait à une hauteur différente selon la longueur de l'information. */
.mc-agenda-pied {
   margin-top: auto;
   display: flex;
   align-items: center;
   justify-content: space-between;
   gap: .5rem;
   padding-top: .5rem;
}

.mc-agenda-progression-bloc {
   flex: 1 1 auto;
   min-width: 0;
}

.mc-agenda-progression {
   height: 4px;
   background: var(--line, #dee2e6);
   border-radius: 2px;
   overflow: hidden;
   margin-bottom: .3rem;
}

.mc-agenda-progression > div {
   height: 100%;
   background: var(--dominante-color, #065d89);
}

.mc-agenda-etat {
   font-size: var(--fs-xs, .8125rem);
   color: var(--slate);
}

/* Largeur égale à la hauteur - sinon un bouton icône-seule de btn-sm reste
   plus large que haut (le padding horizontal de Bootstrap dépasse le
   vertical). */
/* LA HAUTEUR seule est réduite (abdAllah, 07/09) : le bouton faisait 36 px là où
   la cellule qui le porte en fait 31, et c'est lui qui décidait de la hauteur des
   lignes. La LARGEUR reste à 2,25 rem - elle ne gênait pas, et la réduire
   serrait les icônes.

   L'ICÔNE suit : le glyphe Phosphor porte sa propre taille, sans quoi le bouton
   garderait la hauteur d'avant. */
.btn-actions {
   width: 2.25rem;
   height: 1.5rem;
   padding-left: 0;
   padding-right: 0;
   display: inline-flex;
   align-items: center;
   justify-content: center;
}

.btn-actions > i {
   font-size: .95rem;
   line-height: 1;
}

/* Bouton "Informations" (classes-de-la-session.php) - transparent par
   défaut (juste l'icône, sans fond ni bordure visibles), un fond léger
   apparaît seulement au survol. */
.mc-info-classe-action {
   background: transparent;
   border: none;
   color: var(--slate);
}

.mc-info-classe-action:hover,
.mc-info-classe-action:focus-visible {
   background: var(--panel-soft);
   color: var(--dominante-color);
}

/* Un événement déjà passé (sa fin, ou son début à défaut de fin, est
   antérieure à aujourd'hui) - le texte se barre et s'estompe, la carte
   reste lisible mais se distingue d'un coup d'œil des événements à venir. */
.mc-agenda-passe {
   opacity: .55;
   filter: grayscale(60%);
}

.mc-agenda-passe .mc-agenda-titre,
.mc-agenda-passe .mc-agenda-info,
.mc-agenda-passe .mc-agenda-jusquau,
.mc-agenda-passe .mc-agenda-destinataires {
   text-decoration: line-through;
}

.card-header {
   font-size: 0.97rem;
   font-weight: var(--fw-bold);
   line-height: 1.3;
   letter-spacing: -.01em;
   padding: .85rem 1.25rem;
   background: var(--dc-12-t, rgba(6, 93, 137, .12));
   border-bottom: 0;
   border-radius: 0;
   color: inherit;
   display: flex;
   flex-wrap: wrap;
   align-items: center;
   justify-content: space-between;
   gap: .6rem;
}

.card-body {
   padding: 1rem 1.25rem 1.25rem;
   background: transparent;
   color: inherit;
}

.card-footer {
   background: var(--dc-12-t, rgba(6, 93, 137, .12));
   border-top: 1px solid var(--line);
   border-radius: 0;
   color: inherit;
   padding: .75rem 1.25rem;
}

/* Le modal se distingue de la carte : un bandeau de tête ET de pied colorés,
   symétriques - la carte, elle, reste transparente (voir
   .card-header/.card-footer juste au-dessus).

   EXACTEMENT la couleur d'.input-group-text (--dc-12-t, 12% d'opacité) -
   pas la couleur dominante pleine, essayée un temps : elle se voit très bien
   en pratique (la capture d'écran le confirme sur les champs du formulaire),
   inutile de forcer plus sombre. Texte et bordure reprennent aussi
   .input-group-text à l'identique - un seul traitement pour « une zone
   teintée par la dominante », qu'elle appartienne à un champ ou à un modal.

   --bs-modal-inner-border-radius à 0 : Bootstrap arrondit par défaut les
   coins de modal-header/footer via cette variable, alors que .modal-content
   est ANGLES VIFS dans tout le projet (voir plus haut : border-radius: 0).
   Sans ce recalage, la couleur du bandeau débordait visiblement des coins
   carrés du modal - invisible tant que le fond était transparent, flagrant
   dès qu'il a pris une couleur. */
.modal-header,
.modal-footer {
   --bs-modal-inner-border-radius: 0;
   background: var(--dc-12-t, rgba(6, 93, 137, .12));
   border-color: var(--line);
   color: var(--dominante-color);
}

/* Le sous-titre du modal-header - même idée que .card-header p (petit,
   grisé), mais une couleur à soi : --slate-dim est pensée pour un fond
   neutre (--panel), le modal-header a le sien, une teinte de la dominante. */
.modal-header p {
   margin: .15rem 0 0;
   color: var(--dominante-color);
   opacity: .75;
   font-size: var(--fs-panel-sub);
   font-weight: var(--fw-regular);
   letter-spacing: 0;
}

.modal-header {
   font-size: 0.97rem;
   font-weight: var(--fw-bold);
   padding: 1rem 1.25rem;
   border-bottom: 1px solid var(--line);
}

.modal-footer {
   border-top: 1px solid var(--line);
   padding: .75rem 1.25rem;
}

.modal-header .btn-close {
   filter: invert(0);
}

/* Icône du titre de modale - même principe que .form-label .ph-duotone
   (margin-right, jamais margin sur le span qui suit) mais un cran plus
   grosse : ici elle porte seule l'identité de la modale, une icône de
   16px dans un titre lui-même petit passait presque inaperçue. */
/* 2rem DANS TOUTES LES MODALES (abdAllah, 28/09). Titre aligné au centre de
   l'icône : l'icône grossie seule le laissait sur sa ligne de base, décalé
   vers le bas. */
.modal-title {
   display: flex;
   align-items: center;
}

.modal-title .ph-duotone,
.modal-header > .ph-duotone {
   font-size: 2rem;
   margin-right: .6rem;
   line-height: 1;
   flex-shrink: 0;
}

.modal-body {
   font-size: var(--fs-base);
   line-height: var(--lh-normal);
   padding: 1.25rem;
   background: transparent;
   color: inherit;
}

.chip {
   display: inline-block;
   padding: 3px 9px;
   border-radius: 20px;
   font-size: .6875rem;
   font-weight: var(--fw-bold);
   letter-spacing: 0;
}

.chip-teal {
   color: #3fa796;
   background: rgba(63, 167, 150, .14);
}

.form-control,
.form-select,
.input-group-text {
   min-height: var(--btn-h-md);
   padding: .3rem .6rem;
   font-size: 1rem;
   line-height: 1.4;
   border-radius: var(--radius-field);
   border-color: var(--line);
}

.input-group-text {
   background: var(--dc-12-t, rgba(6, 93, 137, .12));
   color: var(--dominante-color);
   min-width: 2.5rem;
   text-align: center;
   border-color: var(--line);
}

.form-control-color {
   min-height: var(--btn-h-md);
   padding: 2px;
}

.form-label {
   margin-bottom: .2rem;
   /* 9pt (abdAllah, 28/09) : libellés plus discrets que les champs (0.9rem). */
   font-size: 9pt;
   font-weight: var(--fw-regular);
   line-height: var(--lh-snug);
   color: var(--dominante-color);
}

/* Case et libellé centrés l'un sur l'autre. Bootstrap fait flotter la case
   et la recale avec `margin-top`, un décalage calculé pour une case de 1 em ;
   les nôtres font 22 px, elles retombaient trop bas. */
.form-check {
   display: flex;
   align-items: center;
   flex-wrap: wrap;
   gap: .5rem;
   min-height: 0;
   margin-bottom: 0;
   padding-left: 0;
}

.form-check-inline {
   display: inline-flex;
   margin-right: 0;
}

.form-check .form-check-input {
   flex: 0 0 auto;
   float: none;
   margin: 0;
}

.form-check-label {
   margin: 0;
}

/* Le message de validation prend toute la largeur sous la case */
.form-check .invalid-feedback {
   flex: 0 0 100%;
   margin-top: .15rem;
}

.form-range {
   height: 1.1rem;
}

[data-theme="dark"] .card,
[data-theme="dark"] .modal-content {
   background: var(--panel);
   border-color: var(--line);
   color: var(--white, #f3f4f7);
}

[data-theme="dark"] .card-body,
[data-theme="dark"] .modal-body {
   background: transparent;
   color: #f3f4f7;
}

/* card-header/card-footer gardent leur fond de charte (--dc-12-t en clair,
   --dc-20-t en sombre) dans les deux thèmes, comme input-group-text et
   modal-header/footer - ce jeton est recalculé par mc-theme.js à chaque
   thème, aucune règle séparée n'est nécessaire pour le fond lui-même. */
[data-theme="dark"] .card-header,
[data-theme="dark"] .card-footer {
   background: var(--dc-20-t, rgba(6, 93, 137, .2));
   color: var(--dc-60-w, #6b9fba);
}

/* modal-header/footer gardent leur fond de charte (--dc-12-t) en sombre
   comme en clair : ce jeton est recalculé par mc-theme.js à chaque thème,
   aucune règle séparée n'est nécessaire ici. */
[data-theme="dark"] .modal-header,
[data-theme="dark"] .modal-footer {
   background: var(--dc-20-t, rgba(6, 93, 137, .2));
   color: var(--dc-60-w, #6b9fba);
}

[data-theme="dark"] .modal-header p {
   color: var(--dc-60-w, #6b9fba);
}

[data-theme="dark"] .card-header,
[data-theme="dark"] .modal-header {
   border-bottom: 1px solid var(--dc-50-w, #83aec4);
   border-bottom-color: var(--line);
}

[data-theme="dark"] .card-footer,
[data-theme="dark"] .modal-footer {
   border-top-color: var(--line);
}

[data-theme="dark"] .form-control,
[data-theme="dark"] .form-select,
[data-theme="dark"] textarea {
   background: var(--panel-soft);
   border-color: var(--line);
   color: #f3f4f7;
}

[data-theme="dark"] .form-control:focus,
[data-theme="dark"] .form-select:focus {
   background: var(--panel-soft);
   color: #f3f4f7;
   transition: background var(--transition-speed), color var(--transition-speed);
   border-color: var(--dominante-color);
}

/* Fond bleu clair imposé par Chrome au remplissage automatique - sa feuille
   de style écrit background-color en !important, aucune déclaration
   d'auteur ne peut la reprendre directement (même constat déjà posé pour
   la coche de validité, voir tools.css § Formulaires). box-shadow échappe
   à ce verrouillage : un inset couvrant tout le champ masque visuellement
   le fond imposé sans jamais le déclarer lui-même. var(--panel) plutôt
   qu'un blanc fixe : déjà blanc en thème clair, s'adapte de lui-même en
   thème sombre. */
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
select:-webkit-autofill,
select:-webkit-autofill:hover,
select:-webkit-autofill:focus {
   -webkit-box-shadow: 0 0 0 1000px var(--panel) inset;
   box-shadow: 0 0 0 1000px var(--panel) inset;
   -webkit-text-fill-color: var(--text-color);
}

[data-theme="dark"] .input-group-text {
   background: var(--dc-20-t, rgba(6, 93, 137, .2));
   border-color: var(--line);
   color: var(--dc-60-w, #6b9fba);
}

.input-group-text .ph-duotone {
   font-size: 1.2rem;
}

.form-label .ph-duotone,
.form-check-label .ph-duotone {
   margin-right: .35em;
   font-size: 1rem;
   color: var(--dominante-color);
   vertical-align: -0.15em;
}

.input-group-textarea .input-group-text {
   align-items: flex-start;
   padding-top: .45rem;
}

.input-group-range .form-range {
   flex: 1 1 auto;
   width: 1%;
   min-width: 0;
   height: var(--btn-h-md);
   padding: 0 .7rem;
   border: 1px solid var(--line);
   border-left: 0;
   border-radius: 0 var(--radius-field) var(--radius-field) 0;
   background: var(--panel);
}

[data-theme="dark"] .input-group-range .form-range {
   background: var(--panel-soft);
}

.input-group .form-control-color {
   min-width: 3rem;
}

.form-control[type="file"]::-webkit-file-upload-button,
.form-control[type="file"]::file-selector-button {
   margin: -.3rem .6rem -.3rem -.6rem;
   padding: .3rem .6rem;
   border: 0;
   border-right: 1px solid var(--line);
   background: var(--panel-soft);
   color: var(--slate);
   font-size: var(--fs-sm);
}

.input-group .invalid-feedback {
   flex: 0 0 100%;
   order: 10;
   margin-top: .2rem;
}

.form-control-choices {
   display: flex;
   flex-wrap: wrap;
   align-items: center;
   gap: .25rem 1rem;
   cursor: default;
}

.form-control-choices .form-check {
   margin: 0;
}

.form-control-choices .form-check-label {
   cursor: pointer;
}

.form-control-choices .form-check-input {
   cursor: pointer;
}

.form-control-choices:focus,
.form-control-choices:focus-within {
   box-shadow: none;
}

.form-control-choices:focus-within {
   border-color: var(--dominante-color);
}

@media (max-width:767.98px) {
   .card-header {
      font-size: var(--fs-base);
   }

   .modal-body,
   .card-body {
      font-size: var(--fs-sm);
   }

}

/* ========================================================================
   05. UTILITAIRES, ICÔNES, COMPATIBILITÉ, IMPRESSION
   ======================================================================== */

.ph-duotone,
[class^="ph-"],
[class*=" ph-"] {
   display: inline-block;
   letter-spacing: 0;
   word-spacing: 0;
   vertical-align: -0.125em;
}

[data-theme="dark"] .ph-duotone:before {
   opacity: .35;
}

/* ==========================================================================
   PAGE D'ACCÈS - carte retournable connexion / inscription
   --------------------------------------------------------------------------
   La rotation est pilotée par une case à cocher masquée (#basculeAcces) :
   aucune ligne de JavaScript n'est nécessaire pour retourner la carte.

   Les deux faces occupent la MÊME cellule de grille : le conteneur prend
   ainsi la hauteur de la plus haute des deux, sans hauteur fixe à maintenir.
   ========================================================================== */

.page-acces {
   min-height: 100vh;
   min-height: 100dvh;
   background: var(--body-bg-light);

   /* LA CAUSE DU DÉFILEMENT PERMANENT DE CES PAGES, et elle n'était pas dans
      leur contenu : le `body` du projet porte `margin-bottom: 100px` (voir
      tout en haut de ce fichier), une respiration utile sous une longue page
      de gestion. Ici elle s'ajoute à un `.acces-scene` déjà haut de 100vh :
      le document mesure donc TOUJOURS 100px de plus que la fenêtre, et la
      barre de défilement apparaît même quand le contenu tient largement.
      Aucun resserrement du contenu ne pouvait y changer quoi que ce soit.

      Neutralisée pour les seules pages pleine hauteur - connexion,
      installation, pages de message, accueil public : elles se terminent sur
      le bas de l'écran, il n'y a rien à faire respirer en dessous. Les pages
      de gestion gardent leurs 100px.

      dvh après vh, comme partout ailleurs : 100vh compte la barre d'adresse
      mobile, donc une hauteur que l'écran n'offre pas. La ligne vh reste en
      premier, comme repli pour les navigateurs qui ignorent dvh. */
   margin-bottom: 0;
}

.acces-scene {
   display: flex;
   flex-direction: column;
   align-items: center;
   justify-content: center;
   gap: 1.5rem;
   min-height: 100vh;
   min-height: 100dvh;
   padding: 1.5rem 0.5rem;
}

/* connexion.php tient toujours dans un écran : centrer verticalement (ci-
   dessus) y fonctionne bien. Une page de message (404, session-requise…)
   peut porter bien plus - logo, flash, icône, titre, texte, un formulaire
   embarqué - et centrer un contenu plus haut que l'écran pousse tout vers
   le bas au lieu de partir du haut, comme si la page démarrait au milieu
   d'elle-même. Un point de départ fixe, pas un centrage qui dépend d'une
   hauteur qu'on ne maîtrise pas. */
.page-message .acces-scene {
   justify-content: flex-start;
   padding-top: 4rem;
}

/* Décalage léger vers le haut demandé par abdAllah, PC uniquement - même
   breakpoint que le seuil mobile déjà établi ailleurs dans ce fichier
   (767.98px), inversé. transform plutôt que justify-content/padding : ne
   touche pas au centrage lui-même (préférence déjà tranchée plus haut dans
   ce fichier, voir le commentaire sur .acces-carte) - un translateY ne
   modifie pas le flux de mise en page, juste la position visuelle. */
@media (min-width:768px) {
   .page-connexion .acces-scene {
      transform: translateY(-2.5rem);
   }
}

.acces-logo {
   width: 100%;
   max-width: 8rem;
}

/* La case pilote tout : ni visible, ni atteignable au clavier - ce sont les
   <label> qui la commandent qui portent le focus. */
.acces-bascule {
   position: absolute;
   width: 1px;
   height: 1px;
   opacity: 0;
   pointer-events: none;
}

.acces-carte {
   display: flex;
   flex-direction: column;
   width: 100%;
   max-width: 26rem;
   position: relative;
}

.acces-face {
   /* Colonne : le formulaire reste en haut, la rangée de liens suit les
      boutons. */
   display: flex;
   flex-direction: column;
   padding: 0 2rem;
}

/* Chorégraphie séquentielle demandée par abdAllah (remplace l'ancien
   dépliement où les deux faces animaient SIMULTANÉMENT) : au clic, le
   formulaire actif se replie D'ABORD entièrement (5px), PUIS seulement le
   nouveau s'ouvre. height plutôt que max-height : les deux formulaires
   partent du MÊME état de repos (5px), orchestré pas à pas par le script
   en bas de page - CSS pose juste la transition, JS décide quand chaque
   étape se déclenche. linear plutôt que ease-in/cubic-bezier : demande
   explicite d'une animation "non accélérée". */
.page-connexion #formConnexion,
.page-connexion #formInscription {
   overflow: hidden;
   height: 5px;
   padding: 10px;
   transition: height 1s linear;
}

/* "border-bottom noire un peu plus basse du form login" - le rideau
   (.acces-carte-en-mouvement, plus bas) suit le bord inférieur du contenu
   RÉELLEMENT visible ; cette légère marge pousse ce bord un peu plus bas
   spécifiquement pendant que #formConnexion est seul visible, sans toucher
   au formulaire d'inscription. */
.page-connexion #formConnexion {
   margin-bottom: 1.3rem;
}

/* <hr> entre Étudiant et Externe (voir HTML plus bas, bloc Situation) -
   surcharge le style générique de hr (margin:1rem auto, partagé par tout
   le projet) pour cette page seule, sans y toucher ailleurs. */
.page-connexion hr {
   margin: .7rem auto;
}

/* Formulaire d'inscription centré verticalement dans sa hauteur fixe
   (800px), PC uniquement - sur mobile le contenu
   remplit déjà toute cette hauteur (plus de retours à la ligne sur une
   largeur étroite), le centrage n'y a pas d'utilité. */
@media (min-width:768px) {
   .page-connexion #formInscription {
      display: flex;
      flex-direction: column;
      justify-content: center;
   }
}

/* Rideau - posée par le script UNIQUEMENT le temps de la chorégraphie
   complète (étape 1 à 6), retirée une fois le nouveau formulaire stabilisé.
   Sur .acces-carte (pas .acces-face) : une seule ligne commune aux deux
   formulaires plutôt qu'une par face.
   Un ::after plutôt qu'un border-bottom classique : une bordure ne peut pas
   balayer horizontalement depuis un point central, seule sa LARGEUR
   change. left:50% + translateX(-50%) garde le pseudo-élément centré peu
   importe sa largeur - l'animer de 0 à 100% donne l'effet demandé
   (« part d'un point au centre et élargit sur les côtés jusqu'aux bords »).
   Au retrait de la classe, la transition rejoue automatiquement en sens
   inverse (100%→0, toujours centrée) - effet fermeture symétrique sans
   code séparé. */
.acces-carte::after {
   content: '';
   position: absolute;
   left: 50%;
   bottom: 0;
   width: 0;
   height: 7px;
   background: #606060;
   transform: translateX(-50%);
   transition: width .5s ease;
}

.acces-carte.acces-carte-en-mouvement::after {
   width: 100%;
}

/* Les deux faces sont posées à même la page : ni cadre, ni fond, ni ombre. */
.acces-recto,
.acces-verso {
   background: none;
   border: none;
   box-shadow: none;
}

/* Bascule et soumission côte à côte, largeurs égales : la même paire, dans
   le même ordre, sur les deux faces - seuls les libellés s'échangent. */
.acces-actions {
   display: flex;
   gap: .75rem;
}

.acces-actions > .btn {
   flex: 1 1 0;
   min-width: 0;
}

/* Le <label> déguisé en bouton doit s'aligner comme un vrai bouton. */
.acces-actions > .acces-bascule-lien {
   display: inline-flex;
   align-items: center;
   justify-content: center;
   gap: .4rem;
   margin: 0;
}

/* Deux colonnes fixes, identiques sur les deux faces : gauche « Mot de passe
   oublié », centre la bascule, droite « Retour au site ». Le verso n'ayant pas
   de lien à gauche, sa colonne reste vide - mais « Se connecter » tombe au
   même endroit que « S'inscrire », au pixel près, avant comme après la
   rotation. */
.acces-liens {
   display: grid;
   grid-template-columns: 1fr 1fr;
   align-items: center;
   gap: .75rem;
   /* Les liens suivent les boutons de près. La marge automatique qui les
      poussait en bas n'a plus lieu d'être : c'est la paire de boutons, la
      même sur les deux faces, qui sert désormais de repère au regard. */
   margin-top: .85rem;
   font-size: var(--fs-sm);
   white-space: nowrap;
}

.acces-lien-oubli {
   grid-column: 1;
}

/* Les liens vivent maintenant dans le formulaire : la rangée garde son
   écartement vis-à-vis des boutons. */
.acces-actions + .acces-liens {
   margin-top: .85rem;
}

/* Écarts resserrés sur cette page seule (abdAllah : "les ecarts entre les
   btn est trop grand -> 0.3rem max idem pour mobile") - pas de media query,
   la même valeur vaut sur PC et mobile. Ni flex:1 1 0 (.acces-actions >
   .btn) ni grid-template-columns:1fr 1fr (.acces-liens) ne dépendent du
   gap : l'égalité de largeur des 4 boutons reste intacte. */
.page-connexion .acces-actions,
.page-connexion .acces-liens {
   gap: .3rem;
}

.page-connexion .acces-actions + .acces-liens {
   margin-top: .3rem;
}

.acces-lien-retour {
   grid-column: 2;
}

/* Seul de sa rangée - la face inscription n'a pas de « Mot de passe oublié » -
   il occupe toute la largeur et se centre. `:only-child` évite de viser la
   face : la règle vaut partout où le lien se retrouve seul. */
.acces-liens .acces-lien-retour:only-child {
   grid-column: 1 / -1;
   justify-self: center;
}

/* LARGEURS ÉGALES (abdAllah, 11/10) : deux par ligne, les boutons ont la même largeur - celle de
   la paire du dessus ; seul sur sa ligne, un bouton prend toute la largeur. `minmax(0, 1fr)` : un
   libellé plus long (« Mot de passe oublié ») n'élargit plus sa colonne. */
.acces-liens {
   grid-template-columns: repeat(2, minmax(0, 1fr));
}
.acces-liens > .btn {
   width: 100%;
   min-width: 0;
   overflow: hidden;
   text-overflow: ellipsis;
}
.acces-liens > .btn:only-child {
   grid-column: 1 / -1;
   justify-self: stretch;
}

/* Style « épuré » de front/connexion.php - validé par abdAllah sur mockup
   (coin carré, champs à trait inférieur seul, sans icône affixe) avant tout
   code. Porté par .page-connexion (posée sur ce seul <body>) pour ne
   toucher ni index.php, ni init-bdd.php, ni page-message.php : les trois
   autres pages partagent .page-acces mais gardent leur style .acces-*
   d'origine (input-group + icône, coins arrondis) inchangé. */
.page-connexion .acces-face .form-control,
.page-connexion .acces-face .form-select {
   border-radius: 0;
   border: none;
   border-bottom: 1.5px solid var(--line);
   background: none;
   padding: 0 .7rem;
}

.page-connexion .acces-face .form-control:focus,
.page-connexion .acces-face .form-select:focus {
   background: var(--panel);
}

.page-connexion .acces-face .form-label {
   text-transform: none;
   font-size: .8rem;
   color: var(--slate-dim);
}

.page-connexion .acces-face .btn-primary {
   border-radius: 0;
}

.page-connexion .acces-face .btn-secondary {
   border-radius: 0;
}

/* Champ mot de passe SANS input-group (retiré avec l'icône affixe) : l'œil
   est repositionné en absolu par-dessus le trait inférieur du champ, même
   principe que le mockup validé. */
.page-connexion .acces-champ-mdp {
   position: relative;
}

.page-connexion .acces-champ-mdp .form-control {
   padding-right: 1.6rem;
}

.page-connexion .acces-oeil {
   position: absolute;
   right: 0;
   top: 0;
   margin-top: .5rem;
   margin-right: .5rem;
   background: none;
   border: none;
   padding: 0;
   color: var(--slate-dim);
   font-size: 1.1rem;
   line-height: 1;
}

.page-connexion .acces-oeil:hover,
.page-connexion .acces-oeil:focus-visible {
   color: var(--dominante-color);
}

/* Autoremplissage du navigateur (voir le correctif GLOBAL plus haut dans ce
   fichier, § Formulaires - même mécanisme, box-shadow inset) : sur cette
   page seule, fond de PAGE plutôt que blanc plein, pour rester transparent
   à l'oeil sur le style épuré à trait inférieur - pas de variable dédiée
   déjà adaptée aux 2 thèmes pour ce fond précis (contrairement à --panel),
   donc les 2 valeurs réelles du body sont reprises telles quelles ici. */
.page-connexion input:-webkit-autofill,
.page-connexion input:-webkit-autofill:hover {
   -webkit-box-shadow: 0 0 0 1000px var(--body-bg-light) inset;
   box-shadow: 0 0 0 1000px var(--body-bg-light) inset;
}

[data-theme="dark"] .page-connexion input:-webkit-autofill,
[data-theme="dark"] .page-connexion input:-webkit-autofill:hover {
   -webkit-box-shadow: 0 0 0 1000px #12141c inset;
   box-shadow: 0 0 0 1000px #12141c inset;
}

/* Champ à la fois autorempli ET focus : même fond blanc que le focus normal
   (voir .form-control:focus plus haut), pas le fond transparent ci-dessus -
   la personne est activement en train de le modifier. */
.page-connexion input:-webkit-autofill:focus {
   -webkit-box-shadow: 0 0 0 1000px var(--panel) inset;
   box-shadow: 0 0 0 1000px var(--panel) inset;
}

/* Les deux extrémités du champ mot de passe partagent le fond de l'affixe :
   le bouton œil est un .btn, il ne reprenait donc rien de .input-group-text.

   AUCUNE PORTÉE DE PAGE, et c'est le fond du sujet. Ce raccord a été accroché
   d'abord à .acces-face - la carte retournable de la connexion - puis à
   .acces-scene, son <main>. Les deux fois il a fallu revenir l'élargir, parce
   que le bouton œil n'appartient à aucune page en particulier : il vit dans
   un input-group, partout où un mot de passe se saisit. Quatre pages en
   portent un aujourd'hui (connexion, installation, Paramètres › Base de
   données, Paramètres › Configurations) et la prochaine en héritera sans
   qu'on ait à y penser.

   Le sélecteur décrit donc la SITUATION, pas l'emplacement : un .btn[data-voir]
   dernier enfant d'un .input-group s'aligne sur l'affixe d'en face. Rien à
   ajouter le jour où un cinquième formulaire en aura besoin.

   Le bouton COPIER (.btn[data-copier], Paramètres › API, 08/10) suit la même
   règle : même situation, même affixe. */
.input-group > .btn[data-voir],
.input-group > .btn[data-copier],
.input-group > .btn[data-modele-suppr] {
   background: var(--dc-12-t, rgba(6, 93, 137, .12));
   border-color: var(--line);
   color: var(--dominante-color);

   /* LA GÉOMÉTRIE AUTANT QUE LA COULEUR. Un raccord de teinte seul laissait
      deux blocs de tailles différentes de part et d'autre du champ : .btn
      n'hérite RIEN de .input-group-text, ni sa hauteur, ni sa largeur
      minimale, ni son rembourrage - et porte en plus une marge basse de 3px
      (voir .btn plus haut, posée pour les boutons en ligne) qui le raccourcit
      de 3px dans un input-group, où les enfants s'étirent sur la hauteur.
      D'où un œil visiblement plus grand, décalé, et sans le carré de l'affixe
      d'en face. Les six valeurs ci-dessous sont EXACTEMENT celles de
      .input-group-text : les recopier ici est le seul moyen de garantir la
      symétrie, une classe utilitaire de plus ne ferait qu'empiler. */
   min-height: var(--btn-h-md);
   min-width: 2.5rem;
   padding: .3rem .6rem;
   margin-bottom: 0;
   font-size: .95rem;
   line-height: 1.4;

   /* Seulement les coins DROITS : Bootstrap met déjà les gauches à zéro pour
      le dernier enfant d'un input-group, les arrondir ici rouvrirait la
      jointure avec le champ. */
   border-top-right-radius: var(--radius-field);
   border-bottom-right-radius: var(--radius-field);
}

.input-group > .btn[data-voir]:hover,
.input-group > .btn[data-voir]:focus-visible,
.input-group > .btn[data-copier]:hover,
.input-group > .btn[data-copier]:focus-visible,
.input-group > .btn[data-modele-suppr]:hover,
.input-group > .btn[data-modele-suppr]:focus-visible {
   background: var(--dc-25-t, rgba(6, 93, 137, .25));
   border-color: var(--line);
   color: var(--dominante-color);
   transform: none;
}

/* Thème sombre : la dominante en avant-plan y devient illisible. Cette règle
   vivait dans le groupe des sélecteurs .acces-* plus bas ; elle en sort pour
   suivre la portée générale ci-dessus - sinon le bouton s'alignerait partout
   en clair, mais garderait sa couleur d'origine en sombre hors des pages
   d'accès. Même jeton que le reste du groupe, --dc-60-w. */
[data-theme="dark"] .input-group > .btn[data-voir],
[data-theme="dark"] .input-group > .btn[data-voir]:hover,
[data-theme="dark"] .input-group > .btn[data-voir]:focus-visible,
[data-theme="dark"] .input-group > .btn[data-copier],
[data-theme="dark"] .input-group > .btn[data-copier]:hover,
[data-theme="dark"] .input-group > .btn[data-copier]:focus-visible {
   color: var(--dc-60-w, #6b9fba);
}

/* L'ICÔNE DE GAUCHE d'un champ à copier (08/10) : le champ est en lecture seule, mais
   il n'est pas « fermé » - on le copie. Son affixe garde donc la teinte de la charte,
   au lieu du gris des champs en lecture seule (tools.css). */
.input-group:has(> .form-control[readonly]):has(> .btn[data-copier]) > .input-group-text {
   background: var(--dc-12-t, rgba(6, 93, 137, .12));
   color: var(--dominante-color);
}
[data-theme="dark"] .input-group:has(> .form-control[readonly]):has(> .btn[data-copier]) > .input-group-text {
   background: var(--dc-20-t, rgba(6, 93, 137, .2));
   color: var(--dc-60-w, #6b9fba);
}

/* Les liens des pages d'accès (connexion…). La variante <button> en lien
   (.lien-plat) est retirée le 01/10 : plus aucune page ne s'en servait.
   :not(.acces-lien-retour) - « Retour au site » (les 2 faces) doit rester
   visuellement IDENTIQUE à « S'inscrire » (couleur/fond/survol) : sans
   cette exclusion, ce sélecteur générique (plus spécifique que .btn-
   secondary seul) écrasait sa couleur et son survol natifs, alors que
   « S'inscrire », posé dans .acces-actions et non .acces-liens, n'est
   jamais concerné par cette règle. */
.acces-liens a:not(.acces-lien-retour) {
   padding: .4rem .8rem;
   border-radius: var(--radius-field);
   color: var(--dominante-color);
   cursor: pointer;
   transition: background-color .18s ease, color .18s ease;
}

.acces-liens a:not(.acces-lien-retour):hover,
.acces-liens a:not(.acces-lien-retour):focus-visible {
   background: var(--dc-12-t, rgba(6, 93, 137, .12));
   color: var(--dominante-color-hover);
}

/* Une rotation peut gêner : on la remplace alors par un simple changement. */
@media (prefers-reduced-motion: reduce) {

   .acces-carte,
   .acces-bascule:checked ~ .acces-carte,
   .acces-verso {
      transition: none;
      transform: none;
   }
}

/* --------------------------------------------------------------------------
   Pages de message (404, compte désactivé, accès refusé)
   Même mise en scène que la page d'accès : logo, carte centrée, paire de
   boutons. Seul le contenu de la carte change.
   -------------------------------------------------------------------------- */

/* Sans la classe .card, la section n'a ni fond ni bordure : c'est le cas des
   pages 404 et accès refusé, qui posent leur message à même la page. */
.acces-message {
   width: 100%;
   max-width: 30rem;
   padding: 2rem 1.5rem;
   text-align: center;
}

/* Même palette que .alert-danger (mêmes jetons Bootstrap) - un message qui
   annonce un blocage réel doit se voir comme tel, pas se fondre dans le
   même fond neutre qu'une page 404 ou un compte désactivé. */
.acces-message-danger {
   background: var(--bs-danger-bg-subtle);
   border: 1px solid var(--bs-danger-border-subtle);
   color: var(--bs-danger-text-emphasis);
}

.acces-message-danger .acces-message-icone {
   color: var(--bs-danger-text-emphasis);
}

/* Icône en tête d'un titre d'accès - l'écran d'installation la place à gauche
   de « Base de données ». Dimensionnée en `em` et non en `rem` : elle suit le
   titre qu'elle accompagne, y compris si --fs-xl change un jour, au lieu de
   se figer à une taille absolue qui finirait par jurer.

   vertical-align négatif plutôt qu'un flex sur le h1 : le titre reste un bloc
   de texte centré comme les autres de la page, sans qu'il faille reprendre
   son alignement. */
.acces-titre-icone {
   margin-right: .35em;
   font-size: 1.7em;
   color: var(--dominante-color);
   vertical-align: -.22em;
}

.acces-message-code {
   font-size: 3.5rem;
   font-weight: var(--fw-bold);
   line-height: 1;
   color: var(--dc-25-w, #b6d0dd);
}

.acces-message-icone {
   display: block;
   margin: .5rem 0 1rem;
   font-size: 3rem;
   color: var(--dominante-color);
}

.acces-message-titre {
   margin: 0 0 .75rem;
   font-size: var(--fs-xl);
   font-weight: var(--fw-bold);
   color: var(--slate);
}

.acces-message-texte {
   margin: 0 auto 1.5rem;
   max-width: 26rem;
   font-size: var(--fs-sm);
   line-height: 1.6;
   color: var(--slate-dim);
}

/* Sur ces pages, la paire de boutons ne remplit pas toute la largeur. */
.acces-message .acces-actions {
   justify-content: center;
}

.acces-message .acces-actions > .btn {
   flex: 0 1 12rem;
}

/* Conditions du mot de passe - la puce passe au vert dès la règle satisfaite.
   Les puces sont dessinées en ::before : une liste sans marqueur natif, dont
   l'icône change d'état sans toucher au balisage. */
.mdp-regles {
   margin: .25rem 0 1rem;
   padding: 0;
   list-style: none;
   font-size: var(--fs-xs);
   line-height: 1.7;
   color: var(--slate-dim);
}

.mdp-regles li {
   display: flex;
   align-items: center;
   gap: .4rem;
}

.mdp-regles li::before {
   content: "";
   flex: 0 0 auto;
   width: .55rem;
   height: .55rem;
   border-radius: 50%;
   border: 2px solid var(--dc-30-w, #b6d0dd);
   transition: background-color .15s ease, border-color .15s ease;
}

.mdp-regles li.regle-ok {
   color: var(--state-success);
}

.mdp-regles li.regle-ok::before {
   background: var(--state-success);
   border-color: var(--state-success);
}

/* ==========================================================================
   BANDEAU DES MESSAGES (flash)
   --------------------------------------------------------------------------
   Posé en haut du contenu, sous le bandeau de titre. Les messages sont
   consommés à l'affichage : ils ne reviennent pas au chargement suivant.
   ========================================================================== */

.flash-zone {
   padding: .75rem 1.5rem 0;
}

/* Entrée par le haut, sortie vers le haut : le mouvement dit d'où vient le
   message et où il repart.

   Les animations ne sont pas posées sur .flash-message directement : le
   balisage arrive avec la page, l'entrée se jouerait pendant le chargement,
   souvent avant que l'écran n'affiche quoi que ce soit. C'est le script qui
   ajoute .flash-entre une fois la page prête. */
@keyframes flash-glisse {
   from {
      opacity: 0;
      transform: translateY(-1.25rem);
   }

   to {
      opacity: 1;
      transform: translateY(0);
   }
}

@keyframes flash-glisse-sortie {
   from {
      opacity: 1;
      transform: translateY(0);
      max-height: 12rem;
   }

   to {
      opacity: 0;
      transform: translateY(-1.25rem);
      max-height: 0;
      margin-bottom: 0;
      padding-top: 0;
      padding-bottom: 0;
   }
}

.flash-message {
   /* Invisible tant que le script n'a pas lancé l'entrée. Le <noscript> du
      bandeau rétablit l'affichage si le script ne s'exécute pas. */
   opacity: 0;
   display: flex;
   align-items: flex-start;
   gap: .7rem;
   margin-bottom: .6rem;
   padding: .8rem 3rem .8rem 1rem;
   border-radius: var(--radius-field);
   font-size: var(--fs-sm);
   line-height: var(--lh-snug);
   /* Le message entier se ferme au clic : le curseur doit le dire. */
   cursor: pointer;
}

.flash-icone {
   flex: 0 0 auto;
   font-size: 1.4rem;
   line-height: 1;
}

.flash-corps {
   min-width: 0;
}

.flash-titre {
   margin: 0;
   font-size: var(--fs-sm);
   font-weight: var(--fw-bold);
   line-height: var(--lh-snug);
}

/* Le texte suit le titre ; sans titre, il occupe seul la ligne. */
.flash-texte {
   margin: .15rem 0 0;
}

.flash-titre:only-child,
.flash-texte:only-child {
   margin-top: 0;
}

/* Le bouton de fermeture de Bootstrap est positionné en absolu : le
   rembourrage droit du message lui réserve sa place. */
.flash-message .btn-close {
   padding: 1rem;
}

@media (max-width: 768px) {
   .flash-zone {
      padding: .6rem 1rem 0;
   }
}

.flash-message.flash-entre {
   animation: flash-glisse .35s cubic-bezier(.22, .68, .36, 1) both;
}

.flash-message.flash-sortie {
   overflow: hidden;
   animation: flash-glisse-sortie .3s cubic-bezier(.55, 0, .68, .3) both;
}

/* Certains préfèrent - ou doivent - se passer d'animations. Le mouvement
   disparaît, le fondu reste : le message ne surgit pas brutalement et rien
   ne glisse à l'écran. */
/* Mouvement réduit : plus de glissement, le fondu suffit à signaler l'arrivée
   et le départ. */
@media (prefers-reduced-motion: reduce) {

   .flash-message.flash-entre,
   .flash-message.flash-sortie {
      animation-duration: .2s;
      animation-timing-function: linear;
   }

   .flash-message.flash-entre {
      animation-name: flash-fondu;
   }

   .flash-message.flash-sortie {
      animation-name: flash-fondu-sortie;
   }

   @keyframes flash-fondu {
      from {
         opacity: 0;
      }

      to {
         opacity: 1;
      }
   }

   @keyframes flash-fondu-sortie {
      from {
         opacity: 1;
      }

      to {
         opacity: 0;
      }
   }
}

/* Sur les pages d'accès, le bandeau s'aligne sur la largeur de la carte :
   une alerte pleine largeur au-dessus d'un formulaire étroit flotte. */
.page-acces .flash-zone {
   width: 100%;
   max-width: 32rem;
   padding: 0 0 .25rem;
}

/* Tableau des permissions : une colonne par statut, une case par croisement.
   Les en-têtes de statut restent lisibles sur écran étroit - le tableau
   défile horizontalement dans son .table-responsive plutôt que de comprimer
   les libellés. */
.table-permissions th {
   font-size: var(--fs-sm);
   font-weight: var(--fw-bold);
   white-space: nowrap;
}

.table-permissions tbody th {
   font-weight: var(--fw-regular);
}

.table-permissions tbody th .ph-duotone {
   margin-right: .4rem;
   color: var(--dominante-color);
}

/* La colonne du superviseur est verrouillée : sa case grisée doit se lire
   comme « acquis », pas comme « indisponible ». */
.table-permissions .form-check-input:disabled {
   opacity: 1;
   background-color: var(--dominante-color);
   border-color: var(--dominante-color);
}

/* ---- Chenillard et mention, écran d'installation ------------------------
   Le scanner de KITT est une rangée de segments FIXES dont la luminosité
   varie : la lumière ne se déplace pas, elle se propage. Et elle fait un
   VA-ET-VIENT - elle revient sur ses pas au lieu de resurgir du même côté.

   POURQUOI PAS UN animation-delay PAR SEGMENT. C'était ma première idée, et
   elle est fausse : décaler 12 segments d'un même pas produit un
   chenillard, pas un rebond. La crête traverse, sort par la gauche, et la
   suivante entre par la droite - la simulation le montre sans ambiguïté. Le
   décalage est monotone, il ne peut pas s'inverser à mi-parcours.

   D'OÙ CE MONTAGE, en trois couches superposées :
     1. le fond du ruban  - les segments « éteints », une teinte faible ;
     2. la lueur          - UN seul élément, un dégradé aux bords fondus, qui
                            fait l'aller-retour par translateX + `alternate` ;
                            un seul élément qui rebondit, donc un vrai rebond,
                            garanti par le moteur et non par une arithmétique
                            de décalages ;
     3. la grille (::after) - des séparateurs de la couleur de la CARTE, posés
                            par-dessus. Ils découpent la lueur continue en
                            12 segments distincts : c'est ce qui donne les
                            carrés dont l'opacité varie, sans qu'aucun carré
                            n'ait à être animé individuellement.

   Le tout suit --dominante-color, et --panel pour les séparateurs : ces deux
   jetons basculent seuls en thème sombre, la grille reste donc invisible sur
   les deux fonds sans une seule règle de plus.

   Seul `transform` est animé - composé par le GPU, sans recalcul de mise en
   page. Et tout est en CSS : une animation qui dépendrait d'un script
   s'arrêterait net si celui-ci échouait. */
.acces-chenillard {
   position: relative;

   /* width: 100% EST INDISPENSABLE, ce n'est pas une redondance avec
      max-width : .acces-message porte aussi .card, dont Bootstrap fait un
      conteneur flex en colonne. Sans largeur explicite, cet enfant retombe
      sur la taille de son contenu - nulle, la lueur étant en position
      absolue - et le ruban reste invisible. flex: 0 0 auto le protège de la
      compression sur l'axe principal. */
   flex: 0 0 auto;
   width: 100%;
   max-width: 18rem;
   height: .4rem;
   margin: 15px auto 30px;
   overflow: hidden;
   background: var(--dc-12-t, rgba(6, 93, 137, .12));
}

/* La lueur. Les bords fondus du dégradé font la traînée : un bloc à bords
   nets donnerait un carré qui glisse, pas une lumière qui se propage. */
.acces-chenillard > span {
   position: absolute;
   top: 0;
   bottom: 0;
   left: 0;
   width: 42%;
   /* --dc-60-w et non --dominante-color : la dominante pure est une teinte
      PROFONDE, et une lueur doit éclairer, pas assombrir. Ce jeton en est une
      version éclaircie - même couleur de charte, mais lumineuse.

      SENS DE L'ÉCHELLE, à ne pas inverser : le nombre monte VERS la
      dominante. --dc-40-w (#9bbed0) est donc plus clair que --dc-60-w
      (#6b9fba), lui-même plus clair que la dominante (#065d89). Monter le
      nombre assombrit. */
   background: linear-gradient(90deg,
         transparent 0%,
         var(--dc-60-w, #6b9fba) 42%,
         var(--dc-60-w, #6b9fba) 58%,
         transparent 100%);

   /* 2.6s : un aller simple. Le cycle complet, aller ET retour, en dure donc
      le double - c'est ce que `alternate` implique, et c'est la durée que
      l'œil perçoit. */
   animation: acces-chenillard 2.6s ease-in-out infinite alternate;
}

/* De −50% à 188.1%, et non de 0 à « collé à droite ». C'est le CENTRE de la
   lueur qui doit atteindre chaque extrémité, pas son bord : sinon la crête
   ne balaie que les segments du milieu et les deux bouts ne s'allument
   jamais vraiment - chez KITT, la lumière touche les deux extrémités. La
   lueur déborde donc de part et d'autre, ce que `overflow: hidden` recadre
   proprement. −50% place son centre sur le bord gauche ; 188.1%, soit
   (100 / 42) × 100 − 50, le place sur le bord droit.

   `alternate` fait le retour, et `ease-in-out` marque le ralentissement à
   chaque extrémité - c'est ce temps d'arrêt qui signe le mouvement de KITT. */
@keyframes acces-chenillard {
   from { transform: translateX(-50%); }
   to   { transform: translateX(188.1%); }
}

/* La grille. Des séparateurs de la couleur de la carte, PAR-DESSUS la lueur :
   c'est en masquant qu'ils dessinent les segments, aucun n'existe en propre.
   top/right/bottom/left séparés plutôt que le raccourci `inset`, plus récent :
   son repli serait une grille sans position, donc un aplat qui couvrirait
   tout le ruban. */
.acces-chenillard::after {
   content: "";
   position: absolute;
   top: 0;
   right: 0;
   bottom: 0;
   left: 0;
   background: repeating-linear-gradient(90deg,
         transparent 0,
         transparent calc(100% / 12 - 2px),
         var(--panel, #fff) calc(100% / 12 - 2px),
         var(--panel, #fff) calc(100% / 12));
}

/* Thème sombre : la lueur doit être PLUS CLAIRE que sur fond blanc, donc un
   nombre PLUS BAS - 40 et non 60. La règle précédente disait « un cran plus
   clair » mais montait le nombre : elle assombrissait la lueur sur le fond le
   plus sombre, exactement l'inverse du besoin. Le projet applique déjà cette
   logique ailleurs (voir .input-group-text, qui passe de la dominante pleine
   à --dc-60-w en sombre). Les séparateurs, eux, suivent --panel et n'ont
   besoin de rien. */
[data-theme="dark"] .acces-chenillard > span {
   background: linear-gradient(90deg,
         transparent 0%,
         var(--dc-40-w, #9bbed0) 42%,
         var(--dc-40-w, #9bbed0) 58%,
         transparent 100%);
}

/* Ce réglage système vise exactement les animations perpétuelles comme
   celle-ci. La lueur reste, immobile au centre, plutôt que de disparaître. */
@media (prefers-reduced-motion: reduce) {
   .acces-chenillard > span {
      animation: none;
      transform: translateX(69.0%);
   }
}

/* Survol des deux boutons de l'écran d'installation. Le fond change déjà, via
   les jetons --bs-btn-hover-bg de .btn-primary et .btn-secondary : ce bloc
   n'y touche pas et AJOUTE le relief, un léger soulèvement et une ombre
   portée. Deux effets qui se lisent ensemble - le fond dit « ce bouton
   réagit », le relief dit « il est cliquable ».

   PORTÉE .page-init-bdd .btn, PLUS .acces-actions. Les deux boutons ont quitté
   cette barre : « Se connecter » est monté dans la rangée du mot de passe,
   « Fichier SQL » est descendu seul sous la note. Accrochée à .acces-actions,
   la règle ne touchait plus rien - le relief avait disparu en silence, sans
   qu'aucune vérification ne s'en plaigne. Elle vise donc désormais les boutons
   de la page, où qu'ils soient posés.

   :not([data-voir]) écarte le seul autre .btn de la page, l'œil du champ mot
   de passe : lui appartient à son input-group et ne doit pas se soulever
   au-dessus du champ auquel il est collé.

   Le vocabulaire est celui déjà employé par .search-group .btn:hover plus
   haut dans ce fichier : soulèvement en translateY + ombre. Reprendre un
   geste existant plutôt qu'en inventer un troisième garde l'interface d'une
   seule main.

   .btn ne porte AUCUNE transition dans ce projet : sans la ligne ci-dessous,
   le soulèvement serait instantané, un sursaut plutôt qu'un mouvement. Elle
   ne nomme que transform et box-shadow - surtout pas `all`, qui animerait
   aussi le fond géré par Bootstrap et le rendrait mou. */
.page-init-bdd .btn:not([data-voir]) {
   transition: transform .18s ease-out, box-shadow .18s ease-out;
}

/* Un bouton d'envoi doit faire la MÊME HAUTEUR que le champ posé à sa
   gauche : sans cela il retombe sur sa hauteur naturelle, environ 31px
   (0.875rem × 1.15 + 2 × 0.375rem + les bordures) contre les 34px que
   .form-control tient de --btn-h-md. Trois pixels d'écart suffisent à faire
   voir deux blocs mal appariés là où on attend une seule ligne.

   Le calage VERTICAL, lui, se fait dans le balisage - une étiquette vide en
   vis-à-vis de « Mot de passe » - et non ici : une marge chiffrée en CSS
   serait à corriger le jour où la taille des étiquettes change. */
/* AUCUNE PORTÉE DE PAGE, pour la même raison que le bouton œil plus haut :
   cette classe décrit une SITUATION - un bouton d'envoi posé à côté d'un
   champ, dans une rangée où les deux doivent se lire comme une seule ligne -
   et non un emplacement. Deux pages l'emploient déjà (init-bdd.php et
   Paramètres › Base de données) ; laissée sous .page-init-bdd, elle n'aurait
   servi que la première, et la seconde aurait retrouvé les 3 px de décalage
   sans que rien ne le signale. */
.acces-envoi {
   min-height: var(--btn-h-md);

   /* .btn porte `margin-bottom: 3px` pour tout le projet - une respiration
      utile aux boutons posés en ligne dans une barre d'outils. Ici elle nuit :
      le bouton est le seul contenu de sa colonne, en vis-à-vis d'un champ qui
      n'a pas cette marge, et ces 3px le décalent vers le haut de la ligne.
      Le champ mot de passe d'en face garde, lui, l'espacement de son
      conteneur .mb-2 : c'est ce dernier qui doit régler l'écart, pas une
      marge de bouton. */
   margin-bottom: 0;
}

/* Même piège, même solution : dernier enfant d'un input-group, #btnTesterSmtp
   hérite les 3px de marge basse de .btn (voir plus haut) qui le raccourcit
   face au champ dont il partage la ligne. */
#btnTesterSmtp {
   min-height: var(--btn-h-md);
   margin-bottom: 0;
}

.page-init-bdd .btn:not([data-voir]):hover,
.page-init-bdd .btn:not([data-voir]):focus-visible {
   transform: translateY(-2px);
   box-shadow: 0 4px 10px rgba(20, 23, 31, .18);
}

/* Le clic REPOSE le bouton : sans cet état, il reste soulevé pendant qu'on
   appuie dessus, et le geste ne rend rien. */
.page-init-bdd .btn:not([data-voir]):active {
   transform: translateY(0);
   box-shadow: none;
}

/* Le fond, lui, continue de répondre : c'est le mouvement qui est retiré,
   pas la réaction au survol. */
@media (prefers-reduced-motion: reduce) {
   .page-init-bdd .btn:not([data-voir]),
   .page-init-bdd .btn:not([data-voir]):hover,
   .page-init-bdd .btn:not([data-voir]):focus-visible,
   .page-init-bdd .btn:not([data-voir]):active {
      transition: none;
      transform: none;
   }
}

/* Mention sous la carte, hors de celle-ci : elle appartient à la page, pas au
   formulaire. */
.acces-copyright {
   margin: 0;
   font-size: var(--fs-xs);
   color: var(--slate);
   text-align: center;
}

/* Aucun soulignement, règle du projet : c'est le fond qui marque le survol. */
.acces-copyright a {
   padding: .1rem .35rem;
   border-radius: var(--radius-field);
   color: var(--dominante-color);
   text-decoration: none;
   transition: background .25s;
}

.acces-copyright a:hover,
.acces-copyright a:focus-visible {
   background: var(--dc-12-t, rgba(6, 93, 137, .12));
   color: var(--dominante-color);
   text-decoration: none;
}

[data-theme="dark"] .acces-copyright a {
   color: var(--dc-60-w, #6b9fba);
}

/* ---- Écran d'installation : s'adapter à la fenêtre, quelle qu'elle soit ---
   init-bdd.php porte plus que la connexion - un titre, un texte, CINQ champs,
   deux boutons et une note. Aux mesures par défaut de la scène d'accès
   l'ensemble dépasse la hauteur utile d'un portable courant, et la page
   défile alors qu'elle doit se lire d'un coup d'œil.

   TOUT EST EN clamp(min, vh, max), JAMAIS EN VALEUR FIXE. Une valeur fixe
   choisie sur un écran donné est juste sur celui-là et fausse partout
   ailleurs : trop serrée sur un grand moniteur, encore trop large sur un
   portable. Ici chaque espacement suit la hauteur de la FENÊTRE - la page
   retrouve toute sa respiration au-delà de ~800 px, se resserre d'elle-même
   en dessous, et le `min` empêche l'écrasement illisible sur un mobile en
   paysage. Aucun seuil à maintenir, aucune machine de référence.

   dvh AVANT vh, et non l'inverse : sur mobile, 100vh compte la barre
   d'adresse qui se rétracte au défilement, donc une hauteur que l'écran
   n'offre pas - c'est précisément ce qui fait apparaître un défilement
   résiduel sur téléphone. Les navigateurs qui ignorent dvh gardent la ligne
   vh au-dessus, écrite en premier comme repli.

   L'icône du titre ne varie pas : c'est un choix d'affichage assumé, pas de
   l'espace à récupérer. Et rien n'est masqué ni tronqué - sous ~480 px de
   hauteur utile, la page défile, ce qui reste le comportement correct : un
   overflow caché escamoterait le bouton d'envoi.

   Porté par .page-init-bdd : la connexion et les pages de message gardent
   exactement leurs mesures. */
.page-init-bdd .acces-scene {
   gap: clamp(.5rem, 2vh, 1.5rem);
   padding: clamp(.5rem, 2vh, 1.5rem) .5rem;
}

.page-init-bdd .acces-logo {
   max-width: clamp(4.5rem, 12vh, 8rem);
}

.page-init-bdd .acces-message {
   padding: clamp(1rem, 3vh, 2rem) 1.5rem;
}

.page-init-bdd .acces-message-titre {
   margin-bottom: clamp(.25rem, 1vh, .75rem);
}

.page-init-bdd .acces-message-texte {
   margin-bottom: clamp(.5rem, 2vh, 1.5rem);
}

/* Ces deux marges venaient d'utilitaires mt-* dans le balisage : une valeur
   fixe de plus, que le CSS n'aurait pu reprendre qu'à coups de !important.
   Retirées du HTML, elles suivent la fenêtre comme le reste.

   La première visait .acces-actions, la barre des deux boutons ; celle-ci
   ayant disparu du balisage, la marge revient à ce qui occupe sa place, le
   bouton « Fichier SQL » désormais seul sous la note. */
.page-init-bdd .init-bdd-sql {
   margin-top: clamp(.5rem, 2vh, 1.5rem);
}

.page-init-bdd .init-bdd-note {
   margin-top: clamp(.5rem, 2vh, 1.5rem);
}

/* ---- Page de connexion en thème sombre --------------------------------- */

/* backend/index.php charge mc-theme : la page d'accès peut donc s'afficher
   en sombre, et sa dominante en avant-plan y devenait illisible. */

[data-theme="dark"] .acces-message-icone,
[data-theme="dark"] .acces-titre-icone,
[data-theme="dark"] .form-check-label .ph-duotone {
   color: var(--dc-60-w, #6b9fba);
}

[data-theme="dark"] .acces-message-texte,
[data-theme="dark"] .mdp-regles {
   color: var(--slate, #8a91a6);
}

/* Même largeur qu'une modal-dialog SANS taille (modal-adulte.php,
   modal-enfant.php) - pour une page autonome qui affiche le même
   formulaire hors modale (add-adulte.php, add-enfant.php) et doit lui
   rester visuellement identique. var(), pas 500px en dur : si la largeur
   de modale par défaut change un jour, celle-ci suit sans y repenser. */
.mc-largeur-modale {
   max-width: var(--bs-modal-width, 500px);
}

/* Timeline d'installation - voir inc/timeline-installation.php. Un fond de
   charte (même dominante que card-header/input-group-text), pour se
   distinguer d'un panneau ordinaire sans pour autant crier « attention » -
   ce n'est pas une erreur, juste une étape qui reste à franchir. */
.mc-timeline-install {
   background: var(--dc-12-t, rgba(6, 93, 137, .12));
   border-radius: var(--radius-field);
   padding: .85rem 1.25rem;
   margin: 0 0 1rem;
   box-shadow: rgb(0 0 0 / 42%) 0px 2px 6px;
}

.mc-timeline-install-titre {
   font-size: var(--fs-xs);
   font-weight: var(--fw-bold);
   color: var(--dominante-color);
   margin: 0 0 .6rem;
}

.mc-timeline-install-etapes {
   display: flex;
   align-items: flex-start;
   list-style: none;
   margin: 0;
   padding: 0;
}

/* Le POURQUOI de l'étape en cours - un seul texte à la fois, jamais les
   quatre à la suite : la timeline montre déjà où on en est, ce cadre se
   contente d'expliquer l'étape qu'il reste à franchir. */
.mc-timeline-install-instructions {
   display: flex;
   align-items: flex-start;
   gap: .6rem;
   margin-top: .9rem;
   padding-top: .85rem;
   border-top: 1px solid var(--dc-20-t, rgba(6, 93, 137, .2));
}

.mc-timeline-install-instructions .ph-duotone {
   color: var(--dominante-color);
   font-size: 1.15rem;
   flex-shrink: 0;
   margin-top: .1rem;
}

.mc-timeline-install-instructions p {
   font-size: var(--fs-sm);
   color: var(--text-color);
   margin: 0;
   line-height: 1.45;
}

/* La ligne reliant deux puces se pose sur l'étape SUIVANTE (border-left),
   pas sur la précédente : la toute première étape n'a alors rien à gauche
   dont elle devrait se distinguer, sans condition ':first-child' séparée. */
.mc-timeline-install-etape {
   display: flex;
   flex-direction: column;
   align-items: center;
   gap: .35rem;
   flex: 1 1 0;
   min-width: 0;
   position: relative;
   padding-top: .55rem;
}

.mc-timeline-install-etape:not(:first-child)::before {
   content: '';
   position: absolute;
   top: calc(.55rem + 1.375rem);
   left: -50%;
   width: 100%;
   height: 2px;
   background: var(--dc-25-k, #d0d7de);
   z-index: 0;
}

.mc-timeline-install-faite:not(:first-child)::before {
   background: var(--dominante-color);
}

/* L'étape déjà validée se revisite : ce lien enveloppe puce + libellé,
   reprenant la même mise en page en colonne que .mc-timeline-install-etape
   elle-même - sans quoi les deux enfants perdraient leur centrage en
   passant sous cet intermédiaire. */
.mc-timeline-install-lien {
   display: flex;
   flex-direction: column;
   align-items: center;
   gap: .35rem;
   text-decoration: none;
   color: inherit;
}

.mc-timeline-install-lien:hover .mc-timeline-install-puce {
   transform: scale(1.08);
   box-shadow: 0 0 0 3px var(--dc-20-t, rgba(6, 93, 137, .2));
}

.mc-timeline-install-lien:hover .mc-timeline-install-libelle {
   color: var(--dominante-color);
}

.mc-timeline-install-puce {
   display: flex;
   align-items: center;
   justify-content: center;
   width: 2.75rem;
   height: 2.75rem;
   border-radius: 50%;
   background: #fff;
   border: 2px solid var(--dc-25-k, #d0d7de);
   color: var(--slate-dim);
   font-size: 1.35rem;
   position: relative;
   z-index: 1;
   flex-shrink: 0;
   transition: transform .15s ease, box-shadow .15s ease;
}

.mc-timeline-install-faite .mc-timeline-install-puce {
   background: var(--dominante-color);
   border-color: var(--dominante-color);
   color: #fff;
}

.mc-timeline-install-active .mc-timeline-install-puce {
   border-color: var(--dominante-color);
   color: var(--dominante-color);
}

.mc-timeline-install-libelle {
   font-size: var(--fs-2xs);
   color: var(--slate-dim);
   text-align: center;
   white-space: nowrap;
   transition: color .15s ease;
}

.mc-timeline-install-active .mc-timeline-install-libelle {
   color: var(--dominante-color);
   font-weight: var(--fw-bold);
}

.mc-timeline-install-faite .mc-timeline-install-libelle {
   color: var(--text-color);
}

/* Mobile : les libellés des étapes NON actives disparaissent - sur un
   écran étroit, quatre libellés côte à côte se chevaucheraient ou
   forceraient un défilement horizontal disgracieux. Seule l'étape en
   cours garde son texte, les puces (avec leur icône) suffisent à situer
   les autres d'un coup d'œil. */
@media (max-width: 480px) {
   .mc-timeline-install-etape:not(.mc-timeline-install-active) .mc-timeline-install-libelle {
      display: none;
   }

   .mc-timeline-install-puce {
      width: 2.1rem;
      height: 2.1rem;
      font-size: 1.05rem;
   }

   .mc-timeline-install-etape:not(:first-child)::before {
      top: calc(.55rem + 1.05rem);
   }
}

[data-theme="dark"] .mc-timeline-install-puce {
   background: var(--panel);
}

[data-theme="dark"] .mc-timeline-install-etape:not(:first-child)::before {
   background: var(--dc-25-w, #3a4250);
}

[data-theme="dark"] .mc-timeline-install-faite:not(:first-child)::before {
   background: var(--dominante-color);
}

/* Réglages des couleurs de fond - voir parametres/configurations.php. */
/* Une ligne de réglage - label à gauche, champ (ou interrupteur) compact à
   droite. Voir parametres/configurations.php, carte Réglages. */
.mc-reglage-ligne {
   display: flex;
   align-items: center;
   justify-content: flex-end;
   gap: .5rem;
   margin-bottom: .35rem;
}

/* UNE GRILLE D'INTERRUPTEURS (jours, formats - abdAllah, 02/10) : autant de
   colonnes que la carte en permet, jamais un libellé sous son interrupteur. */
.mc-reglage-grille {
   display: grid;
   grid-template-columns: repeat(auto-fill, minmax(104px, 1fr));
   gap: .5rem .75rem;
}
.mc-reglage-grille .mc-reglage-ligne { justify-content: space-between; min-width: 0; }
.mc-reglage-grille .form-label { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mc-reglage-grille .form-switch { flex-shrink: 0; }

.mc-reglage-champ {
   max-width: 170px;
   font-size: 10pt;
   flex-shrink: 0;
}

/* PAS DE DÉBORDEMENT DANS UNE COLONNE ÉTROITE (abdAllah, 10/10) : le champ (170 px au plus, jamais
   rétréci) et la ligne calée à droite faisaient sortir le libellé par la GAUCHE de la carte quand la
   colonne manquait de place (Configurations, 4 colonnes sur un écran moyen). Le libellé peut
   désormais passer à la ligne entre les mots, sans jamais couper un mot (il reste calé contre son
   champ) ; le champ peut céder jusqu'à 105 px ; la ligne ne déborde plus du côté gauche (« safe »). */
.mc-reglage-ligne { justify-content: safe flex-end; min-width: 0; }
.mc-reglage-ligne > .form-label { flex: 0 1 auto; min-width: min-content; }
.mc-reglage-ligne > .mc-reglage-champ { flex: 0 1 170px; min-width: 105px; }
.mc-reglage-ligne > .mc-reglage-champ.input-group { flex-wrap: nowrap; }
.mc-reglage-ligne > .mc-reglage-champ > .form-control,
.mc-reglage-ligne > .mc-reglage-champ > .form-select { min-width: 0; }

/* L'ICÔNE OU L'UNITÉ DE DROITE, À LARGEUR UNIQUE (abdAllah, 02/10) : « € »,
   une icône, « px », « Mo », « max » - tous les champs s'alignent. */
.mc-reglage-champ > .input-group-text:last-child {
   width: 40px;
   flex-shrink: 0;
   justify-content: center;
   padding-left: 0;
   padding-right: 0;
}

.mc-couleur-groupe-titre {
   font-size: var(--fs-2xs);
   font-weight: var(--fw-bold);
   color: var(--slate-dim);
   text-transform: uppercase;
   letter-spacing: .03em;
}

/* Le bouton « Origine » (à droite de chaque titre de groupe) - l'icône
   Phosphor hérite par défaut d'une taille bien plus grande que le texte
   9pt du bouton, ce qui le rendait plus haut que large. Ramenée à la
   taille du texte qui l'entoure. */
.mc-couleur-reinitialiser .ph-duotone {
   font-size: 1em;
}

/* Le TEXTE reste toujours lisible quelle que soit la teinte de fond
   choisie - un contour (text-shadow, pas de couleur unique qui pourrait
   elle-même se fondre dans un fond clair ou sombre) plutôt qu'une seule
   couleur de texte fixe, qui aurait fini par disparaître sur certaines
   teintes. */
.mc-couleur-swatch {
   display: flex;
   align-items: center;
   justify-content: center;
   height: 1.7rem;
   border-radius: 0;
   border: 1px solid var(--line);
   font-size: 8pt;
   font-weight: var(--fw-bold);
   cursor: pointer;
   text-align: center;
   padding: .25rem .4rem;
   transition: transform .1s ease;
   overflow: hidden;
   white-space: nowrap;
   text-overflow: ellipsis;
}

.mc-couleur-swatch:hover {
   transform: scale(1.04);
}

.mc-couleur-swatch:focus-visible {
   outline: 2px solid var(--dominante-color);
   outline-offset: 2px;
}

/* Retire tout arrondi DANS cette carte précisément - ni le cadre lui-même,
   ni le bouton Effacer, ni la boîte « Module non intégré », qui utilisent
   par ailleurs des classes Bootstrap génériques (.rounded, .btn) partagées
   avec le reste du site : cibler .mc-card-couleurs directement évite de
   toucher au style de ces classes ailleurs. */
.mc-card-couleurs,
.mc-card-couleurs * {
   border-radius: 0 !important;
}

/* Jamais affichée elle-même - seul son sélecteur natif (déclenché par
   .click() en JS) doit apparaître, positionné au clic sur une pastille. */
.mc-couleur-flottante {
   position: fixed;
   width: 1px;
   height: 1px;
   padding: 0;
   border: 0;
   opacity: 0;
   pointer-events: none;
}

/* ========================================================================
   CALENDRIER (backend/planifications/calendrier.php) - lecture seule,
   inspiré de FullCalendar.io, quatre vues (année/mois/semaine/jour).
   ======================================================================== */

.mc-calendrier-titre {
   font-size: 1.6rem;
   font-weight: var(--fw-bold);
}

.mc-calendrier-legende {
   display: flex;
   align-items: center;
   flex-wrap: wrap;
   gap: .4rem 1.2rem;
   font-size: var(--fs-sm);
   color: var(--slate);
   margin-bottom: .75rem;
}

.mc-calendrier-puce {
   display: inline-block;
   width: .9rem;
   height: .9rem;
   border-radius: 3px;
   margin-right: -.8rem;
   vertical-align: middle;
}

/* Icônes du GROUPE de navigation (Précédent/Suivant) - sans cette
   réduction, elles héritent de .btn .ph-duotone (1.2rem), bien plus
   grandes que le texte d'« Aujourd'hui » entre les deux, ce qui rendait
   ces boutons plus hauts que le reste de la ligne.
   La restriction à .btn-group est délibérée (abdAllah, 20/08) : le bouton
   « Imprimer » porte la même classe mais n'appartient pas au groupe, il
   est en taille normale et accompagné d'un libellé - son icône reprend
   donc les 1.2rem de tous les autres boutons du projet. */
.btn-group.mc-calendrier-btn-nav .ph-duotone {
   font-size: 1em;
}

/* --- Vue mois : grille --------------------------------------------- */

.mc-calendrier-mois {
   table-layout: fixed;
}

.mc-calendrier-mois th {
   text-align: center;
   font-size: var(--fs-sm);
   background: var(--dc-12-t, rgba(6, 93, 137, .12));
}

.mc-calendrier-mois td {
   height: 6rem;
   vertical-align: top;
   padding: .5rem;
}

.mc-calendrier-quantieme {
   display: inline-block;
   font-weight: var(--fw-bold);
   color: inherit;
   text-decoration: none;
   margin-bottom: .3rem;
}

.mc-calendrier-quantieme:hover {
   text-decoration: underline;
}

.mc-calendrier-hors-mois {
   background: var(--panel-soft, #f4f6f8);
   color: var(--slate);
}

.mc-calendrier-aujourdhui {
   background: var(--dc-12-t, rgba(6, 93, 137, .12));
}

.mc-calendrier-pastille {
   display: block;
   font-size: var(--fs-xs, .8125rem);
   border-radius: 4px;
   padding: .15rem .4rem;
   margin-bottom: .25rem;
   overflow: hidden;
   text-overflow: ellipsis;
   white-space: nowrap;
   text-decoration: none;
   transition: transform .1s ease, box-shadow .1s ease;
}

.mc-calendrier-pastille-priorite {
   display: flex;
   align-items: center;
   justify-content: center;
   flex-shrink: 0;
   width: 1.3rem;
   border-radius: 4px 0 0 4px;
   font-size: .65rem;
   line-height: 1;
   margin-bottom: .25rem;
}

.mc-calendrier-pastille-priorite + .mc-calendrier-pastille {
   border-radius: 0 4px 4px 0;
}

.mc-calendrier-pastille:hover {
   transform: scale(1.03);
   box-shadow: 0 1px 4px rgba(0, 0, 0, .35);
   text-decoration: none;
}

.mc-calendrier-plus {
   display: block;
   font-size: var(--fs-xs, .8125rem);
   color: var(--dominante-color, #065d89);
   text-decoration: none;
}

.mc-calendrier-plus:hover {
   text-decoration: underline;
}

/* --- Vue mois, en dessous de md : liste plutôt que grille ----------- */

.mc-calendrier-liste {
   display: flex;
   flex-direction: column;
   gap: .6rem;
}

.mc-calendrier-jour-liste {
   background: var(--panel-soft, #f4f6f8);
   border: 1px solid var(--line, #dee2e6);
   border-radius: var(--radius-field, .5rem);
   padding: .6rem .8rem;
}

.mc-calendrier-jour-liste-date {
   font-weight: var(--fw-bold);
   font-size: var(--fs-sm);
   margin-bottom: .3rem;
   text-transform: capitalize;
}

/* --- Vue semaine ----------------------------------------------------- */

.mc-calendrier-semaine {
   display: grid;
   grid-template-columns: repeat(7, minmax(9rem, 1fr));
   gap: .6rem;
   overflow-x: auto;
}

.mc-calendrier-semaine-jour {
   background: var(--panel-soft, #f4f6f8);
   border: 1px solid var(--line, #dee2e6);
   border-radius: var(--radius-field, .5rem);
   padding: .6rem;
   min-height: 8rem;
}

.mc-calendrier-semaine-entete {
   display: block;
   font-weight: var(--fw-bold);
   font-size: var(--fs-sm);
   color: inherit;
   text-decoration: none;
   text-transform: capitalize;
   margin-bottom: .4rem;
}

.mc-calendrier-semaine-entete:hover {
   text-decoration: underline;
}

.mc-calendrier-rien {
   font-size: var(--fs-xs, .8125rem);
   color: var(--slate);
   margin: 0;
}

/* --- Vue jour ---------------------------------------------------------- */

.mc-calendrier-jour {
   display: flex;
   flex-direction: column;
   gap: .6rem;
}

.mc-calendrier-jour-carte {
   position: relative;
   border-left: 4px solid;
   background: var(--panel-soft, #f4f6f8);
   border-radius: var(--radius-field, .5rem);
   padding: .7rem 1rem;
}

.mc-calendrier-jour-type {
   font-size: var(--fs-xs, .8125rem);
   text-transform: uppercase;
   color: var(--slate);
   margin-bottom: .15rem;
}

.mc-calendrier-jour-libelle {
   font-weight: var(--fw-bold);
}

.mc-calendrier-jour-periode {
   font-size: var(--fs-sm);
   color: var(--slate-dim, #5b6174);
   margin-top: .2rem;
}

/* --- Vue année : douze mini-mois --------------------------------------- */

.mc-calendrier-annee {
   display: grid;
   grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr));
   gap: 1rem;
}

.mc-calendrier-mini {
   background: var(--panel-soft, #f4f6f8);
   border: 1px solid var(--line, #dee2e6);
   border-radius: var(--radius-field, .5rem);
   padding: .6rem;
}

.mc-calendrier-mini-titre {
   display: block;
   text-align: center;
   font-weight: var(--fw-bold);
   color: inherit;
   text-decoration: none;
   text-transform: capitalize;
   margin-bottom: .4rem;
}

.mc-calendrier-mini-titre:hover {
   text-decoration: underline;
}

.mc-calendrier-mini-table {
   width: 100%;
   border-collapse: collapse;
   font-size: var(--fs-xs, .8125rem);
   text-align: center;
}

.mc-calendrier-mini-table th {
   color: var(--slate);
   font-weight: var(--fw-regular);
   padding-bottom: .2rem;
}

.mc-calendrier-mini-table td {
   padding: .1rem 0;
}

.mc-calendrier-mini-hors-mois {
   color: var(--line, #dee2e6);
}

.mc-calendrier-mini-table a {
   display: inline-flex;
   align-items: center;
   justify-content: center;
   width: 1.5rem;
   height: 1.5rem;
   border-radius: 50%;
   color: inherit;
   text-decoration: none;
}

.mc-calendrier-mini-marque {
   background: var(--dc-20-t, rgba(6, 93, 137, .2));
   font-weight: var(--fw-bold);
}

.mc-calendrier-mini-aujourdhui {
   background: var(--dominante-color, #065d89);
   color: #fff;
}

/* --- Impression : la barre d'outils s'efface, le calendrier occupe toute
   la feuille, la grille du mois garde ses proportions plutôt que de
   basculer en liste (le média print n'a pas de largeur d'écran mobile).
   Tout le CHROME de la page (navbar, menu déroulant, bandeau de titre,
   messages) s'efface aussi - sans quoi la feuille imprimée reprendrait
   l'intégralité de la page à l'écran, pas seulement le calendrier. */
@media print {
   .mc-calendrier .d-none.d-md-block {
      display: block !important;
   }
   .mc-calendrier .d-md-none {
      display: none !important;
   }

   .navbar,
   #dropdown-menu,
   #horizontal-sidebar,
   .page-header,
   .flash-zone {
      display: none !important;
   }

   .mc-calendrier {
      border: 0;
      box-shadow: none;
      margin: 0;
   }
}

/* Imprimer UNIQUEMENT une section précise de la page (ex. un tableau),
   pas le reste (filtres, boutons, autres cartes) - motif réutilisable,
   projet-wide. Technique CSS classique (visibility, pas display) : garde
   la mise en page, masque juste le rendu, puis fait remonter la section
   ciblée en position absolue au-dessus de tout le reste.

   Usage : poser la classe .section-a-imprimer sur l'élément à imprimer
   (ex. <table class="mc-datatable section-a-imprimer">), et sur le
   bouton : onclick="document.body.classList.add('mc-impression-section'); window.print();"
   .mc-impression-section n'a aucun effet hors de @media print - inutile
   de la retirer après coup. */
@media print {
   body.mc-impression-section * {
      visibility: hidden;
   }
   body.mc-impression-section .section-a-imprimer,
   body.mc-impression-section .section-a-imprimer * {
      visibility: visible;
   }
   /* `position: static` ET NON `absolute` (abdAllah, 10/09) : sortie du flux,
      la section ne donnait plus de hauteur à la page - le body tombait à 132px
      pour une section de 1311, et le tirage rendait une FEUILLE BLANCHE.

      LE `visibility` SUFFIT : le reste est masqué mais garde sa place, et la
      section s'imprime là où elle est. */
   body.mc-impression-section .section-a-imprimer {
      position: static;
      width: 100%;
   }

   /* LE CORPS ET SES ANCÊTRES GARDENT LEUR HAUTEUR : `visibility: hidden` sur
      `body *` n'ôte pas la place, mais certaines pages posent `height: 0` ou
      `overflow: hidden` sur leurs enveloppes - la section s'y retrouvait aplatie.

      `height: auto` et `overflow: visible` les rouvrent, sans toucher au
      `visibility` qui masque leur contenu propre. */
   body.mc-impression-section,
   body.mc-impression-section * {
      height: auto !important;
      max-height: none !important;
      overflow: visible !important;
   }

   /* PLEINE LARGEUR AU TIRAGE (abdAllah, 09/09) : la section imprimée hérite
      des marges de `container`, et le contenu se serrait au milieu de la
      feuille.

      LES ENVELOPPES sont neutralisées, pas la section elle-même. */
   body.mc-impression-section .section-a-imprimer .container,
   body.mc-impression-section .section-a-imprimer .container-fluid,
   body.mc-impression-section .section-a-imprimer .row {
      max-width: none;
      margin: 0;
      padding: 0;
   }

   /* L'EN-TÊTE SOMBRE ET LES RAYURES survivent au tirage : le navigateur les
      efface par défaut pour épargner l'encre, et le tableau perdait ses
      repères. */
   body.mc-impression-section .section-a-imprimer table.table-mc-entete thead th {
      background: var(--dominante-color) !important;
      color: #fff !important;
      -webkit-print-color-adjust: exact;
      print-color-adjust: exact;
   }

   body.mc-impression-section .section-a-imprimer table.table-striped tbody tr:nth-child(odd) td {
      background: var(--dc-7-w, #f2f6f8) !important;
      -webkit-print-color-adjust: exact;
      print-color-adjust: exact;
   }
}

/* ========================================================================
   TÂCHES (backend/planifications/taches.php) - post-it colorés par
   priorité, pastel dérivé de couleurEclaircie().
   ======================================================================== */

.mc-tache-alerte {
   display: inline-flex;
   align-items: center;
   gap: .3rem;
   font-size: var(--fs-sm);
   font-weight: var(--fw-bold);
}

.mc-tache-postit {
   position: relative;
   display: flex;
   flex-direction: column;
   width: 16.5rem;
   border-radius: 2px;
   padding: .85rem .7rem .5rem;
   box-shadow: rgba(0, 0, 0, .22) 2px 4px 8px;
   transform: rotate(-1.4deg);
   transition: transform .15s ease, box-shadow .15s ease;
}

/* Une inclinaison alternée, jamais toutes du même côté - un vrai post-it
   collé à la main ne s'aligne jamais parfaitement, et encore moins tous
   dans le même sens. */
.mc-tache-postit:nth-child(even) {
   transform: rotate(1.2deg);
}

.mc-tache-postit:nth-child(3n) {
   transform: rotate(-.6deg);
}

.mc-tache-postit:hover {
   transform: rotate(0deg) scale(1.02);
   box-shadow: rgba(0, 0, 0, .3) 3px 6px 14px;
   z-index: 1;
}

.mc-tache-epingle {
   position: absolute;
   top: -.4rem;
   left: 50%;
   transform: translateX(-50%);
   width: 1rem;
   height: 1rem;
   border-radius: 50%;
   box-shadow: 1px 2px 3px 0px rgb(0 0 0 / 65%);
}

.mc-tache-corps {
   flex-grow: 1;
}

.mc-tache-titre {
   font-weight: var(--fw-bold);
   margin-bottom: .3rem;
}

.mc-tache-type {
   font-size: var(--fs-sm);
   color: var(--slate-dim, #5b6174);
   margin-bottom: .2rem;
}

.mc-tache-date {
   font-size: var(--fs-xs, .8125rem);
   color: var(--slate);
}

.mc-tache-retard {
   color: #b3261e;
   font-weight: var(--fw-bold);
}

.mc-tache-note {
   font-size: var(--fs-xs, .8125rem);
   background: rgba(255, 255, 255, .55);
   border-radius: 4px;
   padding: .35rem .5rem;
   margin-top: .4rem;
}

.mc-tache-actions {
   display: flex;
   justify-content: flex-end;
   gap: .3rem;
   margin-top: .6rem;
}

/* Tâche faite : le texte se barre et s'estompe, le cercle se remplit -
   même logique visuelle que .mc-agenda-passe pour un événement terminé. */
.mc-tache-faite {
   opacity: .6;
}

.mc-tache-faite .mc-tache-titre,
.mc-tache-faite .mc-tache-type {
   text-decoration: line-through;
}

/* ========================================================================
   RAPPELS (backend/inc/rappels-widget.php) - sur chaque page d'accueil.
   ======================================================================== */

.mc-rappel-carte {
   position: relative;
   display: flex;
   flex-direction: column;
   width: 15.5rem;
   border-radius: var(--radius-field, .5rem);
   background: var(--panel-soft, #f4f6f8);
   border-left: 3px solid var(--dominante-color, #065d89);
   overflow: hidden;
}

.mc-rappel-corps {
   display: flex;
   flex-direction: column;
   flex-grow: 1;
   gap: .3rem;
   padding: .7rem .8rem;
   color: inherit;
   cursor: pointer;
   transition: background .1s ease;
}

.mc-rappel-corps:hover {
   background: var(--dc-12-t, rgba(6, 93, 137, .12));
   color: inherit;
}

.mc-rappel-corps:focus-visible {
   outline: 2px solid var(--dominante-color);
   outline-offset: 2px;
}

.mc-rappel-pied {
   display: flex;
   align-items: center;
   justify-content: center;
   gap: .35rem;
   padding: .45rem .8rem;
   background: var(--dc-12-t, rgba(6, 93, 137, .12));
   color: var(--dominante-color, #065d89);
   font-size: var(--fs-sm);
   font-weight: var(--fw-bold);
   text-decoration: none;
   cursor: pointer;
   transition: background .1s ease;
}

.mc-rappel-pied:hover {
   background: var(--dc-20-t, rgba(6, 93, 137, .2));
   color: var(--dominante-color, #065d89);
}

.mc-rappel-pied:focus-visible {
   outline: 2px solid var(--dominante-color);
   outline-offset: -2px;
}

.mc-rappel-icone {
   flex-shrink: 0;
   font-size: 1.3rem;
   color: var(--dominante-color, #065d89);
}

.mc-rappel-pastille {
   position: absolute;
   top: .4rem;
   right: .4rem;
   width: 1.4rem;
   height: 1.4rem;
   border-radius: 50%;
   display: flex;
   align-items: center;
   justify-content: center;
   line-height: 1;
   z-index: 1;
}

.mc-rappel-pastille .ph-duotone {
   font-size: .8rem;
   margin-right: 0;
}

.mc-rappel-libelle {
   font-weight: var(--fw-bold);
   min-width: 0;
   overflow: hidden;
   text-overflow: ellipsis;
   white-space: nowrap;
}

.mc-rappel-echeance {
   font-size: var(--fs-xs, .8125rem);
   color: var(--slate);
}

/* Icône « rappel défini » - agenda (à gauche du titre, dans son groupe
   propre pour ne pas perturber le space-between titre/chevron) et post-it
   (en haut à droite, symétrique à l'épingle centrée en haut). */
.mc-agenda-rappel {
   color: var(--dominante-color, #065d89);
   font-size: 1.15em;
   animation: mc-rappel-clignote 1.4s ease-in-out infinite;
}

.mc-tache-rappel {
   position: absolute;
   top: .3rem;
   right: .4rem;
   color: rgba(0, 0, 0, .55);
   font-size: 1.3rem;
   animation: mc-rappel-clignote 1.4s ease-in-out infinite;
}

@keyframes mc-rappel-clignote {
   0%, 100% { opacity: 1; }
   50%      { opacity: .35; }
}

/* ========================================================================
   VACANCES - carte mobile (backend/planifications/vacances-et-conges.php),
   à la place du tableau en dessous de md.
   ======================================================================== */

.mc-vacance-carte {
   border: 1px solid var(--line, #dee2e6);
   border-radius: var(--radius-field, .5rem);
   padding: .7rem .8rem;
   background: var(--panel-soft, #f4f6f8);
}

.mc-vacance-libelle {
   font-weight: var(--fw-bold);
}

.mc-vacance-dates {
   font-size: var(--fs-sm);
   color: var(--slate);
}

.mc-vacance-actions {
   display: flex;
   justify-content: flex-end;
   gap: .35rem;
   margin-top: .6rem;
}

/* MCEditor dans #modalFormation (backend/inc/modal-formation.php) : réduit
   par rapport au défaut de tools.css (max-height: 70vh, pensé pour l'éditeur
   plein document de reglement.php). Ici, quatre éditeurs se partagent des
   onglets DANS une modale déjà bornée par modal-dialog-scrollable - un
   éditeur à 70vh y aurait rarement tenu sans un double défilement gênant.
   Sélecteur scopé plutôt que de baisser la valeur par défaut globale, qui
   servirait mal l'éditeur plein document ailleurs dans le projet. */
#modalFormation .mc-editor-content {
   max-height: 25vh;
}

/* Colonne Actions (toujours la dernière) : padding distinct demandé - les
   boutons Modifier/Supprimer ont besoin de moins d'air que le texte des
   autres colonnes. #tableClasses cible le WRAPPER que MCTable construit à la
   place du <table> d'origine - son id est désormais reporté dessus (voir
   mc-table.js, _readSchema()), sans quoi ce sélecteur ne retrouverait plus
   rien une fois le tableau transformé. */
#tableClasses td:last-child {
   padding: 2px 0 0;
}

/* .nav-tabs : défilement horizontal plutôt que de tasser/wrapper le texte
   des onglets - comportement générique pour TOUS les nav-tabs du projet, pas
   un cas particulier d'une seule page. Sans contenu qui déborde, ces règles
   n'ont visuellement aucun effet sur desktop.
   overflow-x:auto SEUL pose AUSSI overflow-y en implicite (un axe non-visible
   force l'autre à sortir de "visible" - même piège déjà documenté ailleurs
   dans ce fichier et dans tools.css) : d'où overflow-y:hidden explicite,
   sans quoi une barre de défilement verticale apparaît sans raison. */
.nav-tabs {
   flex-wrap: nowrap;
   overflow-x: auto;
   overflow-y: hidden;
   padding-top: 5px;
}

/* Bandeau d'alerte module frauduleux - même famille visuelle que
   .flash-message (icône/corps/titre/texte réutilisés tels quels), mais
   sans son mécanisme d'entrée animée : .flash-message est invisible
   (opacity:0) tant qu'un script ne lui ajoute pas .flash-entre, ce qui
   n'a jamais lieu ici puisque ce bandeau n'a pas ce script - d'où
   « présent mais invisible ». Persistant, pas transitoire : pas besoin
   d'entrer depuis le haut, il est déjà là au chargement de la page. */
.alerte-module-frauduleux {
   display: flex;
   align-items: flex-start;
   gap: .7rem;
   margin-bottom: .6rem;
   padding: .8rem 1rem;
   border-radius: var(--radius-field);
   font-size: var(--fs-sm);
   line-height: var(--lh-snug);
}

/* Badges "Modules inclus" (parametres/configurations.php) - coins carrés,
   pas le border-radius par défaut de .badge Bootstrap. */
.badge-module {
   border-radius: 0;
}

/* Case + texte du bloc "Situation" (front/connexion.php) - flex plutôt
   que le float classique de .form-check : reste vraiment aligné même
   quand le texte est long et s'enroule sur plusieurs lignes (ex. le
   libellé "Externe"), là où float peut faire passer tout le label sous
   la case au lieu de rester à sa droite. .situation-check plutôt que
   .form-check directement : celle-ci sert aussi ailleurs (form-switch
   compris), la retoucher globalement risquerait d'y casser autre chose. */
.situation-check {
   display: flex;
   align-items: center;
   flex-wrap: nowrap;
   gap: .5rem;
}

.situation-check .form-check-label {
   min-width: 0;
}

.situation-check .form-check-input {
   flex-shrink: 0;
   margin-top: .15rem;
}

.situation-check .form-check-label {
   margin: 0;
}

/* #navigoMembre : flèche à gauche au survol des liens, même motif exact
   que .menu-link::before/hover::before (backend.css) - scopé à cette
   classe précise plutôt que réutilisé sur .dropdown-item directement,
   pour ne pas affecter d'autres menus déroulants du projet. */
/* z-index explicite - le dropdown se retrouvait sous une carte d'inscription
   voisine (gestion-des-inscriptions.php) malgré le z-index Bootstrap par
   défaut du .dropdown-menu (1000). Reste sous les modals Bootstrap (1055). */
.mc-navigo-menu {
   z-index: 1500;
   padding: 0;
}

.mc-navigo-menu .dropdown-item {
   position: relative;
   overflow: hidden;
}

.mc-navigo-menu .dropdown-item::before {
   content: "";
   position: absolute;
   right: 0;
   top: 0;
   bottom: 0;
   width: 0;
   background: none;
   transition: all .35s ease;
   z-index: 0;
}

.mc-navigo-menu .dropdown-item:hover::before {
   width: 11px;
   /* LA FLÈCHE EN BLANC (08/10) : en dominante, elle se perdait dans le dégradé du survol,
      de la même teinte. Blanche, elle se lit comme une encoche (fond du menu). */
   background: var(--bs-dropdown-bg, #fff);
   clip-path: polygon(100% 0, 100% 100%, 0 50%);
   z-index: 1;
}

/* LE LISERÉ GAUCHE en ombre intérieure (08/10), et non en bordure : une bordure
   s'ajoutait à la boîte (décalage du texte) et débordait de l'entrée en hauteur. L'ombre
   tient exactement dans l'entrée, sans rien déplacer. */
.mc-navigo-menu .dropdown-item:hover {
   box-shadow: inset 5px 0 0 var(--dc-80-k, #054a6e);
}

[data-theme="dark"] .mc-navigo-menu .dropdown-item:hover::before {
   background: var(--bs-dropdown-bg, #2b3035);
}

/* Le TEXTE passe en blanc au survol (abdAllah, 07/09) : le `::before` peint le
   fond en dominante, et une entrée colorée - « Supprimer » en rouge - devenait
   illisible dessus.

   `!important` : `text-danger` de Bootstrap le porte déjà. */
.mc-navigo-menu .dropdown-item:hover,
.mc-navigo-menu .dropdown-item:hover i {
   color: #ffffff !important;
}

/* Bouton "Retour à l'Admin" (navbar.php) - clignotant pour rester visible
   tant qu'une bascule de session (basculer-profil-traitement.php) est
   active ; #de2121, même rouge déjà établi ailleurs dans la charte pour
   signaler un état à ne pas ignorer (bannière FICHE EXTERNE). */
.mc-navbar-retour-admin {
   background-color: #de2121;
   color: #ffffff;
   animation: mc-navbar-clignote 1.2s ease-in-out infinite;
}

.mc-navbar-retour-admin:hover {
   color: #ffffff;
}

@keyframes mc-navbar-clignote {
   0%, 100% { opacity: 1; }
   50%      { opacity: .55; }
}

/* Carte-lien d'un membre (backend/inc/carte-membre-lien.php, colonne
   PROFILS de fiche-membre.php) - effet hover demandé par abdAllah. */
.mc-carte-membre-lien {
   transition: box-shadow .2s ease, transform .2s ease;
}

.mc-carte-membre-lien:hover {
   box-shadow: 0 .25rem .5rem rgba(0, 0, 0, .15);
   transform: translateY(-2px);
}

/* abdAllah (19/08) : les icônes de validation Bootstrap (coche verte /
   croix rouge) sont fixées à droite par background-position dans
   bootstrap.css - jamais inversées selon dir="rtl". Sur un champ RTL
   (ex. arabeMatiere), ça place l'icône du mauvais côté par rapport au
   sens de lecture. Repositionnée à gauche uniquement pour ces champs,
   sans toucher au padding (laissé tel quel, pas demandé). */
.was-validated .form-control[dir="rtl"]:valid,
.form-control[dir="rtl"].is-valid,
.was-validated .form-control[dir="rtl"]:invalid,
.form-control[dir="rtl"].is-invalid {
   background-position: left calc(.375em + .1875rem) center;
}

/* abdAllah (19/08) : colonne Actions de matieres-catalogue.php (dernière
   colonne du datatable) trop large en mode tableau classique - même
   piège que la police RTL au-dessus : width n'est qu'une indication en
   table-layout automatique. width:1% + nowrap force le navigateur à ne
   lui laisser que la place nécessaire. Volontairement dans une media
   query min-width:768px : mc-table.js bascule en mode "cartes" en
   dessous (voir .mc-cards plus haut dans tools.css), où chaque <td>
   passe en display:flex width:100% - un style inline aurait cassé cet
   alignement mobile déjà correct, d'où cette règle externe scoping à
   #tableMatieres et seulement au-dessus du breakpoint. */
@media (min-width: 768px) {
   #tableMatieres table.mc-table th:last-child,
   #tableMatieres table.mc-table td:last-child {
      width: 1%;
      white-space: nowrap;
   }
}

/* abdAllah (19/08) : libellé de classe dans matieres-affectations.php -
   passe en gras au survol pour bien signaler que c'est cliquable. */
.mc-lien-classe-affectation:hover {
   font-weight: var(--fw-bold);
}

/* abdAllah (19/08) : bouton matière du tableau matière×période, motif
   IADN - gris (case+coeff désactivées) par défaut, bleu (couleur
   dominante) une fois activé, avec un flip vertical au clic. */
.mc-btn-matiere {
   border: 1px solid var(--bs-border-color);
   background: linear-gradient(180deg, #f1f3f5, #dee2e6);
   color: var(--bs-secondary-color, #6c757d);
   padding: .375rem .75rem;
   border-radius: var(--bs-border-radius);
   text-align: left;
   transform: rotateX(0deg);
   transition: transform .5s cubic-bezier(.4, 0, .2, 1), background .3s ease, color .3s ease;
}

/* abdAllah (30/09) : boutons plus larges, français en petit, arabe dessous. */
.mc-btn-matiere {
   min-width: 16rem;
}

.mc-btn-matiere-fr {
   font-size: .75rem;
}

/* UNE LIGNE : FR | N/C centré | AR, sans retour à la ligne. Deux colonnes
   égales autour du badge : il reste au milieu quelle que soit la longueur. */
.mc-btn-matiere-texte.mc-btn-matiere-ligne {
   display: grid;
   width: 100%;
   grid-template-columns: 1fr auto 1fr;
   align-items: center;
   gap: .6rem;
   white-space: nowrap;
}

.mc-btn-matiere-ar {
   text-align: right;
}

/* LA GRILLE DES AFFECTATIONS défile dans la hauteur de l'écran (30/09) :
   en-tête collé en haut, ligne Enregistrer collée en bas. */
.mc-affectations-defil {
   overflow-y: auto;
}

.mc-affectations-defil thead {
   position: sticky;
   top: 0;
   z-index: 2;
}

/* Fond OPAQUE : la teinte translucide de l'en-tête laisserait voir les
   lignes qui défilent dessous. */
.mc-affectations-defil .mc-table-affectations.table-mc-entete thead th {
   background: color-mix(in srgb, var(--dominante-color, #065d89) 12%, #fff) !important;
}

.mc-affectations-defil tfoot {
   position: sticky;
   bottom: 0;
   z-index: 2;
}

.mc-affectations-defil .mc-table-affectations tfoot td {
   /* Même teinte que l'en-tête (abdAllah, 30/09). */
   background: color-mix(in srgb, var(--dominante-color, #065d89) 12%, #fff) !important;
   box-shadow: inset 0 1px 0 var(--bs-border-color) !important;
}

/* L'arabe du bouton : plus petit que le 1.35rem général. */
.mc-btn-matiere [dir="rtl"] {
   font-size: 1.1rem;
}

.mc-btn-matiere.active {
   background: linear-gradient(180deg, var(--dominante-color), var(--dominante-color-hover));
   color: #fff;
   border-color: var(--dominante-color);
   transform: rotateX(180deg);
}

/* Le texte tourne avec le bouton (rotateX(180deg) ci-dessus) - contre-
   rotation identique pour l'annuler visuellement (180+180=360=lisible),
   sans perdre l'effet de flip sur le bouton lui-même. */
.mc-btn-matiere-texte {
   display: inline-block;
   transition: transform .5s cubic-bezier(.4, 0, .2, 1);
}

.mc-btn-matiere.active .mc-btn-matiere-texte {
   transform: rotateX(180deg);
}

/* abdAllah (19/08) : cases/coeff. de la ligne d'une matière inactive
   restent techniquement toujours cliquables (plus de disabled HTML - un
   input disabled ne reçoit jamais de clic, donc cocher une case
   n'aurait alors jamais pu activer la matière). Uniquement grisées
   visuellement, pas pointer-events:none. */
.mc-ligne-inactive td {
   opacity: .5;
}

/* abdAllah (19/08) : en-tête du tableau matière×période - même fond que
   .card-header (dominante très diluée) au lieu du fond plein de
   .table-mc-entete (partagée par d'autres tableaux du projet, donc pas
   touchée ici - ciblage via .mc-table-affectations uniquement). Le fond
   étant clair, le texte redevient sombre (color: inherit) au lieu du
   blanc prévu pour un fond plein. */
.mc-table-affectations.table-mc-entete thead th {
   background: var(--dc-12-t, rgba(6, 93, 137, .12)) !important;
   color: inherit !important;
}

/* abdAllah (19/08) : card "Périodes" (matieres-affectations.php) - même
   effet rayé que .table-striped ailleurs dans le projet, mais sur une
   <ul class="list-group"> plutôt qu'un tableau - réutilise la même
   variable Bootstrap pour la cohérence visuelle. */
.mc-list-group-striped .list-group-item:nth-of-type(odd) {
   background-color: var(--bs-table-striped-bg);
}

/* abdAllah (19/08) : texte du select MCSelect (selectClasseAffectation)
   plus grand - ciblé via le conteneur .mc-select-classe-affectation
   plutôt que l'id "mcsel-N-field" généré dynamiquement par mc-select.js
   (incrémental selon le nombre de select sur la page, donc fragile). */
.mc-select-classe-affectation .mc-combo-field {
   font-size: 1.7rem;
}

/* ========================================================================
   NOTIFICATIONS - widget de tableau de bord (22/08)
   ========================================================================
   Une LIGNE par notification, pas une carte de largeur fixe comme
   .mc-rappel-carte : un message fait deux ou trois lignes de texte, une
   largeur imposée le couperait. Prendre toute la largeur disponible rend
   aussi le widget lisible sur téléphone sans media query - c'est le
   conteneur qui rétrécit, le contenu suit.
   ======================================================================== */

.mc-notif-ligne {
   display: flex;
   align-items: flex-start;
   gap: .75rem;
   padding: .6rem .75rem;
   border-radius: var(--radius-field, .5rem);
   background: var(--panel-soft, #f4f6f8);
   border-left: 3px solid var(--dominante-color, #065d89);
}

/* `min-width: 0` : sans lui, un mot long empêche l'élément flex de
   rétrécir et fait déborder toute la ligne sur petit écran. */
.mc-notif-corps {
   flex: 1 1 auto;
   min-width: 0;
}

.mc-notif-titre {
   font-weight: var(--fw-bold, 600);
   line-height: 1.3;
}

.mc-notif-texte {
   font-size: .9rem;
   line-height: 1.35;
}

.mc-notif-date {
   font-size: .8rem;
   color: var(--dc-90-777777, #777);
   margin-top: .15rem;
}

/* Les boutons ne rétrécissent jamais : ce sont des cibles tactiles, elles
   doivent garder leur taille quand le texte pousse. */
.mc-notif-actions {
   display: flex;
   gap: .3rem;
   flex-shrink: 0;
}

/* Sur téléphone, les actions passent SOUS le texte et s'alignent à droite :
   côte à côte, elles ne laissaient qu'une poignée de caractères au message. */
@media (max-width: 575.98px) {
   .mc-notif-ligne {
      flex-direction: column;
      gap: .5rem;
   }

   .mc-notif-actions {
      align-self: flex-end;
   }
}

/* Notification déjà lue : atténuée, pas masquée. Elle garde sa place dans
   l'ordre chronologique - c'est souvent APRÈS l'avoir lue qu'on cherche à
   la retrouver. */
.mc-notif-lue {
   opacity: .62;
   border-left-color: var(--dc-90-777777, #777);
}

/* ========================================================================
   ESPACE ENSEIGNANT - cartes de cours (22/08, revu sur capture)
   ========================================================================
   abdAllah : « élaboré et optimisé pour le format mobile, le plus utilisé ».
   Ces règles sont écrites POUR le téléphone d'abord ; l'écran large n'ajoute
   qu'un `grid-template-columns` en media query.
   ======================================================================== */

/* UNE colonne par défaut - donc sur téléphone, où les journées s'enchaînent
   verticalement. La grille passe à plusieurs colonnes seulement quand la
   place existe : c'est l'écran large qui est l'exception, pas le petit. */
.mc-ustad-jours {
   display: grid;
   grid-template-columns: 1fr;
   gap: .75rem;
   /* `align-items: start` : sans lui, chaque colonne s'étire à la hauteur de
      la plus longue et ses cartes se retrouvent espacées pour rien. */
   align-items: start;
}

@media (min-width: 768px) {
   .mc-ustad-jours {
      /* `auto-fill` + `minmax` : le nombre de colonnes suit la largeur
         disponible sans qu'on ait à le fixer par palier. */
      grid-template-columns: repeat(auto-fill, minmax(17rem, 1fr));
   }
}

/* Les cours d'UN MÊME JOUR, empilés dans leur colonne (abdAllah, 23/08). */
.mc-ustad-jour {
   display: flex;
   flex-direction: column;
   /* PAS de `gap` : les cartes portent `mb-2` (abdAllah, 23/08). Cumuler les
      deux doublerait l'écart entre deux cours d'un même jour. */
   min-width: 0;
}

/* PAS d'`overflow: hidden` ici, même s'il arrondirait joliment l'en-tête :
   il ROGNE le menu déroulant, qui déborde forcément de la carte (abdAllah,
   23/08). Les coins sont donc arrondis sur l'en-tête lui-même.
   `isolation: auto` + z-index posé à l'ouverture : une carte ne doit pas
   passer par-dessus le menu d'une carte voisine. */
.mc-ustad-carte {
   position: relative;
   /* TRANSPARENTE au repos (abdAllah, 23/08) : elle n'apparaît qu'au survol,
      où elle prend la dominante. Déclarée quand même, et non ajoutée à ce
      moment-là : elle occupe déjà sa place, sinon la carte se décalerait d'un
      pixel au passage de la souris. */
   border: 1px solid transparent;
   border-radius: var(--radius-field, .5rem);
   /* Fond BLANC (abdAllah, 23/08). `--panel` et non `#fff` en dur : elle vaut
      déjà #ffffff en thème clair et bascule sur #1a1e29 en sombre, où une
      carte blanche serait aveuglante. */
   background: var(--panel, #ffffff);
   min-width: 0;
   box-shadow: rgba(0, 0, 0, .12) 0 1px 3px, rgba(0, 0, 0, .16) 0 1px 2px;
   /* Seules `box-shadow` et `border-color` sont animées : le navigateur les
      traite sans recalculer la mise en page, donc sans saccade sur mobile. */
   transition: box-shadow .18s ease, border-color .18s ease;
}

/* Survol : la carte se soulève légèrement. `:focus-within` en plus, pour que
   la navigation au clavier produise le même repère visuel que la souris. */
/* Survol REPRIS (abdAllah, 23/08 : le premier ne lui plaisait pas). Plus de
   `translateY` : la carte sautait, et dans une colonne serrée le mouvement
   attirait l'œil plus que l'information. Ici elle ne bouge pas - seule
   l'ombre se diffuse et la bordure prend la couleur dominante. L'effet se lit
   sans déplacer quoi que ce soit. */
.mc-ustad-carte:hover,
.mc-ustad-carte:focus-within {
   border-color: var(--dominante-color, #065d89);
   /* Ombre RESSERRÉE (abdAllah, 23/08) : la précédente s'étalait sur 20px et
      empiétait sur les cartes voisines dans une colonne serrée. */
   box-shadow: rgba(0, 0, 0, .16) 0 3px 6px, rgba(0, 0, 0, .20) 0 3px 6px;
}

/* Filet de filière. En ABSOLU plutôt qu'une `border-left` : le survol pose
   `border-color`, qui réécrit les quatre côtés d'un coup - la couleur de
   filière disparaissait alors du bord gauche. */
/* Filet de SALLE. Longe le CORPS seul - il commence sous l'en-tête, qui va
   lui d'un bord à l'autre (schéma d'abdAllah, 23/08).
   À l'intérieur de la bordure de la carte : posé dessus, il la masquait et la
   carte semblait n'être entourée que sur trois côtés au survol. */
.mc-ustad-carte-filet {
   position: absolute;
   top: 0;
   bottom: 0;
   left: 0;
   /* Épaissi de 5 à 7px (abdAllah, 23/08 : « plus grosse mais pas trop ») -
      la couleur de salle se lit d'un coup d'œil sans dominer la carte. */
   width: 7px;
   /* Seul le coin BAS gauche s'arrondit : en haut, le filet bute contre
      l'en-tête et doit rester d'équerre. */
   border-radius: 0 0 0 calc(var(--radius-field, .5rem) - 1px);
}

/* La carte qui porte un menu OUVERT passe au-dessus de ses voisines.
   `:has()` évite d'avoir à poser une classe en JavaScript. */
.mc-ustad-carte:has(.dropdown-menu.show) {
   z-index: 5;
}

.mc-ustad-carte-entete {
   padding: .35rem .75rem;
   font-size: .85rem;
   font-weight: var(--fw-bold, 600);
   text-align: center;
   /* L'en-tête porte lui-même SES DEUX coins hauts : il va d'un bord à
      l'autre (abdAllah, 23/08), et la carte ne peut pas les découper -
      `overflow: hidden` rognerait le menu déroulant. */
   border-radius: calc(var(--radius-field, .5rem) - 1px) calc(var(--radius-field, .5rem) - 1px) 0 0;
}

.mc-ustad-carte-corps {
   /* Référent du filet ET du menu d'actions, tous deux en absolu. */
   position: relative;
   /* Le rembourrage gauche laisse la place au filet, sans quoi le texte
      passerait dessous. */
   padding: .6rem .75rem .6rem calc(.75rem + 7px);
   min-width: 0;
}

/* Menu d'actions en ABSOLU et non flottant : un flottant rétrécit les
   conteneurs flex qui le suivent (ils ne peuvent pas le chevaucher), et la
   ligne du lieu s'arrêtait avant le bord de la carte - le badge « Ouvrir la
   salle » ne pouvait donc pas atteindre la droite (abdAllah, 23/08). */
.mc-ustad-carte-corps > .dropdown {
   position: absolute;
   /* Ajusté à l'œil par abdAllah (23/08), en deux passes : le bouton affleure
      le coin haut droit du corps sans mordre sur l'en-tête ni déborder. */
   top: 1px;
   right: 1px;
   z-index: 2;
}

/* Survol du bouton d'actions, ASSOMBRI (abdAllah, 23/08) : depuis que la
   carte est blanche, le `--panel-soft` d'origine (#eef0f4) ne s'en détachait
   presque plus. `--line` (#e1e4ea) reste discret mais se voit.
   Réglé ICI et non sur `.mc-info-classe-action`, qui est partagé avec
   fonctionnement/classes-de-la-session.php - la retoucher là-bas modifierait
   une page qui n'a rien demandé. */
.mc-ustad-carte-corps > .dropdown .mc-info-classe-action:hover,
.mc-ustad-carte-corps > .dropdown .mc-info-classe-action:focus-visible {
   background: var(--line, #e1e4ea);
}

.mc-ustad-carte-classe {
   font-weight: var(--fw-bold, 600);
   line-height: 1.3;
   /* Place réservée au menu d'actions, qui se superpose à ce coin : sans
      cette marge, un libellé long passerait dessous. Seul le titre en a
      besoin - le menu ne descend pas plus bas. */
   padding-right: 2.5rem;
}

.mc-ustad-carte-ligne {
   display: flex;
   align-items: center;
   gap: .35rem;
   font-size: .85rem;
   margin-top: .2rem;
   min-width: 0;
}

/* Le libellé se tronque, l'icône jamais : elle porte le sens (salle,
   distanciel, avertissement). */
.mc-ustad-carte-ligne i {
   flex-shrink: 0;
   font-size: 1.1rem;
}

/* `flex: 1 1 auto` : le libellé PREND l'espace restant, ce qui repousse le
   badge au bord droit. Sans cela il tronquait en occupant toute la place, il
   ne restait aucun espace libre, et `ms-auto` n'avait rien à distribuer - le
   badge collait au texte (abdAllah, 23/08). */
.mc-ustad-carte-ligne span {
   flex: 1 1 auto;
   overflow: hidden;
   text-overflow: ellipsis;
   white-space: nowrap;
}

/* Badge « Ouvrir la salle » : il ne se comprime jamais, et se distingue au
   survol pour signaler qu'il est cliquable - un badge ne le dit pas de
   lui-même. */
.mc-ustad-lien-salle {
   /* `margin-left: auto` POUSSE le badge au bord droit. Il manquait - je
      l'avais perdu en remplaçant le bouton (qui portait `ms-auto`) par ce
      badge (abdAllah, 23/08). Posé ici plutôt qu'en classe utilitaire dans le
      HTML : le badge ne s'emploie qu'ici, la règle ne peut pas se perdre au
      prochain remaniement. */
   margin-left: auto;
   flex-shrink: 0;
   text-decoration: none;
}

.mc-ustad-lien-salle:hover {
   filter: brightness(1.15);
}

/* Filière, en bas à droite et discrète : elle NOMME ce que la couleur de
   l'en-tête et du filet indique déjà. Atténuée à dessein - c'est un repère,
   pas une information qu'on vient chercher. */
.mc-ustad-carte-filiere {
   text-align: right;
   font-size: .72rem;
   color: var(--dc-90-777777, #777);
   margin-top: .3rem;
   /* Un libellé long ne doit pas pousser la carte : il se tronque. */
   overflow: hidden;
   text-overflow: ellipsis;
   white-space: nowrap;
}

/* ========================================================================
   SUIVI DES LECTURES D'UNE NOTIFICATION (23/08)
   ======================================================================== */

/* Le compteur « lues / destinataires » est un `btn btn-sm` (abdAllah, 23/08).
   Rien à ajouter : Bootstrap lui donne déjà son curseur, son survol et son
   focus. Seule la largeur est fixée, sinon la colonne bougeait d'une ligne à
   l'autre selon que le compteur affiche « 3 / 9 » ou « 12 / 145 ». */
.mc-suivi-compteur {
   min-width: 5rem;
}

.mc-suivi-titre {
   display: flex;
   align-items: center;
   gap: .3rem;
   font-size: .82rem;
   font-weight: var(--fw-bold, 600);
   color: var(--dominante-color, #065d89);
   margin-bottom: .3rem;
}

/* Les icônes suivent la taille réduite du texte, sinon elles dominent la
   ligne (abdAllah, 23/08). */
.mc-suivi-titre i {
   font-size: 1rem;
}

/* Une LIGNE par destinataire : avatar, nom à gauche, horodatage à droite.
   Le fond reprend la couleur du genre, posée en ligne - même code visuel que
   les listings de membres. */
/* Posée SUR un `.list-group-item` : le rembourrage et le fond restent ceux de
   Bootstrap - sauf le fond de genre, mis en ligne, qui l'emporte. */
.mc-suivi-carte {
   display: flex;
   align-items: center;
   gap: .4rem;
   font-size: 1rem;
   min-width: 0;
   /* Bordure de la couleur du PANNEAU : elle sépare deux cartes voisines dont
      les fonds de genre se toucheraient sinon. `--panel` plutôt que `#fff` en
      dur - elle vaut déjà blanc en thème clair et suit le thème sombre, où un
      liseré blanc trancherait violemment. */
   border: 1px solid var(--panel, #ffffff);
}

/* Le nom PREND la place restante, ce qui repousse l'horodatage à droite, et
   se tronque plutôt que d'élargir la colonne. */
.mc-suivi-nom {
   flex: 1 1 auto;
   min-width: 0;
   overflow: hidden;
   text-overflow: ellipsis;
   white-space: nowrap;
}

/* L'horodatage ne se comprime jamais : tronqué, une date ne veut plus rien
   dire. */
.mc-suivi-date {
   flex-shrink: 0;
   font-size: .72rem;
   opacity: .7;
}

/* Calendrier de classe groupé PAR MOIS (23/08) : sur une année scolaire, la
   liste continue dépassait la centaine de dates.
   Les mois se suivent en COLONNES et non empilés (schéma d'abdAllah) : chacun
   garde ses dates les unes sous les autres, et l'on compare deux mois d'un
   coup d'œil. */
.mc-classe-calendrier-mois-liste {
   display: grid;
   grid-template-columns: 1fr;
   gap: .75rem;
   /* La hauteur fixe passe ICI : elle était sur `.mc-classe-calendrier`, qui
      ne contient plus qu'un mois - chaque bloc aurait alors défilé
      séparément. */
   max-height: 600px;
   overflow-y: auto;
}

@media (min-width: 576px) {
   .mc-classe-calendrier-mois-liste {
      /* `auto-fill` + `minmax` : le nombre de colonnes suit la largeur
         disponible, sans palier à fixer. `start` pour qu'un mois court ne
         s'étire pas à la hauteur du plus rempli. */
      grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
      align-items: start;
   }
}

.mc-classe-calendrier-mois-titre {
   display: flex;
   align-items: center;
   gap: .4rem;
   font-weight: var(--fw-bold, 600);
   color: var(--dominante-color, #065d89);
   border-bottom: 1px solid var(--line, #e1e4ea);
   padding-bottom: .2rem;
   margin-bottom: .4rem;
}

/* Le nombre de séances du mois, discret : c'est un repère, pas l'information
   principale. */
.mc-classe-calendrier-mois-nb {
   font-size: .75rem;
   font-weight: var(--fw-regular, 400);
   opacity: .65;
   /* Poussé à droite du titre, comme sur le schéma. */
   margin-left: auto;
}

/* DANS un bloc de mois, les dates s'empilent : la grille à 4 colonnes de
   `.mc-classe-calendrier` n'a plus lieu d'être, et sa hauteur fixe est
   remontée sur la liste des mois. */
.mc-classe-calendrier-mois .mc-classe-calendrier {
   grid-template-columns: 1fr;
   height: auto;
   overflow: visible;
}

/* ========================================================================
   ICÔNES D'ACTION « INFOS » (23/08)
   ========================================================================
   Modèle de référence : inscriptions/effectifs-des-classes.php.
   Une classe partagée plutôt qu'un `style=` répété sur chaque icône - elles
   étaient une douzaine, à des tailles légèrement différentes.
   ======================================================================== */

.mc-icone-infos {
   font-size: 1.3rem;
   /* Couleur de la CHARTE au repos (abdAllah, 23/08), et non `inherit` :
      l'icône avait autant de couleurs que de contextes - héritée du fond de
      filière ici, du texte du tableau là. Elle se reconnaît maintenant partout
      à la même teinte. */
   color: var(--dominante-color, #065d89);
   transition: color .15s ease;
}

/* Un BOUTON qui ne porte que cette icône se comporte comme un lien : ni fond,
   ni cadre, ni rembourrage (abdAllah, 23/08). Réglé ici plutôt qu'en ajoutant
   une classe au bouton - l'icône suffit à le désigner. */
button:has(> .mc-icone-infos) {
   background: none;
   border: none;
   padding: 0;
   line-height: 1;
}

/* `dropdown-toggle` ajoute un chevron : masqué quand le bouton n'est
   qu'une icône. */
button:has(> .mc-icone-infos)::after {
   display: none;
}

/* COULEUR D'ALERTE au survol, POUR TOUTES LES ITÉRATIONS (abdAllah, 23/08) :
   le sélecteur ne dépend plus de la balise porteuse - `:hover` directement sur
   l'icône couvre aussi bien un <a>, un <button> qu'un futur autre porteur.
   `:focus-visible` sur le parent reste nécessaire : c'est LUI qui reçoit le
   focus clavier, jamais l'icône.

   `--mc-alerte` est CALCULÉE par mc-theme.js : rouge d'ordinaire, mais bleue
   si la dominante de l'établissement est elle-même rouge - sans quoi le survol
   serait invisible. */
.mc-icone-infos:hover,
a:focus-visible > .mc-icone-infos,
button:focus-visible > .mc-icone-infos {
   color: var(--mc-alerte, #dc3545);
}

/* Champ date suivi d'un bouton (23/08) : un `input[type=date]` natif ne se
   mesure pas comme un champ texte - le navigateur y insère ses propres
   commandes et lui impose sa hauteur, supérieure à celle que Bootstrap donne
   au bouton voisin. On aligne les deux sur une hauteur explicite plutôt que de
   laisser chacun décider. */
.mc-groupe-date > .form-control,
.mc-groupe-date > .input-group-text,
.mc-groupe-date > .btn {
   height: 31px;
   display: inline-flex;
   align-items: center;
}

/* ========================================================================
   CARTES DE PROFIL - espaces membres (24/08)
   ========================================================================
   La carte est celle du staff (`.mc-carte-membre-lien`), reprise sans son
   lien : rien à redéfinir ici, seulement ce que le menu d'actions ajoute.
   ======================================================================== */

/* Le menu vit maintenant DANS la ligne d'identité (24/08) : plus de
   positionnement absolu, c'est le flex qui le place. Reste à neutraliser le
   `float-end` du navigo, qui n'a plus lieu d'être et décalerait le menu. */
.mc-carte-membre-lien .dropdown {
   float: none;
}

/* MENU AU-DESSUS DES CARTES VOISINES (abdAllah, 24/08).

   `transform: translateY(-2px)` au survol - l'effet de la carte-lien - crée un
   CONTEXTE D'EMPILEMENT : le menu déroulant, même en `z-index` élevé, reste
   alors enfermé dans sa carte et passe sous les suivantes.

   La carte qui porte un menu OUVERT est donc remontée : `:has()` la désigne
   sans qu'aucun script n'ait à poser de classe. Même remède que pour les
   cartes de cours de l'espace enseignant, le 23/08. */
.mc-carte-membre-lien:has(.dropdown-menu.show) {
   z-index: 5;
}

/* La colonne de grille ferme elle aussi le passage : c'est ELLE qui empile les
   cartes voisines, remonter la carte seule ne suffirait pas. */
.col:has(.mc-carte-membre-lien .dropdown-menu.show) {
   position: relative;
   z-index: 5;
}

/* Et le `transform` est SUSPENDU tant que le menu est ouvert : un contexte
   d'empilement enferme son contenu quoi qu'on fasse du `z-index`, aucune
   valeur ne l'en fait sortir. La carte perd son soulèvement de 2px pendant ce
   temps - invisible, on regarde le menu. */
.mc-carte-membre-lien:has(.dropdown-menu.show):hover {
   transform: none;
}

/* Demande de suppression en cours : signalée sans crier - c'est une attente,
   pas une erreur. LIGNE À PART sous l'identité (abdAllah, 24/08) : en absolu,
   elle passait sous l'identifiant et devenait invisible. */
.mc-carte-membre-suppression {
   font-size: .75rem;
   font-weight: var(--fw-bold, 600);
   text-align: center;
   color: var(--bs-danger, #dc3545);
}

/* L'icône reste lisible à côté d'un texte en .75rem, sans le dominer. */
.mc-carte-membre-suppression > i {
   font-size: 1rem;
   margin-right: .3rem;
}

/* Grille des profils - espaces membres (24/08).
   `auto-fill` avec un maximum de 22rem : la carte ne dépasse jamais une
   largeur de téléphone, et le navigateur en place autant que l'écran permet.
   Un `row-cols-4` figeait le compte et étirait les cartes sur grand écran. */
.mc-profils-grille {
   display: grid;
   grid-template-columns: repeat(auto-fill, minmax(16rem, 22rem));
   gap: .75rem;
}

/* Sous 22rem d'écran utile, une seule colonne qui prend toute la largeur -
   sans quoi la carte déborderait. */
@media (max-width: 26rem) {
   .mc-profils-grille {
      grid-template-columns: 1fr;
   }
}

/* Inscriptions dans une carte de profil - espaces membres (24/08).
   Un bloc par inscription, empilés sous l'identité. */
.mc-carte-inscription {
   border: 1px solid var(--line, #e1e4ea);
   border-radius: var(--radius-field, .5rem);
   background: var(--panel, #fff);
   /* PAS d'`overflow: hidden` (abdAllah, 25/08) : les rebords du ruban
      « Désistée » débordent du bloc par construction - c'est ce qui leur donne
      leur relief - et se trouvaient rognés.
      Les coins hauts de l'en-tête de filière sont arrondis par sa propre
      règle, plus bas : l'`overflow` n'était pas nécessaire pour cela. */
}

/* En-tête aux couleurs de la filière : pleine largeur, coins hauts arrondis
   par l'`overflow: hidden` du parent - même motif que les cartes de cours de
   l'espace enseignant. */
.mc-carte-inscription-filiere {
   /* Coins hauts arrondis ICI, puisque le parent n'a plus d'`overflow`. */
   border-radius: calc(var(--radius-field, .5rem) - 1px) calc(var(--radius-field, .5rem) - 1px) 0 0;
   padding: .2rem .5rem;
   font-size: .7rem;
   font-weight: var(--fw-bold, 600);
   text-transform: uppercase;
   letter-spacing: .02em;
}

.mc-carte-inscription-corps {
   padding: .35rem .5rem;
}

.mc-carte-inscription-classe {
   font-weight: var(--fw-bold, 600);
   font-size: .85rem;
   line-height: 1.25;
}

.mc-carte-inscription-jours {
   font-size: .75rem;
   color: var(--slate-dim, #6c757d);
   margin-top: .1rem;
}

.mc-carte-inscription-jours > i {
   font-size: .9rem;
   margin-right: .25rem;
}

/* État d'une inscription sur une carte de profil (25/08) : « En liste
   d'attente », « En attente de validation ». Une inscription validée n'affiche
   rien - c'est le cas normal. */
/* L'état SOUS les jours, aligné à droite (25/08) : sur leur ligne, un libellé
   long comprimait la liste des jours. */
.mc-carte-inscription-etat {
   margin-top: .25rem;
   text-align: right;
}

.mc-carte-inscription-etat > .badge {
   font-size: .65rem;
   font-weight: var(--fw-bold, 600);
}

/* Icône de l'état d'inscription : à gauche du libellé, un peu plus grande que
   le texte du badge sans le dominer (25/08). */
.mc-carte-inscription-etat > .badge > i {
   font-size: .85rem;
   margin-right: .25rem;
   vertical-align: -.1rem;
}

/* Contrôle des profils (25/08) : la ligne du contrôle ouvert est repérée par
   un filet à gauche, aux couleurs de la charte. */
.mc-controle-actif {
   border-left: 3px solid var(--dominante-color, #065d89);
   padding-left: .5rem !important;
}

.mc-controle-icone {
   font-size: 1.5rem;
   flex-shrink: 0;
}

/* Hôte de toasts DANS la bande de titre (25/08) : le `.mc-toast-host` global
   est en position fixe en haut à droite - il recouvrait la barre et partait au
   bout de quelques secondes. Ici l'alerte reste tant qu'elle n'est pas traitée.

   Le conteneur ne réserve aucune place quand il est vide : `:empty` le retire
   du flux, sinon il creuserait un blanc au milieu de la bande. */
.mc-toast-host-header {
   position: static;
   display: flex;
   flex-wrap: wrap;
   gap: .5rem;
   margin: 0;
   max-width: none;
}

.mc-toast-host-header:empty {
   display: none;
}

/* Le toast de la bande est plus compact que celui qui flotte : il partage la
   ligne avec le titre et l'heure. */
.mc-toast-header {
   margin: 0;
   /* Rembourrage bas plus généreux : la jauge se pose en absolu sur le bord,
      et .4rem la faisait chevaucher le texte (abdAllah, 25/08). */
   padding: .4rem .75rem .6rem;
   font-size: var(--fs-sm);
   cursor: pointer;
}

.mc-toast-header .mc-toast-text strong {
   font-size: var(--fs-sm);
}

/* Les toasts de la bande s'EMPILENT au lieu de se superposer : l'hôte est en
   flex, chacun garde sa place. `flex: 0 1 auto` - ils se compriment si la
   bande manque de largeur, plutôt que de la faire déborder. */
.mc-toast-host-header > .mc-toast {
   position: relative;
   flex: 0 1 auto;
   min-width: 0;
}

/* L'hôte FLOTTANT descend sous la bande (abdAllah, 25/08) : il se cale sur
   `--navbar-h` seule, donc pile sur elle - un toast de confirmation recouvrait
   l'alerte des demandes de suppression.

   `--page-header-h` est mesurée au chargement par inc/page-header.php : la
   bande a une hauteur variable, selon qu'elle porte un sous-titre, une alerte
   ou rien. Repli à 0 sur les pages sans bande - l'écran de connexion, par
   exemple. */
.mc-toast-host:not(.mc-toast-host-header) {
   top: calc(var(--navbar-h, 60px) + var(--page-header-h, 0px) + .75rem);
}

/* Fusion de profils - colonne marquée « Supprimer » (25/08). La fiche entière
   se barre : on doit voir d'un coup d'œil laquelle va disparaître, pas
   seulement l'interrupteur en bas du tableau. */
.mc-fusion-supprime {
   background: var(--state-error-bg, #fdf0f0) !important;
   text-decoration: line-through;
   opacity: .7;
}

/* La ligne des interrupteurs ne se barre jamais : c'est elle qui commande. */
.mc-fusion-decision .mc-fusion-supprime {
   text-decoration: none;
   opacity: 1;
}

.mc-fusion-switch .form-check-input {
   cursor: pointer;
}

.mc-fusion-switch .form-check-label {
   cursor: pointer;
   font-weight: var(--fw-bold, 600);
}

/* Sélecteur d'absorption masqué sous une fiche qui s'en va (25/08) :
   `visibility` et non `display` - la cellule garde sa place, sinon la ligne
   se décale et les colonnes ne s'alignent plus. */
.mc-fusion-masque > .mc-fusion-cible {
   visibility: hidden;
}

/* Badge d'un profil rattaché, au fond de son genre (25/08).
   Les couleurs de `GENRES` sont PÂLES - pensées comme fond de carte : le texte
   blanc par défaut du badge y serait illisible, d'où la couleur sombre et la
   bordure qui le détache du fond de cellule. */
.mc-badge-genre {
   color: var(--ink, #1b2536);
   border: 1px solid rgba(0, 0, 0, .12);
   font-weight: var(--fw-normal, 400);
}

/* Badge d'un profil rattaché, comparatif de fusion (25/08). En ligne dans une
   colonne étroite, les noms se chevauchaient : un par ligne, le nom tronqué
   plutôt que débordant, l'âge poussé à droite. */
.mc-badge-rattache {
   display: flex;
   align-items: center;
   width: 100%;
   min-width: 0;
   text-align: left;
}

/* `min-width: 0` sur l'enfant : sans lui, `text-truncate` ne s'applique pas
   dans un conteneur flex - le texte force sa largeur au lieu de se couper. */
.mc-badge-rattache > span {
   min-width: 0;
}

/* L'âge reste lisible sur un fond pastel : `opacity` le faisait disparaître. */
.mc-badge-rattache > small {
   color: var(--slate-dim, #55607a);
}

/* Interrupteur de décision centré dans sa cellule (25/08) : `form-check` est
   en bloc, `justify-content` n'a d'effet qu'en flex. */
.mc-fusion-switch {
   display: flex;
   align-items: center;
   gap: .5rem;
   padding-left: 0;
}

/* Bootstrap décale l'input de `form-check` par une marge négative, prévue pour
   la puce du bloc - en flex elle sort du centrage. */
.mc-fusion-switch .form-check-input {
   margin-left: 0;
   float: none;
}

/* Inscription désistée dans le comparatif de fusion (25/08) : barrée, comme
   partout ailleurs dans le projet - elle compte encore pour l'historique mais
   n'est plus active. */
.mc-badge-desiste {
   text-decoration: line-through;
   opacity: .65;
}

/* Badge « M » d'un module, sur les cartes d'inscription (25/08).
   Repris de `.mc-combo-badge` du sélecteur - dimensions ET couleurs - pour
   qu'un module se reconnaisse pareil partout, y compris sur un fond de
   filière coloré. */
.mc-badge-module {
   flex: 0 0 auto;
   min-width: 1.35rem;
   padding: 0 .25rem;
   border-radius: .25rem;
   background: var(--dominante-color);
   color: #fff;
   font-size: .7rem;
   font-weight: var(--fw-bold);
   line-height: 1.35rem;
   text-align: center;
   cursor: default;
}

/* Jauge de remplissage d'une classe (effectifs-des-classes, 25/08).
   La barre et sa valeur se superposent : un pourcentage seul se lit, une barre
   se voit - les deux ensemble se comprennent sans effort. */
.mc-jauge-taux {
   position: relative;
   height: 1.15rem;
   /* Fond SOUTENU et non un gris à 6 % : la valeur est blanche, et sur un taux
      faible elle repose surtout sur ce fond-là, pas sur la barre. */
   background: var(--slate-dim, #55607a);
   border-radius: .25rem;
   overflow: hidden;
}

.mc-jauge-taux-barre {
   position: absolute;
   inset: 0 auto 0 0;
   display: block;
   transition: width .3s ease;
}

/* La valeur passe PAR-DESSUS la barre, centrée : à droite elle sortait du
   cadre sur les taux faibles, à gauche elle disparaissait sur les forts.
   `text-shadow` : le texte reste lisible sur les deux fonds qu'il traverse. */
.mc-jauge-taux-valeur {
   position: relative;
   z-index: 1;
   display: block;
   line-height: 1.15rem;
   font-weight: var(--fw-bold);
   font-size: .7rem;

   /* BLANC : les trois fonds que la valeur traverse - vert, orange, rouge -
      sont assez soutenus pour le porter.

      `!important` : la cellule peut porter une couleur de texte héritée d'un
      fond de filière ou de mode, dont la valeur prendrait la teinte. Ici le
      fond est toujours la jauge, jamais celui de la ligne. */
   color: #fff !important;
}

/* Récapitulatif du foyer, onglet Comptabilité (26/08).
   `width: auto` contre le `width: 100%` de Bootstrap : trois montants tiennent
   dans leur largeur, et le tableau se cale à droite sous les cartes.
   Fond clair de la charte : il se détache des cartes sans jurer avec elles. */
.mc-compta-recap {
   /* `!important` : `.table { width: 100% }` de Bootstrap a la même
      spécificité - une classe - et il est chargé APRÈS. Sans lui, la règle
      `50%` du grand écran ne passerait pas. */
   /* PLEINE LARGEUR sur mobile, MOITIÉ sur grand écran (abdAllah, 26/08) :
      serré, le récap se lit mieux - mais sur un écran étroit il n'y a pas la
      place de le serrer, et le réduire le rendait illisible. */
   width: 100% !important;
   max-width: 100%;

   /* Même repli que les autres usages de `--dc-10-w` dans ce fichier. */
   background: var(--dc-10-w, #e6eff3);
}

/* PLEINE LARGEUR sous `md` (abdAllah, 26/08) : serré à droite sur un écran
   étroit, le récapitulatif laissait une bande vide à sa gauche et se lisait
   mal. Il n'a plus de voisin à ce format, autant occuper la place. */
@media (max-width: 767.98px) {
   .mc-compta-recap {
      width: 100% !important;
   }
}

@media (min-width: 992px) {
   .mc-compta-recap {
      width: 50% !important;
   }
}

/* Les cellules héritent du fond de LEUR LIGNE : sans cela, le blanc de
   `.table` les recouvrirait et le fond ne se verrait qu'aux bordures. */
.mc-compta-recap > tbody > tr > td,
.mc-compta-recap > tfoot > tr > td {
   background: transparent;
}

/* Trois fonds pour trois natures : le sous-total en dominante claire, les
   remises en blanc - elles se retranchent -, le total sur `grady-light`.
   Le lecteur suit ainsi la descente vers le montant qui compte. */
.mc-compta-recap .mc-recap-soustotal {
   background: var(--dc-10-w, #e6eff3);
}

.mc-compta-recap .mc-recap-remises {
   background: #ffffff;
}

/* TOTAL DÛ sur `grady-light` (abdAllah, 26/08) : le fond dominante plein
   écrasait le récapitulatif, et le dégradé clair suffit à le détacher. */
.mc-compta-recap .mc-recap-total > td {
   /* Le dégradé vient de `.grady-light`, posée sur la ligne : le recopier ici
      aurait fait deux sources pour la même teinte. Seul le liseré reste. */
   border-top: 2px solid var(--dominante-color);
}

/* En-tête des tableaux de cotisations en dominante CLAIRE : le fond plein de
   `table-mc-entete` écrasait la carte, déjà colorée par le bloc du membre. */
.mc-table-cotisations.table-mc-entete thead th {
   background: var(--dc-10-w, #e6eff3) !important;
   color: var(--dominante-color, #065d89) !important;
}

/* Le libellé pousse le montant à droite, sans largeur fixe : « Remises et
   réductions » et « Sous-total » n'ont pas la même longueur. */
.mc-compta-recap td:first-child {
   padding-right: 2rem;
   white-space: nowrap;
}

/* Bloc du membre, onglet Comptabilité (26/08).
   9rem seulement à partir de `md`, où il est en colonne à gauche du tableau.
   Sous ce seuil il passe au-dessus, en pleine largeur : lui imposer une
   largeur minimale l'empêchait de se réduire et faisait déborder la carte. */
@media (min-width: 768px) {
   .mc-compta-membre {
      /* 9rem était taillé pour un nom ET un prénom ; il ne reste que le
         prénom, la colonne peut se resserrer d'autant. */
      min-width: 5.5rem;
      max-width: 7rem;
   }
}

/* Cellules des tableaux de comptabilité (26/08).
   `nowrap` : un montant coupé en deux lignes se lit mal, et « 1 250,00 »
   passait à la ligne sur sa propre espace insécable dès que la colonne
   serrait. Les colonnes de texte gardent leur `text-truncate`. */
.mc-compta-recap td,
.mc-compta-recap th,
.mc-compta-cout,
.mc-compta-net,
.mc-compta-total-net,
.mc-compta-total-remises {
   white-space: nowrap;
}

/* Les cellules laissent voir le fond de LEUR LIGNE : sans cela, `.table` les
   peint en blanc et les fonds du récap ne se verraient qu'aux bordures.
   `--bs-table-bg-type` est la variable de Bootstrap 5.3 - `accent-bg` a
   disparu dans cette version. */
.mc-compta-recap > tbody > tr > td,
.mc-compta-recap > tfoot > tr > td {
   /* Bootstrap 5.3 peint la cellule par un `box-shadow` interne, pas par
      `background` : le neutraliser est le seul moyen de laisser voir le fond
      de la ligne. */
   box-shadow: none;
   background-color: transparent;
}

/* En-tête COLLANT du tableau des versements (abdAllah, 07/09) : son conteneur
   est limité en hauteur, et les colonnes devenaient illisibles dès qu'on
   faisait défiler. `table-mc-entete` peint déjà le fond, sans quoi les lignes
   passeraient au travers. */
.mc-table-scroll thead th {
   position: sticky;
   top: 0;
   z-index: 2;
}

/* ========================================================================
   TABLEAUX AJUSTÉS À LEUR CONTENU (abdAllah, 07/09) - suivi des plans et
   synthèse des cotisations.
   ======================================================================== */

/* Ces deux listes comptent une dizaine de colonnes, là où les profils en ont
   quinze : étirées sur tout l'écran, leurs cellules se retrouvaient séparées
   par de larges vides.

   `width: max-content` mesure le contenu réel ; `max-width: 100%` empêche le
   débordement quand il dépasse la fenêtre, et `margin: auto` centre le reste
   du temps.

   La classe est posée sur la PAGE et non sur `.mc-table-wrapper` seul : le
   composant sert aussi les listes de profils, qui gardent leur pleine
   largeur. */
.mc-table-ajustee .mc-table-wrapper {
   width: max-content;
   max-width: 100%;
   margin-left: auto;
   margin-right: auto;
}

/* `table-layout: auto` : sans lui, le tableau reprend la largeur de son
   enveloppe et l'ajustement n'a plus d'effet. */
.mc-table-ajustee .mc-table-wrapper table {
   width: auto;
   table-layout: auto;
}

/* ========================================================================
   VIE SCOLAIRE - tableaux en nowrap et feuille d'appel (abdAllah, 26/09)
   ======================================================================== */

/* `text-nowrap` sur un .mc-datatable : mc-table.js reporte la classe sur
   l'enveloppe, dont TOUT hérite. La barre d'outils et le pied gardent leur
   retour à la ligne, et le mode « cartes » du mobile aussi - une carte n'a
   pas de défilement horizontal. */
.text-nowrap > .mc-table-wrapper .mc-toolbar,
.text-nowrap > .mc-table-wrapper .mc-footer {
   white-space: normal;
}

/* Le motif de la feuille d'appel : lisible même quand le tableau se serre.
   Posé sur le groupe (icône + champ, modèle de template.php). */
.mc-appel-table .mc-appel-motif {
   min-width: 180px;
   flex-wrap: nowrap;
}

/* P-A-R pleins : le statut choisi en couleur, les deux autres estompés. */
.mc-appel-statut .btn-check:not(:checked) + .btn {
   opacity: .3;
}

.mc-appel-statut .btn-check:not(:checked) + .btn:hover {
   opacity: .6;
}

/* Le résumé des filtres et la barre du bas n'existent que sur mobile
   (d-md-none dans la page). */
.mc-appel-resume {
   display: flex;
   align-items: center;
   gap: .6rem;
   width: 100%;
   min-height: 52px;
   padding: .5rem .75rem;
   background: var(--panel);
   border: 1px solid var(--line);
   border-radius: var(--radius-field, 8px);
   color: inherit;
   text-align: left;
}

.mc-appel-resume .mc-appel-chevron {
   transition: transform .2s;
}

.mc-appel-resume[aria-expanded="true"] .mc-appel-chevron {
   transform: rotate(180deg);
}

.mc-appel-barre {
   position: sticky;
   bottom: 0;
   z-index: 5;
   display: flex;
   flex-direction: column;
   align-items: stretch;
   gap: .5rem;
   margin: 0 calc(var(--bs-gutter-x, 1.5rem) * -.5);
   padding: .6rem .75rem calc(.6rem + env(safe-area-inset-bottom, 0px));
   background: var(--panel);
   border-top: 1px solid var(--line);
   box-shadow: 0 -4px 12px rgba(4, 56, 82, .08);
}

.mc-appel-barre[hidden] {
   display: none !important;
}

.mc-appel-barre .btn {
   min-height: 48px;
}

.mc-appel-compteurs {
   display: flex;
   flex-wrap: wrap;
   gap: .4rem;
   font-size: .75rem;
   white-space: nowrap;
}

/* Mobile : centrés sous le bouton. */
.mc-appel-barre .mc-appel-compteurs {
   justify-content: center;
}

.mc-appel-compteurs[hidden] {
   display: none !important;
}

.mc-appel-retard {
   color: #a15c00;
}

[data-theme="dark"] .mc-appel-retard {
   color: #ffc107;
}

@media (max-width: 767.98px) {

   .text-nowrap > .mc-table-wrapper.mc-cards table.mc-table td {
      white-space: normal;
   }

   .mc-appel-filtres.est-replie {
      display: none;
   }

   /* LA FEUILLE EN CARTES : une carte par élève - nom et suivi, puis
      P-A-R et le motif sur une ligne. Le même formulaire qu'au bureau. */
   .mc-appel-table,
   .mc-appel-table tbody {
      display: block;
   }

   .mc-appel-table thead {
      display: none;
   }

   .mc-appel-table tr.presence-row {
      display: grid;
      grid-template-columns: auto minmax(0, 1fr) auto;
      grid-template-areas:
         "eleve  eleve  suivi"
         "statut motif  motif";
      align-items: center;
      gap: .5rem;
      padding: .6rem .75rem;
      border-bottom: 1px solid var(--line);
   }

   .mc-appel-table tr.presence-row:last-child {
      border-bottom: 0;
   }

   .mc-appel-table tr.presence-row > td {
      display: block;
      padding: 0;
      border: 0;
      background: transparent;
      box-shadow: none;
   }

   .mc-appel-table tr.presence-row > td:nth-child(1) { grid-area: statut; }
   .mc-appel-table tr.presence-row > td:nth-child(2) { grid-area: eleve; overflow: hidden; text-overflow: ellipsis; }
   .mc-appel-table tr.presence-row > td:nth-child(3) { grid-area: suivi; }
   .mc-appel-table tr.presence-row > td:nth-child(4) { grid-area: motif; }

   .mc-appel-table tr.est-absent {
      background: rgba(220, 53, 69, .08);
   }

   .mc-appel-table tr.est-retard {
      background: rgba(255, 193, 7, .12);
   }

   /* P-A-R compacts, à la hauteur du motif. */
   .mc-appel-table .btn-group .btn {
      width: 36px;
      min-height: 38px;
      padding: 0;
      font-size: .875rem;
   }

   .mc-appel-table .mc-appel-motif {
      min-width: 0;
   }

   /* L'icône est cachée : le champ reprend ses quatre coins arrondis. */
   .mc-appel-table .mc-appel-motif > .motif-input {
      min-height: 38px;
      font-size: 16px;
      border-radius: var(--bs-border-radius) !important;
   }
}

/* SIGNALER UNE ABSENCE - la liste des cours à cocher (26/09). En faute :
   bordure rouge, comme un champ. */
.mc-signalement-cours {
   display: flex;
   flex-direction: column;
   gap: .35rem;
   padding: .5rem .75rem;
   border: 1px solid var(--line);
   border-radius: var(--radius-field, 8px);
}

.mc-signalement-cours.is-invalid {
   border-color: var(--bs-danger, #dc3545);
}

/* mc-select.js - `data-badges` : les pastilles d'une option à photo, à
   droite (26/09). */
.mc-combo-option-badges {
   display: flex;
   flex-wrap: wrap;
   justify-content: flex-end;
   gap: .25rem;
   margin-left: auto;
}

.mc-signalement-cours .form-check {
   margin-bottom: 0;
}

/* Sur la ligne choisie, un liseré blanc détache les pastilles quand leur
   couleur est celle du surlignage. */
.mc-combo-option[aria-selected="true"] .mc-combo-option-badges .badge {
   box-shadow: 0 0 0 1px rgba(255, 255, 255, .8);
}

/* mc-select.js - `data-sous-texte-html` : un simple texte gris à droite
   (l'âge d'un élève), sans pastille (26/09). */
.mc-combo-option-sous-texte-simple {
   margin-left: auto;
   padding-left: .5rem;
   color: var(--bs-secondary-color, #6c757d);
   white-space: nowrap;
}

.mc-combo-option[aria-selected="true"] .mc-combo-option-sous-texte-simple {
   color: inherit;
   opacity: .8;
}

/* ONGLETS DÉFILANTS (fiche membre, 26/09) : sur un écran étroit, les onglets
   restent sur une ligne et défilent horizontalement, sans barre visible. */
.mc-onglets-defilants {
   scrollbar-width: none;
}

.mc-onglets-defilants::-webkit-scrollbar {
   display: none;
}

.mc-onglets-defilants .nav-link {
   white-space: nowrap;
}

/* TABLEAU COMPACT (27/09) : une colonne étroite (col-lg-3), comme le résumé
   des enfants de l'espace famille - marges et texte resserrés. */
.mc-table-compacte th,
.mc-table-compacte td {
   padding: .3rem .35rem !important;
   font-size: .8rem;
}

.mc-table-compacte.table-mc-entete thead th {
   letter-spacing: 0;
   font-size: .65rem;
   padding: .3rem .25rem !important;
}

.mc-table-compacte .btn-actions {
   width: 1.9rem;
   height: 1.4rem;
   min-height: 0;
}

.mc-masque-vide {
   display: none !important;
}

/* LE TEXTE D'UNE INFOBULLE, EN CLAIR SUR MOBILE (abdAllah, 27/09) - voir
   `enClairMobile()` : masqué sur PC, affiché sous `lg`. */
.mc-clair-mobile {
   display: none;
   font-size: .75rem;
   line-height: 1.25;
   color: var(--bs-secondary-color, #6c757d);
   white-space: normal;
   min-width: 8rem;
   margin-top: .15rem;
}
@media (max-width: 991.98px) {
   .mc-clair-mobile {
      display: block;
   }
}

/* CHAMP DÉSACTIVÉ QUI S'EXPLIQUE (abdAllah, 28/09) : un champ `disabled`
   n'émet aucun clic ; il laisse donc passer le clic à la zone
   `data-mc-explication` qui l'entoure, et la boîte d'explication s'ouvre
   (mc-attache.js). */
[data-mc-explication] {
   cursor: pointer;
}

[data-mc-explication] :disabled {
   pointer-events: none;
}

/* GROUPE DE CASES EN FAUTE (abdAllah, 28/09) : quand la règle porte sur le
   GROUPE (« au moins une séance »…), aucune case n'a de contrainte propre et
   chacune passait pour valide - libellé vert sous un message rouge. Le script
   de la page pose `mc-groupe-invalide` sur le conteneur tant que la règle
   échoue : cases et libellés prennent alors la couleur de l'erreur. */
.was-validated .mc-groupe-invalide .form-check-input,
.was-validated .mc-groupe-invalide .form-check-input:valid,
.was-validated .mc-groupe-invalide .form-check-input:valid:checked {
   border-color: var(--bs-form-invalid-border-color, #dc3545);
}

.was-validated .mc-groupe-invalide .form-check-input:valid ~ .form-check-label,
.was-validated .mc-groupe-invalide .form-check-label {
   color: var(--bs-form-invalid-color, #dc3545);
}

/* LES KPI DU PROJET (abdAllah, 28/09) : un liseré de 5px à gauche, de la
   couleur de l'icône. La couleur est posée UNE fois, sur la carte
   (`style="--mc-kpi:…"`) ; l'icône la reprend (`color:var(--mc-kpi)`) : les
   deux ne peuvent plus diverger, même quand la couleur dépend d'un état
   (échéances en retard, solde négatif…). */
.card.mc-kpi {
   border-left: 5px solid var(--mc-kpi, var(--dominante-color));
   transition: transform .15s ease, box-shadow .15s ease;
}

/* TOUS LES KPI SE SOULÈVENT AU SURVOL (abdAllah, 30/09), qu'ils mènent
   quelque part ou non : même effet que `mc-carte-cliquable` (tools.css).
   Le curseur, lui, ne change que sur un KPI-lien. */
.card.mc-kpi:hover {
   transform: translateY(-2px);
   box-shadow: 0 .35rem .75rem rgba(0, 0, 0, .12);
}

/* WIDGET NOTIFICATIONS EN GRILLE (abdAllah, 28/09) : jusqu'à 4 par ligne sur
   PC. Dans une colonne étroite, le bouton passe SOUS le texte, calé en bas à
   droite, pour que le message garde toute la largeur. Sur téléphone, la liste
   est repliée sous l'en-tête (collapse) ; le chevron du bouton se retourne à
   l'ouverture. */
.mc-notifs-grille .mc-notif-ligne {
   flex-direction: column;
   gap: .5rem;
}

.mc-notifs-grille .mc-notif-actions {
   align-self: flex-end;
   margin-top: auto;
}

.mc-notifs-bascule .ph-caret-down {
   transition: transform .2s ease;
}

.mc-notifs-bascule[aria-expanded="true"] .ph-caret-down {
   transform: rotate(180deg);
}

/* TABLEAUX DE BORD - COLONNES À LA HAUTEUR DU VIEWPORT (abdAllah, 28/09).
   Sur PC, `mc-defilant.js` borne le corps des blocs à la place restante sous
   eux ; le contenu défile verticalement ET horizontalement (une ligne longue
   ne se tronque plus, elle se fait défiler). Sous lg, les blocs s'empilent :
   la contrainte est levée et la page défile comme d'habitude. */
.mc-defilant.mc-tdb-defilant {
   overflow-x: auto;
}

@media (max-width: 991.98px) {
   .mc-defilant.mc-tdb-defilant {
      max-height: none !important;
      overflow: visible !important;
   }
}

/* TUILES D'ACCÈS RAPIDE - espace Étudiant SEULEMENT (index7.php, 28/09).
   PAVÉ NUMÉRIQUE : quinze touches carrées, TROIS par ligne, toutes de la même
   taille, le pavé centré. Chaque touche a le relief d'un bouton poussoir -
   dégradé de la dominante, reflet en haut, arête plus sombre en bas, ombre
   portée - et s'ENFONCE au clic (réduction + perte du relief). Une touche
   inaccessible est grisée et sans lien ; une pastille rouge signale ce qui
   attend. */
/* La zone occupe la hauteur restante de l'écran (script d'index7.php) et
   centre le pavé verticalement. */
.mc-tuiles-zone {
   margin-bottom: 1.5rem;
   display: flex;
   align-items: center;
   justify-content: center;
}

.mc-tuiles {
   display: grid;
   /* Touches CARRÉES (`aspect-ratio`) de 6.6rem au plus : sur un petit
      téléphone, le pavé rétrécit avec l'écran au lieu de déborder. */
   grid-template-columns: repeat(3, minmax(0, 1fr));
   gap: .4rem;
   margin: 0 auto;
   padding: .5rem;
   width: 100%;
   max-width: calc(3 * 6.6rem + 2 * .4rem + 1rem);
   border-radius: .5rem;
   background: color-mix(in srgb, var(--dominante-color, #065d89) 8%, #fff);
   box-shadow: inset rgba(0, 0, 0, 0.08) 0px 2px 6px;
}

.mc-tuile {
   position: relative;
   display: flex;
   flex-direction: column;
   align-items: center;
   justify-content: center;
   gap: .5rem;
   aspect-ratio: 1;
   padding: .4rem;
   border-radius: .5rem;
   background: var(--dominante-color, #065d89);
   background: linear-gradient(160deg,
      color-mix(in srgb, var(--dominante-color, #065d89) 78%, #fff) 0%,
      var(--dominante-color, #065d89) 55%,
      color-mix(in srgb, var(--dominante-color, #065d89) 72%, #000) 100%);
   color: #fff;
   text-align: center;
   text-decoration: none;
   /* Relief de touche : reflet en haut, arête sombre en bas, ombre portée. */
   border-bottom: 4px solid color-mix(in srgb, var(--dominante-color, #065d89) 55%, #000);
   box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px,
               inset rgba(255, 255, 255, 0.28) 0px 1px 0px;
   /* Enfoncement LENT ET FLUIDE (28/09) : la touche descend en douceur et
      remonte avec un léger rebond. */
   transition: transform .28s cubic-bezier(.34, 1.4, .64, 1),
               box-shadow .28s ease,
               border-bottom-width .28s ease,
               filter .2s ease;
   -webkit-tap-highlight-color: transparent;
   user-select: none;
}

/* La touche « Ajouter » est un BOUTON (elle ouvre un choix) : mêmes effets,
   sans le cadre ni la police du bouton natif (28/09). */
button.mc-tuile {
   width: 100%;
   border-top: 0;
   border-left: 0;
   border-right: 0;
   font: inherit;
   cursor: pointer;
}

a.mc-tuile:hover,
a.mc-tuile:focus-visible,
button.mc-tuile:hover,
button.mc-tuile:focus-visible {
   color: #fff;
   filter: brightness(1.08);
}

/* BOUTON POUSSOIR : la touche s'enfonce - plus petite, l'arête écrasée,
   l'ombre ramenée sous elle. */
a.mc-tuile:active,
button.mc-tuile:active {
   transition-duration: .18s;
   transition-timing-function: cubic-bezier(.4, 0, .2, 1);
   transform: scale(.93) translateY(2px);
   border-bottom-width: 1px;
   box-shadow: rgba(0, 0, 0, 0.30) 0px 1px 2px,
               inset rgba(0, 0, 0, 0.22) 0px 2px 5px;
   filter: brightness(.95);
}

.mc-tuile .ph-duotone {
   font-size: 2.1rem;
   line-height: 1;
}

.mc-tuile-libelle {
   font-weight: var(--fw-bold, 600);
   font-size: .8rem;
   line-height: 1.15;
}

.mc-tuile-badge {
   position: absolute;
   top: .3rem;
   right: .3rem;
   min-width: 1.3rem;
   height: 1.3rem;
   padding: 0 .3rem;
   border-radius: 1rem;
   background: #dc3545;
   color: #fff;
   font-size: .7rem;
   font-weight: var(--fw-bold, 600);
   line-height: 1.3rem;
   box-shadow: rgba(0, 0, 0, 0.25) 0px 1px 3px;
}

/* Très petit écran (< 360px) : icône et libellé réduits, pour que les
   touches restent carrées même avec « Notifications ». */
@media (max-width: 359.98px) {
   .mc-tuile .ph-duotone { font-size: 1.7rem; }
   .mc-tuile-libelle     { font-size: .68rem; }
}

.mc-tuile-inactive {
   opacity: .4;
   cursor: default;
   box-shadow: none;
}

/* BOÎTE DE CHOIX EN TOUCHES CARRÉES (`mcChoixTuiles()`, mc-attache.js -
   28/09) : ajout de profil (index7), ouverture de fiche membre / enseignant.
   Toutes les touches sur UNE ligne : elles rétrécissent sur un petit écran
   plutôt que de passer à la ligne. */
.mc-choix-tuiles {
   display: grid;
   grid-auto-flow: column;
   grid-auto-columns: minmax(0, 6.6rem);
   gap: .5rem;
   justify-content: center;
}

/* FERMER : même touche, teinte GRISE - on la distingue des choix. */
.mc-tuile.mc-tuile-fermer {
   background: #6c757d;
   background: linear-gradient(160deg, #9aa3a9 0%, #6c757d 55%, #4a5157 100%);
   border-bottom-color: #3d4348;
}

/* Grisée mais EXPLIQUÉE au clic (« Ajouter », 28/09). */
.mc-tuile-inactive[data-mc-explication] {
   cursor: pointer;
}

/* BANDEAU DE PAGE SUR TÉLÉPHONE (abdAllah, 28/09) : le bandeau (titre,
   sous-titre, heure) n'est affiché sur AUCUNE page sous 768px - la place va
   au contenu. D'abord réservé aux tableaux de bord, étendu à toutes les
   interfaces le même jour. */
@media (max-width: 767.98px) {
   /* MASQUÉ MAIS GARDÉ COMME ESPACE (abdAllah, 10/10) : avec `display: none`, le contenu se
      collait à la barre de navigation sur toutes les pages. Le bandeau devient une bande
      invisible de hauteur nulle, et sa marge basse laisse respirer le contenu. */
   .page-header {
      display: block;
      visibility: hidden;
      height: 0;
      min-height: 0;
      padding: 0;
      border: 0;
      margin: 0 0 1rem;
      overflow: hidden;
   }

   /* …SAUF S'IL PORTE UNE ALERTE (demande de suppression, validations,
      liste d'attente) : la bande reste, réduite à ses alertes. Quand la
      dernière s'efface, `:has()` ne trouve plus rien et la bande repart. */
   .page-header:has(.mc-toast-host-header .mc-toast) {
      display: flex;
      visibility: visible;
      height: auto;
      padding: .9rem 1.25rem;
      overflow: visible;
   }

   .page-header:has(.mc-toast-host-header .mc-toast) .page-title-group,
   .page-header:has(.mc-toast-host-header .mc-toast) .date-time {
      display: none;
   }
}

/* EMPLOI DU TEMPS DES ESPACES MEMBRES (organisation/mbr-emploi-du-temps.php,
   abdAllah 28/09). Sur PC, une colonne par jour affiché (`--mc-edt-jours`) ;
   sur téléphone, les jours s'empilent et la page s'ouvre sur aujourd'hui.
   Chaque séance porte un liseré de la couleur de sa filière ; une séance
   annulée ou déplacée ailleurs reste visible, barrée et atténuée. */
.mc-edt-semaine {
   display: grid;
   grid-template-columns: repeat(var(--mc-edt-jours, 5), minmax(0, 1fr));
   gap: .6rem;
}

@media (max-width: 767.98px) {
   .mc-edt-semaine {
      grid-template-columns: 1fr;
   }
}

.mc-edt-jour {
   display: flex;
   flex-direction: column;
   gap: .45rem;
   padding: .5rem;
   border-radius: .5rem;
   background: var(--panel-soft, #f4f6f8);
   scroll-margin-top: 5rem;
}

.mc-edt-aujourdhui {
   background: color-mix(in srgb, var(--dominante-color, #065d89) 10%, #fff);
   box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--dominante-color, #065d89) 45%, #fff);
}

.mc-edt-jour-off {
   opacity: .7;
}

/* EN-TÊTE DE DATE (28/09) : bandeau pleine largeur en haut de la colonne -
   le nom du jour en petit, la date dessous. Le jour courant est à la
   dominante, texte blanc. */
.mc-edt-jour-titre {
   position: relative;
   display: flex;
   flex-direction: column;
   align-items: flex-start;
   gap: 0;
   margin: -.5rem -.5rem .1rem;
   padding: .45rem .65rem;
   overflow-wrap: anywhere;
   border-radius: .5rem .5rem 0 0;
   background: color-mix(in srgb, var(--dominante-color, #065d89) 14%, #fff);
   color: var(--dominante-color, #065d89);
   font-size: 1rem;
   line-height: 1.2;
}

.mc-edt-jour-nom {
   font-size: .72rem;
   font-weight: var(--fw-bold, 600);
   text-transform: uppercase;
   letter-spacing: .04em;
   opacity: .85;
}

.mc-edt-jour-date {
   font-size: 1rem;
   font-weight: var(--fw-bold, 600);
}

.mc-edt-aujourdhui .mc-edt-jour-titre {
   background: var(--dominante-color, #065d89);
   color: #fff;
}

/* Jour vide (pas de cours, vacances, hors période) : l'état vide du projet,
   CENTRÉ dans la hauteur de la colonne. */
.mc-edt-vide {
   flex: 1 1 auto;
   justify-content: center;
   padding: 1rem .5rem;
   font-size: .82rem;
}

.mc-edt-seance {
   /* `min-width: 0` + coupure des mots longs : dans une colonne étroite, rien
      ne doit sortir de la carte (28/09). */
   min-width: 0;
   overflow-wrap: anywhere;
   display: flex;
   flex-direction: column;
   gap: .3rem;
   padding: .5rem .6rem;
   border-radius: .4rem;
   background: #fff;
   border-left: 4px solid var(--mc-edt-couleur, var(--dominante-color));
   box-shadow: rgba(0, 0, 0, 0.08) 0px 1px 3px;
}

.mc-edt-seance-retiree {
   opacity: .6;
}

.mc-edt-seance-retiree .mc-edt-heure,
.mc-edt-seance-retiree .mc-edt-classe {
   text-decoration: line-through;
}

.mc-edt-heure {
   /* L'horaire ne se coupe jamais : le badge d'état passe dessous. */
   white-space: nowrap;
   overflow-wrap: normal;
   font-weight: var(--fw-bold, 600);
   font-size: .85rem;
}

.mc-edt-classe {
   align-self: flex-start;
   white-space: normal;
   text-align: left;
}

.mc-edt-ligne {
   display: flex;
   align-items: flex-start;
   min-width: 0;
   gap: .35rem;
   font-size: .8rem;
   color: var(--dc-90-555555, #555);
}

/* Vacances, vue membre (28/09) : une période passée est atténuée. */
.mc-vacance-passee > td {
   opacity: .5;
}

.mc-edt-ligne > .ph-duotone {
   flex-shrink: 0;
   margin-top: .15rem;
}

.mc-edt-lien-salle {
   align-self: stretch;
   white-space: normal;
   font-size: .78rem;
   padding: .2rem .4rem;
}

/* SECTION VISÉE PAR UN LIEN (`#ancre`, 28/09) : elle s'arrête sous la barre
   de navigation et se signale brièvement. */
.mc-ancre-section {
   scroll-margin-top: 5.5rem;
}

.mc-ancre-section:target {
   animation: mcAncreSignal 1.6s ease-out 1;
}

@keyframes mcAncreSignal {
   0%   { box-shadow: 0 0 0 4px color-mix(in srgb, var(--dominante-color, #065d89) 45%, transparent); }
   100% { box-shadow: 0 0 0 0 transparent; }
}

/* CHANGEMENT D'INTERFACE (abdAllah, 28/09) - Superviseur → Parent, Agent →
   Étudiant… Un CERCLE se referme de l'extérieur vers le centre sur
   l'interface quittée (`mc-bascule-fermeture`, posée par mc-attache.js au
   geste qui change d'interface), puis s'ouvre du centre vers l'extérieur sur
   la nouvelle (`mc-bascule-ouverture`, posée par inc/head.php quand le
   SERVEUR constate le changement). Autour du cercle, la couleur dominante.

   COMPATIBLE AVEC TOUS LES NAVIGATEURS : animation CSS de `clip-path`,
   sans les transitions entre pages (View Transitions), que Firefox ignore.

   Centre et rayon en px (`--mc-cx`, `--mc-cy`, `--mc-r`, posés par le script) :
   le cercle se centre sur la FENÊTRE, même sur une page qu'on a fait
   défiler. Pendant l'animation, <html> prend la couleur dominante : sans fond
   propre, celui de <body> serait reporté sur toute la fenêtre et ne serait pas
   découpé. */
@keyframes mcCercleFerme {
   from { clip-path: circle(var(--mc-r, 75%) at var(--mc-cx, 50%) var(--mc-cy, 50%)); }
   to   { clip-path: circle(0 at var(--mc-cx, 50%) var(--mc-cy, 50%)); }
}

@keyframes mcCercleOuvre {
   from { clip-path: circle(0 at var(--mc-cx, 50%) var(--mc-cy, 50%)); }
   to   { clip-path: circle(var(--mc-r, 75%) at var(--mc-cx, 50%) var(--mc-cy, 50%)); }
}

html.mc-bascule-fermeture,
html.mc-bascule-ouverture,
html.mc-rideau-fermeture,
html.mc-rideau-ouverture {
   background: var(--dominante-color, #065d89);
   overflow: hidden;
}

html.mc-bascule-fermeture body,
html.mc-bascule-ouverture body,
html.mc-rideau-fermeture body,
html.mc-rideau-ouverture body {
   min-height: 100vh;
}

html.mc-bascule-fermeture body {
   animation: mcCercleFerme .8s cubic-bezier(.65, 0, .35, 1) forwards;
   pointer-events: none;
}

html.mc-bascule-ouverture body {
   animation: mcCercleOuvre .8s cubic-bezier(.65, 0, .35, 1) both;
}

/* PUZZLE (abdAllah, 29/09) - remplace le rideau pour entrer dans l'espace
   d'un membre (« Son espace membre ») ou en revenir (« Retour à l'Admin ») :
   8 × 7 pièces de la couleur dominante (calque `.mc-puzzle`, mc-attache.js).
   Fermeture : elles arrivent de l'extérieur de l'écran, au hasard, et se
   collent à leur place jusqu'à couvrir la page quittée (`mc-puzzle-entre`).
   Ouverture : la nouvelle page est masquée dès le <head>
   (`mc-rideau-ouverture`, inc/head.php), puis les pièces repartent au
   hasard vers l'extérieur (`mc-puzzle-sort`). Direction et distance par
   pièce : `--mc-tx` / `--mc-ty`, posées par mc-attache.js.
   Chaque pièce porte le dégradé de la FENÊTRE entière, décalé à sa place :
   assemblées, elles redonnent le fond uni du rideau. */
html.mc-rideau-fermeture,
html.mc-rideau-ouverture {
   background: var(--dominante-color, #065d89);
   background: linear-gradient(180deg,
      var(--dominante-color, #065d89) 0%,
      color-mix(in srgb, var(--dominante-color, #065d89) 82%, #000) 100%) fixed;
}

html.mc-rideau-fermeture body {
   pointer-events: none;
}

/* Avant la pose des pièces : la page n'apparaît pas une seule image. */
html.mc-rideau-ouverture body {
   visibility: hidden;
}

html.mc-puzzle-ouverture {
   overflow: hidden;
}

.mc-puzzle {
   position: fixed;
   inset: 0;
   z-index: 2147483000;
   display: grid;
   grid-template-columns: repeat(8, 1fr);
   grid-template-rows: repeat(7, 1fr);
   pointer-events: none;
   visibility: visible;
}

.mc-puzzle > span {
   display: block;
   background: var(--dominante-color, #065d89);
   background: linear-gradient(180deg,
      var(--dominante-color, #065d89) 0%,
      color-mix(in srgb, var(--dominante-color, #065d89) 82%, #000) 100%);
   background-size: 100vw 100vh;
   animation-duration: .45s;
   animation-fill-mode: both;
   will-change: transform;
}

/* 1.02 et non 1 : les pièces se chevauchent d'un cheveu, aucun joint clair
   entre elles une fois l'écran couvert. Arrivée freinée (elle se « colle »),
   départ accéléré. */
.mc-puzzle-entre > span {
   animation-name: mcPieceEntre;
   animation-timing-function: cubic-bezier(.22, .9, .36, 1);
}

.mc-puzzle-sort > span {
   animation-name: mcPieceSort;
   animation-timing-function: cubic-bezier(.64, 0, .78, .1);
}

/* LE LOGO (abdAllah, 29/09) : MADRASSAT-E en plein centre de l'écran
   couvert, passé en blanc sur la dominante. `--mc-logo` : inc/head.php.
   `html::after` le montre dès le premier affichage de la page qui s'ouvre,
   avant même que le script pose le calque - même taille, même place. */
.mc-puzzle-logo,
html.mc-rideau-ouverture::after,
html.mc-bascule-ouverture::after {
   position: fixed;
   inset: 0;
   background: var(--mc-logo) center / min(28vw, 200px) auto no-repeat;
   filter: brightness(0) invert(1) drop-shadow(0 4px 14px rgba(0, 0, 0, .25));
   pointer-events: none;
}

html.mc-rideau-ouverture::after,
html.mc-bascule-ouverture::after {
   content: '';
   z-index: 2147483001;
}

/* CHANGEMENT D'INTERFACE (cercle) - LE MÊME LOGO (abdAllah, 29/09).
   Fermeture : posé sur <html> par mc-attache.js une fois le cercle refermé.
   Ouverture : affiché dès le premier affichage (`::after`), gardé 0,4 s
   - la même temporisation que le puzzle (PUZZLE_TEMPO, mc-attache.js) -,
   effacé en 0,3 s, et le cercle ne s'ouvre qu'ensuite. */
.mc-interface-logo {
   z-index: 2147483001;
   animation-name: mcLogoEntre;
   animation-timing-function: cubic-bezier(.34, 1.4, .64, 1);
}

/* LE MÊME DÉROULÉ QUE LE PUZZLE (abdAllah, 04/10) : rotation du logo (0,7 s), pause très
   légère (0,15 s), puis le logo s'efface (0,3 s) et le cercle s'ouvre. Mêmes valeurs que
   MC_ROTATION et MC_PAUSE, mc-attache.js. */
html.mc-bascule-ouverture::after {
   animation: mcLogoSort .3s ease-in .85s both;
}

html.mc-bascule-ouverture body {
   animation-delay: 1s;
}

.mc-puzzle-logo {
   z-index: 1;
   animation-duration: .3s;
   animation-fill-mode: both;
}

.mc-puzzle-entre > .mc-puzzle-logo {
   animation-name: mcLogoEntre;
   animation-timing-function: cubic-bezier(.34, 1.4, .64, 1);
}

.mc-puzzle-sort > .mc-puzzle-logo {
   animation-name: mcLogoSort;
   animation-timing-function: ease-in;
}

/* LA ROTATION DU LOGO (abdAllah, 04/10) : un tour complet VERS LA GAUCHE, à l'ouverture de la
   page d'arrivée - changement de statut (cercle) comme changement d'espace membre (puzzle).
   Les animations existantes ne changent pas : la rotation s'y AJOUTE, sur la propriété
   `rotate`, distincte de `transform` qu'elles animent déjà. Elle dure le temps où le logo
   est seul à l'écran (0,7 s) ; viennent ensuite une pause très légère, puis sa sortie. */
html.mc-bascule-ouverture::after {
   animation: mcLogoSort .3s ease-in .85s both,
              mcLogoTourne .7s cubic-bezier(.45, 0, .25, 1) both;
}

/* Le puzzle pose le délai du logo en ligne (850 ms, mc-attache.js) : un seul délai vaudrait
   pour les deux animations et retarderait la rotation. `!important` rend à chacune le sien. */
.mc-puzzle-sort > .mc-puzzle-logo {
   animation-name: mcLogoSort, mcLogoTourne;
   animation-duration: .3s, .7s;
   animation-delay: .85s, 0s !important;
   animation-timing-function: ease-in, cubic-bezier(.45, 0, .25, 1);
}

@keyframes mcLogoTourne {
   from { rotate: 0deg; }
   to   { rotate: -360deg; }
}

@media (prefers-reduced-motion: reduce) {
   html.mc-bascule-ouverture::after { animation: mcLogoSort .3s ease-in .85s both; }
   .mc-puzzle-sort > .mc-puzzle-logo { animation-name: mcLogoSort; }
}

@keyframes mcLogoEntre {
   from { opacity: 0; transform: scale(.7); }
   to   { opacity: 1; transform: scale(1); }
}

@keyframes mcLogoSort {
   from { opacity: 1; transform: scale(1); }
   to   { opacity: 0; transform: scale(1.15); }
}

@keyframes mcPieceEntre {
   from { transform: translate(var(--mc-tx, 0), var(--mc-ty, 0)) scale(.6); }
   to   { transform: translate(0, 0) scale(1.02); }
}

@keyframes mcPieceSort {
   from { transform: translate(0, 0) scale(1.02); }
   to   { transform: translate(var(--mc-tx, 0), var(--mc-ty, 0)) scale(.6); }
}

/* JETONS FIGÉS (abdAllah, 28/09) - modification d'un avertissement : l'élève
   reste affiché, sans la croix pour le retirer (inc/modal-avertissement.php). */
.mc-multi-fige .mc-multi-retirer {
   display: none;
}

/* MES COURS DU JOUR - ENSEIGNANT (index5, abdAllah 28/09) : une carte par
   séance, toutes sur UNE ligne ; au-delà de la largeur, la ligne défile. */
.mc-tdb-seances {
   display: flex;
   gap: .75rem;
   overflow-x: auto;
   /* L'ombre des cartes déborde : sans cette marge, la zone qui défile la
      couperait. */
   padding: 2px 2px .5rem;
}

/* SANS ENVELOPPE (28/09) : chaque carte porte le dessin des cartes « Mes
   cours » (fond, ombre, rayon). */
.mc-tdb-seance {
   flex: 0 0 15rem;
   display: flex;
   flex-direction: column;
   border-radius: var(--radius-field, .5rem);
   background: var(--panel, #fff);
   box-shadow: rgba(0, 0, 0, .12) 0 1px 3px, rgba(0, 0, 0, .16) 0 1px 2px;
   overflow: hidden;
}

.mc-tdb-seance-entete {
   padding: .35rem .75rem;
   font-weight: var(--fw-bold, 600);
   font-size: .85rem;
}

.mc-tdb-seance-corps {
   display: flex;
   flex-direction: column;
   gap: .15rem;
   flex: 1 1 auto;
   padding: .6rem .75rem;
}

/* TABLEAU DE BORD ENSEIGNANT (index5, abdAllah 28/09) - ma journée à gauche,
   le reste en colonne à droite. Grille à zones : sur PC, la colonne de droite
   longe les deux zones de gauche (cours du jour, puis semaine) ; sur
   téléphone, l'ordre devient cours du jour → colonne → semaine. */
.mc-ustad-tdb {
   display: grid;
   grid-template-columns: minmax(0, 1fr);
   grid-template-areas: "jour" "cote" "semaine";
   gap: 0 1.5rem;
}

.mc-ustad-tdb-jour    { grid-area: jour; min-width: 0; }
.mc-ustad-tdb-cote    { grid-area: cote; min-width: 0; }
.mc-ustad-tdb-semaine { grid-area: semaine; min-width: 0; }

@media (min-width: 992px) {
   .mc-ustad-tdb {
      grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
      grid-template-areas: "jour cote" "semaine cote";
      grid-template-rows: auto 1fr;
   }
}

/* ==========================================================================
   MODULE ADHÉSIONS (abdAllah, 28/09) - sorti du <style> de la Synthèse.
   ========================================================================== */
.mc-col-min { width: 1%; white-space: nowrap; }

/* Voyants des mois : encaissé, en attente, à payer, exonéré. */
.mc-mois-btn {
   display: inline-flex; align-items: center; justify-content: center;
   width: 2.9rem; height: 1.9rem; border-radius: .35rem; border: 0; padding: 0;
   font-size: .65rem; font-weight: 700;
   position: relative; overflow: hidden; user-select: none;
}
.mc-mois-btn::after {
   content: ''; position: absolute; top: 0; left: 0; right: 0; height: 50%;
   background: linear-gradient(to bottom, rgba(255,255,255,.35), rgba(255,255,255,0));
   border-radius: .35rem .35rem 0 0; pointer-events: none;
}
.mc-mois-btn.paye    { background: linear-gradient(135deg, var(--dc-80-k, #054a6e), var(--dominante-color)); color: #fff; box-shadow: 0 2px 5px rgba(var(--dominante-rgb, 6,93,137), .45); }
.mc-mois-btn.attente { background: linear-gradient(135deg, #74b9ff, #0984e3); color: #fff; box-shadow: 0 2px 5px rgba(9,132,227,.35); }
.mc-mois-btn.libre   { background: linear-gradient(135deg, #e8e8e8, #d0d0d0); color: #888; box-shadow: 0 1px 3px #535353; border: 1px solid #ccc; margin: 1px; }
.mc-mois-btn.exonere { background: linear-gradient(135deg, #ffeaa7, #fdcb6e); color: #856404; box-shadow: 0 1px 3px rgba(0,0,0,.15); }
.mc-mois-btn.choisi  { background: linear-gradient(135deg, #34c759, #28a745); color: #fff; }
.mc-mois-legende     { width: 1.4rem; height: .9rem; vertical-align: middle; }

/* LE SUIVI DE L'ADHÉSION côté membre (abdAllah, 12/10) : un mois écoulé non couvert est EN RETARD,
   les douze mois en tuiles (six par ligne sur téléphone, douze sur grand écran). */
.mc-mois-btn.libre.retard { background: linear-gradient(135deg, #ff9f9f, #e55353); color: #fff; border-color: #d64545; box-shadow: 0 2px 5px rgba(220,53,69,.35); }
.mc-adh-mois-membre { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: .45rem; }
.mc-adh-mois-membre .mc-mois-btn { width: 100%; height: 3.3rem; margin: 0; flex-direction: column; gap: .15rem; font-size: .78rem; cursor: default; }
.mc-adh-mois-membre .mc-adh-mois-etat { font-size: .62rem; font-weight: 600; opacity: .9; }
@media (min-width: 992px) { .mc-adh-mois-membre { grid-template-columns: repeat(12, minmax(0, 1fr)); } }

/* Tableau de la Synthèse. */
/* `#tableSyntheseAdh` est le BLOC que mc-table.js construit autour du
   tableau : il prend la largeur du tableau sans dépasser la page, et le
   tableau défile à l'intérieur (abdAllah, 28/09). */
#tableSyntheseAdh { width: fit-content; max-width: 100%; }
#tableSyntheseAdh .mc-table-wrapper { max-width: 100%; }
#tableSyntheseAdh .mc-table-scroll { max-width: 100%; overflow-x: auto; }
#tableSyntheseAdh .mc-adh-mois { padding: .25rem .1rem; text-align: center; }
/* L'en-tête de mc-table est un flex calé à gauche : les mois se centrent sur
   leur voyant (abdAllah, 28/09). */
#tableSyntheseAdh th.mc-adh-mois .mc-th-inner { justify-content: center; }
#tableSyntheseAdh tbody tr { cursor: pointer; transition: background .12s; }
#tableSyntheseAdh tbody tr:hover td {
   background: rgba(var(--dominante-rgb, 6,93,137), .07) !important;
   border-top: 1px solid rgba(var(--dominante-rgb, 6,93,137), .25) !important;
   border-bottom: 1px solid rgba(var(--dominante-rgb, 6,93,137), .25) !important;
}
/* « À jour » : toute la largeur des trois colonnes, sans gras ni bordure
   (abdAllah, 28/09). */
.mc-adh-a-jour {
   display: flex; align-items: center; justify-content: flex-start; gap: .5rem;
   width: 100%; padding: .25rem .5rem;
   font-size: .85rem; color: #198754;
}
.mc-adh-a-jour i { font-size: 1.2rem; }

/* Pad de la modale de versement. */
#vsPadMois {
   display: grid; grid-template-columns: repeat(3, 1fr); gap: .3rem;
   border: 1px solid rgba(var(--dominante-rgb, 6,93,137), .25); border-radius: .5rem; padding: .3rem;
}
#vsPadMois .mc-mois-btn { width: 100%; height: 3.3rem; margin: 0; font-size: .72rem; flex-direction: column; gap: .15rem; cursor: default; }
#vsPadMois .mc-mois-btn.libre { cursor: pointer; }
#vsPadMois .mc-mois-btn.libre:hover { filter: brightness(1.05); box-shadow: inset 0 0 0 2px rgba(var(--dominante-rgb, 6,93,137), .5); }
#vsPadMois .mc-mois-btn:disabled { opacity: 1; }
#vsPadMois .vs-cout-mois { font-size: .6rem; opacity: .75; }
.mc-vs-montant { line-height: 1; color: var(--dominante-color); font-weight: var(--fw-bold); }
.mc-vs-montant #vsMontantVal { font-size: 2.8rem; }
.mc-vs-montant sup { font-size: 1.1rem; margin-left: .15rem; }
.mc-vs-carte { border-left: 3px solid var(--mc-vs); }
.mc-vs-carte > div:first-child { font-size: 1.1rem; font-weight: var(--fw-bold); color: var(--mc-vs); }

/* COMPTES BANCAIRES de la page Établissement (abdAllah, 28/09) : une carte
   par compte, fond clair, liseré de 9px à gauche. */
.mc-comptes-liste .min-w-0 { min-width: 0; }
.mc-compte-carte { border-left: 9px solid var(--dc-40-w, #9bbed0) !important; }
/* Le compte PAR DÉFAUT : la dominante foncée ; les autres, plus clairs. */
.mc-compte-carte.mc-compte-defaut { border-left-color: var(--dc-80-k, #054a6e) !important; }
/* …et une teinte claire de la dominante en fond (abdAllah, 30/09) - `!important`
   pour passer devant le `.bg-light` de Bootstrap. */
.mc-compte-carte.mc-compte-defaut { background-color: var(--dc-12-t, rgba(6, 93, 137, .12)) !important; }
.mc-compte-carte.mc-compte-ferme { opacity: .6; }

/* DÉPÔTS EFFECTUÉS (abdAllah, 28/09) : la recherche, plus étroite sur PC -
   la carte est en demi-largeur. Sur téléphone, elle garde toute la ligne. */
@media (min-width: 768px) {
   #tableDepots .mc-toolbar-group.mc-grow { flex-basis: 220px; }
}
/* DÉPÔTS ET SUIVIS (abdAllah, 28/09) : les deux tableaux de la page gardent
   une hauteur minimale, même presque vides. */
#tableADeposer .mc-table-scroll,
#tableDepots .mc-table-scroll { min-height: 230px; }

/* LE MONTANT EN GRAND (abdAllah, 28/09) : modale Dépense, le champ occupe la
   hauteur de deux lignes (date + mode). */
.mc-montant-grand .form-control {
   font-size: 2.25rem;
   color: var(--dominante-color);
}
.mc-montant-grand .input-group-text { font-size: 1.3rem; }

/* LE BLOC DES JUSTIFICATIFS (abdAllah, 28/09), modale Dépense : il remplit la
   colonne sous la zone de dépôt. « Aucun justificatif » tant que les deux
   listes sont vides. */
.mc-justifs-bloc { min-height: 8rem; display: flex; flex-direction: column; }
.mc-justifs-vide {
   display: none; flex: 1 1 auto; flex-direction: column; align-items: center; justify-content: center;
   gap: .25rem; color: var(--slate-dim, #8a94a0); font-size: .8rem;
}
.mc-justifs-vide i { font-size: 1.6rem; opacity: .6; }
#dpListeExistants:empty + #dpListeAttente:empty + .mc-justifs-vide { display: flex; }

/* Modale des périodes (inc/modale-periodes.php, 30/09) : avec « Notes
   visibles le », trois dates sur la ligne d'ajout - chacune garde la largeur
   d'une date complète. */
.mc-periode-date .form-control {
   width: 9rem;
}

/* AJOUT RAPIDE D'UN TYPE D'ÉVALUATION (enseignement, 30/09) : les boutons de
   la ligne prennent la hauteur du champ - la marge basse des boutons du projet
   les raccourcissait de 3px dans l'input-group. */
.mc-type-nouveau .input-group > .btn {
   margin-bottom: 0;
}

/* NIVEAU RETENU de la modale des appréciations (enseignement, 30/09) : un
   mc-combo compact, à la hauteur d'un champ -sm, dans la colonne Résultat. */
.mc-appr-niveau .mc-combo {
   min-height: 31px;
   padding: .15rem .5rem;
}

.mc-appr-niveau .mc-combo-field {
   min-width: 0;
}

.mc-appr-niveau .input-group-text {
   padding-top: .15rem;
   padding-bottom: .15rem;
   line-height: 1;
   min-height: 31px;
}

/* APERÇU D'UN BULLETIN (enseignement, 30/09) : chaque page du PDF, dessinée
   par PDF.js, posée comme une feuille sur fond gris. */
.mc-apercu-page {
   display: block;
   margin: 0 auto 1rem;
   background: #fff;
   box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .15);
}

/* AVATAR ROND D'EN-TÊTE DE MODALE (appréciations, aperçu du bulletin - 30/09) :
   les avatars par défaut sont détourés ; le fond blanc et le filet rendent le
   cercle visible. */
.mc-avatar-rond {
   object-fit: cover;
   vertical-align: middle;
   background: #fff;
   border: 1px solid var(--bs-border-color, #dee2e6);
}

/* AVATAR D'EN-TÊTE DE MODALE (30/09) : tout à gauche, sur la hauteur du titre
   et du sous-titre - même place que `.modal-header > .ph-duotone`. */
.modal-header > .mc-avatar-entete {
   width: 44px;
   height: 44px;
   margin-right: .75rem;
   flex-shrink: 0;
}

/* COULEUR DES DOCUMENTS (Paramètres › Établissement, 30/09) : le groupe
   icône · couleur · Aperçu à la même hauteur que les champs, et centré sur
   son libellé. La marge basse des boutons du thème (3px) décalait le groupe ;
   le champ couleur prend la hauteur d'un champ normal. */
.mc-couleur-documents .input-group > .btn {
   margin-bottom: 0;
}

/* Le bloc de gauche (libellé + consigne) est centré sur le groupe ; ses
   deux lignes, sans marge, restent serrées. */
.mc-couleur-documents-libelle {
   line-height: 1.3;
   /* COLONNE ÉTROITE (abdAllah, 30/09) : sous ~10rem de place pour le
      libellé, le groupe passe à la ligne, calé à droite, au lieu de
      déborder de la carte ou d'écraser le libellé sur 4 lignes. */
   flex: 1 1 10rem;
   min-width: 10rem;
}

.mc-couleur-documents .input-group > .form-control-color {
   height: calc(1.5em + .75rem + 2px);
   width: 3rem;
   flex: 0 0 auto;
}

/* SÉLECTEUR D'ÉLÈVE DU FOYER (inc/selecteur-eleve.php, 30/09) : UN SEUL
   RENDU pour toutes les pages - largeur fixe (18rem, jamais plus large que
   l'écran), la même avec ou sans élève choisi, pour le bandeau d'un seul
   élève comme pour la liste de plusieurs. Aucune marge : la page gère
   l'espacement autour. */
.mc-selecteur-eleve {
   width: 18rem;
   max-width: 100%;
}

.mc-selecteur-eleve .input-group {
   width: 100%;
}

/* MÊME HAUTEUR QUE LES FILTRES des pages (abdAllah, 30/09) : 34px, la
   hauteur des petits champs du thème (`input-group-sm`).
   · la liste : la photo des options réduite à 22px (à 28,8px, elle portait
     le champ à 35,6px) ;
   · le bandeau d'un seul élève : 34px, même taille de texte, photo 24px. */
.mc-selecteur-eleve .mc-combo-option-photo {
   width: 22px;
   height: 22px;
}

.mc-selecteur-eleve.d-flex {
   height: 34px;
   padding-top: 0 !important;
   padding-bottom: 0 !important;
   font-size: var(--fs-sm);
}

/* CORRECTION DES RENDUS (cahier de textes, 30/09) : commentaire, note et
   niveau en PETITE TAILLE, texte et indication compris - comme les champs de
   la modale « Noter des élèves ». Sans cela, le textarea et son indication
   gardaient la grande taille du thème. */
.mc-correction-champ,
.mc-correction-champ .form-control,
.mc-correction-champ .form-select,
.mc-correction-champ .input-group-text {
   font-size: var(--fs-sm);
}

.mc-correction-champ .form-control::placeholder {
   font-size: var(--fs-sm);
}

/* CORRECTION (abdAllah, 30/09) : le commentaire sur toute la largeur, LA
   NOTE SUR LA LIGNE DESSOUS, calée à droite (PC) ; pleine largeur sur mobile. */
.mc-correction {
   display: flex;
   flex-direction: column;
   gap: .35rem;
}

.mc-correction > .mc-correction-commentaire {
   width: 100%;
}

.mc-correction > .mc-correction-note {
   align-self: flex-end;
   width: auto;
}

/* LE CHAMP DE LA NOTE à la largeur de 6 caractères (abdAllah, 30/09) - « 12,75 »
   et sa marge ; le groupe se règle dessus, « /20 » compris. */
.mc-correction > .mc-correction-note > .form-control {
   flex: 0 0 auto;
   width: calc(6ch + 1rem);
}

/* Le message d'erreur sous la note élargit le groupe : champ et « /20 »
   restent calés à droite, le message aussi. */
.mc-correction > .mc-correction-note {
   justify-content: flex-end;
}

.mc-correction > .mc-correction-note > .invalid-feedback {
   text-align: right;
}

/* Le barème (« /20 ») en plus petit (abdAllah, 30/09). */
.mc-correction > .mc-correction-note > .input-group-text {
   font-size: .8rem;
}

.mc-correction > .mc-correction-note:has(.form-select) {
   width: 13rem;
}

/* SUR MOBILE, UNE CARTE PAR ÉLÈVE (abdAllah, 30/09) : sous 768px, trois
   colonnes n'y tiennent pas (« Comme/ntaire », « /20 » à la ligne). Chaque
   ligne devient une carte à liseré ; ses cellules s'empilent : l'élève et son
   statut, le travail rendu, puis la correction sur toute la largeur (note sous
   le commentaire). Sans rendu : une ligne compacte, rien à corriger. */
@media (max-width: 767.98px) {
   .mc-rendus-table thead {
      display: none;
   }

   .mc-rendus-table,
   .mc-rendus-table tbody,
   .mc-rendus-table tr,
   .mc-rendus-table td {
      display: block;
      width: 100% !important;
   }

   .mc-rendus-table tr {
      margin-bottom: .5rem;
      padding: .45rem .6rem;
      border: 1px solid var(--line, #dee2e6);
      border-left: 4px solid var(--dominante-color, #065d89);
      border-radius: .375rem;
      background: var(--panel, #fff);
   }

   .mc-rendus-table td {
      padding: .2rem 0 !important;
      border: 0 !important;
      background: transparent !important;
      white-space: normal !important;
   }

   /* Sans rendu : la seule ligne du nom, liseré clair. */
   .mc-rendus-table tr.mc-rendu-non {
      padding: .3rem .6rem;
      border-left-color: var(--dc-40-w, #9bbed0);
   }

   .mc-rendus-table tr.mc-rendu-non td:not(:first-child) {
      display: none;
   }

   /* Mobile : le niveau (liste) prend la largeur ; la NOTE garde ses 6
      caractères, calée à droite. */
   .mc-correction > .mc-correction-note:has(.form-select) {
      align-self: stretch;
      width: 100%;
   }
}

/* APERÇU D'UN FICHIER RENDU dans la correction (abdAllah, 30/09) : le PDF ou
   l'image au-dessus de la liste, sans quitter la fenêtre. */
.mc-rendu-apercu {
   border: 1px solid var(--line, #dee2e6);
   border-radius: .375rem;
   padding: .5rem;
   background: var(--dc-12-t, rgba(6, 93, 137, .12));
}

.mc-rendu-apercu iframe {
   display: block;
   width: 100%;
   height: 60vh;
   border: 0;
   background: #fff;
}

.mc-rendu-apercu img {
   display: block;
   max-width: 100%;
   max-height: 60vh;
   margin: 0 auto;
}

/* BANQUE D'APPRÉCIATIONS (abdAllah, 30/09) : la liste des phrases types sous
   le champ, bornée en hauteur ; la croix de retrait, petite. */
.mc-appr-banque [data-banque-liste] {
   max-height: 12rem;
   overflow-y: auto;
}

.mc-appr-banque .btn-link {
   color: var(--bs-body-color);
   white-space: normal;
   text-align: left;
   justify-content: flex-start;
   font-weight: 400;
   font-size: var(--fs-sm, .875rem);
}

.mc-appr-banque .btn-link:hover {
   color: var(--bs-primary);
}

.mc-banque-retirer {
   font-size: .6rem;
   margin-top: .3rem;
}

/* VUE SEMAINE DES DEVOIRS (abdAllah, 30/09) - enseignement/mbr-devoirs.php :
   sept colonnes sur grand écran, une par jour ; empilées sur téléphone, où les
   jours sans devoir se réduisent à leur en-tête. */
.mc-semaine-devoirs {
   display: grid;
   grid-template-columns: repeat(7, minmax(0, 1fr));
   gap: .5rem;
}

.mc-semaine-jour {
   border: 1px solid var(--line, #dee2e6);
   border-radius: .375rem;
   padding: .4rem;
   min-height: 6rem;
   display: flex;
   flex-direction: column;
   gap: .35rem;
}

.mc-semaine-aujourdhui {
   border-color: var(--bs-primary);
   background: var(--dc-12-t, rgba(6, 93, 137, .08));
}

.mc-semaine-entete {
   font-size: var(--fs-sm, .875rem);
   font-weight: 600;
}

.mc-semaine-entete span {
   font-weight: 400;
   color: var(--bs-secondary-color);
}

.mc-semaine-rien {
   color: var(--bs-secondary-color);
   font-size: var(--fs-sm, .875rem);
}

.mc-semaine-devoir {
   display: flex;
   flex-wrap: wrap;
   align-items: center;
   gap: .2rem .35rem;
   padding: .3rem .4rem;
   border-radius: .3rem;
   background: var(--bs-body-bg);
   border: 1px solid var(--line, #dee2e6);
   color: var(--bs-body-color);
   text-decoration: none;
   font-size: var(--fs-sm, .875rem);
   line-height: 1.25;
}

.mc-semaine-devoir:hover {
   border-color: var(--bs-primary);
}

.mc-semaine-matiere {
   font-size: .72rem;
   font-weight: 600;
   color: var(--bs-secondary-color);
   width: 100%;
}

.mc-semaine-titre {
   flex: 1 1 auto;
   min-width: 0;
   overflow-wrap: anywhere;
}

@media (max-width: 991.98px) {
   .mc-semaine-devoirs {
      grid-template-columns: 1fr;
   }

   .mc-semaine-jour {
      min-height: 0;
   }

   .mc-semaine-jour.mc-semaine-vide {
      flex-direction: row;
      justify-content: space-between;
   }
}

/* APERÇU DU RACCOURCI (abdAllah, 01/10) - backend/shorts.php : la tuile de la
   barre (.sidebar-link), seule, sans enveloppe (01/10). Deux
   classes : elles l'emportent sur .mc-icone-apercu (tools.css), vignette carrée
   pensée pour une icône seule. Pas d'animation au survol : ce n'est pas un lien. */
.mc-short-apercu.mc-icone-apercu {
   display: inline-flex;
   flex-direction: column;
   width: auto;
   min-width: 62px;
   height: 55px;
   padding: .3rem .55rem;
   border-radius: 5px;
   border: 1px solid var(--dc-70-w, #518eac);
   background: var(--dc-10-w, #e6eff3);
   color: var(--dc-70-k, #044160);
   font-size: var(--fs-2xs);
   line-height: var(--lh-snug);
   white-space: nowrap;
}

.mc-short-apercu.sidebar-link:hover {
   transform: none;
   background: var(--dc-10-w, #e6eff3);
   color: var(--dc-70-k, #044160);
   border-color: var(--dc-70-w, #518eac);
}

[data-theme="dark"] .mc-short-apercu.mc-icone-apercu,
[data-theme="dark"] .mc-short-apercu.sidebar-link:hover {
   color: #ccc;
   background: var(--dc-10-1e1e1e, #1c2429);
   border-color: var(--dc-70-w, #518eac);
}

/* MENU « ⋮ » D'UNE LIGNE (abdAllah, 01/10) - Bulletins : l'icône suffit, sans
   la flèche ajoutée par .dropdown-toggle. */
.mc-sans-fleche::after {
   display: none;
}


/* QOUR'AN › RÉGLAGES (abdAllah, 02/10) : trois cadres distincts, de même
   hauteur - unités, couleurs des résultats, travail non fait. Chacun porte
   la bordure colorée des onglets ; sur ce volet, l'enveloppe commune des
   onglets disparaît (pas de cadre autour des cadres). */
.mc-qc-cadre { height: 100%; padding: .75rem; border: 1px solid var(--dc-30-w, #b4cedc); background: #fff; }
[data-theme="dark"] .mc-qc-cadre { background: #414040; color: #fff; }
.tab-content:has(> .tab-pane.active > .mc-qc-cadres) { border: 0; padding: 0; background: transparent; }

/* QOUR'AN - SUIVI (abdAllah, 02/10). */
/* Les quatre résultats d'une séance : étiquettes à cocher, à la couleur réglée. */
.mc-q-resultats .btn {
   border: 1px solid var(--q-fond);
   color: var(--text-color);
   background: transparent;
}
.mc-q-resultats .btn-check:checked + .btn {
   background: var(--q-fond);
   color: var(--q-texte);
   font-weight: var(--fw-bold);
}
.mc-q-resultats .btn-check:focus-visible + .btn { outline: 2px solid var(--dominante-color); outline-offset: 2px; }
/* Le moushaf dans la fenêtre d'une séance (choix du passage). */
.mc-q-cadre { display: block; width: 100%; height: 62vh; border: 1px solid var(--line); border-radius: var(--radius-field); }
/* Le texte d'un engagement : celui de l'éditeur, à lire. */
.mc-q-engagement img { max-width: 100%; height: auto; }
/* La bande des 60 hizb (60 à 1) : une case par hizb, verte si validé. */
/* Elle prend la largeur disponible (téléphone compris) : 60 cases égales. */
.mc-q-bande { display: flex; gap: 1px; width: 100%; max-width: 480px; min-width: 0; vertical-align: middle; }
.mc-q-bande i { display: block; flex: 1 1 0; min-width: 0; height: 16px; background: var(--panel-soft); border: 1px solid var(--line); }
.mc-q-bande-ligne { display: flex; align-items: center; gap: .4rem; min-width: 0; }
.mc-q-bande-ligne > span, .mc-q-bande-ligne > b { flex-shrink: 0; }
.mc-q-bande-ligne > .mc-q-bande { flex: 1 1 0; width: auto; }
.mc-q-bande i.est-valide { background: var(--dominante-color); border-color: var(--dominante-color); }
/* Les repères de la bande (abdAllah, 05/10) : 60, 1 et le dernier hizb validé portent leur numéro ;
   ces cases s'élargissent juste ce qu'il faut pour qu'il se lise. */
.mc-q-bande-reperes { max-width: 540px; }
.mc-q-bande-reperes i { height: 18px; }
.mc-q-bande i.est-repere { flex: 0 0 1.35rem; display: flex; align-items: center; justify-content: center;
   font-style: normal; font-size: .62rem; font-weight: var(--fw-bold, 700); line-height: 1; color: var(--text-muted, #6c757d); }
/* TROIS TEINTES (abdAllah, 05/10), toutes tirées de la couleur dominante, pour distinguer d'un coup d'œil :
   · les hizb validés : une teinte moyenne ;
   · un repère validé (60 ou 1) : fond très clair, numéro et bord à la couleur dominante ;
   · LE DERNIER hizb validé : la couleur dominante pleine, numéro blanc - là où l'élève en est. */
.mc-q-bande-reperes i.est-valide { background: color-mix(in srgb, var(--dominante-color) 55%, #fff); border-color: color-mix(in srgb, var(--dominante-color) 55%, #fff); }
.mc-q-bande i.est-repere.est-valide { background: color-mix(in srgb, var(--dominante-color) 14%, #fff); color: var(--dominante-color); border-color: var(--dominante-color); }
.mc-q-bande i.est-repere.est-dernier { background: var(--dominante-color); color: #fff; border-color: var(--dominante-color); }
/* Synthèse des validations : les classes à cocher, en badges de même largeur. L'en-tête des
   tableaux est celui de la charte (table-mc-entete, couleur dominante). */
.mc-q-synthese-case { display: flex; align-items: center; gap: .4rem; min-width: 0; }
.mc-q-synthese-case > .form-check-input { flex: 0 0 auto; margin: 0; float: none; }
.mc-q-synthese-case > label { flex: 1 1 0; min-width: 0; margin: 0; cursor: pointer; }
.mc-q-synthese-badge { display: block; width: 100%; text-align: center; border-radius: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* La bande est un bouton (abdAllah, 05/10) : un clic ouvre la liste des validations de l'élève. */
.mc-q-bande-bouton { display: block; width: 100%; padding: 0; border: 0; background: transparent; cursor: pointer; }
.mc-q-bande-bouton:hover .mc-q-bande, .mc-q-bande-bouton:focus-visible .mc-q-bande { outline: 2px solid var(--dominante-color); outline-offset: 2px; }
/* La palette de validation : 60 boutons, de 60 à 1. */
.mc-q-palette { display: grid; grid-template-columns: repeat(auto-fill, minmax(64px, 1fr)); gap: .4rem; }
.mc-q-palette label {
   display: flex; flex-direction: column; align-items: center; justify-content: center;
   min-height: 56px; padding: .25rem;
   border: 1px solid var(--line); border-radius: var(--radius-field);
   background: var(--panel); cursor: pointer; user-select: none;
   font-weight: var(--fw-bold); line-height: 1.2;
}
.mc-q-palette label small { font-weight: var(--fw-regular); font-size: var(--fs-2xs); }
.mc-q-palette .btn-check:checked + label { background: var(--state-success); border-color: var(--state-success); color: #fff; }
.mc-q-palette .btn-check:focus-visible + label { outline: 2px solid var(--dominante-color); outline-offset: 2px; }
.mc-q-palette.est-lecture label { cursor: default; }
/* Les chiffres clés de le bilan. */
.mc-q-chiffres { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: .6rem; }
.mc-q-chiffres > div { padding: .6rem .8rem; border: 1px solid var(--line); border-radius: var(--radius-field); background: var(--panel); }
.mc-q-chiffres b { display: block; font-size: var(--fs-xl); line-height: 1.2; }
.mc-q-chiffres span { font-size: var(--fs-xs); color: var(--slate); }
.mc-q-courbe svg { width: 100%; height: auto; }
/* LA COURBE EN MODE SOMBRE (abdAllah, 05/10) : plus de fond clair - la grille, les repères et les
   dates s'éclaircissent, et les tracés des exercices sont ravivés pour se lire sur le sombre.
   Le dessin lui-même (couleurs en attributs) ne change pas : il sert aussi au rapport PDF. */
[data-theme="dark"] .mc-q-courbe { background: transparent; }
[data-theme="dark"] .mc-q-courbe svg line { stroke: rgba(255, 255, 255, .14); }
[data-theme="dark"] .mc-q-courbe svg line[stroke-dasharray] { stroke: rgba(255, 255, 255, .45); }
[data-theme="dark"] .mc-q-courbe svg text { fill: #aab4c3; }
[data-theme="dark"] .mc-q-courbe svg polyline,
[data-theme="dark"] .mc-q-courbe svg circle { filter: brightness(1.7) saturate(1.15); }

/* TÉLÉPHONE D'ABORD (abdAllah, 02/10) : le module sert surtout sur téléphone. */
/* Une séance dans l'espace famille : trois lignes lisibles, l'action à droite. */
.mc-q-seance { display: grid; grid-template-columns: 1fr auto; gap: .15rem .6rem; align-items: center; }
.mc-q-seance > .mc-q-seance-tete { display: flex; flex-wrap: wrap; align-items: center; gap: .4rem; }
.mc-q-seance > .mc-q-seance-travail { grid-column: 1 / -1; }
.mc-q-seance > .mc-q-seance-detail { grid-column: 1 / -1; font-size: var(--fs-xs); color: var(--slate); }
/* Les actions d'une carte, sous son titre : des boutons pleins et larges. */
.mc-q-actions { display: flex; flex-wrap: wrap; gap: .5rem; }
.mc-q-actions > *, .mc-q-actions form > .btn { flex: 1 1 auto; }
.mc-q-actions form { display: flex; flex: 1 1 auto; }
/* La synthèse : sur téléphone, une fiche par élève au lieu d'un tableau large. */
.mc-q-synthese td.mc-q-synthese-bande { min-width: 300px; }
@media (max-width: 767.98px) {
   .mc-q-synthese thead { display: none; }
   .mc-q-synthese tr { display: grid; grid-template-columns: 1fr auto; gap: .1rem .5rem; padding: .5rem .6rem; border-bottom: 1px solid var(--line); }
   .mc-q-synthese td { display: block; padding: 0; border: 0; background: transparent !important; box-shadow: none !important; }
   .mc-q-synthese td.mc-q-synthese-id { grid-column: 1; grid-row: 1; }
   .mc-q-synthese td.mc-q-synthese-total { grid-column: 2; grid-row: 1 / span 2; align-self: center; }
   .mc-q-synthese td.mc-q-synthese-classe { grid-column: 1; font-size: var(--fs-xs); color: var(--slate); }
   .mc-q-synthese td.mc-q-synthese-bande { grid-column: 1 / -1; min-width: 0; margin-top: .25rem; }
   .mc-q-palette { grid-template-columns: repeat(6, 1fr); gap: .3rem; }
   .mc-q-palette label { min-height: 50px; }
   .mc-q-cadre { height: 70vh; height: 70dvh; }
   .mc-q-chiffres { grid-template-columns: repeat(2, 1fr); }
}
/* Une ligne d'élève, sur téléphone : l'avatar, le nom et l'essentiel. */
/* Élèves & séances, au téléphone : une fiche par élève - avatar et âge à
   gauche, le menu en haut à droite, liseré à la couleur du genre. */
.mc-q-fiche { display: flex; align-items: flex-start; gap: .6rem; }
.mc-q-fiche-avatar { flex: 0 0 auto; text-align: center; line-height: 1.2; }
.mc-q-fiche .mc-q-eleve-corps { flex: 1; min-width: 0; color: inherit; text-decoration: none; }
.mc-q-fiche .badge { margin-top: .15rem; white-space: normal; text-align: left; }
.mc-q-fiche-menu { flex: 0 0 auto; }

/* Menu déroulant en position fixe (Qour'an, liste du suivi) : la transition
   « all » du gabarit le faisait glisser depuis le haut de l'écran. */
.dropdown-menu.mc-menu-fixe {
   transition: none;
}

/* Qour'an, objectif sur une ligne : au téléphone, les listes se resserrent
   pour que la flèche ne recouvre pas le texte. */
@media (max-width: 575.98px) {
   [data-qe-objectif] .form-select {
      padding-left: .4rem;
      padding-right: 1.3rem;
      background-position: right .25rem center;
      text-overflow: ellipsis;
   }
   [data-qe-objectif] .form-control {
      padding-left: .25rem;
      padding-right: .25rem;
   }
}

/* Qour'an, liste des sourates de la fenêtre Paramètres : le nom arabe à
   droite, sans pastille, dans la police du moushaf (Hafs). */
#modalQouranEleve .mc-combo-option-sous-texte,
#modalQouranEleve .mc-combo-option[aria-selected="true"] .mc-combo-option-sous-texte,
#modalQouranTilawa .mc-combo-option-sous-texte,
#modalQouranTilawa .mc-combo-option[aria-selected="true"] .mc-combo-option-sous-texte {
   background: none;
   color: inherit;
   padding: 0;
   border-radius: 0;
   font-family: 'KFGQPC Hafs', 'Open Sans', sans-serif;
   font-size: 1.15rem;
   line-height: 1.2;
   direction: rtl;
}

/* Qour'an, passage de l'objectif, SUR DEUX RANGS (abdAllah, 03/10) : la
   sourate de début et « du » en haut, la sourate de fin et « au » en bas (le
   nombre de versets s'affiche dans le champ quantité). Chaque rang porte SA zone de message :
   deux fautes, deux messages, chacun sous son rang. 2 px entre les cases,
   coins arrondis aux seuls angles du bloc. */
.mc-qe-passage {
   display: grid;
   grid-template-columns: minmax(0, 1fr);
   gap: 2px;
}
.mc-qe-rang {
   grid-column: 1;
   display: grid;
   grid-template-columns: minmax(0, 1fr) 5rem;
   gap: 2px;
}
.mc-qe-rang > .mc-combo,
.mc-qe-rang > .form-select,
.mc-qe-rang > .form-control {
   border-radius: 0 !important;
   margin: 0 !important;
   min-width: 0;
   position: relative;
}
/* La liste habillée remplit sa case (elle se réduisait à sa flèche). */
.mc-qe-rang > .mc-combo { width: 100% !important; justify-self: stretch; }
.mc-qe-rang:first-child > :first-child { border-radius: 5px 0 0 0 !important; }
.mc-qe-rang:nth-child(2) > :first-child { border-radius: 0 0 0 5px !important; }
.mc-qe-rang > .invalid-feedback { grid-column: 1 / -1; margin-top: 0; }
/* Faute sur un verset : le message se centre sous la case du verset. */
.mc-qe-rang > .invalid-feedback.mc-qe-sous-verset { grid-column: 2; text-align: center; white-space: nowrap; justify-self: center; }
.mc-qe-rang:first-child > .form-control { border-radius: 0 5px 0 0 !important; }
.mc-qe-rang:nth-child(2) > .form-control { border-radius: 0 0 5px 0 !important; }

/* La sourate choisie, dans le champ fermé : le français à gauche, l'arabe à
   droite dans la police du moushaf (abdAllah, 03/10). */
.mc-qe-rang .mc-combo-value, #modalQouranTilawa .mc-combo-value { display: flex; align-items: baseline; justify-content: space-between; gap: .5rem; min-width: 0; }
.mc-qe-rang .mc-qe-fr, #modalQouranTilawa .mc-qe-fr { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mc-qe-rang .mc-qe-ar, #modalQouranTilawa .mc-qe-ar { flex: 0 0 auto; font-family: 'KFGQPC Hafs', 'Open Sans', sans-serif; font-size: 1.15rem; line-height: 1.2; direction: rtl; }
#modalQouranTilawa .input-group > .mc-combo { flex: 1 1 auto; width: 1% !important; min-width: 0; }

/* Qour'an, liste des sourates : une ligne sur deux teintée (abdAllah, 02/10).
   L'option survolée et l'option choisie gardent leur couleur. */
#modalQouranEleve .mc-combo-list .mc-combo-option:nth-child(even):not([aria-selected="true"]):not(.mc-combo-active),
#modalQouranTilawa .mc-combo-list .mc-combo-option:nth-child(even):not([aria-selected="true"]):not(.mc-combo-active) {
   background-color: var(--dc-7-w, rgba(0, 0, 0, .04));
}

/* Qour'an, « Choisir dans le moushaf » au bout du libellé : hors flux, posé
   au ras du champ (réglage d'abdAllah, 02/10). */
[data-qe-moushaf] {
   position: absolute;
   right: 0;
   bottom: 0;
   padding: 0 .6rem !important;
   min-height: 0;
}

/* Qour'an, fenêtre de séance (03/10) : quatre blocs distincts, encadrés ; une
   carte par exercice, à sa couleur. */
/* ENFANT / ADULTE (abdAllah, 04/10) : l'enfant sur fond blanc, l'adulte sur un fond
   grisé zébré - liste des élèves, bloc d'en-tête de l'élève, onglet de la fiche membre. */
.mc-q-adulte { background: repeating-linear-gradient(-45deg, #e9ecef, #e9ecef 8px, #f6f7f8 8px, #f6f7f8 16px) !important; }
.mc-q-adulte > .card-body { background: transparent; }
/* Dans la liste, l'ENFANT garde son badge blanc ; l'ADULTE a un badge grisé zébré -
   le badge seul, pas la ligne. */
/* Le badge « Adulte » : un fond gris uni, sans zébra (abdAllah, 05/10). */
.mc-q-badge-adulte { background: #ced4da !important; color: #212529 !important; }
[data-theme="dark"] .mc-q-adulte { background: repeating-linear-gradient(-45deg, rgba(255,255,255,.10), rgba(255,255,255,.10) 8px, rgba(255,255,255,.03) 8px, rgba(255,255,255,.03) 16px) !important; }
/* Bilan, le récapitulatif (abdAllah, 04/10) : points d'attention, barres et calendrier. */
.mc-q-attention { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr)); gap: .35rem .75rem; }
.mc-q-attention li { display: flex; align-items: flex-start; gap: .45rem; padding: .35rem .55rem; border-left: 4px solid; border-radius: .3rem; font-size: var(--fs-sm); }
.mc-q-attention li .ph-duotone { font-size: 1.15rem; line-height: 1.2; flex: 0 0 auto; }
.mc-q-attention-danger { border-color: #dc3545; background: color-mix(in srgb, #dc3545 10%, transparent); }
.mc-q-attention-danger .ph-duotone { color: #dc3545; }
.mc-q-attention-warning { border-color: #e8a33d; background: color-mix(in srgb, #e8a33d 12%, transparent); }
.mc-q-attention-warning .ph-duotone { color: #b7791f; }
.mc-q-attention-info { border-color: var(--dominante-color, #065d89); background: color-mix(in srgb, var(--dominante-color, #065d89) 8%, transparent); }
.mc-q-attention-info .ph-duotone { color: var(--dominante-color, #065d89); }
.mc-q-barres { display: flex; align-items: flex-end; gap: .3rem; height: 7.5rem; }
.mc-q-barre { flex: 1 1 0; min-width: 0; height: 100%; display: flex; flex-direction: column; justify-content: flex-end; align-items: center; gap: .15rem; }
.mc-q-barre b { font-size: var(--fs-xs); line-height: 1; min-height: .8rem; }
.mc-q-barre span { width: 100%; max-width: 2.2rem; min-height: 2px; border-radius: .25rem .25rem 0 0; background: linear-gradient(var(--dominante-color, #065d89), color-mix(in srgb, var(--dominante-color, #065d89) 65%, #fff)); }
.mc-q-barre small { font-size: var(--fs-2xs, .65rem); color: var(--slate-dim, #6c757d); white-space: nowrap; }
.mc-q-calendrier { display: flex; gap: 3px; overflow-x: auto; padding-bottom: .25rem; }
.mc-q-cal-jours, .mc-q-cal-semaine { display: grid; grid-template-rows: repeat(7, 1rem); gap: 3px; flex: 0 0 auto; }
.mc-q-cal-jours span { font-size: .6rem; line-height: 1rem; color: var(--slate-dim, #6c757d); padding-right: .2rem; }
.mc-q-cal-case { display: inline-block; width: 1rem; height: 1rem; border-radius: 3px; border: 1px solid #dee2e6; background: #f1f3f5; vertical-align: -2px; }
.mc-q-cal-case.est-hors { border-color: transparent; background: transparent; }
.mc-q-cal-case.est-present { background: color-mix(in srgb, var(--dominante-color, #065d89) 35%, #fff); border-color: color-mix(in srgb, var(--dominante-color, #065d89) 45%, #fff); }
.mc-q-cal-case.est-absent { background: #495057; border-color: #495057; }
/* Bilan : le bloc Tilawa garde la hauteur du bloc Hizb validés (abdAllah, 04/10). Côte à
   côte, sa carte est sortie du flux - c'est le bloc des hizb qui fixe la hauteur de la
   ligne - et son tableau défile ; empilés (écran étroit), le tableau est plafonné. */
.mc-q-tilawa-egal > .card { display: flex; flex-direction: column; }
.mc-q-tilawa-egal .table-responsive { flex: 1 1 auto; min-height: 0; overflow-y: auto; max-height: 24rem; }
.mc-q-tilawa-egal thead th { position: sticky; top: 0; z-index: 1; }
@media (min-width: 1200px) {
   .mc-q-tilawa-egal { position: relative; min-height: 12rem; }
   .mc-q-tilawa-egal > .card { position: absolute; top: 0; bottom: 0; left: calc(var(--bs-gutter-x) * .5); right: calc(var(--bs-gutter-x) * .5); height: auto !important; }
   .mc-q-tilawa-egal .table-responsive { max-height: none; }
}
/* Bilan, les hizb validés : des tuiles 3D (modèle `.mc-tuile`), à la suite et centrées. */
.mc-q-hizb-tuiles { display: flex; flex-wrap: wrap; justify-content: center; gap: .3rem; }
.mc-q-hizb-tuile { flex: 0 0 3.4rem; width: 3.4rem; aspect-ratio: auto; min-height: 3.1rem; gap: 0; justify-content: center; align-items: center; padding: .4rem .1rem; border-radius: .35rem; border-bottom-width: 3px; cursor: default; }
.mc-q-hizb-tuile b { font-size: .9rem; line-height: 1.1; }
.mc-q-hizb-tuile span { font-size: 7pt; line-height: 1.1; margin-top: 4px; opacity: .92; }
/* Non validé : la même tuile, grisée. */
.mc-q-hizb-non { background: linear-gradient(160deg, #f1f3f5 0%, #dee2e6 55%, #ced4da 100%); border-bottom-color: #adb5bd; color: #868e96; box-shadow: none; }
/* Validation des hizb : les mêmes tuiles, cliquables - la case décochée donne la tuile grisée. */
.mc-q-hizb-cases .mc-q-hizb-tuile { cursor: pointer; margin: 0; user-select: none; }
.mc-q-hizb-cases .btn-check:not(:checked) + .mc-q-hizb-tuile { background: linear-gradient(160deg, #f1f3f5 0%, #dee2e6 55%, #ced4da 100%); border-bottom-color: #adb5bd; color: #868e96; box-shadow: none; }
/* Trois états (abdAllah, 04/10) : non validé grisé ; VALIDÉ (enregistré) à la couleur
   dominante ; SÉLECTION (coché, pas encore enregistré) dans une teinte claire de la dominante. */
.mc-q-hizb-cases .btn-check:checked + .mc-q-hizb-tuile:not(.est-valide) {
   background: linear-gradient(160deg,
      color-mix(in srgb, var(--dominante-color, #065d89) 14%, #fff) 0%,
      color-mix(in srgb, var(--dominante-color, #065d89) 26%, #fff) 55%,
      color-mix(in srgb, var(--dominante-color, #065d89) 38%, #fff) 100%);
   border-bottom-color: color-mix(in srgb, var(--dominante-color, #065d89) 60%, #fff);
   color: var(--dominante-color, #065d89);
}
.mc-q-hizb-cases .btn-check:focus-visible + .mc-q-hizb-tuile { outline: 2px solid var(--dominante-color); outline-offset: 2px; }
.mc-q-hizb-cases .btn-check:disabled + .mc-q-hizb-tuile { cursor: default; }
.mc-q-hizb-anciens .mc-q-hizb-tuile { filter: grayscale(.85); opacity: .8; }
/* Le bloc d'en-tête de l'élève : le dégradé `.grady-light` de la charte est posé sur la carte
   (le liseré, à la couleur du genre, est posé en ligne) ; le corps le laisse voir. */
.mc-q-carnet-tete > .card-body { background: transparent; }
/* L'en-tête commun des fenêtres du module : l'élève à gauche, l'objet de la fenêtre à droite. */
.mc-q-modale-objet { margin-left: auto; padding: 0 .75rem; font-size: var(--fs-sm); font-weight: var(--fw-bold); color: var(--dominante-color); text-transform: uppercase; letter-spacing: .04em; text-align: right; }
.modal-header .mc-q-modale-objet + .btn-close { margin-left: 0; }
.mc-q-modale-objet { line-height: 1.2; }
.mc-q-modale-sous { display: block; font-size: var(--fs-xs); font-weight: var(--fw-normal, 400); color: var(--slate); text-transform: none; letter-spacing: 0; }
.mc-q-modale-sous:empty { display: none; }
/* Le titre du bloc s'écrit à la VERTICALE, dans une bande à la couleur dominante (abdAllah, 03/10). */
.mc-qs-bloc { border: 1px solid var(--line); border-radius: 8px; margin-bottom: .7rem; display: flex; overflow: hidden; }
.mc-qs-bloc-titre { flex: 0 0 1.7rem; background: var(--qs-teinte); color: var(--dominante-contrast, #fff); display: flex; align-items: center; justify-content: center; padding: .5rem 0; }
/* Une teinte par bloc, de la plus soutenue à la plus claire, toutes tirées de
   la couleur dominante ; la bordure du bloc prend la teinte de son titre. */
.mc-qs-bloc { --qs-teinte: var(--dominante-color); border-color: var(--qs-teinte); }
.mc-qs-bloc-1 { --qs-teinte: color-mix(in srgb, var(--dominante-color) 50%, #000); }
.mc-qs-bloc-2 { --qs-teinte: color-mix(in srgb, var(--dominante-color) 75%, #000); }
.mc-qs-bloc-4 { --qs-teinte: color-mix(in srgb, var(--dominante-color) 75%, #fff); }
.mc-qs-bloc-titre span { writing-mode: vertical-rl; transform: rotate(180deg); white-space: nowrap; font-size: var(--fs-xs); font-weight: var(--fw-bold); letter-spacing: .08em; text-transform: uppercase; }
.mc-qs-bloc-corps { flex: 1 1 auto; min-width: 0; padding: .6rem .7rem; }
.mc-qs-objectifs th, .mc-qs-objectifs td { font-size: var(--fs-sm); }
.mc-qs-objectifs thead th { width: 30%; }
.mc-qs-objectifs thead th:first-child { width: 10%; background: none; }
.mc-qs-ex { border: 1px solid var(--line); border-radius: 6px; overflow: hidden; height: 100%; display: flex; flex-direction: column; }
.mc-qs-ex-titre { display: flex; justify-content: space-between; align-items: center; padding: .3rem .6rem; font-weight: var(--fw-bold); }
.mc-qs-ex-corps { padding: .5rem; flex: 1 1 auto; }
/* SUIVI ADULTE : aucune signature - la colonne de la révision disparaît, et la
   remarque et la prochaine séance se partagent la ligne. */
.mc-qs-adulte .mc-qs-semaine th:last-child, .mc-qs-adulte .mc-qs-semaine td:last-child:not([colspan]) { display: none !important; }
@media (min-width: 992px) { .mc-qs-adulte .mc-qs-col-texte { flex: 1 1 0; width: auto; max-width: none; } }
/* TÉLÉPHONE (abdAllah, 04/10) : des CARTES à la place des tableaux de la fenêtre de séance. */
.mc-qs-obj-cartes { display: grid; gap: .5rem; }
.mc-qs-obj-carte { border: 1px solid var(--line); border-radius: 6px; overflow: hidden; background: #fff; }
.mc-qs-obj-carte-titre { padding: .25rem .6rem; font-weight: var(--fw-bold); }
.mc-qs-obj-carte dl { display: grid; grid-template-columns: auto 1fr; gap: .15rem .75rem; padding: .4rem .6rem; font-size: var(--fs-sm); }
.mc-qs-obj-carte dt { font-weight: var(--fw-bold); }
.mc-qs-obj-carte dd { margin: 0; text-align: right; }
@media (max-width: 991.98px) {   /* sous 992 px d'écran, la fenêtre ne fait que 500 px */
   .mc-qs-semaine, .mc-qs-semaine tbody, .mc-qs-semaine tr, .mc-qs-semaine td { display: block; }
   .mc-qs-semaine { border: 0 !important; }
   .mc-qs-semaine thead { display: none; }
   /* Un jour = une carte : le jour et sa case, la date et la signature, puis Jadid et Qadim. */
   .mc-qs-semaine tbody tr { display: grid; grid-template-columns: auto auto 1fr auto; align-items: center; gap: .35rem .5rem;
      border: 1px solid var(--line); border-radius: 6px; padding: .5rem .6rem; margin-bottom: .5rem; background: #fff; }
   .mc-qs-semaine tbody tr > td { padding: 0; border: 0; background: none !important; box-shadow: none !important; }
   .mc-qs-semaine tbody tr > td:nth-child(1) { text-align: left !important; }
   .mc-qs-semaine tbody tr > td:nth-child(3) { color: var(--slate); }
   .mc-qs-semaine tbody tr > td:nth-child(4), .mc-qs-semaine tbody tr > td:nth-child(5) { grid-column: 1 / -1; }
   .mc-qs-semaine tbody tr > td[data-libelle]::before { content: attr(data-libelle); display: block; font-size: var(--fs-xs); color: var(--slate); }
   .mc-qs-semaine tbody tr > td:nth-child(6) { grid-column: 4; grid-row: 1; }
   .mc-qs-semaine tbody tr > td[colspan] { grid-column: 1 / -1; }
   #qsSemaine input[type="text"] { min-width: 0; }
}
/* L'en-tête de la révision : gris clair, pour ne pas concurrencer la bande du titre. */
/* L'en-tête de la révision de la semaine : le dégradé `.grady-light` de la charte. */
.table-mc-entete.mc-qs-semaine thead th { background: linear-gradient(#fff, #ddd) !important; color: var(--dominante-color, #065d89) !important; }
[data-theme="dark"] .table-mc-entete.mc-qs-semaine thead th { background: linear-gradient(var(--dc-60-333333, #184c67), var(--dc-60-k, #043852)) !important; color: var(--text-color, #f3f4f7) !important; }
#qsSemaine td.mc-qs-jour-nom { color: var(--dominante-color); font-weight: var(--fw-bold); }
#qsSemaine .mc-qs-jour-off td { color: var(--slate); }
#qsSemaine input[type="text"] { min-width: 9rem; }
.mc-qs-jour-off input[type="text"] { opacity: .55; }
.mc-qs-barre { height: 1.8rem; border-radius: 0; flex: 0 0 auto; position: relative; }
.mc-qs-barre-texte { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; font-size: var(--fs-sm); color: #212529; pointer-events: none; }
.mc-qs-barre-clair { color: #fff; clip-path: inset(0 100% 0 0); transition: clip-path .6s ease; }
/* Dégradé VERTICAL (clair en haut, teinte pleine en bas) et zébrures en biais. */
.mc-qs-barre .progress-bar { min-width: 0; padding: 0; background-color: var(--qs-barre, var(--dominante-color));
   background-image: linear-gradient(-45deg, rgba(255,255,255,.18) 25%, transparent 25%, transparent 50%, rgba(255,255,255,.18) 50%, rgba(255,255,255,.18) 75%, transparent 75%, transparent),
                     linear-gradient(180deg, color-mix(in srgb, var(--qs-barre, var(--dominante-color)) 70%, #fff), var(--qs-barre, var(--dominante-color)));
   background-size: 1.2rem 1.2rem, 100% 100%; }
.mc-qs-signature { height: auto; min-height: calc(6em + .75rem + 2px); font-size: var(--fs-sm); background: var(--bs-light, #f8f9fa); }
.mc-qs-bloc.bg-light .table, .mc-qs-bloc.bg-light .table > :not(caption) > * > * { --bs-table-bg: transparent; background-color: transparent; }

/* ══ MODE SOMBRE - RETOUCHES (abdAllah, 05/10) ═════════════════════════════════════════════
   Relevées sur les pages du module Qour'an. Les cinq premières règles touchent des composants
   COMMUNS au projet (barre et pied des tableaux, bouton secondaire, sous-titre, texte d'aide,
   liens de tableau) : ils n'avaient pas de teinte sombre et restaient clairs, ou illisibles. */
[data-theme="dark"] .mc-toolbar,
[data-theme="dark"] .mc-footer,
[data-theme="dark"] .mc-info { background: #1d2733 !important; color: #dfe6ee; }
[data-theme="dark"] .btn-secondary { background: rgba(255, 255, 255, .10); border-color: rgba(255, 255, 255, .18); color: #d9e8f1; }
[data-theme="dark"] .btn-secondary:hover,
[data-theme="dark"] .btn-secondary:focus-visible,
[data-theme="dark"] .btn-check:checked + .btn-secondary { background: rgba(255, 255, 255, .20); border-color: rgba(255, 255, 255, .35); color: #fff; }
[data-theme="dark"] .mc-sous-titre { color: #a9b4c6; }
[data-theme="dark"] .form-text { color: rgba(255, 255, 255, .62) !important; }
[data-theme="dark"] .table a:not(.btn):not(.badge):not(.dropdown-item) { color: #8cc8e6; }

/* Les cases de chiffres (KPI) : un fond sombre à la place du `bg-light`, le libellé lisible. */
[data-theme="dark"] .mc-kpi.bg-light { background: #1b2330 !important; }
/* LE FOND BLANC POSÉ EN LIGNE sur les cases de dix pages (abdAllah, 10/10) : en sombre, il cachait
   le libellé (éclairci pour le sombre) - le même fond sombre partout. */
[data-theme="dark"] .mc-kpi { background: #1b2330 !important; }
[data-theme="dark"] .mc-kpi .text-muted { color: rgba(255, 255, 255, .72) !important; }

/* Réglages : les libellés des cadres sur fond sombre. */
[data-theme="dark"] .mc-qc-cadre .form-label,
[data-theme="dark"] .mc-qc-cadre .mc-couleur-groupe-titre { color: #dfe7ee; }

/* Massahif : la barre du haut. */
[data-theme="dark"] .mc-moushaf .entete { background: #1d2733; color: #e7ebe8; }
[data-theme="dark"] .mc-moushaf .entete .titre { color: #e7ebe8; }

/* Hizb : la tuile non validée s'assombrit ; la sélection reste une teinte de la dominante. */
[data-theme="dark"] .mc-q-hizb-non,
[data-theme="dark"] .mc-q-hizb-cases .btn-check:not(:checked) + .mc-q-hizb-tuile {
   background: linear-gradient(160deg, #3a4250 0%, #2f3642 55%, #262c36 100%); border-bottom-color: #1b2028; color: #9aa5b5; }
[data-theme="dark"] .mc-q-hizb-cases .btn-check:checked + .mc-q-hizb-tuile:not(.est-valide) {
   background: color-mix(in srgb, var(--dominante-color, #065d89) 45%, #2f3642); border-bottom-color: var(--dominante-color, #065d89); color: #fff; }

/* Le badge « Adulte » : gris uni, en sombre. */
[data-theme="dark"] .mc-q-badge-adulte { background: #5a6472 !important; color: #fff !important; }

/* La bande des hizb : les repères sur un fond sombre plutôt que blanc. */
[data-theme="dark"] .mc-q-bande i.est-repere { color: #c3cbd8; }
[data-theme="dark"] .mc-q-bande i.est-repere.est-valide { background: color-mix(in srgb, var(--dominante-color) 30%, #1b2330); color: #fff; }
[data-theme="dark"] .mc-q-bande i.est-repere.est-dernier { background: var(--dominante-color); color: #fff; }
/* Le chiffre et l'icône d'une case : la couleur de la case, éclaircie pour se lire sur le sombre
   (le violet du hifdh ou la dominante y disparaissaient). */
[data-theme="dark"] .mc-kpi .card-body > div:first-child,
[data-theme="dark"] .mc-kpi > .ph-duotone { color: color-mix(in srgb, var(--mc-kpi, #9ec5fe) 50%, #fff) !important; }
[data-theme="dark"] .mc-kpi > .ph-duotone { opacity: .55 !important; }
/* Synthèse des validations : l'identifiant (lien) et « Tout sélectionner » lisibles sur le sombre. */
[data-theme="dark"] .mc-q-synthese .mc-q-synthese-id a { color: #8cc8e6; }
[data-theme="dark"] #formQouranSynthese .form-check-label { color: #dfe7ee; }
/* Un badge de classe ne s'étire pas sur toute la page quand il n'y a qu'une filière. */
.mc-q-synthese-case > label { max-width: 14rem; }

/* ══ QOUR'AN - LA NOTICE (abdAllah, 05/10) : un parcours d'étapes numérotées, reliées par un trait. */
.mc-q-notice-accroche { display: flex; align-items: center; gap: .6rem; margin: 0 0 1rem; font-size: 1.05rem; color: var(--dominante-color); font-weight: var(--fw-bold, 700); }
.mc-q-notice-accroche .ph-duotone { font-size: 1.8rem; flex: 0 0 auto; }
.mc-q-notice-parcours { list-style: none; margin: 0; padding: 0; }
.mc-q-notice-etape { position: relative; display: flex; gap: .9rem; padding-bottom: 1rem; }
/* Le trait du chemin, d'un numéro au suivant. */
.mc-q-notice-etape::before { content: ''; position: absolute; left: 1.1rem; top: 2.3rem; bottom: 0; width: 2px;
   background: repeating-linear-gradient(to bottom, color-mix(in srgb, var(--dominante-color) 45%, transparent) 0 6px, transparent 6px 11px); }
.mc-q-notice-etape:last-child { padding-bottom: 0; }
.mc-q-notice-etape:last-child::before { display: none; }
.mc-q-notice-numero { flex: 0 0 2.2rem; width: 2.2rem; height: 2.2rem; display: flex; align-items: center; justify-content: center; border-radius: 50%;
   background: var(--dominante-color); color: #fff; font-weight: var(--fw-bold, 700); font-size: 1rem; box-shadow: 0 2px 0 color-mix(in srgb, var(--dominante-color) 65%, #000); z-index: 1; }
.mc-q-notice-carte { flex: 1 1 0; min-width: 0; padding: .7rem .9rem; border: 1px solid var(--line, #dee2e6); border-left: 4px solid var(--dominante-color);
   border-radius: .4rem; background: var(--panel, #fff); }
.mc-q-notice-titre { display: flex; align-items: center; gap: .45rem; margin: 0 0 .35rem; font-size: 1.05rem; font-weight: var(--fw-bold, 700); color: var(--dominante-color); }
.mc-q-notice-titre .ph-duotone { font-size: 1.35rem; flex: 0 0 auto; }
.mc-q-notice-carte p .ph-duotone { vertical-align: -.15em; }
.mc-q-notice-astuce { display: inline-flex; align-items: flex-start; gap: .35rem; padding: .2rem .55rem; border-radius: .35rem; font-size: var(--fs-sm, .875rem);
   background: color-mix(in srgb, #ffc107 18%, transparent); }
.mc-q-notice-astuce .ph-duotone { color: #c98a00; font-size: 1.1rem; flex: 0 0 auto; }
.mc-q-notice-fin .mc-q-notice-numero { background: #198754; box-shadow: 0 2px 0 #0f5132; }
.mc-q-notice-fin .mc-q-notice-carte { border-left-color: #198754; }
[data-theme="dark"] .mc-q-notice-accroche, [data-theme="dark"] .mc-q-notice-titre { color: #8cc8e6; }
[data-theme="dark"] .mc-q-notice-astuce .ph-duotone { color: #ffcd39; }

/* PARENTS/PROFS - « Mes rendez-vous » (abdAllah, 07/10) : les créneaux en TUILES DÉGRADÉES (modèle `.mc-tuile`),
   l'heure de début en gras, celle de fin en petit. Libre : teinte claire de la dominante ; celui de l'élève :
   dominante pleine ; déjà réservé : grisé. */
.mc-pp-tuiles { display: flex; flex-wrap: wrap; gap: .35rem; }
.mc-pp-tuile { flex: 0 0 3.9rem; width: 3.9rem; aspect-ratio: auto; min-height: 3rem; gap: 0; padding: .35rem .1rem; border-radius: .35rem; border-width: 0 0 3px; font: inherit; cursor: pointer;
   background: linear-gradient(160deg,
      color-mix(in srgb, var(--dominante-color, #065d89) 14%, #fff) 0%,
      color-mix(in srgb, var(--dominante-color, #065d89) 26%, #fff) 55%,
      color-mix(in srgb, var(--dominante-color, #065d89) 38%, #fff) 100%);
   border-bottom-color: color-mix(in srgb, var(--dominante-color, #065d89) 60%, #fff);
   color: var(--dominante-color, #065d89); }
/* Début au-dessus, fin en dessous - même quand le script d'envoi enveloppe le contenu du bouton. */
.mc-pp-tuile b, .mc-pp-tuile small { display: block; }
.mc-pp-tuile > span { display: flex; flex-direction: column; align-items: center; }
.mc-pp-tuile b { font-size: .92rem; line-height: 1.1; }
.mc-pp-tuile small { font-size: 7.5pt; line-height: 1.1; margin-top: 3px; opacity: .85; }
button.mc-pp-tuile:not(:disabled):hover, button.mc-pp-tuile:not(:disabled):focus-visible { transform: translateY(-2px); filter: brightness(1.04); }
button.mc-pp-tuile:not(:disabled):active { transform: translateY(2px); border-bottom-width: 1px; }
.mc-pp-tuile.est-mien { cursor: default; color: #fff;
   background: linear-gradient(160deg,
      color-mix(in srgb, var(--dominante-color, #065d89) 78%, #fff) 0%,
      var(--dominante-color, #065d89) 55%,
      color-mix(in srgb, var(--dominante-color, #065d89) 72%, #000) 100%);
   border-bottom-color: color-mix(in srgb, var(--dominante-color, #065d89) 55%, #000); }
.mc-pp-tuile.est-pris, .mc-pp-tuile:disabled { cursor: not-allowed; background: linear-gradient(160deg, #f1f3f5 0%, #dee2e6 55%, #ced4da 100%); border-bottom-color: #adb5bd; color: #868e96; box-shadow: none; }
.mc-pp-tuile.est-suite { outline: 2px solid var(--dominante-color, #065d89); outline-offset: -2px; }
[data-theme="dark"] .mc-pp-tuile.est-pris, [data-theme="dark"] .mc-pp-tuile:disabled { background: linear-gradient(160deg, #3a3f44 0%, #2f3338 100%); border-bottom-color: #23262a; color: #8a9199; }
/* Le voyant d'une réunion : vert, le rendez-vous est pris ; orange, il reste à prendre ; gris, réservations fermées. */
.mc-pp-voyant { display: inline-block; width: .7rem; height: .7rem; border-radius: 50%; vertical-align: middle; box-shadow: 0 0 0 2px rgba(0, 0, 0, .06); }

/* ══ NOTICE DÉTAILLÉE D'UN MODULE (abdAllah, 08/10) : recherche, sommaire, rubriques dépliables par page. */
.mc-nd-recherche { max-width: 34rem; margin: 0 0 1rem; }
.mc-nd-resultat { margin: .35rem 0 0; font-size: var(--fs-sm, .875rem); color: var(--dominante-color); font-weight: var(--fw-bold, 700); }
.mc-nd.est-recherche .mc-nd-onglets, .mc-nd.est-recherche .mc-nd-sommaire,
.mc-nd.est-recherche .mc-q-notice-accroche, .mc-nd.est-recherche .mc-nd-intro { display: none; }
.mc-nd.est-recherche .tab-content > .tab-pane { display: block; opacity: 1; }
::highlight(mc-nd-trouve) { background: #ffe066; color: #000; }
.mc-nd-intro { margin: 0 0 1rem; padding: .7rem .9rem; border-left: 4px solid var(--dominante-color); border-radius: .35rem;
   background: color-mix(in srgb, var(--dominante-color) 6%, transparent); }
.mc-nd-intro > :last-child { margin-bottom: 0; }
.mc-nd-sommaire { margin: 0 0 1rem; padding: .7rem .9rem; border: 1px solid var(--line, #dee2e6); border-radius: .4rem; }
.mc-nd-sommaire-titre { display: block; margin-bottom: .35rem; font-weight: var(--fw-bold, 700); color: var(--dominante-color); }
.mc-nd-sommaire-titre .ph-duotone { font-size: 1.3rem; vertical-align: -.2em; }
.mc-nd-sommaire ol { margin: 0; padding-left: 1.4rem; columns: 2 18rem; column-gap: 2rem; }
.mc-nd-sommaire li { break-inside: avoid; padding: .1rem 0; }
.mc-nd-sommaire a { text-decoration: none; }
.mc-nd-sommaire a .ph-duotone { color: var(--dominante-color); vertical-align: -.1em; }
.mc-nd-page { margin: 0 0 .6rem; border: 1px solid var(--line, #dee2e6); border-left: 4px solid var(--dominante-color); border-radius: .4rem; scroll-margin-top: 5rem; }
.mc-nd-page > summary { display: flex; align-items: center; gap: .8rem; padding: .6rem .9rem; cursor: pointer; list-style: none; }
.mc-nd-page > summary::-webkit-details-marker { display: none; }
.mc-nd-page[open] > summary { border-bottom: 1px solid var(--line, #dee2e6); background: color-mix(in srgb, var(--dominante-color) 6%, transparent); }
.mc-nd-numero { flex: 0 0 2rem; width: 2rem; height: 2rem; display: flex; align-items: center; justify-content: center; border-radius: 50%;
   background: var(--dominante-color); color: #fff; font-weight: var(--fw-bold, 700); }
.mc-nd-entete { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.mc-nd-titre { font-size: 1.05rem; font-weight: var(--fw-bold, 700); color: var(--dominante-color); }
.mc-nd-titre .ph-duotone { font-size: 1.3rem; vertical-align: -.2em; }
.mc-nd-qui { font-size: var(--fs-sm, .875rem); color: var(--bs-secondary-color, #6c757d); }
.mc-nd-qui .ph-duotone { vertical-align: -.15em; }
.mc-nd-fleche { font-size: 1.3rem; color: var(--dominante-color); transition: transform .2s; }
.mc-nd-page[open] .mc-nd-fleche { transform: rotate(180deg); }
.mc-nd-corps { padding: .9rem; }
.mc-nd-resume { display: flex; flex-wrap: wrap; align-items: flex-start; gap: .6rem 1rem; margin-bottom: .8rem; }
.mc-nd-resume > div { flex: 1 1 24rem; }
.mc-nd-resume > div > :last-child { margin-bottom: 0; }
.mc-nd-captures { display: flex; flex-wrap: wrap; gap: 1rem; margin: 0 0 1rem; }
.mc-nd-captures figure { flex: 1 1 22rem; max-width: 100%; margin: 0; }
.mc-nd-captures img { display: block; max-width: 100%; height: auto; margin: 0 auto; border: 1px solid var(--line, #dee2e6); border-radius: .35rem;
   box-shadow: 0 2px 8px rgba(0, 0, 0, .08); }
/* PROPORTIONS RÉSERVÉES (abdAllah, 09/10) : le PHP pose width/height, d'où le navigateur tire les proportions.
   Sans eux (dimensions illisibles sur le serveur), un 16/9 provisoire réserve la place jusqu'au chargement. */
.mc-nd-captures img:not([width]) { aspect-ratio: auto 16 / 9; }
.mc-nd-captures figcaption { margin-top: .35rem; text-align: center; font-size: var(--fs-sm, .875rem); color: var(--bs-secondary-color, #6c757d); }
.mc-nd-sous-titre { margin: 1rem 0 .5rem; font-size: 1rem; font-weight: var(--fw-bold, 700); color: var(--dominante-color); }
.mc-nd-sous-titre .ph-duotone { font-size: 1.3rem; vertical-align: -.2em; }
.mc-nd-sous-titre small { font-weight: normal; color: var(--bs-secondary-color, #6c757d); }
.mc-nd-etapes, .mc-nd-regles { margin: 0 0 .5rem; padding-left: 1.4rem; }
.mc-nd-etapes li, .mc-nd-regles li { margin-bottom: .35rem; }
.mc-nd-etapes ul, .mc-nd-regles ul { margin: .25rem 0 0; }
.mc-nd-champs th[scope=row] { white-space: nowrap; font-weight: var(--fw-bold, 700); }
.mc-nd-champs td, .mc-nd-champs th { vertical-align: top; }
.mc-nd-faq details { margin-bottom: .4rem; border: 1px solid var(--line, #dee2e6); border-radius: .35rem; }
.mc-nd-faq summary { padding: .45rem .7rem; cursor: pointer; font-weight: var(--fw-bold, 700); }
.mc-nd-faq summary .ph-duotone { color: var(--dominante-color); vertical-align: -.15em; }
.mc-nd-faq details > div { padding: 0 .7rem .6rem 1.9rem; }
.mc-nd-faq details > div > :last-child { margin-bottom: 0; }
.mc-nd-installation { margin-top: 1rem; padding: .2rem .9rem .5rem; border: 1px dashed #c98a00; border-radius: .35rem; background: rgba(255, 193, 7, .07); }
.mc-nd-installation .mc-nd-sous-titre, .mc-nd-installation .mc-nd-sous-titre .ph-duotone { color: #a26f00; }
.mc-nd-installation ul { margin: 0; padding-left: 1.4rem; }
.mc-nd-installation li { margin-bottom: .3rem; }
.mc-nd kbd { background: var(--dominante-color); }
[data-theme="dark"] .mc-nd-titre, [data-theme="dark"] .mc-nd-sous-titre, [data-theme="dark"] .mc-nd-sommaire-titre { color: #8cc8e6; }
[data-theme="dark"] .mc-nd-installation .mc-nd-sous-titre, [data-theme="dark"] .mc-nd-installation .mc-nd-sous-titre .ph-duotone { color: #ffcd39; }
/* LE SOMMAIRE SE DISTINGUE (abdAllah, 11/10) : un encart teinté de la couleur dominante, son titre en bandeau,
   chaque entrée en ligne cliquable qui s'éclaire au survol. */
.mc-nd-sommaire {
   padding: 0; overflow: hidden; border: 1px solid color-mix(in srgb, var(--dominante-color) 30%, transparent);
   border-radius: .5rem; background: color-mix(in srgb, var(--dominante-color) 5%, var(--bs-body-bg, #fff));
   box-shadow: rgba(0, 0, 0, .08) 0 2px 8px;
}
.mc-nd-sommaire-titre {
   margin: 0; padding: .5rem .9rem; color: #fff !important;
   background: linear-gradient(color-mix(in srgb, var(--dominante-color) 72%, #fff), var(--dominante-color));
}
.mc-nd-sommaire ol { padding: .5rem .9rem .6rem 2.3rem; }
.mc-nd-sommaire li::marker { color: var(--dominante-color); font-weight: var(--fw-bold, 700); }
.mc-nd-sommaire a .ph-duotone { font-size: 1.1rem; line-height: 1; vertical-align: middle; }
.mc-nd-sommaire a { display: inline-flex; align-items: center; gap: .35rem; vertical-align: middle; padding: .1rem .4rem; margin-left: -.4rem; border-radius: .3rem; transition: background .15s ease, transform .15s ease; }
.mc-nd-sommaire a:hover, .mc-nd-sommaire a:focus-visible { background: color-mix(in srgb, var(--dominante-color) 14%, transparent); transform: translateX(3px); }
/* L'EN-TÊTE D'UNE RUBRIQUE AU SURVOL (abdAllah, 11/10) : un fond teinté, la rubrique s'élève, le numéro grossit
   et le titre glisse légèrement. */
.mc-nd-page { transition: box-shadow .2s ease, transform .2s ease; }
.mc-nd-page > summary { transition: background .2s ease; border-radius: .3rem; background: #f5f5f5; }
[data-theme="dark"] .mc-nd-page > summary { background: rgba(255, 255, 255, .04); }
.mc-nd-page > summary .mc-nd-numero { transition: transform .2s ease, box-shadow .2s ease; }
.mc-nd-page > summary .mc-nd-titre { transition: transform .2s ease; }
.mc-nd-page:hover { box-shadow: rgba(0, 0, 0, .12) 0 4px 12px; transform: translateY(-1px); }
.mc-nd-page > summary:hover, .mc-nd-page > summary:focus-visible { background: color-mix(in srgb, var(--dominante-color) 12%, transparent); outline: none; }
.mc-nd-page > summary:hover .mc-nd-numero, .mc-nd-page > summary:focus-visible .mc-nd-numero { transform: scale(1.12); box-shadow: 0 0 0 4px color-mix(in srgb, var(--dominante-color) 20%, transparent); }
.mc-nd-page > summary:hover .mc-nd-titre, .mc-nd-page > summary:focus-visible .mc-nd-titre { transform: translateX(4px); }
@media (prefers-reduced-motion: reduce) { .mc-nd-page, .mc-nd-page > summary .mc-nd-numero, .mc-nd-page > summary .mc-nd-titre, .mc-nd-sommaire a { transition: none; transform: none !important; } }

/* DEMANDE DE PAIEMENT (08/10) : le reste du formulaire grisé tant que le type manque.
   Le sélecteur de type est celui de la modale de versement (mc-type-choix, tools.css). */
.mc-dp-suite { min-width: 0; margin: 0; padding: 0; border: 0; transition: opacity .2s; }
.mc-dp-suite:disabled { opacity: .5; }

/* INTERRUPTEUR À TEXTE (08/10) : le libellé de l'état est écrit dans la piste
   (data-on coché, data-off sinon). Le case native reste là, invisible, pour le
   clavier et l'envoi du formulaire. Usage :
   <label class="mc-switch-texte"><input type="checkbox" …><span data-on="Test" data-off="Production"></span></label> */
.mc-switch-texte { position: relative; display: inline-flex; flex-shrink: 0; margin: 0; cursor: pointer; user-select: none; }
.mc-switch-texte input { position: absolute; opacity: 0; width: 1px; height: 1px; pointer-events: none; }
.mc-switch-texte span { position: relative; display: inline-flex; align-items: center; min-width: 7.2rem; height: 1.7rem;
   padding: 0 .75rem 0 1.85rem; border-radius: 2rem; background: var(--dominante-color); color: #fff;
   font-size: .78rem; font-weight: var(--fw-bold, 700); letter-spacing: .02em; transition: background-color .25s, padding .25s; }
.mc-switch-texte span::before { content: attr(data-off); }
.mc-switch-texte span::after { content: ""; position: absolute; top: .2rem; left: .2rem; width: 1.3rem; height: 1.3rem; border-radius: 50%;
   background: #fff; box-shadow: 0 1px 3px rgba(0, 0, 0, .25); transition: left .25s; }
.mc-switch-texte input:checked + span { justify-content: flex-start; padding: 0 1.85rem 0 .75rem; background: #d97706; }
.mc-switch-texte input:checked + span::before { content: attr(data-on); }
.mc-switch-texte input:checked + span::after { left: calc(100% - 1.5rem); }
.mc-switch-texte input:not(:checked) + span { justify-content: flex-end; }
.mc-switch-texte input:focus-visible + span { box-shadow: 0 0 0 .2rem var(--dc-30-t, rgba(6, 93, 137, .3)); }
.mc-switch-texte:hover span { filter: brightness(1.08); }
[data-theme="dark"] .mc-switch-texte span { background: var(--dc-80-999999, #23698c); }
[data-theme="dark"] .mc-switch-texte input:checked + span { background: #b86200; }

/* « Difficulté signalée » (08/10) : le badge d'une demande où le référent ne peut pas payer. */
.mc-badge-difficulte { background-color: #fd7e14; color: #fff; }

/* DEMANDE DE PAIEMENT › ADHÉSION (08/10) : les tuiles des mois, celles de la modale de
   versement de la Synthèse des adhésions (#vsPadMois), sur 6 colonnes. */
.mc-dp-pad {
   display: grid; grid-template-columns: repeat(6, 1fr); gap: .3rem;
   border: 1px solid rgba(var(--dominante-rgb, 6,93,137), .25); border-radius: .5rem; padding: .3rem;
}
.mc-dp-pad .mc-mois-btn { width: 100%; height: 3rem; margin: 0; font-size: .72rem; flex-direction: column; gap: .15rem; cursor: default; }
.mc-dp-pad .mc-mois-btn.libre:not(:disabled) { cursor: pointer; }
.mc-dp-pad .mc-mois-btn.libre:not(:disabled):hover { filter: brightness(1.05); box-shadow: inset 0 0 0 2px rgba(var(--dominante-rgb, 6,93,137), .5); }
.mc-dp-pad .mc-mois-btn:disabled { opacity: 1; }
.mc-dp-pad .vs-cout-mois { font-size: .6rem; opacity: .75; }
@media (max-width: 575.98px) { .mc-dp-pad { grid-template-columns: repeat(4, 1fr); } }


/* DEMANDE DE PAIEMENT › OPTION INDISPONIBLE (08/10) : seul le sélecteur de référent reste,
   pour en choisir un autre ; le message s'affiche dessous. */
.mc-dp-indispo > .row > :not(#dpBlocFoyer) { display: none !important; }

/* TRAIT VERTICAL ENTRE DEUX COLONNES (abdAllah, 08/10) - Paramètres › API, carte HelloAsso.
   À partir de md seulement : empilées, les colonnes n'en ont pas besoin. */
@media (min-width: 768px) {
   .mc-col-separee { border-left: 1px solid var(--bs-border-color); }
}

/* LE BOUTON OFFICIEL « Payer avec HelloAsso » (abdAllah, 08/10) - checkout/mbr-paiement.
   Styles fournis par HelloAsso (dev.helloasso.com › Bouton : Payer avec HelloAsso, version
   claire). LE VIOLET DE HELLOASSO REMPLACÉ (abdAllah, 08/10) par le dégradé `.grady-dark`
   de l'ERP : fond du libellé, bordures, survol et halo du focus. */
.HaPay {
  width: fit-content;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  -webkit-box-pack: center;
  -ms-flex-pack: center;
}

.HaPay * {
  font-family: "Open Sans", "Trebuchet MS", "Lucida Sans Unicode",
    "Lucida Grande", "Lucida Sans", Arial, sans-serif;
  transition: all 0.3s ease-out;
}

.HaPayButton {
  align-items: stretch;
  -webkit-box-pack: stretch;
  -ms-flex-pack: stretch;
  background: none;
  border: none;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  padding: 0;
  border-radius: 8px;
}

.HaPayButton:hover {
  cursor: pointer;
}

.HaPayButton:not(:disabled):focus {
  box-shadow: 0 0 0 0.25rem color-mix(in srgb, var(--dominante-color, #065d89) 25%, transparent);
  -webkit-box-shadow: 0 0 0 0.25rem color-mix(in srgb, var(--dominante-color, #065d89) 25%, transparent);
}

.HaPayButton:not(:disabled):hover .HaPayButtonLabel,
.HaPayButton:not(:disabled):focus .HaPayButtonLabel {
  background: var(--dominante-color, #065d89);
}

.HaPayButton:not(:disabled):hover .HaPayButtonLogo,
.HaPayButton:not(:disabled):focus .HaPayButtonLogo,
.HaPayButton:not(:disabled):hover .HaPayButtonLabel,
.HaPayButton:not(:disabled):focus .HaPayButtonLabel {
  border: 1px solid var(--dominante-color, #065d89);
}

.HaPayButton:disabled {
  cursor: not-allowed;
}

.HaPayButton:disabled .HaPayButtonLogo,
.HaPayButton:disabled .HaPayButtonLabel {
  border: 1px solid #d1d6de;
}

.HaPayButtonLogo {
  background-color: #ffffff;
  border: 1px solid var(--dominante-color, #065d89);
  border-top-left-radius: 8px;
  border-bottom-left-radius: 8px;
  padding: 10px 16px;
  width: 30px;
}

.HaPayButtonLabel {
  align-items: center;
  -webkit-box-pack: center;
  -ms-flex-pack: center;
  justify-content: space-between;
  column-gap: 5px;
  background: var(--dominante-color, #065d89);
  background: linear-gradient(color-mix(in srgb, var(--dominante-color, #065d89) 72%, #fff), var(--dominante-color, #065d89));
  border: 1px solid var(--dominante-color, #065d89);
  border-top-right-radius: 8px;
  border-bottom-right-radius: 8px;
  color: #ffffff;
  font-size: 16px;
  font-weight: 800;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  padding: 0 16px;
}

.HaPayButton:disabled .HaPayButtonLabel {
  background: #d1d6de;   /* « background » : le dégradé serait resté par-dessus */
  color: #505870;
}

.HaPaySecured {
  align-items: center;
  -webkit-box-pack: center;
  -ms-flex-pack: center;
  justify-content: space-between;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  column-gap: 5px;
  padding: 8px 16px;
  font-size: 12px;
  font-weight: 600;
  color: #2e2f5e;
}

.HaPay svg {
  fill: currentColor;
}

/* LE LOGO DU BOUTON HELLOASSO (08/10) : le code de HelloAsso suppose des boîtes
   « content-box » ; Bootstrap les met en « border-box », et la largeur de 30px absorbait
   alors les 32px de marge intérieure - le logo disparaissait. */
.HaPay img { box-sizing: content-box; }

/* LES CARTES DES ÉVÉNEMENTS (abdAllah, 09/10) - events/evenements.php : coins arrondis, ombre
   sombre ; l'image au format 1130 / 600, qui s'agrandit doucement quand on la survole.
   NI `overflow: hidden` NI `transform` SUR LA CARTE : le premier coupait le menu d'actions, le
   second (une transformation crée un repère pour `position: fixed`) le déplaçait en fin de
   survol. L'arrondi du haut est porté par l'image elle-même. */
.mc-ev-carte {
   border: 0;
   border-radius: .75rem;
   box-shadow: 0 .35rem 1rem rgba(0, 0, 0, .28);
}
.mc-ev-visuel {
   aspect-ratio: 1130 / 600;
   overflow: hidden;
   border-radius: .75rem .75rem 0 0;
   background: var(--bs-light);
}
/* UNE OMBRE AU BAS DE L'IMAGE SEULEMENT (09/10) - la carte de la liste et le bloc de la fiche
   (events/evenement.php) : l'étalement négatif la retire des côtés. */
.mc-ev-visuel,
.mc-ev-ombre-bas {
   position: relative;
   z-index: 1;
   box-shadow: 0 7px 10px -5px rgba(0, 0, 0, .6);
}
.mc-ev-visuel img {
   width: 100%;
   height: 100%;
   object-fit: cover;
   display: block;
   transition: transform .4s ease;
}
/* LE SURVOL porte sur l'image seule, pas sur la carte. */
.mc-ev-visuel:hover img { transform: scale(1.06); }

/* LES TARIFS EN TUILES (abdAllah, 09/10) - events/evenements.php : la tuile du projet
   (`.mc-tuile`) en petit, comme celles des hizb ; les externes dans une teinte claire. */
.mc-ev-tarif {
   width: 5.4rem;
   aspect-ratio: auto;
   min-height: 3.1rem;
   gap: 0;
   padding: .35rem .3rem;
   border-radius: .35rem;
   border-bottom-width: 3px;
   cursor: default;
}
.mc-ev-tarif span { font-size: 7pt; line-height: 1.1; opacity: .92; text-transform: uppercase; letter-spacing: .03em; }
.mc-ev-tarif b    { font-size: .85rem; line-height: 1.2; margin-top: 3px; white-space: nowrap; }
.mc-ev-tarif-ext {
   background: linear-gradient(160deg,
      color-mix(in srgb, var(--dominante-color, #065d89) 14%, #fff) 0%,
      color-mix(in srgb, var(--dominante-color, #065d89) 26%, #fff) 55%,
      color-mix(in srgb, var(--dominante-color, #065d89) 38%, #fff) 100%);
   border-bottom-color: color-mix(in srgb, var(--dominante-color, #065d89) 60%, #fff);
   color: var(--dominante-color, #065d89);
}

/* LE DESCRIPTIF DÉPLIANT D'UN ÉVÉNEMENT (abdAllah, 09/10) - liste et fiche : 2 lignes, puis
   « Lire la suite » (inc/scripts-descriptif-evenement.php). */
.mc-ev-descriptif {
   display: -webkit-box;
   -webkit-line-clamp: 2;
   -webkit-box-orient: vertical;
   overflow: hidden;
}
.mc-ev-descriptif.est-deplie {
   display: block;
   -webkit-line-clamp: unset;
   overflow: visible;
}
.mc-ev-descriptif > :last-child { margin-bottom: 0; }
/* LE DESCRIPTIF EN THÈME SOMBRE (abdAllah, 10/10) : un texte clair, et les couleurs posées dans le
   texte (un collage depuis un traitement de texte garde souvent un noir) cèdent au thème. */
[data-theme="dark"] .mc-ev-descriptif,
[data-theme="dark"] .mc-ev-texte { color: #d6dee6 !important; }
[data-theme="dark"] .mc-ev-descriptif [style*="color"],
[data-theme="dark"] .mc-ev-texte [style*="color"],
[data-theme="dark"] .mc-ev-descriptif font[color],
[data-theme="dark"] .mc-ev-texte font[color] { color: inherit !important; }
.mc-ev-deplier { font-size: var(--fs-xs, .75rem); text-decoration: none; }
/* LA LISTE (10/10) : déplié, le descriptif ne dépasse pas la hauteur de l'écran ; il défile. */
.mc-ev-descriptif-defile .mc-ev-descriptif.est-deplie {
   max-height: 40vh;
   overflow-y: auto;
   padding-right: .25rem;
}

/* LE DÉCOMPTE AVANT L'ÉVÉNEMENT (abdAllah, 10/10) - sous les infos des cartes de la liste : des
   chiffres à chasse fixe, pour que le texte ne danse pas à chaque seconde. */
.mc-ev-decompte-bloc { font-variant-numeric: tabular-nums; white-space: nowrap; }
/* EN COURS (abdAllah, 10/10) : le bloc du décompte de la liste passe au vert ; l'indicateur du
   décompte de la FICHE clignote tant que l'événement se déroule. */
.grady-dark.mc-ev-encours {
   background: #198754 !important;
   background: linear-gradient(color-mix(in srgb, #198754 72%, #fff), #198754) !important;
}
/* TOUT L'INDICATEUR CLIGNOTE (abdAllah, 10/10) - le cadre, le texte et l'icône s'effacent puis
   reviennent, sur un fond vert clair. Sans exception « animations réduites » : c'est voulu. */
@keyframes mc-kpi-clignote {
   0%, 100% { opacity: 1; }
   50%      { opacity: .15; }
}
.card.mc-kpi.mc-kpi-clignote {
   background-color: #d1e7dd !important;
   animation: mc-kpi-clignote 1s ease-in-out infinite;
}

/* LE TITRE ET LA DATE SUR L'IMAGE (abdAllah, 10/10) - cartes de la liste et fiche : le titre en
   blanc ombré, la date dans une pastille claire, sur un voile sombre en bas de l'image. Les tailles
   suivent la LARGEUR DE L'IMAGE (cqi : unités de conteneur), du téléphone au grand écran. */
.mc-ev-visuel { container-type: inline-size; }
.mc-ev-surimage {
   position: absolute;
   inset: auto 0 0 0;
   display: flex;
   flex-direction: column;
   align-items: flex-start;
   gap: .35rem;
   padding: 2.5rem 5cqi 5cqi;
   background: linear-gradient(transparent, rgba(0, 0, 0, .55));
   pointer-events: none;
}
.mc-ev-surimage-titre {
   max-width: 100%;
   color: #fff;
   font-weight: 800;
   font-size: clamp(1rem, 7.5cqi, 2.2rem);
   line-height: 1.1;
   text-shadow: 0 2px 4px rgba(0, 0, 0, .6);
   display: -webkit-box;
   -webkit-line-clamp: 2;
   -webkit-box-orient: vertical;
   overflow: hidden;
}
.mc-ev-surimage-date {
   max-width: 100%;
   padding: .15rem .65rem;
   border-radius: 2rem;
   background: rgba(255, 255, 255, .92);
   color: #1d2330;
   font-weight: 600;
   font-size: clamp(.7rem, 3.6cqi, 1rem);
   white-space: nowrap;
   overflow: hidden;
   text-overflow: ellipsis;
}
/* LE PIED DES CARTES D'ÉVÉNEMENT (10/10) : le descriptif ; les coins du bas suivent la carte. */
.mc-ev-carte > .card-footer { border-radius: 0 0 .75rem .75rem; padding: .6rem 1rem; }

/* LE FLYER DE L'ESPACE MEMBRE (abdAllah, 10/10) - events/mbr-evenements.php : un cadre au format
   690 × 410 ; l'affiche entière (contain) sur un fond flouté tiré d'elle-même, quel que soit son
   format - une affiche en hauteur n'envahit plus la carte. */
/* CARTE MEMBRE ARRONDIE (abdAllah, 10/10) : le flyer suit l'arrondi du haut. */
.mc-ev-carte-mbr { border-radius: .75rem; overflow: hidden; }
.mc-ev-carte-mbr > .mc-ev-flyer { border-radius: .75rem .75rem 0 0; }
/* Le titre et la date en surimpression sur le flyer membre (10/10) : tailles relatives au cadre. */
.mc-ev-flyer { container-type: inline-size; }
.mc-ev-flyer {
   position: relative;
   aspect-ratio: 690 / 410;
   overflow: hidden;
   background: var(--bs-light);
}
.mc-ev-flyer::before {
   content: "";
   position: absolute;
   inset: -20px;
   background: var(--mc-ev-flyer) center / cover no-repeat;
   filter: blur(14px) brightness(.85);
}
.mc-ev-flyer img {
   position: relative;
   display: block;
   width: 100%;
   height: 100%;
   object-fit: contain;
}

/* LE CARROUSEL DES ÉVÉNEMENTS - accueils de l'espace membre (abdAllah, 10/10). D'abord le
   téléphone : un format plus haut (16/9) ; dès la tablette, le format bannière, plus large.
   Le titre et la date en surimpression (.mc-ev-surimage) ; les coins suivent la carte. */
.mc-ev-carrousel { overflow: hidden; }
.mc-ev-carrousel .card-header { align-items: center; }
.mc-ev-carrousel-visuel { aspect-ratio: 16 / 9; border-radius: 0; box-shadow: none; }
@media (min-width: 768px) {
   .mc-ev-carrousel-visuel { aspect-ratio: auto; height: clamp(220px, 28vw, 320px); }
}
/* Sur grand écran, le texte garde des marges raisonnables (les unités de conteneur grandiraient trop). */
.mc-ev-carrousel .mc-ev-surimage { padding: 2.5rem clamp(1rem, 5cqi, 2rem) clamp(.8rem, 5cqi, 1.6rem); }
.mc-ev-carrousel .mc-ev-surimage-titre { font-size: clamp(1.1rem, 7.5cqi, 2rem); }
/* Les points EN HAUT : en bas, ils couvriraient la date. */
.mc-ev-carrousel .carousel-indicators { top: .4rem; bottom: auto; margin-bottom: 0; z-index: 3; }
.mc-ev-carrousel .carousel-control-prev,
.mc-ev-carrousel .carousel-control-next { width: 3rem; z-index: 3; }

/* LES BADGES LONGS PASSENT À LA LIGNE SUR TÉLÉPHONE (abdAllah, 10/10) : un badge ne coupe pas
   son texte (white-space: nowrap) ; un objectif de Qour'an ou un intitulé long débordait de
   sa carte. Sous 576px, le badge garde sa forme mais revient à la ligne dans sa largeur. */
@media (max-width: 575.98px) {
   .badge {
      white-space: normal;
      max-width: 100%;
      text-align: left;
      line-height: 1.3;
   }
}

/* LE DÉGRADÉ ROUGE (abdAllah, 10/10) - le pendant de `.grady-dark` pour un message bloquant
   (inscriptions closes, complet) : rouge plus clair en haut, texte blanc. */
.grady-rouge {
   background: #dc3545 !important;
   background: linear-gradient(color-mix(in srgb, #dc3545 72%, #fff), #dc3545) !important;
   color: #fff !important;
}

/* LES DEUX DÉCOMPTES (abdAllah, 10/10) - inscriptions | événement : deux blocs côte à côte sur le
   dégradé de la dominante ; « Clôturées » en rouge, « En cours » en vert (.mc-ev-encours). */
/* MÊME LARGEUR pour les deux blocs (abdAllah, 10/10) : base 0, et plus de `flex-fill` (1 1 auto, !important). */
.mc-ev-decomptes .mc-ev-decompte-bloc { flex: 1 1 0 !important; min-width: 0; }
.mc-ev-decompte-lib { font-size: .68rem; text-transform: uppercase; letter-spacing: .04em; opacity: .9; }
.mc-ev-decompte-val { font-size: 1.05rem; font-variant-numeric: tabular-nums; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.grady-dark.mc-ev-clos {
   background: #dc3545 !important;
   background: linear-gradient(color-mix(in srgb, #dc3545 72%, #fff), #dc3545) !important;
}
/* LES DEUX DÉCOMPTES EN CLAIR (abdAllah, 10/10) : `.grady-light`, avec un fin contour ; « En cours »
   reste vert et « Clôturées » rouge, texte blanc. */
.grady-light.mc-ev-decompte-bloc { border: 1px solid var(--line, #dee2e6); }
.grady-light.mc-ev-encours {
   background: #198754 !important;
   background: linear-gradient(color-mix(in srgb, #198754 72%, #fff), #198754) !important;
   color: #fff !important;
   border-color: #198754;
}
.grady-light.mc-ev-clos {
   background: #dc3545 !important;
   background: linear-gradient(color-mix(in srgb, #dc3545 72%, #fff), #dc3545) !important;
   color: #fff !important;
   border-color: #dc3545;
}

/* LES DÉGRADÉS JAUNE ET VERT (abdAllah, 10/10), pendants de `.grady-dark` et `.grady-rouge` :
   le jaune (texte foncé) pour une échéance qui court, le vert pour ce qui est en cours. */
.grady-jaune {
   background: #ffc107 !important;
   background: linear-gradient(color-mix(in srgb, #ffc107 60%, #fff), #ffc107) !important;
   color: #3d2f00 !important;
}
.grady-vert {
   background: #198754 !important;
   background: linear-gradient(color-mix(in srgb, #198754 72%, #fff), #198754) !important;
   color: #fff !important;
}
/* Les deux décomptes : ROUGE une fois les inscriptions clôturées, VERT pendant l'événement - par-dessus
   le jaune et le dégradé de la dominante (`mc-ev-clos` / `mc-ev-encours`, posés aussi par le script). */
.mc-ev-decompte-bloc.mc-ev-clos {
   background: #dc3545 !important;
   background: linear-gradient(color-mix(in srgb, #dc3545 72%, #fff), #dc3545) !important;
   color: #fff !important;
}
.mc-ev-decompte-bloc.mc-ev-encours {
   background: #198754 !important;
   background: linear-gradient(color-mix(in srgb, #198754 72%, #fff), #198754) !important;
   color: #fff !important;
}
.mc-ev-decompte-lib { white-space: normal; line-height: 1.15; }

/* SYNTHÈSE DES COTISATIONS - LES FILTRES EMPILÉS (abdAllah, 10/10) : chaque groupe prend la
   largeur de la colonne (les filtres de filière et de classe posent une largeur en ligne, d'où
   le !important), le champ s'étire, et l'icône comme le bouton d'effacement suivent la hauteur
   du champ. */
.mc-synthese-filtres > .input-group { width: 100% !important; min-width: 0 !important; flex-wrap: nowrap; }
.mc-synthese-filtres > .input-group > .mc-combo { flex: 1 1 auto; width: 1% !important; min-width: 0; }
/* UNE SEULE HAUTEUR pour l'icône, le champ et le bouton : celle des filtres des autres listes. */
.mc-synthese-filtres > .input-group > .input-group-text,
.mc-synthese-filtres > .input-group > .mc-combo,
.mc-synthese-filtres > .input-group > .btn { height: 34px; min-height: 34px; display: flex; align-items: center; }

/* LA BORDURE DE SURVOL D'UN COMBO DANS UN INPUT-GROUP (abdAllah, 10/10) : le bouton voisin
   (-1px de marge, Bootstrap) recouvrait son bord droit. Au survol et au focus, le combo passe
   devant, comme le fait Bootstrap pour un form-control. */
.input-group > .mc-combo:hover,
.input-group > .mc-combo:focus-within { z-index: 5; }

/* PARAMÈTRES › LE SITE WEB (abdAllah, 10/10) - les volets à la hauteur de l'écran (ils défilent, la
   page reste courte), les titres de rubrique en grady-dark, les points forts en cartes, le slider
   en cartes que l'on glisse. */
@media (min-width: 992px) {
   .mc-sw-volets { max-height: calc(100vh - 290px); overflow-y: auto; overflow-x: hidden; padding-right: .35rem; }
}
.mc-sw-titre { padding: .45rem .75rem; border-radius: .5rem; margin-bottom: .75rem; font-size: .85rem; text-transform: uppercase; letter-spacing: .03em; color: #fff; }
/* LES TITRES DE LA NEWSLETTER (abdAllah, 11/10) : sans bandeau, à la couleur dominante, un <hr> dessous. */
.mc-sw-titre.mc-sw-titre-filet { padding: 0 .1rem; border-radius: 0; color: var(--dominante-color); }
/* « PLANNINGS EN LIGNE » (abdAllah, 11/10) : la liste des sessions à droite de son libellé, sur une seule
   ligne de la colonne Activations - sans la largeur minimale des listes (150 px), trop large ici. */
/* LA LISTE DES RUBRIQUES DE LE SITE WEB (abdAllah, 11/10) : à la largeur de son contenu - le gabarit des
   options (mc-select.js) donne au champ la largeur de la plus longue, comme les listes de filtres. */
.mc-sw-choix { display: inline-flex; flex-wrap: nowrap; max-width: 100%; }
.mc-sw-choix .mc-combo { flex: 0 1 auto; width: auto; }
.mc-sw-choix .mc-combo-field { min-width: 0; width: auto; }
.mc-sw-choix .mc-combo-gabarit { display: grid; }
.mc-sw-choix .mc-combo-panel { min-width: max-content; }
/* LES ICÔNES DE LA LISTE DES RUBRIQUES (abdAllah, 11/10) : plus grandes, à la couleur dominante. */
.mc-sw-choix .mc-combo .ph-duotone { font-size: 1.3rem; color: var(--dominante-color); vertical-align: -.2rem; }
/* La même taille au survol (11/10) : tools.css grossit l'icône de l'option survolée (1.1rem). */
.mc-sw-choix .mc-combo .mc-combo-option.mc-combo-active .ph-duotone { font-size: 1.3rem; }
.mc-sw-choix .mc-combo-option.mc-combo-active .ph-duotone,
.mc-sw-choix .mc-combo-option[aria-selected="true"] .ph-duotone { color: inherit; }
/* SITE ÉTEINT (abdAllah, 11/10) : le voile sur les activations en sommeil. */
.mc-sw-voile-cadre { position: relative; }
.mc-sw-voile {
   position: absolute; inset: 0; z-index: 3;
   display: flex; flex-direction: column; align-items: center; justify-content: center; gap: .35rem;
   background: color-mix(in srgb, var(--bs-body-bg, #fff) 72%, transparent);
   backdrop-filter: blur(1.5px);
   border-radius: var(--bs-border-radius, .375rem);
   color: var(--dominante-color); font-weight: 600; text-align: center;
}
.mc-sw-voile .ph-duotone { font-size: 2rem; }
.mc-sw-plannings { flex: 0 0 8.6rem; width: 8.6rem; min-width: 0; }
.mc-sw-plannings .input-group-text { min-width: 0; padding-left: .35rem; padding-right: .35rem; }
.mc-sw-plannings .mc-combo { flex: 1 1 auto; min-width: 0; padding: 0; }
.mc-sw-plannings .mc-combo-field { min-width: 0; padding-left: .4rem !important; padding-right: .3rem !important; gap: .2rem; }
.mc-sw-plannings .mc-combo-arrow { margin-left: 0; padding: 0; }
/* Les onglets du Site WEB sur deux lignes (abdAllah, 10/10) : l'icône au-dessus, le libellé dessous. */
.mc-sw-onglet { display: flex; flex-direction: column; align-items: center; gap: .15rem; line-height: 1.15; }
.mc-sw-onglet .ph-duotone { font-size: 1.5rem; }
.mc-sw-titre .fw-normal { text-transform: none; letter-spacing: 0; opacity: .85; }
/* LES CARTES D'ARTICLES (abdAllah, 11/10) : le survol du site public - la photo s'agrandit dans son cadre,
   la carte prend le dégradé radial à la couleur du site (--sw-site, sinon la dominante). */
.mc-ar-carte .card > .position-relative { overflow: hidden; }
.mc-ar-carte .card-img-top { transition: transform .45s ease; }
.mc-ar-carte .card { transition: background .2s ease; }
.mc-ar-carte .card:hover .card-img-top { transform: scale(1.12); }
/* SANS PHOTO (11/10) : le dégradé des cartes du site public (site.css, .mc-site-article-sans-image) -
   de la couleur du site (--sw-site, sinon la dominante) vers sa version foncée, en diagonale. */
.mc-ar-sans-photo { color: #fff; opacity: .9; background: linear-gradient(135deg, var(--sw-site, var(--dominante-color, #065d89)), color-mix(in srgb, var(--sw-site, var(--dominante-color, #065d89)) 55%, #000)); }
.mc-ar-sans-photo .ph-duotone { font-size: 3rem !important; }
/* Le pied garde son fond (11/10) : seul le corps prend le dégradé. */
.mc-ar-carte .card:hover .card-body { background: radial-gradient(ellipse at 50% 62%, #fff 0%, color-mix(in srgb, var(--sw-site, var(--dominante-color)) 6%, #fff) 40%, color-mix(in srgb, var(--sw-site, var(--dominante-color)) 22%, #fff) 100%); }
@media (prefers-reduced-motion: reduce) { .mc-ar-carte .card:hover .card-img-top { transform: none; } }
/* LES ICÔNES DES TITRES (abdAllah, 11/10) : 2rem, À DROITE du titre (après un éventuel bouton). */
.mc-sw-titre:has(> .mc-sw-titre-icone) { display: flex; align-items: center; gap: .5rem; }
.mc-sw-titre > .mc-sw-titre-icone { order: 99; margin-left: auto; font-size: 2rem; line-height: 1; flex-shrink: 0; }
/* Avec un bouton (le slider) : le titre pousse le bouton à droite, l'icône le suit. */
.mc-sw-titre:has(> .btn) > .mc-sw-titre-icone { margin-left: 0; }
/* « AFFICHÉ QUAND LE SLIDER EST VIDE » (abdAllah, 11/10) : en gras, en rouge. */
.mc-sw-titre .mc-sw-alerte { font-weight: 700 !important; color: var(--bs-danger, #dc3545); opacity: 1; }
.mc-sw-titre .btn-light { text-transform: none; letter-spacing: 0; }
/* L'ONGLET ACCUEIL (abdAllah, 10/10) : des titres sans bandeau - le texte à la couleur du thème,
   un filet dessous. */
.mc-sw-titre.mc-sw-titre-simple { color: var(--dominante-color); padding: 0 0 .4rem; border-radius: 0; border-bottom: 1px solid var(--line, #dee2e6); }
.mc-sw-titre-simple .btn { text-transform: none; letter-spacing: 0; }
/* Les quatre blocs de l'onglet Accueil (abdAllah, 10/10) : un filet épais à la couleur du thème. */
.mc-sw-bloc { border: 1px solid var(--line, #dee2e6); border-left: 7px solid var(--dominante-color); border-radius: .5rem; padding: 1rem; margin-bottom: 1rem; }
.mc-sw-bloc:last-child { margin-bottom: 0; }
/* Rayés (abdAllah, 10/10) : un bloc sur deux teinté de la couleur du thème (clair comme sombre). */
.mc-sw-bloc:nth-child(odd) { background: color-mix(in srgb, var(--dominante-color) 6%, transparent); }
/* L'icône sur son disque, comme sur le site (site.css, .mc-site-atout i). */
.mc-sw-atout-icone { font-size: 2.4rem; color: var(--dominante-color); background: color-mix(in srgb, var(--dominante-color) 8%, transparent); width: 72px; height: 72px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; }
.mc-sw-atout-titre { font-size: 1.05rem; }
/* LES POINTS FORTS (abdAllah, 10/10) : des champs sans cadre, un simple filet dessous ; le choix de
   l'icône et le texte en .85rem ; cartes (bordure à la couleur du thème) et champs aux coins
   légèrement arrondis. */
.mc-sw-atout { border: 1px solid var(--sw-site, var(--dominante-color)) !important; border-radius: .5rem; overflow: hidden; }
/* UN FOND CLAIR (abdAllah, 11/10) : le dégradé radial des points forts du site (celui des cartes d'articles),
   à la couleur DU SITE (--sw-site, posée sur le formulaire et suivie en direct par la Charte graphique), comme
   la bordure ;
   les champs, transparents, le laissent voir. */
.mc-sw-atout { background: radial-gradient(ellipse at 50% 50%, #fff 0%, color-mix(in srgb, var(--sw-site, var(--dominante-color)) 6%, #fff) 40%, color-mix(in srgb, var(--sw-site, var(--dominante-color)) 22%, #fff) 100%); }
.mc-sw-atout .form-control, .mc-sw-atout .form-select { background-color: transparent; }
.mc-sw-atout .form-control, .mc-sw-atout .form-select { border: 0; border-bottom: 1px solid var(--line, #dee2e6); border-radius: .25rem; box-shadow: none; }
.mc-sw-atout .form-control:focus, .mc-sw-atout .form-select:focus { border-bottom-color: var(--dominante-color); }
.mc-sw-atout .form-select, .mc-sw-atout textarea.form-control { font-size: .85rem; }
.mc-sw-diapo { cursor: grab; }
.mc-sw-diapo.est-tiree { opacity: .45; }
/* Une diapo masquée sur le web (abdAllah, 10/10) : grisée, avec son badge. */
.mc-sw-diapo .mc-sw-masquee { display: none; }
.mc-sw-diapo.est-masquee .mc-sw-masquee { display: inline-block; }
.mc-sw-diapo.est-masquee .card-img-top, .mc-sw-diapo.est-masquee .card-body { opacity: .5; filter: grayscale(.7); }
/* La carte d'une diapo se soulève au survol (abdAllah, 10/10) - même effet que les KPI. */
.mc-sw-diapo > .card { transition: transform .15s ease, box-shadow .15s ease; border-radius: .5rem; overflow: hidden; box-shadow: rgba(0, 0, 0, .16) 0 3px 6px, rgba(0, 0, 0, .23) 0 3px 6px !important; }
.mc-sw-diapo:not(.est-tiree) > .card:hover { transform: translateY(-2px); box-shadow: rgba(0, 0, 0, .19) 0 10px 20px, rgba(0, 0, 0, .23) 0 6px 6px !important; }
.mc-sw-diapo .mc-sw-poignee { text-shadow: 0 1px 3px rgba(0, 0, 0, .6); }

/* LE SITE WEB › L'APERÇU DIRECT DE LA COULEUR (abdAllah, 10/10) : bandeau en dégradé vers la teinte foncée,
   titre et tarif dans la couleur, bouton à texte blanc ; --apercu suit le sélecteur. */
.mc-sw-apercu {
   --apercu-fonce: color-mix(in srgb, var(--apercu) 55%, #000);
   border-radius: 5px;
   overflow: hidden;
   background: #fff;
   box-shadow: rgba(0, 0, 0, .16) 0 3px 6px, rgba(0, 0, 0, .23) 0 3px 6px;
}
.mc-sw-apercu-bandeau {
   padding: .8rem 1rem;
   color: #fff;
   background: linear-gradient(135deg, var(--apercu), var(--apercu-fonce));
   transition: background .2s ease;
}
.mc-sw-apercu-bandeau-titre { font-weight: 800; font-size: 1.15rem; line-height: 1.2; }
.mc-sw-apercu-bandeau-texte { font-size: .8rem; opacity: .9; }
.mc-sw-apercu-corps {
   display: flex;
   align-items: center;
   justify-content: space-between;
   gap: .75rem;
   padding: .7rem 1rem;
   border-left: 5px solid var(--apercu);
}
.mc-sw-apercu-titre { font-weight: 700; font-size: .9rem; color: color-mix(in srgb, var(--apercu) 62%, #000); }
.mc-sw-apercu-prix { font-weight: 600; font-size: 1.2rem; color: var(--apercu); line-height: 1.2; }
.mc-sw-apercu-bouton {
   display: inline-flex;
   align-items: center;
   gap: .3rem;
   padding: .35rem .8rem;
   border-radius: 5px;
   font-size: .85rem;
   font-weight: 600;
   color: #fff;
   background: var(--apercu);
   white-space: nowrap;
}

/* ── LE MODULE COMMUNICATION (abdAllah, 11/10) ─────────────────────────────────────────────── */
/* L'extrait d'un modèle : deux lignes au plus dans la liste. */
.mc-mo-extrait { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; font-size: .85rem; color: var(--bs-secondary-color); }
/* Le compteur sous un SMS. */
.mc-envoi-compteur { min-height: 1.2rem; }
/* Le Compilateur : la SÉLECTION RAPIDE en touches (abdAllah, 11/10) - la tuile carrée de l'accueil (.mc-tuile) :
   dégradé, reflet, arête sombre, ombre ; à la couleur de la filière ou de la modalité (--co-fond, --co-texte).
   Cochée, la touche reste ENFONCÉE et porte une coche ; la case native reste là, invisible (clavier, lecteurs). */
.mc-co-tuiles {
   /* Sans plateau autour (abdAllah, 11/10) : les touches seules. */
   display: flex; flex-direction: column; align-items: center; gap: .4rem;
   width: fit-content; max-width: 100%; margin: 0 auto;
}
.mc-co-tuiles-ligne { display: flex; flex-wrap: wrap; justify-content: center; gap: .4rem; }
.mc-co-tuile {
   position: relative;
   display: flex; flex-direction: column; align-items: center; justify-content: center; gap: .2rem;
   width: 5.8rem; min-height: 4.1rem; padding: .3rem .35rem; margin: 0;   /* contenu centré sur la face de la touche */
   border-radius: .45rem; cursor: pointer; user-select: none; -webkit-tap-highlight-color: transparent;
   color: var(--co-texte); text-align: center;
   background: var(--co-fond);
   background: linear-gradient(160deg,
      color-mix(in srgb, var(--co-fond) 78%, #fff) 0%,
      var(--co-fond) 55%,
      color-mix(in srgb, var(--co-fond) 82%, #000) 100%);
   border-bottom: 3px solid color-mix(in srgb, var(--co-fond) 60%, #000);
   box-shadow: rgba(0, 0, 0, .24) 0 3px 8px, inset rgba(255, 255, 255, .28) 0 1px 0;
   transition: transform .28s cubic-bezier(.34, 1.4, .64, 1), box-shadow .28s ease, border-bottom-width .28s ease, filter .2s ease;
}
.mc-co-tuile:hover { filter: brightness(1.06); }
.mc-co-tuile > .ph-duotone { flex-shrink: 0; font-size: 1.3rem; line-height: 1; }
.mc-co-tuile > .mc-tuile-libelle { flex-shrink: 0; font-weight: 700; font-size: .7rem; line-height: 1.15; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
label.mc-co-tuile > input.form-check-input { position: absolute !important; top: 0; left: 0; opacity: 0; width: 1px; height: 1px; margin: 0; pointer-events: none; }
.mc-co-tuile:has(> .form-check-input:focus-visible) { outline: 2px solid var(--dominante-color); outline-offset: 2px; }
/* Enfoncée au clic, et tant qu'elle est cochée. */
.mc-co-tuile:active,
.mc-co-tuile-cochee {
   transform: scale(.93) translateY(2px);
   border-bottom-width: 1px;
   box-shadow: rgba(0, 0, 0, .30) 0 1px 2px, inset rgba(0, 0, 0, .22) 0 2px 5px;
   filter: brightness(.95);
}
.mc-co-tuile-cochee::after {
   content: '\2713';
   position: absolute; top: .2rem; right: .2rem;
   width: 1.05rem; height: 1.05rem; border-radius: 50%;
   display: flex; align-items: center; justify-content: center;
   background: var(--dominante-color, #065d89); color: #fff;
   font-size: .65rem; font-weight: 700; line-height: 1;
   box-shadow: rgba(0, 0, 0, .25) 0 1px 3px;
}
@media (max-width: 575.98px) { .mc-co-tuile { width: 5rem; min-height: 3.8rem; } .mc-co-tuile > .ph-duotone { font-size: 1.15rem; } .mc-co-tuile > .mc-tuile-libelle { font-size: .65rem; } }
/* Les classes d'une filière, en colonnes. */
.mc-co-classes { column-width: 13rem; column-gap: .75rem; }
.mc-co-classes > div { break-inside: avoid; }
/* Les colonnes Élèves et Staff : la hauteur de l'écran, leur liste défile. */
.mc-co-colonne { height: calc(100vh - 11rem); min-height: 22rem; }
.mc-co-colonne > .card-body { min-height: 0; }
.mc-co-liste { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
.mc-co-ligne { display: flex; align-items: center; gap: .5rem; padding: .3rem .4rem; margin: 0; border-bottom: 1px solid var(--bs-border-color-translucent); cursor: pointer; }
.mc-co-ligne:nth-child(odd) { background: var(--bs-tertiary-bg); }
.mc-co-ligne:hover { background: color-mix(in srgb, var(--dominante-color) 8%, transparent); }
.mc-co-ligne > .form-check-input { margin: 0; flex-shrink: 0; }
.mc-co-ligne[hidden] { display: none; }
@media (max-width: 1199.98px) { .mc-co-colonne { height: 26rem; } }

/* ==========================================================================================
   L'APPLICATION MOBILE - LA BARRE DU BAS (abdAllah, 11/10) : sur téléphone seulement (sous 768 px),
   dans l'application installée comme dans le navigateur (inc/barre-bas.php). La bulle Tawassoul
   s'efface (l'entrée « Messages » la remplace) ; le bouton « retour en haut » remonte au-dessus.
   ========================================================================================== */
.mc-barre-bas { display: none; }

@media (max-width: 767.98px) {
   .mc-barre-bas {
      display: flex;
      position: fixed;
      left: 0;
      right: 0;
      bottom: 0;
      z-index: 1035;
      padding: .25rem .25rem calc(.25rem + env(safe-area-inset-bottom));
      /* Le fond : le dégradé `.grady-dark` porté par la barre (abdAllah, 11/10). */
      border-top: 1px solid rgba(255, 255, 255, .15);
      box-shadow: 0 -4px 14px rgba(0, 0, 0, .18);
   }
   .mc-barre-bas-lien {
      position: relative;
      flex: 1 1 0;
      min-width: 0;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      gap: .1rem;
      min-height: 3.25rem;
      padding: .2rem 0;
      border: 0;
      border-radius: .6rem;
      background: transparent;
      color: rgba(255, 255, 255, .78);
      font-size: .68rem;
      line-height: 1.1;
      text-decoration: none;
      -webkit-tap-highlight-color: transparent;
   }
   .mc-barre-bas-lien i { font-size: 1.55rem; }
   .mc-barre-bas-lien span { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
   /* LE SURVOL SUR FOND FONCÉ (abdAllah, 11/10) : un voile blanc, l'icône remonte un peu. */
   .mc-barre-bas-lien { transition: background-color .15s ease, color .15s ease; }
   .mc-barre-bas-lien i { transition: transform .15s ease; }
   .mc-barre-bas-lien:hover,
   .mc-barre-bas-lien:focus-visible { color: #fff; background: rgba(255, 255, 255, .14); }
   .mc-barre-bas-lien:hover i { transform: translateY(-2px); }
   .mc-barre-bas-lien.actif,
   .mc-barre-bas-lien:active { color: #fff; background: rgba(255, 255, 255, .22); }
   .mc-barre-bas-lien.actif span { font-weight: var(--fw-bold, 700); }
   .mc-barre-bas-pastille {
      position: absolute;
      top: .1rem;
      left: calc(50% + .45rem);
      min-width: 1.15rem;
      height: 1.15rem;
      padding: 0 .3rem;
      border-radius: 1rem;
      background: var(--bs-danger, #dc3545);
      color: #fff;
      box-shadow: 0 0 0 2px rgba(255, 255, 255, .85);
      font-size: .65rem;
      line-height: 1.15rem;
      text-align: center;
   }

   html.mc-avec-barre-bas body { padding-bottom: calc(4rem + env(safe-area-inset-bottom)); }
   html.mc-avec-barre-bas .mc-tw-bulle { display: none !important; }
   html.mc-avec-barre-bas #scrollTopBtn { bottom: calc(4.6rem + env(safe-area-inset-bottom)); }
}

/* L'APPLICATION MOBILE - LE BLOC « INSTALLER L'APPLICATION » (abdAllah, 11/10) : l'icône, et dessous son
   libellé ; un seul bloc, sans bouton autour (inc/pwa-installer.php). Connexion, présentation, accueil
   du site. Sur iPhone, son mode d'emploi s'affiche dessous. */
.mc-pwa-zone {
   display: flex;
   flex-direction: column;
   align-items: center;
   margin-top: 1rem;
}
/* La zone ne prend aucune place tant que l'application ne peut pas s'installer. */
.mc-pwa-zone:not(:has(.mc-pwa-bloc:not([hidden]))) { display: none; }
.mc-pwa-bloc {
   display: flex;
   flex-direction: column;
   align-items: center;
   cursor: pointer;
}
/* LE BOUTON N'EST QUE L'IMAGE (abdAllah, 11/10) : fond transparent, sans bordure ; l'ombre est celle de
   l'image. 7rem (connexion, présentation), 10rem sur l'accueil du site. */
.mc-pwa-bouton {
   padding: 0;
   border: 0;
   background: transparent;
   line-height: 0;
   cursor: pointer;
   -webkit-tap-highlight-color: transparent;
}
.mc-pwa-bouton img {
   margin-top: 2rem;
   width: 7rem;
   height: 7rem;
   object-fit: contain;
   /* L'OMBRE SUIT LE DESSIN (coins arrondis transparents de l'icône), pas un rectangle. */
   filter: drop-shadow(0 .45rem .7rem rgba(0, 0, 0, .22));
}
.mc-pwa-bloc-grand .mc-pwa-bouton img { width: 10rem; height: 10rem; }
/* AU SURVOL (abdAllah, 11/10) : l'image avance (zoom) en s'inclinant légèrement, puis le zoom arrière
   s'enchaîne aussitôt - une seule séquence, jouée à chaque survol, sans attendre que la souris parte. */
.mc-pwa-bouton img { transition: filter .45s ease; }
.mc-pwa-bloc:hover .mc-pwa-bouton img,
.mc-pwa-bouton:focus-visible img {
   animation: mc-pwa-survol .9s cubic-bezier(.34, 1.3, .64, 1) both;
   filter: drop-shadow(0 .8rem 1.1rem rgba(0, 0, 0, .28));
}
@keyframes mc-pwa-survol {
   0%   { transform: none; }
   45%  { transform: scale(1.12) rotate(5deg); }
   100% { transform: none; }
}
.mc-pwa-bouton:active img { transform: scale(.94); }
@media (prefers-reduced-motion: reduce) { .mc-pwa-bloc:hover .mc-pwa-bouton img { animation: none; } }
.mc-pwa-texte {
   margin-top: .75rem;
   color: var(--dominante-color);
   font-weight: var(--fw-bold, 700);
   font-size: .95rem;
}
.mc-pwa-bloc-grand .mc-pwa-texte { margin-top: 1rem; font-size: 1.1rem; }
/* L'ARRIVÉE PAR LE BAS, EN DERNIER (connexion, présentation) : jouée quand le bloc apparaît. */
.mc-pwa-bloc-anime:not([hidden]) { animation: mc-pwa-monte 1.1s cubic-bezier(.22, 1, .36, 1) 1.4s both; }
.mc-pwa-bloc-anime.mc-pwa-bloc-dernier:not([hidden]) { animation-delay: 1.6s; }
@keyframes mc-pwa-monte { from { opacity: 0; transform: translateY(36px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .mc-pwa-bloc-anime:not([hidden]) { animation: none; } }
.mc-pwa-ios {
   margin-top: .5rem;
   max-width: 22rem;
   padding: .5rem .75rem;
   border-radius: .5rem;
   background: rgba(var(--dominante-rgb, 6, 93, 137), .08);
   color: var(--bs-body-color);
   text-align: center;
   line-height: 1.5;
}
/* Sur l'accueil du site, la section entière s'efface tant que l'application ne peut pas s'installer. */
.mc-site-appli:not(:has(.mc-pwa-bloc:not([hidden]))) { display: none; }
.mc-site-appli .mc-pwa-zone { margin-top: 0; }

/* CONNEXION SUR PETIT ÉCRAN (abdAllah, 11/10) : chaque bouton garde son libellé sur une ligne. La taille
   du texte suit la largeur de la rangée (unités de conteneur) : pleine taille sur PC, un peu réduite sur
   un téléphone étroit, plutôt que « Se connecter » sur deux lignes ou « Mot de passe oublié » coupé. */
.acces-actions,
.acces-liens {
   container-type: inline-size;
}
.acces-actions > .btn,
.acces-liens > .btn {
   white-space: nowrap;
   padding-left: .2rem;
   padding-right: .2rem;
   letter-spacing: 0;
   font-size: clamp(.58rem, 4.4cqi, .95rem);
   /* MÊME HAUTEUR pour tous : « S'inscrire » (un <label>) dépassait « Se connecter » de 3 px. */
   height: 2.35rem;
   display: inline-flex;
   align-items: center;
   justify-content: center;
}
.acces-actions > .btn i { font-size: 1.15em; }
