@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');

/* ════════════════════════════════════════════════════════════════════════════
   CHARTE COULEURS MY E-MAM — référence unique (Lot 1, 02/08/2026, Elena)
   Source : PDF « Code couleur my e-mam » + arbitrages Cyrille 02/08/2026 19:01.

   TEINTES OFFICIELLES :
   - vert      #29A59B  (+ clairs #4CBFB4 #7BDBCF #9CE8DD #C7F2EA)
   - gris      #5D686E  (+ clairs #7A878C #97A5AA #BAC8CC #DAE7EA)
   - framboise #EF3054  (+ rose #E595AC)
   - orange    #F9893D  (+ pêche #F9B698)

   DÉRIVATIONS DOCUMENTÉES (assombrissement de la MÊME teinte, contraste AA) :
   - commit 9bb123ce : vert #1F7E76 (AA 4.9:1) / #17635D / #124E49 ;
     gris #49545B / #3E464A ; framboise #C71C3F / #9B1531 ;
     orange #A85212 (AA 5.4:1) / #7A3A0B
   - Lot 1 (nouvelles, ci-dessous) :
     · Texte principal clair  #2E3538  = gris charte #5D686E assombri ×0.5
       (contraste 11.9:1 sur blanc)
     · Fonds très clairs (blanc teinté vert charte, éclaircissements de #C7F2EA) :
       #F6FAF9 (fond page), #F7FBFA / #F3F8F7 (gradient body),
       #EEF7F6 (surface-tint), #F1F7F6 (surface-alt)
     · GAMME DARK (4 paliers, assombrissements du gris charte #5D686E,
       teinte conservée ~201°) — remplace les anciens fonds bleu nuit
       #0F172A / #111C31 / #122338 / #19253D :
       P1 #141718 (×0.22) fond de page (gradient jusqu'à #1A1D1F)
       P2 #1E2123 (×0.32) cartes, panneaux, sidebar, surfaces
       P3 #272C2E (×0.42) surfaces secondaires, hovers, lignes de tableaux
       P4 #33393C (×0.55) éléments surélevés, bordures fortes
     · Texte dark : #E8F1F0 (blanc teinté vert charte) + gris clairs charte
       #BAC8CC (soft) / #97A5AA (muted)

   SÉMANTIQUE (mapping unique, audit 02/08/2026) :
   - Succès  : fond rgba(41,165,155,.12) / texte #1F7E76 — dark #7BDBCF sur rgba .24
   - Erreur  : fond rgba(239,48,84,.10) / texte #C71C3F  — dark #E595AC sur rgba .20
   - Alerte  : fond rgba(249,137,61,.12) / texte #A85212 — dark #F9B698 sur rgba .20
     (jamais de texte blanc sur #F9893D — 2.42:1)
   - Info / neutre : la charte n'a PAS de bleu → INFO = GRIS ardoise
     (fond rgba(93,104,110,.12) / texte #49545B — dark #BAC8CC)
   - Tokens (Lot 2, 03/08/2026) : le mapping texte ci-dessus est exposé en
     variables CSS adaptées clair/sombre — --em-success-text (#1F7E76 / dark
     #7BDBCF), --em-warning-text (#A85212 / dark #F9B698), --em-danger-text
     (#C71C3F / dark #E595AC). À réutiliser pour tout état inline (Lots 3-5).
   - Lot 2 : héros Bilan Ramadan = dégradé #1F7E76 → #17635D (deux verts
     charte assombris déjà documentés, texte blanc AA 4.9:1) — remplace
     l'ancien #1e6b65 → #145c56 non documenté.
   - Lot 3 (03/08/2026, AUCUNE teinte nouvelle — choix de mapping) :
     · Camembert Pipeline commercial : À contacter #5D686E, Attente/Relancer
       #F9893D, Négociation #A85212, Client #29A59B, Standby #BAC8CC,
       Perdu #EF3054 (teintes déjà documentées, sémantique info=gris).
     · « Converti en projet » (Boîte à idées) = vert très foncé #17635D
       (aplat/badge/bordure) — remplace l'indigo #6366f1 hors charte.
     · KPI « Dont dons » (Événements) = --em-success-text (vert foncé,
       adapté dark) — remplace le violet #7c3aed.
     · Jauge remplissage Événements : dégradé #29A59B → #7BDBCF ;
       seuil > 80 % : #F9893D → #EF3054.

   - Lot 4 (03/08/2026, board mosquée + rapport mensuel) :
     · Fonds teal très clairs du rapport mensuel PDF : #E6F7F5 / #D9F0ED
       (éclaircissements du vert pâle charte #C7F2EA, header dégradé
       rapport-mensuel.html) — OFFICIALISÉS comme dérivés charte.
       rapport-mensuel.html garde ses tokens locaux (:root) mais chacun
       pointe désormais sur une valeur charte/dérivée (--ink #2E3538,
       --muted #5D686E, --line #DAE7EA, --line-2 #EEF7F6, --chip #F1F7F6).
     · Camembert Comptabilité mosquée (13 catégories, AUCUNE teinte
       nouvelle — familles et luminosités alternées pour segments voisins
       distincts) : zakat #17635D, facture #EF3054, loyers #5D686E,
       électricité #F9893D, ablutions #9CE8DD, auditorium #E595AC,
       imam #29A59B, charges #A85212, nour #7BDBCF, ramadan #F9B698,
       tv #97A5AA, aspirateurs #DAE7EA, séminaire #C71C3F.
       Catégories principales dons : cagnotte/dons #29A59B, sadaqa
       rgba(41,165,155,.40), iftar #F9893D, autres #7A878C.
     · Dark board mosquée : sidebar #111c31 (bleu nuit) → P2 #1E2123 ;
       logout dark rose #ffaaaa → rose charte #E595AC (light : blanc .75,
       hover framboise conservé).

   - Lot 5 (03/08/2026, DERNIER lot — AUCUNE teinte nouvelle, fin de chantier) :
     · Toast global emNotify/_emToastColored (toutes sections my e-mam) :
       success #1F7E76 / warn #A85212 / error #C71C3F, texte blanc AA garanti
       (remplace #22c55e/#f59e0b/#ef4444 dont le blanc était < 3:1).
     · Actus & prêches + Banque d'images : note validation ambre #F5A623 →
       orange charte rgba(249,137,61,…) ; pilules Rangements récents :
       auto #1F7E76 (typo #1F7D76 corrigée), validé gris info #49545B/#BAC8CC,
       attente #A85212/#F9B698, échec #C71C3F/#E595AC (ex #A33125/#FF8A7A).
     · Outils admin data (Rapports, saisie downloads, batch, renommage Stripe,
       diagnostic) : boutons/textes danger #c0392b → #9B1531 (boutons) et
       #C71C3F (textes) ; panneau Renommer violet #8b5cf6/#faf5ff → gris info
       #7A878C + rgba(93,104,110,.05) ; panneau diagnostic ambre #f59e0b/#fffbeb
       → #F9893D + rgba(249,137,61,.08) ; consoles #1e293b/#e2e8f0 → P2
       #1E2123 / #E8F1F0 ; paires sauvegardé/manquant #f0fdf4/#fef2f2 →
       #E6F7F5 / rgba(239,48,84,.06) ; ternaires état saisies →
       tokens --em-success/warning/danger-text.
     · Bibliothèque : statuts docs #10b981/#9ca3af → tokens succès/muted ;
       « Non analysé » et bouton Analyser ambre → --em-warning-text ;
       Supprimer #ef4444 → --em-danger-text ; spinners #f59e0b → #F9893D.
     · Liens my e-mam : séparateur Cagnottes #e67e22 → orange charte
       (rgba(249,137,61,.12) + --em-warning-text) ; séparateur + icône SVG
       « Événements » violet #7c3aed → framboise charte (rgba(239,48,84,.10)
       + --em-danger-text) — framboise = identité événementiel/festif.
     · Mon profil : avatar dégradé #1e8a82 → #1F7E76.
     · Calendrier fêtes musulmanes : badge high #1e6b65 → #1F7E76, medium
       #a14e10 → #A85212, none #94a3b8/#475569 → gris charte #97A5AA/#49545B
       + overrides dark ajoutés (#7BDBCF/#F9B698/#BAC8CC).
     · Fallbacks var() des tokens de base partagés normalisés PARTOUT
       (y compris zones Consulting — exception 2 : les tokens de base
       évoluent) : --em-border → #DAE7EA, --em-surface-alt → #F1F7F6,
       --em-text-soft → #5D686E, --em-card → #1E2123, --em-text → #2E3538.
     · Pages annexes : inscription.html et access-denied.html — tokens locaux
       recalés (texte #2E3538, muted #5D686E, border #DAE7EA, bg #F6FAF9,
       erreur #C71C3F, anthracite footer → gris charte #3E464A, filets
       #BAC8CC/#97A5AA, encart #F7FBFA) ; evenements.html #f6fbfa → #F6FAF9.
     · Organigramme Équipe dark (#0c2d2a/#145c56, dashboard.html) : NON
       touché — la section Équipe appartient à l'univers Consulting depuis
       l'arbitrage menus du 27/07/2026 (exception 2 ci-dessous).

   EXCEPTIONS ASSUMÉES (arbitrages Cyrille 02/08/2026) :
   1. LOGOS DE MARQUES TIERCES : Stripe (#635BFF), Google, Supabase, Airtable,
      Make, Brevo, Claude… gardent leurs couleurs officielles. Ne JAMAIS les
      recaler sur la charte.
   2. UNIVERS CONSULTING : les couleurs fonctionnelles Consulting restent
      telles quelles — pilules .em-priority-*, statuts projets .project-status--*,
      les 13 couleurs « pôles agents » (.em-owner-cat-*, plus bas dans ce
      fichier), roadmap #6366F1/#818CF8. Seuls les tokens de base partagés
      (fonds, bordures, textes) évoluent.
      → CADUQUE depuis le 04/08/2026 : voir la section Consulting ci-dessous.
        L'univers Consulting a désormais SA PROPRE charte (bleue) ; ces
        composants sont recalés lots 2-4 du chantier charte-couleurs-consulting.
   ════════════════════════════════════════════════════════════════════════════ */

/* ════════════════════════════════════════════════════════════════════════════
   CHARTE COULEURS CYRILLE FOURRÉ CONSULTING — référence unique
   (Lot 1 « socle bleu », 06/08/2026, Elena)

   Source : PDF « Code couleur Cyrille Fourré Consulting » (lu le 04/08/2026)
   + arbitrages Cyrille 06/08/2026 17:39.
   Décision fondatrice (Cyrille 04/08/2026 18:43, option A) : UN UNIVERS =
   UNE CHARTE. L'univers my e-mam garde la charte verte documentée ci-dessus ;
   l'univers Consulting (Mon Bureau, Prospection, Pilotage, Veille, Mon
   entreprise, + groupe Commun quand il est affiché côté Consulting) applique
   la charte bleue ci-dessous. Les deux ne se croisent jamais : tout est scopé
   par la classe body.univers-consulting.

   TEINTES OFFICIELLES (11) :
   - bleus   #15152D (nuit) · #185D96 (profond) · #37A6CA (cyan)
             · #49B9D1 (clair) · #6EDADD (turquoise clair)
   - gris    #969696 · #AFAFAF · #D7D7D7 · #DAE7EA
   - oranges #F9893D · #F9B698   (IDENTIQUES à la charte my e-mam)
   - AUCUN VERT : le vert #29A59B appartient exclusivement à my e-mam.
   ⚠️ Coquille du PDF : le bleu nuit y est écrit « #151512d » (7 caractères) ;
      les valeurs R21/V21/B45 font foi → #15152D. Signalé à Cyrille 04/08/2026.

   RÈGLE DE LISIBILITÉ — 6 des 11 teintes ne peuvent PAS porter de texte.
   Contrastes mesurés sur fond BLANC (seuil AA texte courant = 4.5:1) :
     #15152D 17.84 ✓ · #185D96  6.90 ✓   ← les 2 seules utilisables en texte
     #37A6CA  2.81 ✗ · #49B9D1  2.30 ✗ · #6EDADD 1.65 ✗
     #969696  2.96 ✗ · #AFAFAF  2.19 ✗ · #F9893D 2.42 ✗   ← les 6 interdites
     (#D7D7D7 1.44 · #DAE7EA 1.27 · #F9B698 1.73 : teintes de surface/bordure,
      jamais destinées au texte — elles servent de FOND, avec texte foncé.)
   Conséquence : toute sémantique portée par l'une des 6 teintes interdites
   passe par une dérivation assombrie (ci-dessous) en mode clair, et retrouve
   la teinte charte pleine en mode sombre, où elle est posée sur fond bleu nuit.

   DÉRIVATIONS DOCUMENTÉES (5) — assombrissement de la MÊME teinte, contraste
   AA vérifié sur blanc :
     · #124570 = #185D96 assombri ......... 9.95:1  (bleu profond, aplats/texte)
     · #236B83 = #37A6CA assombri ......... 6.00:1  (cyan → SUCCÈS en texte)
     · #1E5B6F = #6EDADD assombri ......... 7.55:1  (turquoise, accents foncés)
     · #5A5A5A = #969696 assombri ......... 6.90:1  (texte secondaire)
     · #707070 = #AFAFAF assombri ......... 4.95:1  (texte tertiaire/discret)
   Rappel : les dérivations orange (#A85212) et framboise (#C71C3F / #9B1531)
   sont déjà documentées plus haut — elles sont communes aux deux univers.

   FONDS CLAIRS DÉRIVÉS (éclaircissements du gris bleuté charte #DAE7EA
   vers le blanc, teinte conservée) :
     · #F7FAFA (22 %) surface-alt et haut du dégradé de page
     · #F5F8F9 (28 %) fond de page
     · #F0F5F7 (40 %) surface-tint
   GAMME SOMBRE (4 paliers dérivés du bleu nuit #15152D — teinte 240° et
   saturation ~36 % conservées sur toute la gamme) :
     P1 #0B0B18 (L 6.9 %)  fond de page (dégradé jusqu'à P2)
     P2 #15152D (L 12.9 %) = bleu nuit charte — cartes, panneaux, barre latérale
     P3 #1E1E41 (L 18.6 %) surfaces secondaires, survols, lignes de tableaux
     P4 #2A2A5A (L 25.9 %) éléments surélevés, bordures fortes (lots 2-4)
   Texte sombre : #E8EEF6 (blanc teinté bleu, 15.29:1 sur P2) + gris charte
   #AFAFAF (8.13:1) et #969696 (6.03:1).

   MAPPING SÉMANTIQUE (arbitrages Cyrille 06/08/2026 17:39) :
   - Succès / validé : LE VERT DISPARAÎT de l'univers Consulting.
     clair  fond rgba(55,166,202,.14) / texte #236B83 ....... 5.27:1
     sombre fond rgba(55,166,202,.24) / texte #6EDADD ....... 7.31:1
   - Erreur / danger : le FRAMBOISE #EF3054 RESTE — couleur système d'erreur
     commune aux deux univers (convention de sécurité, icônes conservées).
     clair  fond rgba(239,48,84,.10) / texte #C71C3F ........ 4.96:1
     sombre fond rgba(239,48,84,.20) / texte #E595AC ........ 6.48:1
   - Alerte / en attente : oranges inchangés (communs aux deux chartes).
     clair  fond rgba(249,137,61,.12) / texte #A85212 ....... 4.89:1
     sombre fond rgba(249,137,61,.20) / texte #F9B698 ....... 7.41:1
     (jamais de texte blanc sur #F9893D — 2.42:1)
   - Info / primaire : bleu profond #185D96 (fond rgba(24,93,150,.10),
     texte #124570 = 8.57:1) — sombre : #49B9D1 sur rgba(73,185,209,.18).
   - Neutre / inactif : gris charte (clair fond rgba(150,150,150,.16),
     texte #5A5A5A = 5.94:1 ; sombre texte #D7D7D7 sur rgba(175,175,175,.16)).
   Règle d'accompagnement (identique à my e-mam) : jamais de distinction d'état
   par la couleur seule — icônes et libellés (⚠️ ❌ ✅ ⏳) conservés.

   PÉRIMÈTRE DU LOT 1 (« socle bleu ») :
   - Barre latérale Consulting réécrite aux teintes officielles (dashboard.html,
     bloc « UNIVERS CONSULTING »). Les bleus précédents (#060B22 / #0A1130 /
     #2563EB / #35C9DC / #EEF2FF / #A7B1CC) avaient été relevés à l'œil sur le
     site web en juillet 2026 : AUCUN n'appartenait à la charte.
   - Override des tokens --em-* sous body.univers-consulting (clair + sombre),
     DÉPLACÉ le 07/08/2026 dans assets/css/consulting-theme.css (séparation des
     univers, pas 2) : bascule d'un coup toutes les surfaces, bordures
     et textes de l'univers Consulting qui passent déjà par les tokens.
   PÉRIMÈTRE DU LOT 2 (« Mon Bureau + Comité de direction », 06/08/2026) :
   - Mon Bureau et Comité de direction sont des menus EXCLUSIVEMENT Consulting
     (SIDEBAR_CONSULTING, arbitrage menus Cyrille 27/07/2026 — ils ne figurent
     plus dans SIDEBAR_CONFIG['super-admin']). Leurs couleurs écrites en dur ont
     donc été RÉÉCRITES SUR PLACE en bleu, sans scoping : il n'existe aucun
     rendu my e-mam de ces écrans à préserver. C'est la correction de l'erreur
     fondatrice du chantier (« Mon Bureau était en vert my e-mam par erreur »).
   - Les composants VRAIMENT partagés avec my e-mam (toast global
     _emToastColored, rendu markdown des rapports, cartes Sentinel-Veille /
     Livia / Digest veille / Propositions, bannière d'alertes) passent, eux, par
     les tokens --em-acc-* ci-dessous : valeur my e-mam inchangée, valeur bleue
     sous body.univers-consulting.
   RESTE À FAIRE (lots 3-4) : couleurs en dur des sections Projets, Équipe,
   Veille, Prospection, Mon entreprise + pages/agents-live.html. Elles restent
   visiblement hors charte tant que les lots suivants ne sont pas passés —
   c'est attendu.
   ════════════════════════════════════════════════════════════════════════════ */

:root {
  --em-primary: #29A59B;
  --em-primary-strong: #1F7E76; /* vert charte assombri documenté (AA 4.9:1 sur blanc) */
  --em-primary-light: #4CBFB4;
  --em-primary-soft: #7BDBCF;
  --em-primary-pale: #C7F2EA;
  --em-surface-tint: #EEF7F6;   /* fond très clair dérivé (blanc teinté vert charte) */
  --em-surface-alt: #F1F7F6;    /* fond alternatif dérivé (nouveau token Lot 1) */
  --em-text: #2E3538;           /* gris charte #5D686E assombri ×0.5 (11.9:1) */
  --em-text-soft: #5D686E;
  --em-text-muted: #7A878C;
  --em-border: #DAE7EA;         /* gris pâle charte */
  --em-bg: #F6FAF9;             /* fond page clair dérivé (blanc teinté vert) */
  --em-card: #FFFFFF;
  --em-surface: #FFFFFF;
  --em-shadow: 0 10px 30px rgba(41, 165, 155, 0.08);
  --em-shadow-soft: 0 6px 18px rgba(93, 104, 110, 0.08);
  --em-danger: #EF3054;
  --em-warning: #F9893D;
  --em-success: #1F7E76;        /* texte succès = vert charte assombri AA */
  /* Tokens texte sémantiques (Lot 2) — teintes déjà documentées, adaptées dark plus bas */
  --em-success-text: #1F7E76;   /* vert charte assombri (AA 4.9:1 sur blanc) */
  --em-warning-text: #A85212;   /* orange charte assombri (AA 5.4:1 sur blanc) */
  --em-danger-text: #C71C3F;    /* framboise charte assombrie (AA 5.9:1 sur blanc) */
  /* Fond « succès / à jour » très léger pour une LIGNE ENTIÈRE de tableau
     (Journal des abonnements, mandat Cyrille 25/10/2026 10h55 « fond vert pour
     que ça saute aux yeux »). Vert charte #29A59B à 10 % sur blanc = #EAF6F5 :
     --em-text 11.3:1, --em-text-soft 5.2:1, --em-danger-text 5.2:1,
     --em-warning-text 4.9:1 — tout reste AA. Pendant sombre dans body.em-dark. */
  --em-success-bg: rgba(41, 165, 155, 0.10);
  /* TEXTE des boutons « fantômes » (.em-btn--ghost) en mode CLAIR — 10/08/2026.
     Ces boutons ne sont pas posés sur du blanc : ils portent un voile vert
     rgba(41,165,155,0.05) qui, sur les fonds clairs du board, assombrit le fond
     et fait tomber --em-primary-strong (#1F7E76) sous le seuil AA. Mesures :
     4.30:1 sur --em-surface-alt, 3.92:1 sur une carte #D2EBEE — seuil 4.5:1.
     On reprend la dérivation charte DÉJÀ documentée --em-acc-ok-tx /
     --em-acc-solid-hover (#17635D), dont le rôle déclaré est précisément
     « texte posé sur les fonds verts très clairs ». Aucune teinte nouvelle
     n'entre dans la charte. Résultat : 6.21:1 et 5.66:1.
     Le mode SOMBRE n'est PAS concerné : il est déjà conforme et reste piloté
     par la règle body.em-dark .em-btn:not(...) (spécificité 0,4,1 > 0,1,0). */
  --em-btn-ghost-text: #17635D;
  /* ─── Tokens « accent » (chantier charte-couleurs-consulting, Lot 2, 06/08/2026)
     Ils existent pour les couleurs qui étaient ÉCRITES EN DUR dans des styles
     inline générés en JS (cartes Mon Bureau, Comité de direction, Veille…), là où
     un override CSS ne peut pas gagner. Les valeurs ci-dessous sont EXACTEMENT
     celles qui étaient en dur côté my e-mam : la bascule est donc un no-op strict
     pour l'univers my e-mam (clair ET sombre — ils ne sont volontairement PAS
     redéclarés dans body.em-dark, l'ancien code ne changeait pas non plus en
     sombre). Ils sont redéfinis en bleu sous body.univers-consulting —
     désormais dans assets/css/consulting-theme.css (séparation, 07/08/2026).

     Deux familles à ne pas confondre :
       · les tokens « TEXTE » (--em-acc-link, --em-acc-*-tx) s'éclaircissent en
         mode sombre, car ils sont posés sur une surface foncée ;
       · les tokens « APLAT » (--em-acc-solid, --em-acc-neutral*) gardent la même
         valeur dans les deux modes, car ils portent du texte BLANC : les
         éclaircir casserait le contraste du blanc. */
  --em-acc-link: #1F7E76;          /* TEXTE : lien / libellé accentué */
  --em-acc-link-bg: rgba(41,165,155,0.10); /* fond doux du même lien */
  --em-acc-solid: #1F7E76;         /* APLAT + texte blanc (boutons pleins) */
  --em-acc-solid-hover: #17635D;   /* APLAT + blanc, état appuyé / confirmation */
  --em-acc-ok: #29A59B;            /* liseré / bordure « tout va bien » */
  --em-acc-ok-bg: #E6F7F5;         /* fond « tout va bien » très clair */
  --em-acc-ok-pale: #C7F2EA;       /* fond « tout va bien » clair (pastilles) */
  --em-acc-ok-tx: #17635D;         /* texte posé sur les deux fonds ci-dessus */
  --em-acc-neutral: #5D686E;       /* gris neutre (badges, textes secondaires) */
  /* Version TEXTE du gris neutre. --em-acc-neutral est un APLAT (il porte du
     blanc) et garde donc la même valeur dans les deux modes ; quand ce gris sert
     de COULEUR DE TEXTE sur la page sombre, il devient illisible. Ce token-ci
     s'éclaircit en mode sombre, comme les autres tokens de texte.
     Valeur claire STRICTEMENT identique à --em-acc-neutral : le mode clair ne
     bouge pas. Ajouté le 08/08/2026 (Elena, dette lisibilité sombre). */
  --em-acc-neutral-tx: #5D686E;    /* TEXTE gris neutre (clair) */
  /* Variantes « appuyées » des textes d'alerte : framboise et orange encore
     plus assombris que --em-danger-text / --em-warning-text. Servent aux
     compteurs et chiffres qui doivent taper fort sur fond clair. Comme les
     autres jetons de TEXTE, elles s'éclaircissent en mode sombre (voir le bloc
     body.em-dark). Valeurs claires strictement identiques aux couleurs écrites
     en dur qu'elles remplacent (#9B1531 / #7A3A0B) : le clair ne bouge pas.
     Ajoutées le 08/08/2026 (Elena, dette lisibilité sombre). */
  --em-danger-text-strong: #9B1531;   /* framboise très assombrie (blanc 6.56:1) */
  --em-warning-text-strong: #7A3A0B;  /* orange très assombri */
  --em-acc-neutral-dk: #49545B;    /* gris neutre foncé */
  --em-acc-neutral-bd: #BAC8CC;    /* gris de bordure / pointillés */
  --em-acc-neutral-lt: #97A5AA;    /* gris clair de liseré */
  --em-pill-glow: rgba(41,165,155,.55); /* halo de la pilule active (Lot 3) */
  --em-ctl-border: rgba(41, 165, 155, 0.14); /* liseré pilules/boutons/champs (Lot 4) */
  --em-radius-xs: 10px;
  --em-radius-sm: 14px;
  --em-radius-md: 20px;
  --em-radius-lg: 28px;
  --em-radius-xl: 36px;
  --em-max-width: 1400px;
  --em-sidebar-width: 280px;
  --em-topbar-height: 76px;
  --em-banner-height: 108px;
  --em-transition: 180ms ease;
}

* {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
}

body {
  margin: 0;
  font-family: "Inter", system-ui, -apple-system, Arial, sans-serif;
  color: var(--em-text);
  background: linear-gradient(180deg, #f7fbfa 0%, #f3f8f7 100%);
}

/* Mode sombre — gamme grise dérivée du gris charte #5D686E (paliers P1-P4, cf. en-tête) */
body.em-dark {
  --em-bg: #141718;             /* P1 */
  --em-card: #1E2123;           /* P2 */
  --em-text: #E8F1F0;           /* blanc teinté vert charte */
  --em-text-soft: #BAC8CC;      /* gris clair charte */
  --em-text-muted: #97A5AA;     /* gris clair charte */
  --em-border: rgba(123, 219, 207, 0.16); /* vert clair charte #7BDBCF à 16 % */
  --em-surface: #1E2123;        /* P2 */
  --em-surface-tint: #272C2E;   /* P3 */
  --em-surface-alt: #272C2E;    /* P3 */
  --em-shadow: 0 10px 40px rgba(0, 0, 0, 0.28);
  /* Tokens texte sémantiques en dark = clairs charte (cf. mapping en-tête) */
  --em-success-text: #7BDBCF;
  --em-warning-text: #F9B698;
  --em-danger-text: #E595AC;
  /* Fond « à jour » sombre : vert charte à 16 % sur P2 = #203636 (1.27:1 vs la
     carte, visible sans crier) ; textes clairs 11.1:1, soft 7.4:1, danger 5.6:1. */
  --em-success-bg: rgba(41, 165, 155, 0.16);
  --em-acc-neutral-tx: #BAC8CC;  /* gris clair charte (8.9:1 sur P2) */
  --em-danger-text-strong: #EDB5C5;   /* rose pâle charte (le pendant clair de #9B1531) */
  --em-warning-text-strong: #F9B698;  /* pêche charte (le pendant clair de #7A3A0B) */
  background: linear-gradient(180deg, #141718 0%, #1A1D1F 100%); /* P1 → nuance P1 */
}

/* ═══ DETTE DE LISIBILITÉ EN MODE SOMBRE — 08/08/2026 (Elena) ═══════════════
   Mandat Cyrille 08/08/2026 15:44, dans la suite du défaut repéré à l'œil sur
   l'écran Rapports (fonds clairs figés, corrigé par Nadia en 3dfbf6d9).
   Même famille de défaut : une couleur qui NE SUIT PAS le thème alors que le
   texte, lui, le suit. Toutes les règles ci-dessous sont préfixées body.em-dark
   — elles ne peuvent donc pas s'appliquer en mode clair. */

/* Chiffre de tendance des cartes de suivi (« +219 », « +0 % vs juin 2026 »).
   Il utilise --em-success, un vert assombri CALIBRÉ POUR LE BLANC : 4.83:1 sur
   fond clair, mais seulement 3.36:1 sur la page sombre. On bascule sur le token
   de texte prévu pour le sombre (#7BDBCF côté my e-mam, #6EDADD côté Consulting) :
   mesuré 3.36 → 11.55. */
body.em-dark .em-kpi__trend { color: var(--em-success-text); }

/* Grands chiffres des cartes (« 6 481,98 € »). En clair ils sont passés au
   vert assombri (voir .em-kpi__value) ; sur fond sombre c'est l'inverse, la
   teinte vive de la charte reste la plus lisible — comportement inchangé. */
body.em-dark .em-kpi__value { color: var(--em-primary); }

/* ── UNIVERS CONSULTING ──
   Séparation des univers — pas 2 (07/08/2026, Elena, mandat Cyrille) : TOUTES
   les règles de l'univers Consulting (tokens Lot 1-4, cartes, badge, barre
   latérale, cadre) vivent désormais dans assets/css/consulting-theme.css,
   chargé par dashboard.html APRÈS ce fichier et après son <style> principal.
   NE PLUS AJOUTER de règle body.univers-consulting ici : ce fichier est
   100 % my e-mam (+ tokens :root partagés). */

img {
  max-width: 100%;
  display: block;
}

a {
  color: inherit;
  text-decoration: none;
}

button,
input,
select {
  font: inherit;
}

.em-page {
  min-height: 100vh;
}

.em-banner {
  background: #DAE7EA; /* gris pâle charte */
  border-bottom: 1px solid rgba(41, 165, 155, 0.12);
}

body.em-dark .em-banner {
  background: #1E2123; /* P2 */
}

.em-banner__inner {
  max-width: var(--em-max-width);
  min-height: var(--em-banner-height);
  margin: 0 auto;
  padding: 18px 24px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
}

.em-brandline {
  display: flex;
  align-items: center;
  gap: 16px;
}

.em-brandline__logo {
  width: 58px;
  height: 58px;
  border-radius: 50%;
  background: rgba(255,255,255,0.92);
  padding: 10px;
  box-shadow: var(--em-shadow-soft);
  object-fit: contain;
}

.em-brandline__title {
  margin: 0;
  font-size: 1.95rem;
  line-height: 1;
  color: var(--em-primary);
  letter-spacing: -0.02em;
}

.em-brandline__subtitle,
.em-banner__address,
.em-kpi__meta,
.em-section__eyebrow,
.em-page__meta,
.em-card__meta,
.em-footer__text,
.em-stat__label,
.em-table th,
.em-empty,
.em-subtle {
  font-family: "Inter", system-ui, -apple-system, Arial, sans-serif;
  font-weight: 300;
}

.em-brandline__subtitle,
.em-banner__address {
  margin: 6px 0 0;
  color: var(--em-text-soft);
  line-height: 1.45;
  font-size: 1.1rem;
}

.em-banner__address {
  max-width: 460px;
  text-align: left;
}

.em-topbar {
  position: sticky;
  top: 0;
  z-index: 60;
  backdrop-filter: blur(14px);
  background: rgba(255,255,255,0.82);
  border-bottom: 1px solid rgba(41, 165, 155, 0.12);
}

body.em-dark .em-topbar {
  background: rgba(20, 23, 24, 0.82); /* P1 */
}

.em-topbar__inner {
  max-width: var(--em-max-width);
  min-height: var(--em-topbar-height);
  margin: 0 auto;
  padding: 0 24px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
}

.em-topbar__left {
  display: flex;
  align-items: center;
  gap: 14px;
}

.em-topbar__logo {
  width: 38px;
  height: 38px;
  border-radius: 10px;
  object-fit: contain;
  background: rgba(255,255,255,0.9);
  padding: 4px;
  box-shadow: var(--em-shadow-soft);
}

/* Logo rectangulaire (ex. my e-mam SVG) */
.em-topbar__logo--wide {
  width: auto;
  height: 40px;
  border-radius: 8px;
  padding: 6px 10px;
  background: var(--em-primary);
}

.em-appname {
  color: var(--em-primary);
  font-size: 1.55rem;
}

.em-nav {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

/* Hamburger menu button — hidden on desktop */
.em-nav__burger {
  display: none;
  background: none;
  border: none;
  font-size: 1.5rem;
  cursor: pointer;
  padding: 8px 12px;
  border-radius: 8px;
  color: var(--em-text);
  transition: background 0.2s;
}
.em-nav__burger:hover {
  background: rgba(41, 165, 155, 0.08);
}

.em-nav__link {
  padding: 14px 18px;
  border-radius: 999px;
  color: var(--em-text-soft);
  transition: background var(--em-transition), color var(--em-transition), transform var(--em-transition);
}

.em-nav__link:hover,
.em-nav__link:focus-visible {
  background: rgba(41, 165, 155, 0.08);
  color: var(--em-primary-strong);
}

.em-nav__link.is-active {
  background: rgba(41, 165, 155, 0.14);
  color: var(--em-primary-strong);
  font-weight: 700;
}

.em-shell {
  max-width: var(--em-max-width);
  margin: 0 auto;
  padding: 32px 24px 48px;
}

.em-layout {
  display: grid;
  grid-template-columns: 1fr;
  gap: 24px;
}

.em-layout--admin {
  grid-template-columns: var(--em-sidebar-width) minmax(0, 1fr);
  align-items: start;
}

.em-sidebar {
  position: sticky;
  top: calc(var(--em-topbar-height) + 24px);
  background: rgba(255,255,255,0.72);
  border: 1px solid rgba(41, 165, 155, 0.12);
  border-radius: var(--em-radius-lg);
  box-shadow: var(--em-shadow-soft);
  padding: 20px;
}

body.em-dark .em-sidebar {
  background: rgba(30, 33, 35, 0.78); /* P2 */
}

.em-sidebar__title {
  margin: 0 0 14px;
  font-size: 1rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--em-primary-strong);
}

.em-sidebar__menu {
  display: grid;
  gap: 8px;
}

.em-sidebar__link {
  padding: 14px 16px;
  border-radius: 16px;
  color: var(--em-text-soft);
  transition: background var(--em-transition), color var(--em-transition), transform var(--em-transition);
}

.em-sidebar__link:hover,
.em-sidebar__link:focus-visible,
.em-sidebar__link.is-active {
  background: rgba(41, 165, 155, 0.12);
  color: var(--em-primary-strong);
}

.em-content {
  min-width: 0;
}

.em-page__eyebrow {
  display: inline-block;
  margin: 0 0 12px;
  color: var(--em-primary);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-size: 0.95rem;
}

.em-page__title {
  margin: 0;
  font-size: clamp(2.1rem, 4vw, 3.7rem);
  line-height: 0.98;
  letter-spacing: -0.03em;
}

.em-page__meta {
  margin: 14px 0 0;
  color: var(--em-text-soft);
  font-size: 1.25rem;
}

.em-toolbar {
  display: flex;
  gap: 12px;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  margin: 26px 0 12px;
}

.em-toolbar > div {
  min-width: 0;
}

.em-pillgroup {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}

/* Liseré : via token (Lot 4) — vert 14 % côté my e-mam (valeur :root strictement
   identique à l'ancienne couleur en dur), bleu profond 16 % côté Consulting. */
.em-pill,
.em-btn,
.em-search input,
.em-select {
  border: 1px solid var(--em-ctl-border, rgba(41, 165, 155, 0.14));
  border-radius: 999px;
  background: #fff;
}

body.em-dark .em-pill,
body.em-dark .em-btn:not(.em-btn--primary):not(.em-btn--danger),
body.em-dark .em-search input,
body.em-dark .em-select {
  background: rgba(255,255,255,0.06);
  color: var(--em-text);
}

.em-pill {
  padding: 14px 18px;
  color: var(--em-text-soft);
  font: inherit;
  cursor: pointer;
}

/* APLATS PORTANT DU TEXTE BLANC — arbitrage Cyrille 08/08/2026 21:06.
   Le vert charte #29A59B ne donne que 3.02:1 sous du blanc, et son dégradé
   vers #4CBFB4 descend à 2.59:1 : le libellé des boutons pleins et des pilules
   actives n'était pas lisible, dans les DEUX modes. On ne touche pas à la
   charte : #29A59B reste le vert my e-mam partout ailleurs (bandeaux, textes,
   icônes, accents). Ici on utilise les DÉRIVATIONS ASSOMBRIES déjà documentées
   de ce même vert — --em-acc-solid (#1F7E76, blanc 4.83:1) et
   --em-acc-solid-hover (#17635D, blanc 6.51:1) — dont le rôle déclaré est
   précisément « APLAT + texte blanc (boutons pleins) ». Le dégradé est conservé
   (même allure), il va simplement de vert foncé à vert moyen au lieu de vert
   moyen à vert clair. Paire déjà employée par le héros Bilan Ramadan.
   L'univers Consulting garde son apparence d'aujourd'hui : voir la règle
   miroir dans consulting-theme.css. */
.em-pill.is-active,
body.em-dark .em-pill.is-active {
  background: linear-gradient(135deg, var(--em-acc-solid-hover) 0%, var(--em-acc-solid) 100%);
  color: #fff;
  border-color: transparent;
}

.em-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 15px 22px;
  color: var(--em-primary-strong);
  background: #fff;
  box-shadow: var(--em-shadow-soft);
  transition: transform var(--em-transition), box-shadow var(--em-transition), background var(--em-transition);
  cursor: pointer;
}

.em-btn:hover,
.em-btn:focus-visible {
  transform: translateY(-1px);
  box-shadow: var(--em-shadow);
}

/* Même arbitrage que .em-pill.is-active ci-dessus : dérivations assombries du
   vert charte, parce que ce fond porte du texte blanc. 2.59:1 -> 4.83:1. */
.em-btn--primary {
  background: linear-gradient(135deg, var(--em-acc-solid-hover) 0%, var(--em-acc-solid) 100%);
  color: #fff;
  border-color: transparent;
}

/* Le voile vert ci-dessous assombrit le fond : la couleur de texte héritée de
   .em-btn (--em-primary-strong) n'y tient plus le seuil AA. On repasse donc par
   un token dédié, redéclaré en bleu sous body.univers-consulting (valeur
   identique à celle appliquée aujourd'hui : la bascule est un no-op strict pour
   l'univers Consulting). Voir --em-btn-ghost-text dans :root. */
.em-btn--ghost {
  background: rgba(41, 165, 155, 0.05);
  color: var(--em-btn-ghost-text);
}

.em-btn--danger {
  color: #fff;
  background: var(--em-danger);
  border-color: transparent;
}

.em-search {
  min-width: min(100%, 320px);
}

.em-search input,
.em-select {
  width: 100%;
  padding: 14px 18px;
  color: var(--em-text);
}

.em-grid {
  display: grid;
  gap: 18px;
}

/* FIX 04/08/2026 (débordement mobile) : un enfant de grille a une taille minimale
   automatique = min-content (un canvas de graphique ou un texte long peut alors
   élargir la piste au-delà de l'écran). min-width:0 rend chaque carte rétrécissable. */
.em-grid > * { min-width: 0; }

.em-grid--kpis {
  margin-top: 28px;
  grid-template-columns: repeat(4, minmax(0, 1fr));
}

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

.em-card {
  background: rgba(255,255,255,0.78);
  border: 1px solid rgba(41, 165, 155, 0.1);
  border-radius: var(--em-radius-md);
  box-shadow: var(--em-shadow-soft);
  padding: 24px;
}

body.em-dark .em-card {
  background: rgba(30, 33, 35, 0.84); /* P2 */
}

.em-card--glass {
  backdrop-filter: blur(10px);
}

.em-kpi {
  min-height: 174px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}

.em-kpi__label {
  margin: 0;
  font-size: 1.1rem;
  color: var(--em-text-soft);
}

.em-kpi__value {
  margin: 10px 0 0;
  font-size: clamp(1.6rem, 2.2vw, 2.6rem);
  line-height: 1.15;
  /* 06/09/2026 : --em-primary (#29A59B) mesuré 2.99:1 sur carte blanche, seuil
     3:1 — 56 écarts déclarés + 1 nouveau à chaque changement de montant. On
     passe au vert charte assombri documenté (4.9:1) ; en sombre, une règle
     body.em-dark plus bas garde la teinte vive (même motif que .em-kpi__trend). */
  color: var(--em-primary-strong);
  word-break: break-word;
}

.em-kpi__trend {
  color: var(--em-success);
  margin-top: 10px;
  font-size: 1.05rem;
}

.em-kpi__meta {
  margin-top: 10px;
  color: var(--em-text-soft);
  font-size: 1rem;
}

.em-card__head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 12px;
  margin-bottom: 18px;
}

.em-card__head > div {
  min-width: 0;
}

.em-card__title {
  margin: 0;
  font-size: 1.45rem;
  overflow-wrap: anywhere;
}

.em-card__meta {
  margin: 4px 0 0;
  color: var(--em-text-soft);
  font-size: 1.04rem;
}

.em-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 12px;
  border-radius: 999px;
  font-size: 0.92rem;
  white-space: nowrap;
}

.em-badge--success {
  color: var(--em-success);
  background: rgba(41, 165, 155, 0.12); /* vert charte 12 % */
}
body.em-dark .em-badge--success {
  color: #7BDBCF; /* vert clair charte */
  background: rgba(41, 165, 155, 0.24);
}

.em-badge--info {
  color: #49545B; /* gris charte assombri documenté — info = gris */
  background: rgba(93, 104, 110, 0.12); /* gris charte 12 % */
}
body.em-dark .em-badge--info {
  color: #BAC8CC; /* gris clair charte */
  background: rgba(151, 165, 170, 0.16);
}

.em-badge--warning {
  color: #A85212; /* orange charte assombri documenté (AA 5.4:1) */
  background: rgba(249, 137, 61, 0.13);
}
body.em-dark .em-badge--warning {
  color: #F9B698; /* pêche charte */
  background: rgba(249, 137, 61, 0.20);
}

.em-chart-wrap {
  position: relative;
  height: 180px;
  width: 100%;
  min-width: 0;
}

/* FIX 04/08/2026 : un canvas garde une largeur intrinsèque (attribut width) tant
   que Chart.js ne l'a pas redimensionné — il ne doit jamais élargir la page. */
.em-chart-wrap canvas { max-width: 100%; }

.em-chart {
  display: block;
  width: 100% !important;
  height: 100% !important;
}

.em-panel {
  background: rgba(255,255,255,0.74);
  border: 1px solid rgba(41, 165, 155, 0.1);
  border-radius: var(--em-radius-lg);
  box-shadow: var(--em-shadow-soft);
  padding: 32px 44px;
}

body.em-dark .em-panel {
  background: rgba(30, 33, 35, 0.84); /* P2 */
}

/* Cartes/panneaux univers Consulting : voir assets/css/consulting-theme.css */

.em-statrow {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 14px;
  margin-top: 18px;
}

.em-stat {
  border-radius: 18px;
  background: rgba(41, 165, 155, 0.05);
  padding: 18px;
}

.em-stat__value {
  font-size: 1.6rem;
  color: var(--em-primary-strong);
  margin: 0 0 6px;
}

.em-stat__label {
  color: var(--em-text-soft);
  margin: 0;
}

.em-table-wrap {
  overflow: auto;
  border: 1px solid rgba(41, 165, 155, 0.08);
  border-radius: 22px;
}

/* Conteneur défilant à hauteur fixe + en-tête collant (04/09/2026, retour Cyrille
   sur la page Comptabilité trésorier : le tableau Reçus fiscaux s'étalait sur
   toute la page). Volontairement DISTINCT de .em-table-wrap : ce dernier perd son
   border à 767px (voir plus bas, pattern "tableau → cartes" d'autres tableaux)
   et n'a pas de hauteur maxi — le défilement vertical recherché ici lui est propre. */
.em-recus-scroll {
  overflow: auto;
  max-height: 420px;
  border: 1px solid rgba(41, 165, 155, 0.08);
  border-radius: 22px;
}

.em-recus-scroll thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--em-surface, #fff);
}

@media (max-width: 767px) {
  .em-recus-scroll {
    max-height: 320px;
  }
}

/* ── Comptabilité trésorier sur mobile (audit mobile 28/09/2026, lot 4 — Elena) ──
   Le composant assets/js/comptabilite-tresorier.js est monté sur les DEUX boards
   (l'hôte porte data-ct-mounted) : ses règles mobiles vivent ici, pas dans une page.
   Présentation uniquement — aucun montant, aucun droit, aucun CSV ne passe par ici. */
@media (max-width: 1023px) {
  /* Cibles tactiles 44 px : tous les boutons et champs de l'écran, téléphone ET
     tablette (une tablette se pilote au doigt ; en 768 px les boutons faisaient
     31 à 41 px). Le visuel bureau ne change pas (paddings du gabarit inchangés). */
  [data-ct-mounted] .em-btn,
  [data-ct-mounted] select,
  [data-ct-mounted] input:not([type="checkbox"]):not([type="radio"]) {
    min-height: 44px;
    box-sizing: border-box;
  }
}

@media (max-width: 767px) {
  /* Liste des donateurs en cartes : le cadre défilant à hauteur fixe (retour
     Cyrille 04/09) reste borné, mais 320 px ne montrent qu'une carte et demie. */
  .em-recus-scroll:has(.ct-table--cartes) {
    max-height: min(480px, 70vh);
  }

  /* Tableaux → CARTES (≤ 5 colonnes utiles + actions) : « donateurs » et « reçus
     émis » du bloc Reçus fiscaux. Les libellés sont lus dans data-label, posés par
     le JS d'après l'EN-TÊTE du tableau (poserLibellesDepuisEntete) — JAMAIS écrits
     en dur ici (faute des cartes Mosquées corrigée au lot 1 : un libellé CSS finit
     par mentir). Les min-width 820/760 px du gabarit sont neutralisés. */
  .ct-table--cartes {
    display: block !important;
    width: 100% !important;
    min-width: 0 !important;
  }
  .ct-table--cartes thead {
    display: none !important;
  }
  .ct-table--cartes tbody {
    display: block !important;
    width: 100% !important;
  }
  .ct-table--cartes tr {
    display: block !important;
    width: 100% !important;
    box-sizing: border-box;
    margin: 0 0 10px;
    padding: 10px 12px;
    border: 1px solid var(--em-border, #DAE7EA);
    border-radius: 10px;
    background: var(--em-surface, #fff);
  }
  .ct-table--cartes td {
    display: flex !important;
    justify-content: space-between;
    align-items: flex-start;
    gap: 8px;
    width: 100%;
    box-sizing: border-box;
    min-width: 0;
    padding: 4px 0 !important;
    border: none !important;
    text-align: right !important;
    white-space: normal !important;
    overflow-wrap: anywhere;
  }
  .ct-table--cartes td[data-label]::before {
    content: attr(data-label);
    flex: 0 0 42%;
    text-align: left;
    font-weight: 600;
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    color: var(--em-text-soft, #5D686E);
  }
  /* Première cellule = titre de la carte (nom du donateur, numéro du reçu),
     son libellé au-dessus en petit. */
  .ct-table--cartes td:first-child {
    display: block !important;
    text-align: left !important;
    font-weight: 700 !important;
    font-size: 0.95rem;
    padding-bottom: 6px !important;
    margin-bottom: 4px;
    border-bottom: 1px solid var(--em-border, #DAE7EA) !important;
  }
  .ct-table--cartes td:first-child[data-label]::before {
    display: block;
    margin-bottom: 2px;
  }
  /* Cellule Actions : boutons empilés, pleine largeur, 44 px de haut. */
  .ct-table--cartes td.ct-cell-actions {
    flex-direction: column;
    align-items: stretch;
    text-align: left !important;
    padding-top: 8px !important;
  }
  .ct-table--cartes td.ct-cell-actions::before {
    flex: none;
  }
  .ct-table--cartes td.ct-cell-actions .em-btn {
    width: 100%;
    margin: 0 0 6px !important;
    justify-content: center;
  }
  /* Ligne dépliée « Choisir des dons… » (une cellule sur 6 colonnes) : bloc plein,
     une case à cocher par ligne, 44 px de haut. */
  .ct-table--cartes td[colspan] {
    display: block !important;
    text-align: left !important;
    padding: 8px 0 0 !important;
  }
  .ct-table--cartes td[colspan] label {
    display: flex !important;
    align-items: center;
    min-height: 44px;
    margin: 0 !important;
  }
}

.em-mosquee-cell {
  display: flex;
  align-items: center;
  gap: 12px;
}

.em-mosquee-cell--header {
  gap: 20px;
  margin-top: 12px;
  align-items: center;
}

.em-mosquee-logo {
  width: 36px;
  height: 36px;
  object-fit: contain;
  border-radius: 8px;
  flex-shrink: 0;
  background: rgba(255,255,255,0.9);
  padding: 3px;
  box-shadow: var(--em-shadow-soft);
}

.em-mosquee-logo--lg {
  width: 64px;
  height: 64px;
  border-radius: 14px;
  padding: 6px;
}

.em-table {
  width: 100%;
  border-collapse: collapse;
  min-width: 760px;
  background: transparent;
}

/* Tableaux LARGES (beaucoup de colonnes : téléchargements mensuels, gestion des
   rôles, activité commerciale HubSpot) : la largeur mini de 760 px est conservée
   à toutes les tailles, ils défilent dans leur cadre. Tous les autres tableaux
   perdent cette largeur mini sous 991 px (voir plus bas) — audit mobile 28/09/2026 :
   un tableau de 4 colonnes n'a aucune raison de forcer 760 px sur un écran de 375. */
.em-table--large {
  min-width: 760px;
}

.em-table th,
.em-table td {
  padding: 18px 16px;
  border-bottom: 1px solid rgba(41, 165, 155, 0.08);
  text-align: left;
}

.em-table th {
  color: var(--em-text-soft);
  background: rgba(41, 165, 155, 0.03);
  font-size: 1rem;
}

.em-table tbody tr:hover {
  background: rgba(41, 165, 155, 0.04);
}

.em-table td strong {
  font-size: 1.05rem;
}

.em-link {
  color: var(--em-primary);
  font-weight: 700;
}

.em-number-positive {
  color: var(--em-success);
}

.em-number-primary {
  color: var(--em-primary);
}

.em-section {
  margin-top: 28px;
}

.em-section__eyebrow {
  display: inline-block;
  margin-bottom: 10px;
  font-size: 0.95rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--em-primary-strong);
}

.em-footer {
  margin-top: 40px;
  padding: 28px 0 36px;
}

.em-footer__panel {
  max-width: var(--em-max-width);
  margin: 0 auto;
  padding: 30px 24px;
  background: rgba(255,255,255,0.7);
  border: 1px solid rgba(41, 165, 155, 0.1);
  border-radius: var(--em-radius-lg);
  box-shadow: var(--em-shadow-soft);
}

.em-footer__panel--compact {
  padding: 18px 24px;
  display: flex;
  align-items: center;
}

/* ── Toast ───────────────────────────────────────────────── */
.em-toast {
  position: fixed;
  bottom: 28px;
  left: 50%;
  transform: translateX(-50%) translateY(12px);
  background: var(--em-text);
  color: #fff;
  padding: 12px 22px;
  border-radius: 50px;
  font-size: 0.95rem;
  font-weight: 500;
  box-shadow: 0 8px 24px rgba(0,0,0,0.18);
  opacity: 0;
  transition: opacity 220ms ease, transform 220ms ease;
  z-index: 9999;
  pointer-events: none;
  white-space: nowrap;
}
.em-toast.is-visible {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}
body.em-dark .em-toast {
  background: var(--em-primary);
}

body.em-dark .em-footer__panel {
  background: rgba(30, 33, 35, 0.84); /* P2 */
}

.em-footer__logo {
  width: 260px;
  max-width: 100%;
  margin-bottom: 20px;
}

.em-footer__brand {
  margin-bottom: 24px;
  padding-bottom: 20px;
  border-bottom: 1px solid rgba(41, 165, 155, 0.1);
}

.em-footer__grid {
  display: grid;
  grid-template-columns: 1.2fr 1fr 1fr;
  gap: 22px;
}

.em-footer__title {
  margin: 0 0 10px;
  font-size: 1.55rem;
  color: var(--em-primary);
}

.em-footer__text {
  margin: 0;
  color: var(--em-text-soft);
  line-height: 1.65;
  font-size: 1.08rem;
}

.em-switch {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: var(--em-text-soft);
}

.em-switch input {
  accent-color: var(--em-primary);
}

.em-mobile-toggle {
  display: none;
}

@media (max-width: 1199px) {
  .em-layout--admin {
    grid-template-columns: 1fr;
  }

  .em-sidebar {
    position: static;
  }
}

@media (max-width: 991px) {
  .em-grid--kpis,
  .em-grid--2,
  .em-statrow,
  .em-footer__grid {
    grid-template-columns: 1fr 1fr;
  }

  /* Audit mobile 28/09/2026 : sous 991 px un tableau prend la largeur de son
     contenu, plus 760 px d'office. Seuls les tableaux .em-table--large gardent
     leur largeur mini (ils défilent dans .em-table-wrap). */
  .em-table {
    min-width: 0;
  }
  .em-table--large {
    min-width: 760px;
  }

  .em-banner__inner,
  .em-topbar__inner {
    padding-left: 18px;
    padding-right: 18px;
  }

  .em-shell {
    padding-left: 18px;
    padding-right: 18px;
  }
}

@media (max-width: 767px) {
  :root {
    --em-topbar-height: auto;
    --em-banner-height: auto;
  }

  .em-banner__inner,
  .em-topbar__inner,
  .em-toolbar,
  .em-brandline {
    align-items: flex-start;
  }

  .em-banner__inner,
  .em-topbar__inner {
    flex-direction: column;
  }

  .em-grid--kpis,
  .em-statrow,
  .em-footer__grid {
    grid-template-columns: 1fr;
  }

  /* Les charts restent côte à côte même sur mobile */
  .em-grid--2 {
    grid-template-columns: 1fr 1fr;
  }

  .em-page__title {
    font-size: 2.4rem;
  }

  .em-nav__burger {
    display: block;
  }

  .em-nav {
    width: 100%;
    flex-direction: column;
    gap: 0;
    display: none;
    background: var(--em-surface);
    border-radius: 12px;
    padding: 8px 0;
    box-shadow: 0 4px 16px rgba(0,0,0,0.1);
  }

  .em-nav.is-open {
    display: flex;
  }

  .em-nav__link {
    white-space: nowrap;
    width: 100%;
    padding: 12px 18px;
    border-radius: 0;
  }

  .em-nav__link:first-child {
    border-radius: 12px 12px 0 0;
  }

  .em-nav__link:last-child {
    border-radius: 0 0 12px 12px;
  }

  .em-sidebar__menu {
    grid-template-columns: 1fr 1fr;
  }

  .em-card,
  .em-footer__panel {
    padding: 20px;
  }

  /* Audit mobile 28/09/2026 : la hauteur mini de 174 px des cartes KPI
     (empilées en 1 colonne ici) creusait ~700 px de vide avant le contenu. */
  .em-kpi {
    min-height: auto;
  }

  .em-panel {
    padding: 28px 44px;
  }

  .em-chart-wrap {
    height: 130px;
  }

  /* ── Tableau Dons détail en Cards sur mobile ── */
  #dons-detail-table thead {
    display: none;
  }
  #dons-detail-table,
  #dons-detail-table tbody,
  #dons-detail-table tr,
  #dons-detail-table td {
    display: block;
    width: 100%;
  }
  #dons-detail-table tr {
    background: var(--em-surface-tint, #EEF7F6);
    border: 1px solid rgba(41, 165, 155, 0.12);
    border-radius: 12px;
    padding: 12px 14px;
    margin-bottom: 8px;
  }
  body.em-dark #dons-detail-table tr {
    background: var(--em-surface-tint, #272C2E);
  }
  #dons-detail-table td {
    padding: 2px 0;
    border-bottom: none;
    display: block;
    font-size: 0.9rem;
  }
  #dons-detail-table td:first-child {
    font-weight: 700;
    color: var(--em-primary, #29A59B);
    padding-bottom: 4px;
    margin-bottom: 4px;
    border-bottom: 1px solid rgba(41, 165, 155, 0.1);
  }

  /* ── Tableau Mosquées en Cards sur mobile ── */
  #mosqueesTable thead {
    display: none;
  }
  #mosqueesTable,
  #mosqueesTable tbody,
  #mosqueesTable tr,
  #mosqueesTable td {
    display: block;
    width: 100%;
  }
  #mosqueesTable tr {
    background: var(--em-surface-tint, #EEF7F6);
    border: 1px solid rgba(41, 165, 155, 0.12);
    border-radius: 14px;
    padding: 16px;
    margin-bottom: 12px;
  }
  body.em-dark #mosqueesTable tr {
    background: var(--em-surface-tint, #272C2E);
  }
  #mosqueesTable td {
    padding: 4px 0;
    border-bottom: none;
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: 0.92rem;
  }
  #mosqueesTable td:nth-child(1) {
    justify-content: flex-start;
    padding-bottom: 10px;
    margin-bottom: 8px;
    border-bottom: 1px solid rgba(41, 165, 155, 0.1);
  }
  /* Libellés des cartes : posés par le board via data-label (dashboard.css
     « #mosqueesTable td::before { content: attr(data-label) } », valeurs dans
     mosquees-dons-suivi.js). Les 5 libellés écrits en dur ici (« Nouveaux
     (févr.) », « Dons (févr.) », « Abonnés »…) ont été retirés le 28/09/2026
     (audit mobile, BLOQUANT) : leur sélecteur plus fort gagnait sur le
     data-label et affichait des mois faux toute l'année. Ne pas les remettre. */
  #mosqueesTable td:last-child {
    margin-top: 8px;
    padding-top: 10px;
    border-top: 1px solid rgba(41, 165, 155, 0.1);
    justify-content: center;
  }
  #mosqueesTable td:last-child .em-link {
    display: block;
    width: 100%;
    text-align: center;
    padding: 10px;
    background: rgba(41, 165, 155, 0.08);
    border-radius: 8px;
    font-weight: 600;
  }
  /* Le cadre garde son défilement (overflow: auto hérité) : un tableau large
     défile DANS son cadre au lieu de pousser toute la page. L'ancien
     « overflow: visible » mobile a été retiré le 28/09/2026 (audit mobile) —
     toute page sans surcharge débordait. Les 3 tableaux-cartes (Mosquées,
     Détail collectes, Comparatif) sont en display:block à 100 % : rien à défiler. */
  .em-table-wrap {
    border: none;
  }
}

@media (max-width: 479px) {
  .em-panel {
    padding: 24px 22px;
  }

  .em-brandline {
    flex-direction: row;
  }

  .em-brandline__logo {
    width: 48px;
    height: 48px;
  }

  .em-sidebar__menu {
    grid-template-columns: 1fr;
  }

  .em-pillgroup,
  .em-toolbar {
    width: 100%;
  }

  .em-search {
    min-width: 100%;
  }
}

/* ═══════════════════════════════════════
   Toggle Switch — Interrupteur ON/OFF
   ═══════════════════════════════════════ */
.em-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  cursor: pointer;
  user-select: none;
  font-size: 0.875rem;
  color: var(--em-text-soft, #7A878C);
}
.em-toggle__input {
  display: none;
}
.em-toggle__track {
  position: relative;
  width: 40px;
  height: 22px;
  background: var(--em-border, #DAE7EA);
  border-radius: 11px;
  transition: background 0.2s ease;
  flex-shrink: 0;
}
.em-toggle__track::after {
  content: '';
  position: absolute;
  top: 2px;
  left: 2px;
  width: 18px;
  height: 18px;
  background: #fff;
  border-radius: 50%;
  transition: transform 0.2s ease;
  box-shadow: 0 1px 3px rgba(0,0,0,0.15);
}
.em-toggle__input:checked + .em-toggle__track {
  background: var(--em-primary, #29A59B);
}
.em-toggle__input:checked + .em-toggle__track::after {
  transform: translateX(18px);
}
.em-toggle__label {
  font-weight: 500;
}

/* ============================================================
   Badges de statut inscriptions séminaires (Confirmé / Remboursé)
   Utilisés dans la table #sem-inscrits-tbody.
   ============================================================ */
.em-status-confirmed {
  background: rgba(41, 165, 155, 0.12); /* vert charte 12 % */
  color: #1F7E76; /* vert charte assombri AA */
  padding: 2px 8px;
  border-radius: 6px;
  font-size: 0.72rem;
  font-weight: 600;
  white-space: nowrap;
}
.em-status-refunded {
  background: rgba(239, 48, 84, 0.10); /* framboise charte 10 % */
  color: #C71C3F; /* framboise charte assombrie AA */
  padding: 2px 8px;
  border-radius: 6px;
  font-size: 0.72rem;
  font-weight: 600;
  white-space: nowrap;
}
.em-row-refunded td {
  text-decoration: line-through;
  text-decoration-color: rgba(199, 28, 63, 0.4); /* #C71C3F */
}

/* ═══ Journal des abonnements — lignes par statut (25/10/2026, Elena) ═══════
   Mandat Cyrille 25/10/2026 10h55 : « colorer les mosquées qui sont à jour,
   fond vert pour que ça saute aux yeux ». direction.js pose sur chaque <tr>
   une classe par GROUPE de statut : em-abo-row--ok (à jour), --confirm
   (à confirmer), --late (en retard / à mettre en place), --off (hors contrat).
   SEUL le groupe « ok » est coloré aujourd'hui — pas de rouge ni d'orange sans
   mandat ; les autres classes sont posées pour que la suite soit facile.
   La couleur vient du jeton --em-success-bg (clair + sombre), jamais écrite
   dans direction.js. Fond sur le <tr> : les cellules n'ont pas de fond propre,
   la ligne entière se teinte, les boutons de la colonne Actions gardent leur
   aspect. Test : scripts/tests/test-journal-abonnements-ligne-a-jour.mjs */
.em-abo-row--ok {
  background: var(--em-success-bg);
}
[data-theme="dark"] .em-status-confirmed,
body.em-dark .em-status-confirmed {
  background: rgba(41, 165, 155, 0.24);
  color: #7BDBCF; /* vert clair charte */
}
[data-theme="dark"] .em-status-refunded,
body.em-dark .em-status-refunded {
  background: rgba(239, 48, 84, 0.20);
  color: #E595AC; /* rose charte */
}

/* ═══════════════════════════════════════════════════════════
   Roadmap Phase 1 — Quick wins (06/05/2026, Elena)
   - em-progress-bar : barre fine 4px dans cartes projet
   - em-priority-badge : badge pill top-right (P0/P1/P2/high/medium/low)
   - em-owner-avatar : cercle 24px initiales agent owner
   - em-roadmap-filter-pill : filtres timeline
   - em-kpi-trend : flèche tendance vs J-7 (↑↓→)
   ═══════════════════════════════════════════════════════════ */

/* Progress bar fine */
.em-progress-bar {
  width: 100%;
  height: 4px;
  background: #DAE7EA; /* gris pâle charte */
  border-radius: 2px;
  overflow: hidden;
  margin: 6px 0 4px;
}
/* Barre de progression : passe par le token — #29A59B côté my e-mam,
   #185D96 côté Consulting. Aujourd'hui utilisée uniquement par la section
   Projets (Consulting) ; le token la rend sûre si elle est réutilisée ailleurs. */
.em-progress-bar__fill {
  height: 100%;
  background: var(--em-primary);
  border-radius: 2px;
  transition: width 300ms ease-out;
}
[data-theme="dark"] .em-progress-bar,
body.em-dark .em-progress-bar { background: #33393C; } /* P4 my e-mam */
/* .em-progress-bar sombre univers Consulting : voir assets/css/consulting-theme.css */

@media (prefers-reduced-motion: reduce) {
  .em-progress-bar__fill { transition: none; }
}

/* Badge priorité (top-right de la carte) */
.em-priority-badge {
  position: absolute;
  top: 8px;
  right: 8px;
  font-size: 11px;
  font-weight: 700;
  padding: 2px 6px;
  border-radius: 4px;
  color: #fff;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  line-height: 1.3;
  z-index: 2;
  pointer-events: none;
}
/* Variante « aplat + texte blanc » du badge de priorité (Lot 3 charte Consulting).
   Classes utilisées uniquement par la section Projets (dashboard.html), écran
   exclusivement Consulting → réécriture sur place. Chaque teinte tient 4.5:1
   avec le texte blanc du badge. En pratique la déclinaison « fond doux + texte
   coloré » du <style> de dashboard.html gagne (feuille plus tardive) ; ces
   valeurs sont le filet de sécurité et doivent rester dans la charte. */
.em-priority-p0 { background: #9B1531; }       /* 8.25 · framboise très assombrie */
.em-priority-p1 { background: #124570; }       /* 9.95 · bleu profond assombri */
.em-priority-high { background: #A85212; }     /* 5.41 · orange assombri */
.em-priority-p2,
.em-priority-medium { background: #5A5A5A; }   /* 6.90 · gris charte assombri */
.em-priority-low { background: #236B83; }      /* 6.00 · cyan assombri */

/* Avatar/initiales agent owner */
.em-owner-avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  font-size: 10px;
  font-weight: 700;
  color: #fff;
  letter-spacing: 0.02em;
  border: 2px solid var(--em-surface, #fff);
  position: relative;
  cursor: help;
  flex-shrink: 0;
}
.em-owner-avatar + .em-owner-avatar { margin-left: -8px; }
.em-owner-avatar-group {
  display: inline-flex;
  align-items: center;
}
[data-theme="dark"] .em-owner-avatar,
body.em-dark .em-owner-avatar { border-color: var(--em-card, #1E2123); } /* fallback my e-mam, le token suit l'univers */

/* Couleurs catégories agents */
/* ─── COULEURS DES PÔLES AGENTS (Lot 3 charte Consulting, 07/08/2026) ────────
   Ces pastilles ne sont posées QUE par la section Projets (renderProjects et
   renderRoadmap, dashboard.html) — un écran exclusivement Consulting : elles
   sont donc réécrites SUR PLACE en charte bleue, sans scoping.
   Contrainte : aplat portant les INITIALES EN BLANC → chaque teinte doit tenir
   4.5:1 avec le blanc. Les 5 bleus, 4 gris, 1 orange et 1 framboise de la charte
   n'offrent que 13 teintes lisibles pour 15 catégories : 4 dérivations
   supplémentaires (même teinte charte, luminosité abaissée) complètent la série.
   Toutes vérifiées sur blanc, aucune sous 4.5:1. */
.em-owner-cat-security { background: #9B1531; }   /* 8.25 · framboise très assombrie — Dmitri, Raven, Mudge, Nyx, Argus */
.em-owner-cat-tech { background: #185D96; }       /* 6.90 · bleu profond charte — Nadia, Akira, Sentinel-* */
.em-owner-cat-frontend { background: #1F6A7A; }   /* 6.17 · #49B9D1 assombri (L 55→30 %) — Elena, Hana */
.em-owner-cat-data { background: #124570; }       /* 9.95 · #185D96 assombri — Karim, Lina, Omar */
.em-owner-cat-qa { background: #236B83; }         /* 6.00 · #37A6CA assombri — Mei, Ravi, Clara, Tomas */
.em-owner-cat-doc { background: #1A4F61; }        /* 8.99 · #37A6CA assombri (L 50→24 %) — Ingrid, Hugo, Sana, Anthony */
.em-owner-cat-product { background: #1E5B6F; }    /* 7.55 · #6EDADD assombri — Viktor, Hana, Remi */
.em-owner-cat-marketing { background: #C71C3F; }  /* 5.73 · framboise assombrie — Jade, Nour, Felix, Aisha, Mateo */
.em-owner-cat-commercial { background: #A85212; } /* 5.41 · orange assombri — Tao, Leila, Bastien, Ines */
.em-owner-cat-finance { background: #19696B; }    /* 6.41 · #6EDADD assombri (L 65→26 %) — Sofia, Moussa */
.em-owner-cat-legal { background: #3F3F3F; }      /* 10.53 · gris charte assombri — Thea, Solène, Samara, Elif, Rafael */
.em-owner-cat-infra { background: #0E3758; }      /* 12.31 · #185D96 assombri (L 34→20 %) — Kenji, Zara, Ivan, Priya */
.em-owner-cat-memory { background: #813604; }     /* 8.53 · #F9893D assombri (L 61→26 %) — Herodote, Talia, Iris */
.em-owner-cat-boss { background: #15152D; }       /* 17.84 · bleu nuit charte — Cyrille, Servane, Gabin, Anthony, Claude Code */
.em-owner-cat-default { background: #707070; }    /* 4.95 · gris charte assombri — fallback inconnu */

/* Tooltip natif via title= ; backup CSS hover si besoin */
.em-owner-avatar[title]:hover::after {
  content: attr(title);
  position: absolute;
  bottom: calc(100% + 6px);
  left: 50%;
  transform: translateX(-50%);
  background: rgba(30,33,35,0.95); /* P2 */
  color: #fff;
  font-size: 11px;
  font-weight: 500;
  padding: 4px 8px;
  border-radius: 6px;
  white-space: nowrap;
  pointer-events: none;
  z-index: 10;
  letter-spacing: 0;
  text-transform: none;
}
@media (prefers-reduced-motion: reduce) {
  .em-owner-avatar[title]:hover::after { display: none; }
}

/* Filter pills Roadmap */
.em-roadmap-filter-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 12px 0 16px;
  align-items: center;
}
.em-roadmap-filter-pill {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 5px 12px;
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 600;
  border: 1px solid var(--em-border, #DAE7EA);
  background: var(--em-surface, #fff);
  color: var(--em-text-soft, #7A878C);
  cursor: pointer;
  transition: background 0.18s, border-color 0.18s, color 0.18s;
  user-select: none;
  font-family: inherit;
}
.em-roadmap-filter-pill:hover {
  border-color: var(--em-primary, #29A59B);
  color: var(--em-primary, #29A59B);
}
.em-roadmap-filter-pill.is-active {
  background: var(--em-primary, #29A59B);
  border-color: var(--em-primary, #29A59B);
  color: #fff;
}
.em-roadmap-filter-pill__count {
  font-size: 0.68rem;
  background: rgba(255,255,255,0.25);
  padding: 1px 6px;
  border-radius: 8px;
  font-weight: 700;
}
.em-roadmap-filter-pill:not(.is-active) .em-roadmap-filter-pill__count {
  background: var(--em-surface-alt, #F1F7F6);
  color: var(--em-text-soft, #7A878C);
}
[data-theme="dark"] .em-roadmap-filter-pill,
body.em-dark .em-roadmap-filter-pill {
  background: var(--em-card, #1E2123);
  border-color: rgba(123,219,207,0.18);
}
[data-theme="dark"] .em-roadmap-filter-pill:not(.is-active) .em-roadmap-filter-pill__count,
body.em-dark .em-roadmap-filter-pill:not(.is-active) .em-roadmap-filter-pill__count {
  background: rgba(123,219,207,0.10);
}
@media (prefers-reduced-motion: reduce) {
  .em-roadmap-filter-pill { transition: none; }
}

/* KPI trend arrow */
.em-kpi-trend {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  font-size: 0.72rem;
  font-weight: 600;
  margin-left: 6px;
  vertical-align: middle;
}
.em-kpi-trend--up { color: #1F7E76; } /* vert charte assombri AA */
.em-kpi-trend--down { color: #C71C3F; } /* framboise charte assombrie AA */
.em-kpi-trend--flat { color: var(--em-text-soft, #97A5AA); }
[data-theme="dark"] .em-kpi-trend--up,
body.em-dark .em-kpi-trend--up { color: #7BDBCF; } /* vert clair charte */
[data-theme="dark"] .em-kpi-trend--down,
body.em-dark .em-kpi-trend--down { color: #E595AC; } /* rose charte */

/* Carte avec position relative pour badge absolu */
.roadmap-card { position: relative; }

/* === Audits vague 2 (2026-06-14, Elena) — Contour clavier visible (WCAG 2.4.7) ===
   Rétablit un anneau de focus net pour la navigation clavier, sans gêner la souris.
   :focus-visible ne se déclenche qu'au clavier (pas au clic souris). */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible,
[role="button"]:focus-visible,
[role="tab"]:focus-visible,
.em-btn:focus-visible,
.em-nav__link:focus-visible,
.em-sidebar__link:focus-visible {
  outline: 2px solid var(--em-primary-strong);
  outline-offset: 2px;
  border-radius: 6px;
}
/* Fin audits vague 2 — focus visible */

/* ════════════════════════════════════════════════════════════════
   Onglet Comparatif du Suivi (Lot 2 v2 classement-anonyme-mosquees,
   27/08/2026, Elena) — tableau de comparaison pur des 19 mosquées.
   Charte verte stricte : tokens sémantiques existants uniquement.
   ════════════════════════════════════════════════════════════════ */
/* Chiffres à chasse fixe : colonnes alignées, comparaison à l'œil */
#comparatifTable tbody td,
#comparatifTable tfoot td {
  font-variant-numeric: tabular-nums;
}
/* Croissance dons vs mois précédent : vert charte assombri / framboise charte
   (tokens AA --em-success-text / --em-danger-text, adaptés clair/sombre) */
.comparatif-croiss { font-weight: 600; white-space: nowrap; }
.comparatif-croiss--up { color: var(--em-success-text, #1F7E76); }
.comparatif-croiss--down { color: var(--em-danger-text, #C71C3F); }
/* Base faible (02/09/2026) : mois précédent sous 50 € → écart en euros, gris
   discret (--em-text-muted charte), jamais le vert/framboise d'un vrai % */
.em-trend--faible { color: var(--em-text-muted, #7A878C); font-weight: 500; white-space: nowrap; }
body.em-dark .em-trend--faible { color: var(--em-text-soft, #BAC8CC); }
/* Ligne TOTAL réseau : collée en bas du conteneur défilant (desktop),
   fond opaque pour rester lisible au-dessus des lignes qui défilent */
#comparatifTable tfoot tr.comparatif-total-row td {
  position: sticky;
  bottom: 0;
  background: var(--em-surface, #FFFFFF);
  border-top: 2px solid var(--em-primary, #29A59B);
  font-weight: 600;
  z-index: 1;
}

/* ── Graphique comparatif (Lot 2 v3, 27/08/2026) : 5 métriques, un graphique
      en barres horizontales à la fois. HTML/CSS pur, tokens charte. ── */
.comparatif-chip {
  padding: 7px 14px;
  background: var(--em-bg, #F6FAF9);
  color: var(--em-text-soft);
  border: 1px solid var(--em-border, #DAE7EA);
  border-radius: 999px;
  cursor: pointer;
  font-size: 0.83rem;
  font-weight: 600;
  transition: background 0.2s, color 0.2s;
}
/* Puce active : même dérivation assombrie que les onglets du Suivi
   (--em-acc-solid sous texte blanc — le vert plein ne donne que 3.02:1) */
.comparatif-chip.is-active {
  background: var(--em-acc-solid, #1F7E76);
  color: #fff;
  border-color: transparent;
}
.comparatif-chart-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 3px 0;
}
.comparatif-chart-label {
  flex: 0 0 190px;
  max-width: 190px;
  font-size: 0.82rem;
  font-weight: 600;
  text-align: right;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.comparatif-chart-track {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}
.comparatif-chart-bar {
  display: inline-block;
  height: 18px;
  border-radius: 5px;
  background: var(--em-primary, #29A59B);
  transition: width 0.4s ease;
  /* Retour JB 28/08 : la barre peut RÉTRÉCIR pour laisser sa place à la
     valeur (flex-shrink 1) — à 100 % la valeur du n°1 ne sort plus du
     cadre blanc. min-width garde la barre visible même très comprimée. */
  flex: 0 1 auto;
  min-width: 3px;
}
/* Croissance : vert charte assombri / framboise charte selon le signe */
.comparatif-chart-bar--up { background: var(--em-success-text, #1F7E76); }
.comparatif-chart-bar--down { background: var(--em-danger-text, #C71C3F); }
.comparatif-chart-value {
  font-size: 0.8rem;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  color: var(--em-text-soft);
  flex: 0 0 auto; /* la valeur garde toujours sa largeur, jamais rognée */
}
@media (prefers-reduced-motion: reduce) {
  .comparatif-chip, .comparatif-chart-bar { transition: none; }
}

/* ── Comparatif en cards sur mobile (recette 375px) — même pattern que le
      tableau Mosquées, libellés lus depuis data-label (posés par le JS) ── */
@media (max-width: 767px) {
  #comparatifTable thead { display: none; }
  #comparatifTable,
  #comparatifTable tbody,
  #comparatifTable tfoot,
  #comparatifTable tr,
  #comparatifTable td {
    display: block;
    width: 100%;
  }
  #comparatifTable tr {
    background: var(--em-surface-tint, #EEF7F6);
    border: 1px solid rgba(41, 165, 155, 0.12);
    border-radius: 14px;
    padding: 16px;
    margin-bottom: 12px;
  }
  body.em-dark #comparatifTable tr { background: var(--em-surface-tint, #272C2E); }
  #comparatifTable td {
    padding: 4px 0;
    border-bottom: none;
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: 0.92rem;
  }
  #comparatifTable td:first-child {
    justify-content: flex-start;
    padding-bottom: 10px;
    margin-bottom: 8px;
    border-bottom: 1px solid rgba(41, 165, 155, 0.1);
  }
  #comparatifTable td[data-label]:not(:first-child)::before {
    content: attr(data-label);
    font-weight: 600;
    color: var(--em-text-soft);
    font-size: 0.82rem;
  }
  /* Carte TOTAL réseau : accent charte, sticky desktop neutralisé */
  #comparatifTable tfoot tr.comparatif-total-row td { position: static; border-top: none; background: transparent; }
  #comparatifTable tfoot tr.comparatif-total-row { border: 2px solid var(--em-primary, #29A59B); }
  /* Graphique : libellés tronqués avec ellipse + valeur compacte (375px) */
  .comparatif-chart-label { flex-basis: 96px; max-width: 96px; font-size: 0.75rem; }
  .comparatif-chart-value { font-size: 0.72rem; }
  .comparatif-chart-bar { height: 14px; }
}

/* ═══════════════════════════════════════════════════════════════════════
   AUDIT MOBILE 28/09/2026 — LOT 3 : CIBLES TACTILES 44 px (Elena, 29/09/2026)
   Deux classes communes aux DEUX boards (dashboard.html et pages/dashboard.html).
   · .em-close-44 : croix de fermeture des modales. La zone cliquable fait 44×44
     minimum (Apple HIG / WCAG 2.5.5) ; le glyphe garde sa taille, il est centré.
     Avant : ~15×25 à 37×30 selon la croix (mesuré en 375 px, Chrome headless).
   · .em-tap-44 : pour un bouton qu'on ne veut pas agrandir visuellement (barre du
     haut : agrandir les 4 boutons ferait déborder la barre en 375 px). Un ::before
     invisible étend la zone de clic à 44×44 minimum, centré sur le bouton ; le
     clic sur ce pseudo-élément arrive au bouton lui-même. Ne pas poser sur des
     boutons empilés à moins de 44 px de distance (la zone du suivant passerait
     devant) : dans ce cas, utiliser une vraie hauteur mini (voir dashboard.css).
   ═══════════════════════════════════════════════════════════════════════ */
.em-close-44 {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  padding: 0;
  box-sizing: border-box;
  touch-action: manipulation;
}
.em-tap-44 {
  position: relative;
  touch-action: manipulation;
}
.em-tap-44::before {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: max(100%, 44px);
  height: max(100%, 44px);
  transform: translate(-50%, -50%);
}

/* ═══════════════════════════════════════════════════════════════════════
   JUSTIFICATIF DE VIREMENT (Comptabilité trésorier) — Elena, 07/10/2026
   Script : assets/js/justificatif-versement.js. Moteur : Nadia
   (/api/tresorier/justificatif-versement).
   · Écran : liste des virements dans la carte « Justificatifs de virement »,
     puis un CALQUE plein écran qui porte une feuille A4 (thème clair/sombre
     par les variables --em-*).
   · Impression : tout le board est masqué (body.em-jv-ouvert), seule la
     feuille sort, en A4 paysage (12 colonnes lisibles), en noir sur blanc,
     coupure de page ENTRE les lignes, en-tête du tableau répété à chaque page.
   ═══════════════════════════════════════════════════════════════════════ */
.em-jv-actions { display: flex; gap: 10px; flex-wrap: wrap; margin: 0 0 8px; }
.em-jv-actualiser {
  padding: 8px 14px; border-radius: 10px; font-size: 0.85rem; cursor: pointer;
  background: var(--em-surface, #fff); color: var(--em-text); border: 1px solid var(--em-border, #DAE7EA);
}
.em-jv-statut { margin: 0 0 10px; min-height: 1.1em; font-size: 0.82rem; color: var(--em-text-soft); }
.em-jv-statut--attente { color: var(--em-text); }
.em-jv-statut--ok { color: var(--em-primary-strong, #1F7E76); font-weight: 600; }
.em-jv-statut--ko, .em-jv-statut--ecart {
  padding: 10px 12px; border-radius: 10px; font-weight: 600; color: var(--em-text);
  background: rgba(239, 48, 84, 0.10); border: 1px solid rgba(239, 48, 84, 0.35);
}
.em-jv-statut--info {
  padding: 10px 12px; border-radius: 10px; color: var(--em-text);
  background: var(--em-surface-alt, #F1F7F6); border: 1px solid var(--em-border, #DAE7EA);
}
.em-jv-vide, .em-jv-note { margin: 0 0 10px; font-size: 0.82rem; color: var(--em-text-soft); }
.em-jv-liste-cadre { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.em-jv-liste { width: 100%; border-collapse: collapse; font-size: 0.82rem; min-width: 520px; }
.em-jv-liste th {
  text-align: left; padding: 6px 8px; font-weight: 600; color: var(--em-text-soft);
  border-bottom: 1px solid var(--em-border, #DAE7EA);
}
.em-jv-liste td { padding: 8px; border-bottom: 1px solid var(--em-border, #DAE7EA); color: var(--em-text); vertical-align: middle; }
.em-jv-liste .em-jv-montant { font-weight: 700; white-space: nowrap; }
.em-jv-sous { display: block; font-size: 0.74rem; color: var(--em-text-soft); }
.em-jv-voir { padding: 7px 12px; border-radius: 10px; font-size: 0.8rem; cursor: pointer; white-space: nowrap; }
.em-jv-badge { display: inline-block; padding: 2px 10px; border-radius: 999px; font-size: 0.74rem; font-weight: 700; }
.em-jv-badge--ok { background: var(--em-primary-pale, #C7F2EA); color: #1F7E76; }
.em-jv-badge--attente { background: rgba(249, 137, 61, 0.16); color: #A85212; }
.em-jv-badge--ko { background: rgba(239, 48, 84, 0.14); color: #B3213F; }
body.em-dark .em-jv-badge--ok { background: rgba(41, 165, 155, 0.22); color: #7BDBCF; }
body.em-dark .em-jv-badge--attente { color: #F9B98A; }
body.em-dark .em-jv-badge--ko { color: #F58AA0; }

/* Calque + feuille A4 à l'écran */
body.em-jv-ouvert { overflow: hidden; }
.em-jv-calque {
  position: fixed; inset: 0; z-index: 10000; overflow: auto;
  background: rgba(20, 23, 24, 0.55); padding: 16px;
  -webkit-overflow-scrolling: touch;
}
.em-jv-barre {
  position: sticky; top: 0; z-index: 1; display: flex; flex-wrap: wrap; gap: 10px; align-items: center;
  max-width: 297mm; margin: 0 auto 12px; padding: 10px 12px; border-radius: 12px;
  background: var(--em-surface, #fff); border: 1px solid var(--em-border, #DAE7EA);
}
.em-jv-barre .em-btn { padding: 10px 16px; border-radius: 10px; font-size: 0.88rem; cursor: pointer; min-height: 44px; }
.em-jv-fermer { background: var(--em-surface, #fff); color: var(--em-text); border: 1px solid var(--em-border, #DAE7EA); }
.em-jv-astuce { font-size: 0.78rem; color: var(--em-text-soft); }
/* La feuille est un PAPIER : toujours claire, même quand le board est en mode
   sombre (08/10/2026 — logos ORIAS/ACPR/France FinTech et logo transpar'ensemble
   faits pour un fond blanc). Les variables sont reposées sur la feuille : tout ce
   qu'elle contient reste en clair, sans règle « body.em-dark » à contrer. */
.em-jv-feuille {
  --em-surface: #fff; --em-surface-alt: #F1F7F6; --em-text: #1D2326; --em-text-soft: #5D686E;
  --em-border: #DAE7EA; --em-primary: #29A59B; --em-primary-strong: #1F7E76;
  box-sizing: border-box; max-width: 297mm; margin: 0 auto; padding: 12mm 12mm;
  background: #fff; color: #1D2326; border-radius: 6px; color-scheme: light;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.25); font-size: 0.82rem;
}
.em-jv-mise-en-page { width: 100%; border-collapse: collapse; }
.em-jv-mise-en-page > tbody > tr > td, .em-jv-mise-en-page > tfoot > tr > td { padding: 0; }
.em-jv-pied-page {
  padding: 8px 0 0 !important; border-top: 1px solid var(--em-border); font-size: 0.68rem;
  color: var(--em-text-soft); text-align: center;
}
/* En-tête = l'émetteur (transpar'ensemble, IFP), puis la bande titre. */
.em-jv-tete { padding-bottom: 0; }
.em-jv-emetteur { display: flex; justify-content: space-between; align-items: center; gap: 16px; }
.em-jv-emetteur-ident { display: flex; align-items: center; gap: 14px; min-width: 0; }
.em-jv-logo-te { flex: none; width: 123px; height: 52px; object-fit: contain; }
.em-jv-emetteur-coord { min-width: 0; }
.em-jv-emetteur-nom { margin: 0 0 2px; font-size: 0.95rem; font-weight: 800; }
.em-jv-emetteur-qualite { font-weight: 700; color: var(--em-primary-strong); }
.em-jv-emetteur-ligne { margin: 0; font-size: 0.72rem; line-height: 1.4; color: var(--em-text-soft); }
.em-jv-partenaires { flex: none; display: flex; align-items: center; gap: 14px; }
.em-jv-partenaire { flex: none; object-fit: contain; }
.em-jv-titre-bande {
  display: flex; justify-content: space-between; align-items: flex-end; gap: 16px;
  margin-top: 10px; padding: 8px 0; border-top: 1px solid var(--em-border); border-bottom: 3px solid var(--em-primary);
}
.em-jv-titre { margin: 0; font-size: 1.25rem; font-weight: 800; color: var(--em-primary-strong); }
.em-jv-via { margin: 2px 0 0; font-size: 0.7rem; color: var(--em-text-soft); display: flex; align-items: center; gap: 4px; }
.em-jv-logo-myemam { flex: none; width: 14px; height: 14px; border-radius: 3px; }
.em-jv-tete-doc { text-align: right; }
.em-jv-ref { margin: 0; font-size: 0.76rem; color: var(--em-text-soft); }
/* Ensuite : la mosquée bénéficiaire. */
.em-jv-beneficiaire {
  display: flex; align-items: center; gap: 12px; margin: 12px 0 0; padding: 8px 12px;
  border: 1px solid var(--em-border); border-left: 4px solid var(--em-primary); border-radius: 8px;
}
.em-jv-beneficiaire-lib { margin: 0; font-size: 0.66rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--em-text-soft); }
.em-jv-logo { flex: none; width: 110px; height: 48px; object-fit: contain; }
.em-jv-mosquee-nom { margin: 0; font-size: 1.1rem; font-weight: 700; }
.em-jv-mosquee-asso { margin: 2px 0 0; font-size: 0.78rem; color: var(--em-text-soft); }
.em-jv-bandeau { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; margin: 14px 0 4px; }
.em-jv-cle { padding: 8px 10px; border: 1px solid var(--em-border, #DAE7EA); border-radius: 8px; }
.em-jv-cle-lib { display: block; font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.03em; color: var(--em-text-soft); }
.em-jv-cle-val { display: block; font-weight: 600; margin-top: 2px; }
.em-jv-cle-val--fort { font-size: 1.25rem; font-weight: 800; color: var(--em-primary-strong, #1F7E76); }
.em-jv-mention { margin: 4px 0 12px; font-size: 0.72rem; color: var(--em-text-soft); }
.em-jv-feuille h3 { margin: 14px 0 6px; font-size: 0.95rem; font-weight: 700; }
.em-jv-table-totaux { border-collapse: collapse; min-width: 320px; max-width: 520px; width: 100%; }
.em-jv-table-totaux th { text-align: left; font-weight: 500; padding: 4px 8px 4px 0; }
.em-jv-table-totaux td { padding: 4px 0; }
.em-jv-table-totaux .em-jv-sous-total th, .em-jv-table-totaux .em-jv-sous-total td { border-top: 1px solid var(--em-border, #DAE7EA); font-weight: 600; }
.em-jv-table-totaux .em-jv-total th, .em-jv-table-totaux .em-jv-total td { border-top: 2px solid var(--em-primary, #29A59B); font-weight: 800; font-size: 0.95rem; }
.em-jv-num { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
.em-jv-controle { margin: 8px 0 0; font-size: 0.76rem; color: var(--em-primary-strong, #1F7E76); }
.em-jv-table-cadre { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.em-jv-table { width: 100%; border-collapse: collapse; font-size: 0.72rem; min-width: 980px; }
.em-jv-table th { text-align: left; padding: 4px 5px; font-weight: 600; border-bottom: 1px solid var(--em-text-soft, #5D686E); }
.em-jv-table .em-jv-rappel th { font-weight: 500; font-size: 0.68rem; color: var(--em-text-soft); border-bottom: none; }
.em-jv-table td { padding: 3px 5px; border-bottom: 1px solid var(--em-border, #DAE7EA); vertical-align: top; }
.em-jv-email, .em-jv-ref-stripe { overflow-wrap: anywhere; }
.em-jv-ligne--remboursement td, .em-jv-ligne--prelevement_rejete td { background: rgba(239, 48, 84, 0.06); }
.em-jv-partiel { display: block; font-size: 0.66rem; color: #A85212; white-space: normal; }
.em-jv-ligne-total td { font-weight: 700; border-top: 2px solid var(--em-text-soft, #5D686E); }
.em-jv-pied { margin: 14px 0 0; font-size: 0.7rem; color: var(--em-text-soft); }

@media (max-width: 767px) {
  .em-jv-calque { padding: 8px; }
  .em-jv-feuille { padding: 16px 12px; }
  .em-jv-emetteur, .em-jv-emetteur-ident, .em-jv-titre-bande { flex-wrap: wrap; }
  .em-jv-tete-doc { text-align: left; }
}
@media (prefers-reduced-motion: reduce) {
  .em-jv-calque { scroll-behavior: auto; }
}

@media print {
  @page { size: A4 landscape; margin: 10mm; }
  body.em-jv-ouvert { overflow: visible !important; background: #fff !important; }
  body.em-jv-ouvert > *:not(.em-jv-calque) { display: none !important; }
  body.em-jv-ouvert .em-jv-calque { position: static !important; inset: auto; padding: 0 !important; overflow: visible !important; background: #fff !important; }
  body.em-jv-ouvert .em-jv-barre { display: none !important; }
  body.em-jv-ouvert .em-jv-feuille {
    max-width: none; margin: 0; padding: 0; box-shadow: none; border-radius: 0;
    background: #fff !important; color: #000 !important; font-size: 9pt;
  }
  body.em-jv-ouvert .em-jv-feuille * { color: #000 !important; }
  body.em-jv-ouvert .em-jv-table-cadre { overflow: visible !important; }
  body.em-jv-ouvert .em-jv-table { min-width: 0; font-size: 7.5pt; }
  body.em-jv-ouvert .em-jv-table thead { display: table-header-group; }
  /* Mention réglementaire (ACPR, Orias, IFP) en bas de CHAQUE page imprimée. */
  body.em-jv-ouvert .em-jv-mise-en-page > tfoot { display: table-footer-group; }
  body.em-jv-ouvert .em-jv-pied-page { font-size: 7pt; border-top-color: #999 !important; }
  body.em-jv-ouvert .em-jv-beneficiaire { break-inside: avoid; page-break-inside: avoid; border-color: #999 #999 #999 #29A59B !important; }
  body.em-jv-ouvert .em-jv-tete, body.em-jv-ouvert .em-jv-beneficiaire { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  body.em-jv-ouvert .em-jv-table tr,
  body.em-jv-ouvert .em-jv-table-totaux tr,
  body.em-jv-ouvert .em-jv-bandeau,
  body.em-jv-ouvert .em-jv-tete { break-inside: avoid; page-break-inside: avoid; }
  body.em-jv-ouvert .em-jv-cle, body.em-jv-ouvert .em-jv-table td, body.em-jv-ouvert .em-jv-table th { border-color: #999 !important; }
  body.em-jv-ouvert .em-jv-ligne--remboursement td, body.em-jv-ouvert .em-jv-ligne--prelevement_rejete td { background: #f3f3f3 !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
}

/* ═══ Bandeau « Données d'exemple » — mosquée DÉMO uniquement (L3, 01/11/2026) ═══
   Posé par assets/js/em-mosquee-demo.js en tête de la fiche démo. Discret
   (une ligne fine, couleurs de la charte) mais lisible à l'écran filmé.
   Mode sombre : body.em-dark (em-ui-v2.js, clé emTheme). */
.em-bandeau-demo {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 12px 0 14px;
  padding: 8px 14px;
  background: var(--em-primary-pale, #C7F2EA);
  border: 1px solid rgba(41, 165, 155, 0.45);
  border-left: 4px solid var(--em-primary, #29A59B);
  border-radius: 10px;
  color: #1F4F4A;
  font-size: 0.85rem;
  line-height: 1.35;
}
.em-bandeau-demo__pastille {
  flex-shrink: 0;
  padding: 2px 9px;
  border-radius: 999px;
  background: var(--em-primary, #29A59B);
  color: #fff;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.06em;
}
.em-bandeau-demo__texte { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; min-width: 0; }
.em-bandeau-demo__texte strong { font-weight: 700; }
.em-bandeau-demo__detail { font-size: 0.78rem; opacity: 0.85; }
body.em-dark .em-bandeau-demo,
[data-theme="dark"] .em-bandeau-demo {
  background: rgba(41, 165, 155, 0.16);
  border-color: rgba(41, 165, 155, 0.5);
  color: #D7F3EF;
}
@media (max-width: 600px) {
  .em-bandeau-demo { margin: 8px 0 10px; padding: 7px 10px; font-size: 0.8rem; }
  .em-bandeau-demo__detail { display: none; }
}
