/* ═══ Typo premium : SATOSHI (variable 300–900) ═══ */
@font-face{font-family:'Satoshi';font-style:normal;font-weight:300 900;font-display:swap;src:url('fonts/satoshi-variable.woff2') format('woff2');}
/* Alias : le code historique qui demande Montserrat rend Satoshi
   (refonte typo en 1 endroit, sans toucher aux références éparpillées). */
@font-face{font-family:'Montserrat';font-style:normal;font-weight:300 900;font-display:swap;src:url('fonts/satoshi-variable.woff2') format('woff2');}
/* POPPINS — vraie fonte, rétablie le 2026-08-11 (contrat V7 §5.5 : « Titre de page /
   Titre de panneau → Poppins 600 »). Elle était aliasée sur Satoshi depuis la refonte
   typo ; les deux .woff2 n'ont jamais quitté le dépôt, donc rien n'est « ajouté » ici
   au sens du §3.3 — on cesse simplement de détourner la famille.
   ⚠️ Deux graisses SEULEMENT (600, 700). C'est la raison pour laquelle `--font-title`
   ne pointe PAS ici : le logo (`inc/helpers_logo.php`) le consomme en 780 et 800, que
   Poppins ne sait pas rendre et que le navigateur synthétiserait — or le logo est hors
   périmètre par consigne. Poppins est donc exposée par `--font-display`, réservée aux
   titres du contrat V7. */
@font-face{font-family:'Poppins';font-style:normal;font-weight:600;font-display:swap;src:url('fonts/poppins-latin-600-normal.woff2') format('woff2');}
@font-face{font-family:'Poppins';font-style:normal;font-weight:700;font-display:swap;src:url('fonts/poppins-latin-700-normal.woff2') format('woff2');}
@font-face{font-family:'JetBrains Mono';font-style:normal;font-weight:400;font-display:swap;src:url('fonts/jetbrains-mono-latin-400-normal.woff2') format('woff2');}
@font-face{font-family:'JetBrains Mono';font-style:normal;font-weight:500;font-display:swap;src:url('fonts/jetbrains-mono-latin-500-normal.woff2') format('woff2');}
@font-face{font-family:'JetBrains Mono';font-style:normal;font-weight:600;font-display:swap;src:url('fonts/jetbrains-mono-latin-600-normal.woff2') format('woff2');}

/* ════════════════════════════════════════════════════════
   PROSPEKT-HIM — Design System V2
   ════════════════════════════════════════════════════════ */

/* ─── VARIABLES ─── */
/* ════════════════════════════════════════════════════════
   THÈME : Futuristic / Liquid Glass — accent azur #0A6FD0
   Nightfall (nuit) DÉFINITIF · light conservé en option [data-theme="light"]
   ════════════════════════════════════════════════════════ */

/* ═══ Variables GLOBALES (communes aux 2 thèmes) ═══ */
:root {
  /* [DS-0 2026-08-08] Les rayons ne sont PLUS déclarés ici. L'échelle Blue Frost
     (6/8/10/12/14/16 px) a été remplacée par une valeur unique de 2 px dans
     css/tokens.css, seul fichier autorisé à déclarer --radius*. Les règles de
     cette feuille continuent de consommer var(--radius…) sans changement.
     Verrouillé par tests/design_tokens_contract_test.js. */

  /* base accent réutilisable (tue les rgba(var(--accent-rgb),…) littéraux au balayage P3) */
  --accent-rgb: 8,112,207;

  /* ═══ Échelle de BREAKPOINTS (RÉFÉRENCE — les var CSS ne fonctionnent pas dans @media,
     donc on documente). Le commentaire précédent annonçait « ces 4 valeurs, pas une de plus »
     alors que css/ en compte une vingtaine : une règle écrite que le code contredit n'aide
     personne. On décrit donc le système EFFECTIF, et on s'y tient pour tout NOUVEAU palier. ═══

     PALIERS STRUCTURANTS (les seuls à utiliser pour une nouvelle règle) :
        480px  = mobile (densité / typo réduite)                    [~10 usages]
        640px  = petit mobile / bascule de grilles denses           [~12 usages] ← palier réel, longtemps non documenté
        768px  = tablette portrait → bascule structurelle (1 colonne, drawer, tables → cartes)  [~33 usages]
        1024px = tablette paysage / petit PC (élargissement, 3 → 2 colonnes)                    [~17 usages]
        1280px = petit PC / borne haute du fluide

     À SAVOIR : 769px n'est PAS une erreur, c'est le complément exact de max-width:768px
     (suivi.php, onboarding.php). Les autres paliers présents (360/380/400/460/520/560/620/
     680/720/760/820/900/980/1100…) sont HISTORIQUES et liés à un composant précis :
     ne pas s'en inspirer, et les rapprocher de la valeur canonique la plus proche
     lors d'un passage responsive sur le composant concerné. */

  /* ═══ Échelle unique des CARTES & GRILLES (cohérence Liquid Glass) ═══
     Source de vérité unique. Désormais FLUIDES (clamp) → continuité mobile→PC sans bascule dure.
     La borne MAX du clamp = l'ancien rendu desktop (donc desktop INCHANGÉ). */
  --card-pad: clamp(1rem, 2.2vw, 1.25rem) clamp(1rem, 2.6vw, 1.5rem);  /* desktop ≈ 20px 24px (inchangé) */
  --card-pad-sm: 1rem;          /* repli mobile (encore consommé par d'anciens @media) */
  --grid-gap: clamp(0.75rem, 1.5vw, 1rem);   /* desktop = 16px (inchangé), mobile → 12px */
  --grid-gap-sm: 0.75rem;       /* repli mobile */

  /* ═══ Conteneur de lecture & gouttières (tokenisés, réutilisables par toutes les pages) ═══ */
  --container: 1320px;          /* largeur max de lecture (ex-valeur en dur dans .main) */

  /* Accent — bleu Futuristic */
  /* --accent et --accent-hover définis dans les blocs thématiques [data-theme] ci-dessous */
  --accent-soft: rgba(var(--accent-rgb), 0.08);
  --accent-soft-strong: rgba(var(--accent-rgb), 0.14);
  --accent-border: rgba(var(--accent-rgb), 0.20);

  --accent-warm: #F0925F;

  /* ═══ Marque Prospekt-him — code couleur du logo V1.2 (azur → bleu nuit) ═══
     Tokens de MARQUE (moments forts : logo, hero, CTA premium). Distincts de
     --accent (qui pilote l'UI courante) : ne pas les confondre. */

  /* ═══ Motion — courbes partagées (parité avec demo.php) ═══ */
  --ease-snappy: cubic-bezier(.34, 1.56, .64, 1);  /* pop / overshoot / clic */

  /* ═══ Échelle d'espacement (FLAT MINIMAL — rythme 4px) ═══ */
  --sp-1: 4px;  --sp-2: 8px;  --sp-3: 12px; --sp-4: 16px;
  --sp-5: 20px; --sp-6: 24px; --sp-7: 28px; --sp-8: 32px;
  --sp-10: 40px;

  /* ═══ Z-index (stack explicite) — RECALÉ M1.1 (2026-07-02) ═══
     Bug corrigé : modales/toasts (ex-100/200) passaient SOUS le drawer détail
     mobile (.detail-panel, 900-950) → invisibles quand ouvertes DEPUIS le
     drawer Tâches/Prospects. Nouvelle échelle documentée, couche par couche
     (chaque palier laisse de la marge pour des ajouts futurs) :
       nav (pilule/topbar/drawer nav)         60 – 81   (inchangé)
       panneaux/drawers (.detail-panel…)     900 – 950  (détail-panel.css)
       modales 1er niveau (.modal-backdrop)  1000 – 1100
       modales 2e niveau (imbriquées, ex.
         pm-sendmodal/pm-sentmodal)          1150 – 1200
       menus/pickers flottants AU-DESSUS
         des modales qui les ouvrent
         (.stage-picker, .datepicker-*, .rch-menu, .agenda-dropdown,
          .ent-search-results, .tk-menu, .pm-more-menu)   1300
       toasts / undo (.toast, .tk-undo)      1400
       confetti (.pm-confetti-layer)         1500
       bandeau cookies (nop-cookie.js)       2147483000+ (INTOUCHABLE, volontaire)
     Principe : une modale ou un toast doit TOUJOURS passer au-dessus d'un
     drawer/panneau ouvert ; un picker doit TOUJOURS passer au-dessus de la
     modale qui l'a ouvert. */
  --z-navbar: 60;
  --z-topbar: 70;
  --z-mnav-veil: 80;    /* voile du drawer mobile : au-dessus de la topbar (70) */
  --z-mnav-drawer: 81;  /* le drawer lui-même, juste au-dessus de son voile */
  --z-panel: 900;
  --z-panel-mobile: 950; /* le drawer plein écran de .detail-panel, au-dessus du panneau posé */
  --z-modal: 1000;
  --z-modal-l2: 1150;
  --z-float: 1300;
  --z-toast: 1400;
  --z-confetti: 1500;
}

/* ═══ Thème « Futuristic » clair — appliqué quel que soit data-theme ═══ */
:root[data-theme="light"], :root[data-theme="dark"], :root {
  color-scheme: light;

  /* Texte — bleu-profond Blue Frost */
  --text: #07162F;
  --text-secondary: #5D6B82;
  --text-muted: #7A8898;
  --text-dim: #6E7280;

  /* Surfaces — blanc bleuté */
  --bg: #F6FAFF;
  --bg-soft: #F9FCFF;
  --surface: #FFFFFF;
  --surface-hover: #F2F7FD;
  --surface-2: #f0f2f7;
  --border: #E3ECF6;
  --border-soft: #EEF4FA;
  --border-strong: #D0DCE8;

  /* Aurora — RÉACTIVÉE (le verre frosted a besoin d'un fond bleuté à flouter) */
  --aurora-grad-1: rgba(8,112,207,.06);
  --aurora-grad-2: rgba(8,112,207,.04);
  --aurora-grad-3: rgba(99,147,218,.04);
  --aurora-base: #F6FAFF;
  --grain-opacity: .018;

  /* ═══ Matière (clair) — frosted UNIQUEMENT sur le chrome flottant ;
     cards (panel) translucides SANS blur GPU (perf scroll mobile) ═══ */
  --m-nav-bg: rgba(246,250,255,.80);
  --m-nav-border: #E3ECF6;
  /* [DS-5] --m-nav-shadow supprimé : la barre flottante lit --elev-2 directement. */
  --m-overlay-bg: rgba(255,255,255,.88);
  --m-ctl-bg: #FFFFFF;
  --m-ctl-bg-hover: #F2F7FD;
  --m-ctl-border: #E3ECF6;
  --m-panel-bg: rgba(255,255,255,.94);
  --m-panel-border: #E3ECF6;
  --row-hover: #F2F7FD;
  --input-glass-bg: #FFFFFF;

  /* Glass surfaces génériques — translucides bleutées */
  --glass-2: #FFFFFF;
  --glass-5: #EAF4FF;
  --glass-border: #E3ECF6;
  --glass-border-strong: #D0DCE8;

  /* Accent — Blue Frost (D2 : fill #0870CF AA boutons ; lien-texte #0661B4 AA) */
  --accent: #0870CF;
  --accent-rgb: 8,112,207;
  --violet: #6D28D9; /* type Contact (pastilles) — fiabilise color-mix même sans theme-experiment.css */
  --violet-soft: #EDE9FE; /* fond violet doux (dashboard) — fiabilise le rendu même sans theme-experiment.css */
  --accent-hover: #065FAF;
  --accent-active: #0661B4;
  --accent-link: #0661B4;
  --on-accent: #FFFFFF;
  --on-danger: #FFFFFF; /* texte sur fond --danger plein (clair : rouge soutenu, blanc AA) */
  --accent-soft: rgba(var(--accent-rgb), 0.10);
  --accent-soft-strong: rgba(var(--accent-rgb), 0.16);
  --accent-border: rgba(var(--accent-rgb), 0.28);

  /* Info (token manquant auparavant) */

  /* Signature : dégradé bleu → bleu clair ; accent chaud conservé */
  --accent-warm: #F0925F;

  /* Statuts (clair, contrastes pour fond blanc bleuté) */
  --success: #18A957;
  --success-soft: rgba(24, 169, 87, 0.12);
  --success-border: rgba(24, 169, 87, 0.28);

  /* [Ciblup V4, 2026-08-10] L'ambre #D97706 devient l'ocre #8A6400 de la V4.
     Même motif que le rouge d'alerte : #D97706 est une couleur chaude très
     saturée, et sur une interface à accent unique elle se lisait comme un second
     accent. L'ocre garde la fonction (attention) et perd la concurrence.
     Mesuré à la main : #8A6400 sur blanc = 5,38:1 (AA texte) ; sur son propre
     --warning-soft posé sur blanc = 4,58:1 — juste au-dessus du seuil, d'où le
     jeton dédié --warning-text (#6B4E00, 6,58:1) pour tout ce qui est du TEXTE
     sur ce fond. Cf. css/tokens.css. */
  --warning: #8A6400;
  --warning-soft: rgba(138, 100, 0, 0.12);
  --warning-border: rgba(138, 100, 0, 0.28);

  --danger: #E5484D;
  --danger-soft: rgba(229, 72, 77, 0.10);
  --danger-border: rgba(229, 72, 77, 0.26);

  /* [DS-5] Les quatre ombres « Blue Frost » (--shadow-sm/md/lg/card) sont supprimées :
     leurs derniers lecteurs pointent maintenant sur --elev-1/--elev-2. Elles étaient
     encore déclarées ici alors que tokens.css, chargé en dernier, les masquait — la
     valeur d'origine n'était donc plus jamais lue, seulement transportée. */

  /* Charts (lus en JS via getComputedStyle — P4) */
  --chart-primary: #0870CF;
  --chart-secondary: #0E7FC8;
  --chart-grid: rgba(8,35,70,.06);
  --chart-axis: #5D6B82;
  --chart-tooltip-bg: #0F2138;
  --chart-tooltip-text: #F8FAFC;

  /* ═══ Focus / contours — anneau bleu doux Blue Frost (ne modifie JAMAIS le radius) ═══ */
  --focus-ring-color: rgba(8,112,207,.55);
  --focus-ring: 2px solid var(--focus-ring-color);
  --focus-offset: 2px;
  --field-focus-border: var(--accent);
  /* Le halo était figé en azur (8,112,207) alors que la bordure suit --accent :
     depuis le passage à l'indigo #3A64F2 (theme-experiment.css) un champ au focus
     affichait une bordure indigo cernée d'un halo azur. On l'exprime en
     rgba(var(--accent-rgb),…) pour qu'il suive AUTOMATIQUEMENT tout futur accent. */
  --field-focus-ring: 0 0 0 3px rgba(var(--accent-rgb),.12);
}

/* ═══════════════════════════════════════════════════════════════
   THÈME « MODE NUIT » — Verre Minuit (data-theme="dark")
   Élévation INVERSÉE (surfaces plus claires que le fond), matière
   liquid glass sombre, accent bleu éclairci (#3FA0FF). Override du
   bloc clair ci-dessus. Contraste WCAG AA/AAA vérifié.
   ═══════════════════════════════════════════════════════════════ */
:root[data-theme="dark"] {
  color-scheme: dark;

  /* TEXTE — Blue Frost Dark (blanc cassé, jamais blanc pur agressif) */
  --text: #F8FAFC;
  --text-secondary: #CBD5E1;
  --text-muted: #94A3B8;
  --text-dim: #84888F;

  /* SURFACES — 🆕 NUIT MONOCHROME : gris neutre pur (ZÉRO teinte bleue/slate).
     Seules les SURFACES sont neutralisées ; le CONTENU garde ses couleurs (accent/statuts/charts plus bas). */
  --bg: #0a0a0a;
  --bg-soft: #0e0e0e;
  --surface: #141414;
  --surface-hover: #1a1a1a;
  --surface-2: #1a1d23;
  --border: rgba(161,161,161,.16);
  --border-soft: rgba(161,161,161,.10);
  --border-strong: rgba(161,161,161,.24);

  /* FOND AURORA — 🆕 halo NEUTRE gris (plus de bleu) */
  --aurora-grad-1: rgba(92,92,92,.12);
  --aurora-grad-2: rgba(92,92,92,.07);
  --aurora-grad-3: rgba(141,141,141,.07);
  --aurora-base: #0a0a0a;
  --grain-opacity: .03;

  /* MATIÈRE (nuit) — frosted sur le chrome ; cards (panel) opaques (perf scroll) — gris neutre */
  --m-nav-bg: rgba(23,23,23,.78);
  --m-nav-border: rgba(161,161,161,.16);
  /* [DS-5] Pendant nuit de --m-nav-shadow, supprimé lui aussi. */

  /* MATIÈRE — overlays, contrôles, panneaux (cartes) — gris neutre */
  --m-overlay-bg: rgba(26,26,26,.88);
  --m-ctl-bg: #1a1a1a;
  --m-ctl-bg-hover: #232323;
  --m-ctl-border: rgba(161,161,161,.18);
  --m-panel-bg: rgba(20,20,20,.92);
  --m-panel-border: rgba(161,161,161,.16);
  --row-hover: rgba(161,161,161,.06);
  --input-glass-bg: #0e0e0e;

  /* VERRE générique — 🆕 sombre translucide NEUTRE (gris) */
  --glass-2: #141414;
  --glass-5: #232323;
  --glass-border: rgba(161,161,161,.16);
  --glass-border-strong: rgba(161,161,161,.24);

  /* ACCENT (D1) — texte/lien/icône #3FA0FF (AA 6,9:1) ; remplissage #0870CF */
  --accent: #3FA0FF;
  --accent-rgb: 63,160,255;
  --violet: #A78BFA; /* type Contact en nuit (contraste AA sur fond sombre) */
  --violet-soft: rgba(167,139,250,.15); /* fond violet doux en nuit (dashboard) */
  --accent-hover: #6FB8FF;
  --accent-active: #0A7BE3;
  --accent-link: #3FA0FF;
  --on-accent: #06122E;
  --accent-soft: rgba(var(--accent-rgb), 0.14);
  --accent-soft-strong: rgba(var(--accent-rgb), 0.22);
  --accent-border: rgba(var(--accent-rgb), 0.38);

  /* Info */

  --accent-warm: #F0925F;

  /* STATUTS — AA sur sombre ; *-soft = translucides */
  --success: #3AD77F;
  --success-soft: rgba(58, 215, 127, 0.16);
  --success-border: rgba(58, 215, 127, 0.34);
  --warning: #F5A623;
  --warning-soft: rgba(245, 166, 35, 0.16);
  --warning-border: rgba(245, 166, 35, 0.34);
  --danger: #FF6B6B;
  --on-danger: #3A0A0A; /* nuit : rouge clair #FF6B6B → texte foncé pour rester AA (le blanc y tombait à ~2,4:1) */
  --danger-soft: rgba(255, 107, 107, 0.15);
  --danger-border: rgba(255, 107, 107, 0.32);

  /* [DS-5] Pendant nuit des quatre ombres supprimées ci-dessus (cf. commentaire du
     bloc clair) : plus aucun lecteur, l'élévation passe par --elev-0/1/2. */

  /* Charts nuit (lus en JS — P4) */
  --chart-primary: #3FA0FF;
  --chart-secondary: #38BDF8;
  --chart-grid: rgba(148,163,184,.12);
  --chart-axis: #94A3B8;
  --chart-tooltip-bg: #141B25;
  --chart-tooltip-text: #F8FAFC;

  /* FOCUS — anneau clair froid, lisible sur nuit */
  --focus-ring-color: rgba(63,160,255,.65);
  --focus-ring: 2px solid var(--focus-ring-color);
  --focus-offset: 2px;
  --field-focus-border: var(--accent);
  /* Même correctif qu'en clair : halo figé en azur (63,160,255) alors que la bordure
     suivait --accent → désaccord bordure/halo, encore plus visible en nuit (.22). */
  --field-focus-ring: 0 0 0 3px rgba(var(--accent-rgb), 0.22);
}

/* ── NUIT : lisibilité du texte sur SURFACES PLEINES à fond accent ──
   En nuit l'accent est éclairci (#3FA0FF) : un label BLANC dessus ≈ 2,5:1 (illisible).
   Sur ces surfaces pleines uniquement, on passe le texte en navy sombre
   (#06122e ≈ 6,8:1 sur #3FA0FF). N'affecte JAMAIS le thème clair. */
/* [DS-3] Les trois sélecteurs .appnav-*.active ont quitté ce bloc : leur état actif
   n'est plus un aplat d'accent mais --surface-hover, sur laquelle --on-accent (un
   navy très sombre) devenait illisible. Ils héritent désormais de --text. */
:root[data-theme="dark"] .btn-accent,
:root[data-theme="dark"] .modal-btn-primary,
:root[data-theme="dark"] .agenda-create-btn {
  color: var(--on-accent); /* theme-aware : #06122e sur #3FA0FF (v2) OU #fff sur #3A64F2 (theme-experiment) */
}
:root[data-theme="dark"] .btn-accent svg {
  color: var(--on-accent);
}

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

/* [DS-5] Reset des contrôles de formulaire.
   Le navigateur ne fait PAS hériter la police aux button/input/select/textarea :
   sans cette règle ils retombent sur la valeur par défaut de l'agent utilisateur
   (Arial 13,333 px), hors échelle typographique et hors polices du projet.
   Jusqu'ici chaque composant redéclarait « font-family: inherit » dans son coin,
   donc tout nouveau contrôle ratait la règle en silence — constaté sur
   .sbx-credits-add, .mnav-burger et .mnav-link (ce dernier porte du texte visible
   en navigation mobile). Un reset unique ferme la classe de bug d'un coup ;
   les composants qui veulent une autre taille la déclarent après, comme avant.
   Volontairement limité à la police : hériter aussi color/line-height changerait
   la couleur du texte saisi et la hauteur des champs sur tout le site, très
   au-delà du défaut constaté. */
button, input, select, textarea, optgroup {
  font-family: inherit;
  font-size: inherit;
}

html, body {
  height: 100%;
  font-family: 'Montserrat', system-ui, -apple-system, sans-serif;
  font-size: var(--fs-base);
}
/* Titres historiques : famille pilotée par `--font-title` (Satoshi, cf. css/tokens.css).
   Les titres du contrat V7 passeront sur `--font-display` (vraies Poppins) en U2.
   (.recap-title / .acompte-title retirés de cette liste le 2026-07-28 : sélecteurs orphelins
   du « calculateur de devis », supprimé du fichier — ils ne visaient plus rien.) */
h1, h2, h3, h4, h5, h6,
.page-title, .section-title, .modal-title, .auth-title, .tpl-title,
.kpi-value, .kpi-card .value {
  font-family: var(--font-title);
}

/* ═══ Échelle typographique cohérente (additive) ═══
   Rôles unifiés pour les titres bruts (h1–h4 n'avaient aucune taille
   explicite : purement additif). Les classes de titre existantes
   (.page-title / .auth-title / .section-title) sont alignées plus bas
   dans la cascade pour ne rien casser.
   [DS-5] Ces quatre règles portaient des valeurs libres (deux clamp() et deux
   tailles en rem) qui, avec une racine à 14px, donnaient 42 / 28 / 17,5 / 14px :
   deux crans hors échelle et un demi-pixel. Elles tombent désormais sur les
   quatre crans de titre de l'échelle. Le clamp() est abandonné ici parce qu'un
   titre BRUT (sans classe) n'est jamais un héros de page : les héros portent
   tous leur propre classe, qui garde sa fluidité là où elle sert. */
h1 { font-size: var(--fs-display); line-height: var(--lh-tight); letter-spacing: -0.02em; }
h2 { font-size: var(--fs-xl); line-height: var(--lh-tight); letter-spacing: -0.015em; }
h3 { font-size: var(--fs-lg); line-height: var(--lh-tight); }
h4 { font-size: var(--fs-md); line-height: var(--lh-tight); }

/* Fond d'app UNI — les 3 halos « Aurora » (gauche/bas/droite) retirés sur
   décision propriétaire 2026-07-04 : sous les voiles floutés (célébration,
   modales), ils ressortaient en gros cercles baveux. Les pages d'auth gardent
   leur composition propre (.auth-page, plus bas). */
body {
  background: var(--bg);
}

html {
  scroll-behavior: smooth;
  scrollbar-gutter: stable;
  overflow-y: scroll;            /* scrollbar toujours présente → la barre de nav centrée ne "saute" plus d'une page à l'autre */
  background: var(--bg);         /* l'inter-page n'est plus blanc → flash atténué même sans View Transitions */
}

/* ════════════════════════════════════════════════════════════
   ANTI-FLASH NAVIGATION — View Transitions API (cross-document)
   Chaque page opte-in : le navigateur fait une transition douce
   au lieu d'un "blanc". La barre .appnav (view-transition-name)
   est capturée séparément → elle PERSISTE et ne clignote plus.
   Navigateurs non compatibles : comportement classique (graceful).
   ════════════════════════════════════════════════════════════ */
@view-transition { navigation: auto; }
::view-transition-old(root),
::view-transition-new(root) { animation-duration: .20s; }
/* La barre de nav ne s'anime pas ET ne se DÉDOUBLE pas : on masque l'ancienne capture
   (sinon les deux ombres se superposent → ombre « accentuée » pendant le fondu),
   on n'affiche que la nouvelle (nav identique d'une page à l'autre → transparent).
   ⚠ Scopé :not(.theme-switching) : pour la NAV MPA seulement, PAS pour le switch jour/nuit. */
:root:not(.theme-switching)::view-transition-group(appnav) { animation-duration: 0s; }
:root:not(.theme-switching)::view-transition-old(appnav) { animation: none; opacity: 0; }
:root:not(.theme-switching)::view-transition-new(appnav) { animation: none; opacity: 1; mix-blend-mode: normal; }

/* ═══ Fondu TRÈS DOUX du basculement jour/nuit (≈ .65s) ═══
   Crossfade de TOUTE la page (fond, cartes, texte) + la nav fond AVEC (pas de « pop »).
   Surclasse la durée nav (.20s) via la spécificité de :root.theme-switching. */
:root.theme-switching::view-transition-old(root),
:root.theme-switching::view-transition-new(root) { animation-duration: .65s; animation-timing-function: cubic-bezier(.4, 0, .2, 1); }
/* Pendant le switch, la nav perd son view-transition-name → capturée DANS root :
   elle fond avec toute la page au même rythme, sans groupe séparé qui « pop ». */
:root.theme-switching .appnav { view-transition-name: none; }
@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) { animation: none !important; }
}

body { display: flex; min-height: 100dvh; }

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

::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: var(--radius); }
::-webkit-scrollbar-thumb:hover { background: var(--text-muted); }

/* ─── PRÉSENCE TEAM (popover « Équipe » de la topbar sbx — .sidebar* mort retiré 2026-06-23) ─── */
.presence-list {
  display: flex;
  flex-direction: column;
  gap: 2px;
  max-height: 200px;
  overflow-y: auto;
  padding-right: 4px;
}
.presence-list::-webkit-scrollbar { width: 4px; }
.presence-list::-webkit-scrollbar-thumb { background: var(--border); border-radius: var(--radius); }
.presence-loading {
  font-size: var(--fs-micro);
  color: var(--text-muted);
  padding: 8px 12px;
  font-style: italic;
}
.presence-item {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 7px 10px;
  border-radius: var(--radius-sm);
  transition: background 0.15s ease;
}
.presence-item:hover { background: var(--surface-hover); }
.presence-item.is-me { background: var(--accent-soft); }
.presence-item.is-me:hover { background: var(--accent-soft); opacity: 0.85; }

.presence-avatar {
  position: relative;
  width: 28px;
  height: 28px;
  border-radius: var(--radius);
  /* [DS-3] Aplat d'accent : la pastille de présence porte une initiale, pas un ornement. */
  background: var(--accent);
  color: var(--on-accent);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: var(--fw-bold);
  font-size: var(--fs-micro);
  flex-shrink: 0;
}
.presence-dot {
  position: absolute;
  bottom: -2px;
  right: -2px;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  border: 2px solid var(--surface);
  box-sizing: border-box;
}
.presence-dot.online { background: var(--success); box-shadow: 0 0 0 1px rgba(22,163,74,0.35); }
.presence-dot.away { background: #FBBF24; box-shadow: 0 0 0 1px rgba(251,191,36,0.4); }
[data-theme="dark"] .presence-dot.away { background: #fbbf24; }
.presence-dot.offline { background: var(--border-strong); box-shadow: 0 0 0 1px rgba(107,114,128,0.4); }

.presence-info {
  flex: 1;
  min-width: 0;
}
.presence-name {
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: 1.3;
}
.presence-status {
  font-size: var(--fs-micro);
  line-height: 1.4;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.presence-status.online { color: var(--success); font-weight: var(--fw-semibold); }
.presence-status.away { color: #FBBF24; font-weight: var(--fw-medium); }
.presence-status.offline { color: var(--text-muted); }

/* ─── MAIN AREA ─── */
.main {
  flex: 1;
  padding: 7.25rem 2.25rem 2.5rem;   /* padding haut = espace (aéré) sous la barre de nav flottante */
  min-width: 0;
  max-width: 100%;
  margin: 0;                    /* plus de sidebar : contenu pleine largeur */
  background: transparent;
  border: none;
  border-radius: 0;
  overflow-x: hidden;
  min-height: 100dvh;
  box-shadow: none;
}
/* Phase 5 — densité fidèle à la maquette : le contenu est calé à une
   largeur de lecture confortable et CENTRÉ dans l'espace après la sidebar,
   au lieu de s'étirer d'un bord à l'autre sur grand écran.
   !important pour battre les .section{max-width:100%} etc. ; les overlays
   en position:fixed (datepicker, modales) ne sont pas affectés visuellement. */
.main:not(.main-wide) > *:not(.page-header):not(.datepicker-backdrop):not(.datepicker-popover):not([class*="modal"]):not(.toast) {
  max-width: var(--container) !important; /* ex-1320px en dur, désormais tokenisé */
  margin-left: auto !important;
  margin-right: auto !important;
}

.page-header {
  display: flex; align-items: flex-start; justify-content: space-between;
  margin-bottom: 2rem; gap: 1rem;
}
.page-title { font-size: var(--fs-xl); font-weight: var(--fw-bold); color: var(--text); letter-spacing: -0.01em; }
.page-title-row { display: flex; align-items: center; gap: 12px; }
.page-header-icon { flex: none; width: 44px; height: 44px; border-radius: var(--radius); background: rgba(var(--accent-rgb), .12); color:var(--accent-link); display: flex; align-items: center; justify-content: center; }
.page-header-icon svg { width: 20px; height: 20px; }
.page-subtitle { font-size: var(--fs-base); color: var(--text-secondary); margin-top: 6px; line-height: 1.55; }

.section { margin-bottom: 2.75rem; max-width: 100%; min-width: 0; }
.section-header {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 1rem; gap: 1rem; flex-wrap: wrap;
}
.section-title {
  font-size: var(--fs-md); font-weight: var(--fw-semibold); color: var(--text);
  display: flex; align-items: center; gap: var(--sp-2);
}
.section-tag {
  font-family: var(--font-data);
  font-size: var(--fs-micro);
  padding: var(--sp-1) var(--sp-2);
  border-radius: var(--radius-pill);
  background: var(--bg-soft);
  color: var(--text-muted);
  border: 1px solid var(--border);
}


/* ─── DASHBOARD ─── */

/* ─── QUICK ACCESS CARDS ─── */

/* ─── TEMPLATE & KEYWORD CARDS ─── */
.tpl-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
  gap: 1rem;
}
.tpl-card {
  /* [DS-3] Carte posée dans une grille → élévation 1. Elle consommait l'ombre de
     panneau flottant (24px de diffusion), réservée à ce qui passe au-dessus du
     contenu. Fond et bordure restent sur les alias, raccordés au jeu canonique
     dans tokens.css. */
  background: var(--m-panel-bg);
  border: 1px solid var(--m-panel-border);
  box-shadow: var(--elev-1);
  border-radius: var(--radius-lg);
  padding: var(--card-pad);
  display: flex; flex-direction: column;
  transition: border-color .15s ease;
}
.tpl-card:hover {
  border-color: var(--accent-border);
}
.tpl-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 10px; margin-bottom: 10px; }
.tpl-title { font-size: var(--fs-base); font-weight: var(--fw-semibold); color: var(--text); line-height: 1.3; flex: 1; }
.tpl-content {
  font-family: var(--font-data);
  font-size: var(--fs-xs);
  color: var(--text-secondary);
  background: var(--bg-soft);
  border-radius: var(--radius);
  padding: 12px;
  max-height: 110px;
  overflow: hidden;
  line-height: 1.6;
  position: relative;
  white-space: pre-wrap;
  margin-bottom: 12px;
  /* Le fondu signale la troncature sans poser un calque decoratif sur le texte. */
  -webkit-mask-image: linear-gradient(to bottom, #000 0, #000 calc(100% - 40px), transparent 100%);
  mask-image: linear-gradient(to bottom, #000 0, #000 calc(100% - 40px), transparent 100%);
}
.tpl-meta {
  display: flex; justify-content: space-between;
  font-size: var(--fs-micro);
  color: var(--text-muted);
  margin-bottom: 12px;
  font-family: var(--font-data);
}
/* keyword cards */
.kw-block-header {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 1rem;
  gap: 10px; flex-wrap: wrap;
}
/* ─── ANTI-DÉBORDEMENT GLOBAL ─── */
/* Empêche tout contenu (URL, chaîne longue) de casser le layout */
code, pre {
  overflow-wrap: anywhere;
  word-break: break-word;
}

/* Conteneurs flex : forcer min-width:0 pour autoriser l'enfant à shrinker */
.tpl-card, .presence-item {
  min-width: 0;
}
.tpl-card > * {
  min-width: 0;
}

/* ─── CATEGORY BADGES (Color variants) ─── */
.cat-pill {
  font-family: var(--font-data);
  font-size: var(--fs-micro); font-weight: var(--fw-semibold);
  padding: 3px 9px;
  border-radius: var(--radius-pill);
  letter-spacing: 0.03em;
  white-space: nowrap;
}
.cat-pill-blue   { background: rgba(var(--accent-rgb),0.1); color:var(--accent-link); border: 1px solid rgba(var(--accent-rgb),0.25); }
.cat-pill-green  { background: rgba(14, 165, 233, 0.12); color: #0284C7; border: 1px solid rgba(14, 165, 233, 0.30); }
.cat-pill-teal   { background: rgba(20,184,166,0.1); color: #0D9488; border: 1px solid rgba(20,184,166,0.25); }
.cat-pill-orange { background: rgba(245,158,11,0.1); color: #D97706; border: 1px solid rgba(245,158,11,0.25); }
/* « Violet » rendait EXACTEMENT la même pastille que « Bleu » (fond + texte accent) :
   deux choix distincts dans le sélecteur de catégorie (communication.php) donnaient
   la même couleur. On lui rend une teinte propre via le token --violet, déjà défini
   en clair (#6D28D9) et en nuit (#A78BFA) — donc lisible dans les deux thèmes. */
.cat-pill-purple { background: var(--violet-soft); color: var(--violet); border: 1px solid color-mix(in srgb, var(--violet) 28%, transparent); }
.cat-pill-pink   { background: rgba(236,72,153,0.1); color: #DB2777; border: 1px solid rgba(236,72,153,0.25); }
.cat-pill-yellow { background: rgba(250,204,21,0.1); color: #CA8A04; border: 1px solid rgba(250,204,21,0.25); }
.cat-pill-red    { background: rgba(239,68,68,0.1); color: #DC2626; border: 1px solid rgba(239,68,68,0.25); }
.cat-pill-gray   { background: var(--bg-soft); color: var(--text-secondary); border: 1px solid var(--border); }

/* ─── Overrides MODE NUIT : texte éclairci pour maintenir le contraste AA ─── */
[data-theme="dark"] .cat-pill-orange { color: #fb923c; background: rgba(251,146,60,.15); }
[data-theme="dark"] .cat-pill-red    { color: #f87171; background: rgba(248,113,113,.15); }
[data-theme="dark"] .cat-pill-yellow { color: #facc15; background: rgba(250,204,21,.15); }
[data-theme="dark"] .cat-pill-pink   { color: #f472b6; background: rgba(244,114,182,.15); }
[data-theme="dark"] .cat-pill-green  { color: #4ade80; background: rgba(74,222,128,.15); }
[data-theme="dark"] .cat-pill-teal   { color: #2dd4bf; background: rgba(45,212,191,.15); }

/* (Famille .cat-color-dot* retirée en bloc — DS-4 2026-08-08. Elle n'avait aucun
   émetteur depuis le balayage du 2026-07-28, et son commentaire d'alors prévoyait
   déjà « à supprimer d'un bloc, ou pas du tout ». Les slugs de couleur restent
   portés par .cat-pill* ci-dessus et par CAT_HEX_COLORS de js/nop-suivi-core.js. */

/* ─── Sélecteur de TYPE de prospect (modale de création — prospects.php / #modalClient) ───
   Seul rescapé de l'ancien bloc « CALCULATEUR DEVIS » : ~300 lignes (47 sélecteurs :
   .tunnel-card, .presta-*, .tjm-*, .opt-*, .recap-*, .acompte-*, .devis-*, .step*,
   input[type=range]…) héritées de l'outil de devis de l'agence, sans aucun rapport avec le
   CRM de prospection et sans UNE SEULE occurrence dans le markup — pourtant servies sur
   CHAQUE page. Retirées le 2026-07-28 après balayage AVEC BORNES DE MOT sur *.php/*.js/
   *.html/*.css (indispensable : sans bornes, .recap-card/.step-num/.recap-title ressortaient
   à tort à cause des .pm-recap-card/.pm-step-num de css/guided-journey.css).
   ⚠️ NE PAS supprimer ce groupe : il est vivant (prospects.php) et sert de base à la
   surcharge css/clients.css (.choice-card). */
.choice-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.choice-card {
  padding: 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  cursor: pointer;
  font-size: var(--fs-base);
  font-weight: var(--fw-semibold);
  color: var(--text);
  transition: all 0.15s ease;
  text-align: center;
}
.choice-card:hover { border-color: var(--border-strong); }
.choice-card.active {
  border-color: var(--accent);
  background: var(--accent-soft);
  color:var(--accent-link);
}

/* ─── LOGIN PAGES — Aurora Glass ─── */
.auth-page {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  min-height: 100dvh;
  padding: 2rem 1rem;
  background:
    radial-gradient(ellipse 60% 50% at 80% 20%, var(--aurora-grad-1) 0%, transparent 70%),
    radial-gradient(ellipse 50% 50% at 20% 80%, var(--aurora-grad-2) 0%, transparent 70%),
    radial-gradient(ellipse 40% 40% at 50% 50%, var(--aurora-grad-3) 0%, transparent 70%),
    var(--aurora-base);
  position: relative;
  /* Formulaire plus haut que l'écran (ex. signup) : on SCROLLE au lieu de clipper haut+bas.
     overflow-x:hidden garde l'aurora confinée ; margin-block:auto (sur .auth-card) centre quand ça rentre. */
  overflow-x: hidden;
  overflow-y: auto;
}
.auth-page::before,
.auth-page::after { display: none; }
/* 🆕 Footer légal des pages publiques (login/signup) — INCASSABLE : remplit son parent (carte OU body flex),
   les liens s'enroulent (flex-wrap), le copyright passe sur sa propre ligne. Ne déborde jamais. */
.auth-legal-foot{align-self:stretch;width:100%;max-width:100%;box-sizing:border-box;display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:3px 7px;margin-top:1.5rem;padding-top:1.1rem;border-top:1px solid var(--border);font-size:var(--fs-xs);line-height:1.7;color:var(--text-muted)}
.auth-legal-foot a{color:var(--text-muted);text-decoration:none;white-space:nowrap}
.auth-legal-foot a:hover{color:var(--accent);text-decoration:underline}
.auth-legal-foot span{opacity:.4}
.auth-legal-copy{flex-basis:100%;text-align:center;margin-top:.35rem;opacity:.85}

.auth-card {
  position: relative;
  z-index: 1;
  width: 100%; max-width: 420px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 2.5rem;
  box-shadow: var(--elev-2);
  animation: modalIn 0.4s cubic-bezier(0.16, 1, 0.3, 1);
  margin-block: auto; /* centre verticalement quand ça rentre ; sinon top-aligné et scrollable (pas de clip) */
}
@media (max-width: 480px) {
  .auth-page { padding: 1rem 0.75rem; }
  .auth-card { padding: 1.75rem 1.25rem; border-radius: var(--radius-lg); }
  .auth-title { font-size: var(--fs-lg) !important; }
}
.auth-logo {
  display: flex; align-items: center; justify-content: center; gap: 12px;
  margin-bottom: 2rem;
}
.auth-logo-mark {
  /* Plus de carré : on n'affiche que le logo, en couleur d'accent (currentColor). */
  display: flex; align-items: center; justify-content: center;
  color:var(--accent-link);
}
.auth-logo-mark svg { width: 46px; height: 46px; }
.auth-logo-text {
  font-weight: var(--fw-bold); font-size: var(--fs-lg);
  color: var(--text);
  letter-spacing: -0.01em;
}
.auth-title {
  font-size: var(--fs-xl); font-weight: var(--fw-bold);
  color: var(--text);
  margin-bottom: 6px;
  text-align: center;
  letter-spacing: -0.02em;
}

/* ═══ Alignement des titres-rôles sur l'échelle typo (additive) ═══
   Placé après les définitions d'origine pour gagner la cascade à
   spécificité égale, sans supprimer aucun sélecteur. Bornes des clamp
   choisies pour englober les tailles historiques (24px ≈ borne basse)
   → aucun saut visuel au repos, juste une montée fluide sur grand écran.
   .section-title (sous-titre 16px) garde sa taille : son rôle ≈ h4, déjà
   calibré ; le toucher changerait tous les en-têtes de section (non-additif). */
.page-title, .auth-title { font-size: clamp(1.5rem, 4vw, 2rem); line-height: 1.15; }
/* [U2 — contrat V7 §5.5] « Titre de page : Poppins 600, 24 px, ligne 32 px. » Le
   contrat fixe une taille, pas une plage : le titre de page sort donc du clamp
   ci-dessus, qui montait jusqu'à 32 px sur grand écran. .auth-title n'est PAS visé
   (les pages d'authentification ne portent pas la coque V7) et garde son clamp.
   Les réductions mobiles en --fs-lg plus bas restent prioritaires (!important). */
.page-title {
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  font-size: 24px;
  line-height: 32px;
}
.auth-sub {
  font-size: var(--fs-base);
  color: var(--text-secondary);
  text-align: center;
  margin-bottom: 1.75rem;
}
.auth-error {
  font-size: var(--fs-sm);
  color: var(--danger);
  background: var(--danger-soft);
  border: 1px solid var(--danger-border);
  padding: 10px 14px;
  border-radius: var(--radius-sm);
  margin-top: 1rem;
  text-align: center;
}
.auth-warning {
  font-size: var(--fs-sm);
  color: var(--warning);
  background: var(--warning-soft);
  border: 1px solid var(--warning-border);
  padding: 10px 14px;
  border-radius: var(--radius-sm);
  margin-top: 1rem;
  text-align: center;
}
.auth-success {
  font-size: var(--fs-sm);
  color: var(--success);
  background: var(--success-soft);
  border: 1px solid var(--success-border);
  padding: 10px 14px;
  border-radius: var(--radius-sm);
  margin-top: 1rem;
  text-align: center;
}
.auth-link {
  display: block; text-align: center;
  margin-top: 1.5rem;
  font-size: var(--fs-sm);
  color: var(--text-secondary);
  transition: color 0.15s ease;
}
.auth-link:hover { color:var(--accent-link); }

/* [DS-3] La surcharge du bouton primaire de l'auth-card a été retirée : elle
   ajoutait un dégradé vertical, un liseré blanc en incrustation, une lueur colorée
   sous le bouton et un soulèvement de 2 px au survol — quatre ornements qui n'ont
   d'équivalent nulle part ailleurs sur le site. Le bouton hérite désormais de la
   primitive .btn-primary : aplat d'encre neutre, sans élévation ni mouvement. */

/* ============================================ */
/* RESPONSIVE — TABLETTE & MOBILE                */
/* ============================================ */

/* ════════════════════════════════════════════════════════════
   NAV MOBILE (≤768px) — topbar + hamburger + drawer latéral.
   Remplace l'ancien système .sidebar/.burger-btn (code mort).
   Desktop/tablette ≥769px : on garde la pilule flottante .appnav.
   ════════════════════════════════════════════════════════════ */
.mnav-topbar, .mnav-overlay, .mnav-drawer { display: none; }

@media (max-width: 768px) {
  /* La pilule flottante laisse place au drawer */
  .appnav {
    display: none !important;
  }

  /* Barre supérieure fixe : hamburger + marque */
  .mnav-topbar {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    position: fixed;
    top: 0; left: 0; right: 0;
    height: calc(56px + env(safe-area-inset-top));
    padding: env(safe-area-inset-top) var(--sp-3) 0;
    z-index: var(--z-topbar);
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    box-shadow: none;
  }
  .mnav-burger {
    -webkit-appearance: none; appearance: none;
    display: inline-flex; align-items: center; justify-content: center;
    width: 44px; height: 44px;
    border-radius: var(--radius);
    border: 1px solid var(--glass-border);
    background: var(--surface);
    color: var(--text);
    cursor: pointer; flex-shrink: 0;
    transition: background .15s ease, transform .15s ease;
  }
  .mnav-burger:active { transform: scale(0.95); }
  .mnav-burger svg { width: 22px; height: 22px; }
  .mnav-brand { display: inline-flex; align-items: center; gap: var(--sp-2); min-width: 0; font-family: var(--font-title); font-weight: var(--fw-bold); font-size: var(--fs-md); color: var(--text); letter-spacing: -.01em; }
  .mnav-brand img { flex-shrink: 0; }
  .mnav-brand-txt { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .mnav-brand-accent { color:var(--accent-link); }
  /* Toggle jour/nuit dans la topbar mobile/tablette (la pilule .appnav est masquée ici) */
  .mnav-theme {
    -webkit-appearance: none; appearance: none;
    margin-left: auto; flex-shrink: 0;
    display: inline-flex; align-items: center; justify-content: center;
    width: 44px; height: 44px;
    border-radius: var(--radius);
    border: 1px solid var(--glass-border);
    background: var(--surface);
    color: var(--text);
    cursor: pointer;
    transition: background .15s ease, transform .15s ease;
  }
  .mnav-theme:hover { color:var(--accent-link); }
  .mnav-theme:active { transform: scale(0.95); }
  .mnav-theme svg { width: 20px; height: 20px; }

  /* Overlay */
  .mnav-overlay {
    display: block;
    position: fixed; inset: 0;
    background: var(--overlay-veil);
    z-index: var(--z-mnav-veil);
    opacity: 0; visibility: hidden;
    transition: opacity .25s ease, visibility .25s ease;
    -webkit-tap-highlight-color: transparent;
  }
  /* Drawer latéral gauche */
  .mnav-drawer {
    display: flex; flex-direction: column;
    position: fixed; top: 0; left: 0;
    width: min(82vw, 320px);
    height: 100dvh;
    z-index: var(--z-mnav-drawer);
    background: var(--surface);
    box-shadow: var(--elev-2);
    transform: translateX(-100%);
    transition: transform .3s cubic-bezier(.4, 0, .2, 1);
    padding: calc(env(safe-area-inset-top) + 14px) 0 calc(env(safe-area-inset-bottom) + 14px);
    overflow-y: auto; -webkit-overflow-scrolling: touch;
  }
  body.mnav-open { overflow: hidden; }
  body.mnav-open .mnav-overlay { opacity: 1; visibility: visible; }
  body.mnav-open .mnav-drawer { transform: translateX(0); }

  /* En-tête du drawer : avatar + nom + plan */
  .mnav-head {
    display: flex; align-items: center; gap: var(--sp-3);
    padding: var(--sp-1) 18px var(--sp-4);
    margin-bottom: var(--sp-1);
    border-bottom: 1px solid var(--glass-border);
  }
  .mnav-avatar {
    width: 42px; height: 42px; border-radius: 50%;
    background: var(--accent-soft); color:var(--accent-link);
    display: inline-flex; align-items: center; justify-content: center;
    font-weight: var(--fw-bold); font-size: var(--fs-base); text-transform: uppercase;
    background-size: cover; background-position: center;
    border: 1px solid var(--border); flex-shrink: 0; overflow: hidden;
  }
  .mnav-head-name { font-weight: var(--fw-semibold); font-size: var(--fs-base); color: var(--text); }
  .mnav-head-plan { font-size: var(--fs-micro); font-weight: var(--fw-semibold); color:var(--accent-link); margin-top: 1px; }

  /* Liens du drawer */
  .mnav-links { display: flex; flex-direction: column; gap: 2px; padding: 10px var(--sp-3); flex: 1; }
  .mnav-link {
    display: flex; align-items: center; gap: 14px;
    min-height: 48px; padding: 0 14px;
    border-radius: var(--radius);
    color: var(--text-muted); text-decoration: none;
    font-size: var(--fs-md); font-weight: var(--fw-semibold);
  }
  .mnav-link svg { width: 20px; height: 20px; flex-shrink: 0; }
  /* [DS-3] Même convention d'état actif que .sbx-link de la sidebar desktop : surface
     pleine + filet d'accent à gauche, au lieu de l'aplat d'accent et de sa lueur.
     Le filet est un inset : il ne prend aucune place, donc rien ne se décale. */
  .mnav-link.active { color: var(--text); background: var(--accent-soft); box-shadow: none; }
  .mnav-link.active svg { opacity: 1; color: var(--accent); }
  .mnav-link:not(.active):active { background: var(--row-hover); }
  .mnav-sep { height: 1px; background: var(--glass-border); margin: var(--sp-2) 18px; }
  .mnav-link.mnav-logout { color: var(--danger); }
}

/* ── Pop-up « expérience optimale sur grand écran » (affiché par JS sur petit mobile, 1×/session) ── */
.mobile-notice-backdrop {
  position: fixed; inset: 0; z-index: var(--z-modal);
  display: flex; align-items: center; justify-content: center;
  padding: var(--sp-6);
  background: var(--overlay-veil);
}
.mobile-notice-backdrop[hidden] { display: none; }
.mobile-notice {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 26px 22px 22px;
  max-width: 340px; width: 100%;
  text-align: center;
  box-shadow: var(--elev-2);
}
/* [DS-5] Le font-size:38px et son line-height:1 sont retirés : ils dataient de l'époque où ce
   bloc portait un glyphe textuel. Son unique enfant est aujourd'hui l'emblème rendu par
   renderLogo(44) (inc/layout.php), une image dimensionnée par .a2hs-logo img ci-dessous — la
   taille de police n'avait donc plus aucune cible. C'est la sonde à 375px qui l'a exhumé. */
.mobile-notice-icon { margin-bottom: 10px; }
.mobile-notice h3 { font-size: var(--fs-md); font-weight: var(--fw-bold); margin: 0 0 8px; color: var(--text); }
.mobile-notice p { font-size: var(--fs-base); color: var(--text-secondary); line-height: 1.6; margin: 0 0 18px; }
.mobile-notice .btn { width: 100%; justify-content: center; }

/* ── Pop-up « Ajouter à l'écran d'accueil » (A2HS) — réutilise .mobile-notice ── */
.mobile-notice .a2hs-logo { display: flex; justify-content: center; }
.mobile-notice .a2hs-logo img { width: 44px; height: 44px; border-radius: var(--radius); }
.mobile-notice .a2hs-steps {
  list-style: none; margin: 0 0 18px; padding: 0;
  display: flex; flex-direction: column; gap: 11px; text-align: left;
}
.mobile-notice .a2hs-steps li { display: flex; align-items: flex-start; gap: 10px; font-size: var(--fs-sm); color: var(--text-secondary); line-height: 1.45; }
.mobile-notice .a2hs-steps li b { color: var(--text); font-weight: var(--fw-semibold); }
.mobile-notice .a2hs-step-n {
  flex: 0 0 22px; width: 22px; height: 22px; margin-top: 1px;
  border-radius: 50%; background: var(--accent); color: var(--on-accent);
  font-size: var(--fs-xs); font-weight: var(--fw-bold); display: inline-flex; align-items: center; justify-content: center;
}
.mobile-notice .a2hs-ic { display: inline-flex; vertical-align: -2px; color: var(--accent); }
.mobile-notice .a2hs-actions { display: flex; flex-direction: column; gap: 8px; }

/* ─── Tablette : 1024px et moins ─── */
@media (max-width: 1024px) {
  .kpi-grid { grid-template-columns: repeat(2, 1fr); }
          .tpl-grid { grid-template-columns: 1fr; gap: 0.75rem; }
  /* ⚠️ HISTORIQUE : ce padding-top dégageait la pilule flottante `.appnav`, qui n'est
     PLUS rendue (la nav réelle est la sidebar `.sbx-sidebar` inlinée dans inc/layout.php,
     repliée en icônes par son bloc @media(min-width:769px) and (max-width:1024px)).
     La règle est de toute façon neutralisée par les `!important` de inc/layout.php sur
     `.main` — ne pas s'en servir comme référence pour une correction responsive. */
  .main { padding: 6.5rem 1.5rem 2rem; }
  
  /* Profile grid responsive */
  .profile-grid { grid-template-columns: 1fr !important; gap: 1rem !important; }
  }

/* ─── Mobile : 768px et moins ─── */
@media (max-width: 768px) {
  /* ===== SÉCURITÉ TOTALE — ANTI-DÉBORDEMENT ===== */
  html, body { overflow-x: hidden !important; max-width: 100vw !important; width: 100%; }
  * { max-width: 100% !important; box-sizing: border-box !important; }
  
  /* Tout texte qui dépasse → coupe forcée */
  code, pre {
    white-space: normal !important;
    overflow-wrap: anywhere !important;
    word-break: break-all !important;
    overflow: hidden !important;
    text-overflow: clip !important;
  }
  
  /* Cards des keywords : largeur explicite + flex-wrap */
          
  /* Tabs : scrollables horizontalement, jamais débordement parent */
  .tabs {
    display: flex !important;
    overflow-x: auto !important;
    overflow-y: hidden;
    flex-wrap: nowrap !important;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    /* Hack containment : flex:1 1 0 + min-width:0 force le shrink */
    flex: 1 1 0 !important;
    min-width: 0 !important;
    max-width: 100% !important;
    width: auto !important;
    margin-left: 0 !important;
    box-sizing: border-box;
  }
  .tabs::-webkit-scrollbar { display: none; }
  .tab { flex-shrink: 0; white-space: nowrap; }
  .tab-count { display: inline-block; }
  
  /* (Nav mobile = système .mnav-* défini plus haut : topbar + drawer.
      L'ancien drawer .sidebar/.burger-btn a été retiré — c'était du code mort.) */
  
  /* Main : largeur totale + désactivation container "boîte" sur mobile */
  .main {
    margin: 0 !important;
    padding: calc(56px + env(safe-area-inset-top) + 1.5rem) 1rem 1.5rem !important; /* top = topbar fixe (56px) + air */
    min-height: 100dvh;
    width: 100%;
    max-width: 100%;
    overflow-x: hidden;
    background: var(--bg) !important;
    border: none !important;
    border-radius: 0 !important;
    box-sizing: border-box;
  }
  
  /* Page header */
  .page-header { 
    flex-direction: column;
    align-items: stretch;
    gap: 0.75rem;
    margin-bottom: 1.25rem;
  }
  .page-header > div:first-child { width: 100%; }
  /* Le slot d'actions passe pleine largeur dès que l'en-tête est en colonne (≤768) — sinon, entre
     641 et 768 px, les boutons empilés restaient à mi-largeur alignés à droite (full-pass 2026-07-01). */
  .page-actions { width: 100%; }
  .page-header .btn { width: 100%; justify-content: center; }
  /* Accent dégradé décoratif (64×2px) : masqué sur mobile — il flottait, orphelin, sous les boutons empilés */
  .page-header-signature::after { display: none; }
  .page-title { font-size: var(--fs-lg) !important; }
  .page-header-icon { width: 36px; height: 36px; border-radius: var(--radius); }
  .page-header-icon svg { width: 17px; height: 17px; }
  .page-subtitle { font-size: var(--fs-sm) !important; }

  /* KPIs : 2 colonnes serrées */
  .kpi-grid {
    grid-template-columns: repeat(2, 1fr);
    gap: var(--grid-gap-sm);
  }
  .kpi-value { font-size: var(--fs-lg) !important; }
  .kpi-label { font-size: var(--fs-micro) !important; }
  
  /* Sections plus serrées */
  .section { margin-top: 1.5rem; }
  .section-header { margin-bottom: 0.75rem; }
  .section-title { font-size: var(--fs-base); }
  
  .modal-backdrop {
    align-items: flex-end;
    padding: 0;
  }
  .modal-backdrop .modal {
    border-bottom-left-radius: 0;
    border-bottom-right-radius: 0;
    margin: 0 !important;
    width: 100% !important; /* 🆕 P2 responsive : 100% (et non 100vw → évite débordement scrollbar/safe-area) */
    max-height: 92svh;
  }
  
  /* Buttons : cibles tactiles ≥44px (recommandation responsive-craft) */
  .btn { min-height: 44px; }
  .btn-sm { min-height: 44px; }
  .btn-icon { min-height: 44px; min-width: 44px; }
  /* 🆕 Cibles tactiles ≥ 44px : bouton suppression de ligne + onglets (transverse) */
    .tabs .tab { min-height: 44px; }
  
  /* Inputs anti-zoom iOS (font-size >= 16px) : règle désormais POSÉE EN BASE (cf. § INPUTS),
     pour couvrir aussi les viewports > 768px (iPad/iPhone paysage). Conservée hors @media. */

  /* Forms : grilles 2 cols → 1 col */
  .form-grid-2 { grid-template-columns: 1fr !important; }
  .nc-social-grid { grid-template-columns: 1fr !important; }

  /* Sous-nav du COMPTE (Profil/Sécurité/Plan/Admin) : barre d'onglets scrollable, pleine largeur,
     VISIBLE. Neutralise la règle générique .tabs{flex:1 1 0} (pensée pour la barre d'outils du suivi)
     qui faisait collapser cette sous-nav (bandeau fantôme). */
  .account-header .account-tabs.tabs {
    display: flex !important;
    flex: 0 0 auto !important;
    width: 100% !important;
    flex-wrap: nowrap !important;
    overflow-x: auto;
    gap: 6px;
    padding-bottom: 4px;
    margin-left: 0 !important;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    mask-image: linear-gradient(to right, black calc(100% - 28px), transparent);
    -webkit-mask-image: linear-gradient(to right, black calc(100% - 28px), transparent);
  }
  .account-header .account-tabs.tabs::-webkit-scrollbar { display: none; }
  .account-header .account-tabs .tab { flex: 0 0 auto; min-height: 44px; display: inline-flex; align-items: center; } /* [M2.5] cible tactile ≥44px */
  
  /* Toast : centré bas */
  .toast {
    left: 1rem !important;
    right: 1rem !important;
    bottom: 1rem !important;
    width: auto !important;
    max-width: none !important;
  }
  
  /* Sticky action bar */
    
  /* Header des kw-blocks et templates : titre/tabs en haut, actions en dessous */
  .kw-block-header {
    flex-direction: column !important;
    align-items: stretch !important;
    gap: 0.5rem !important;
    width: 100%;
    min-width: 0;
  }
  .kw-block-header > * { min-width: 0; max-width: 100%; }
  .kw-block-header > div:last-child {
    display: flex !important;
    gap: 6px !important;
    justify-content: flex-end;
  }
  .kw-block-header > div:last-child .btn {
    flex: 1;
    justify-content: center;
  }
  /* Dans un header en column, le tabs ne doit pas être flexé à 0 — il garde sa hauteur naturelle */
  .kw-block-header > .tabs {
    flex: 0 0 auto !important;
    width: 100% !important;
    min-height: 40px;
  }
      
/* ─── Tableau prospection V6 expandable : marche déjà sur mobile, on garde ─── */
  /* L'ancien transform .tbl → cards n'est plus nécessaire car renderRow() V6 
     produit déjà des <tr class="row-card"> en cards aérées (responsive built-in).
     overflow:hidden : les row-cards sont déjà responsive, pas besoin de scroll horizontal */
      
  /* Sécurité : si une page utilise encore l'ancien tableau classique (clients, communication),
     on le rend scrollable horizontalement plutôt que de le casser */
  }

/* ─── Très petit mobile (< 380px) ─── */
@media (max-width: 380px) {
  .kpi-grid { grid-template-columns: 1fr; }
  .main { padding: calc(56px + env(safe-area-inset-top) + 1.5rem) 0.75rem 1rem !important; } /* dégage la topbar mobile (56px) + air */
  .page-title { font-size: var(--fs-lg) !important; }
}

/* (body.sidebar-open retiré 2026-06-23 — code mort ; le drawer mobile utilise body.mnav-open) */

/* ============================================================ */
/* V4-DEF : AUDIT FINAL — Fixes pour pages Devis, Security,     */
/* Clients, et autres ajustements                                */
/* ============================================================ */

@media (max-width: 768px) {
  
  /* Sélecteur de type de prospect (modale prospects.php) : reste en 2 colonnes, compact.
     Les ~60 lignes d'overrides mobiles du « calculateur devis » qui l'entouraient
     (.tunnel-card, .numero-pill, .step*, .presta-*, .tjm-*, .opt-*, .recap-*, .acompte-*,
     .input-num, .rev-wrap, .nbjour-*) ont été retirées avec leur bloc de base le 2026-07-28 :
     elles ne ciblaient plus aucun élément du CRM. */
  .choice-grid { gap: 8px; }
  .choice-card { padding: 12px 10px; font-size: var(--fs-sm); }

  /* ─── CLIENTS : search input ─── */
  input[type="text"].input,
  input[type="search"].input,
  .input[type="text"] {
    min-width: 0 !important;
  }
  
  /* ─── INDEX (Dashboard) : welcome banner et stats ─── */
      
  /* Dash rows : déjà 1 col en 1024px, mais on s'assure */
          
  /* Chart : hauteur réduite */
    
  /* ─── SECURITY : historique connexions ─── */
    
  /* ─── MODALES : améliorations supplémentaires ─── */
  .modal-title { font-size: var(--fs-md) !important; gap: 8px !important; }
  .modal-actions {
    flex-direction: column-reverse !important;
    gap: 8px !important;
  }
  .modal-actions .btn { width: 100% !important; }
  
  /* ─── SECURITY : QR code et codes 2FA ─── */
  #qrcode canvas, #qrcode img {
    max-width: 100% !important;
    height: auto !important;
  }
  
  /* ─── FORMS : tous les inputs en pleine largeur ─── */
  .input, .textarea, select.input {
    width: 100% !important;
    box-sizing: border-box;
  }
  
  /* (.sidebar-presence retiré — code mort) */
  
  /* ─── BACKUP : tout texte qui dépasserait ─── */
  table, td, th { max-width: 100%; word-break: break-word; }
  
  /* (bloc « DEVIS HISTORY » retiré le 2026-07-28 : .devis-* était du CSS mort
     hérité du calculateur de devis de l'agence, aucun markup ne l'utilisait.) */
}

/* ─── Très petit mobile (< 380px) ─── */
@media (max-width: 380px) {
  /* .presta-grid / .recap-total-val / .tjm-value retirés le 2026-07-28 : CSS mort du
     calculateur de devis. Seul le sélecteur de type de prospect subsiste ici. */
  .choice-grid { grid-template-columns: 1fr !important; }
}

/* ════════════════════════════════════════════════════════════════
   STABLE V1.1 — RESPONSIVE COMPLET (tablette + mobile)
   Additions ciblées sur V6 expandable + container boîte + Kanban
   ════════════════════════════════════════════════════════════════ */

/* ─── TABLETTE (768–1024px) : container boîte adaptable ─── */
@media (max-width: 1024px) {
  /* ⚠️ HISTORIQUE : commentaire écrit à l'époque de la pilule flottante `.appnav`,
     qui n'est plus rendue. Sur 769–1024px la nav EST une sidebar (`.sbx-sidebar`,
     inc/layout.php, repliée en icônes) — la description « pas de sidebar » est fausse
     et ces règles `.main` sont écrasées par les `!important` de inc/layout.php.
     Conservé tel quel (inerte) ; à supprimer dans un lot d'hygiène CSS dédié.
     But d'origine : retirer les marges gauches FANTÔMES (calc(240px)/calc(210px))
     qui décalaient le contenu vers la droite sur tablette. */
  .main {
    margin: 0 auto;
    padding-left: 1.5rem; padding-right: 1.5rem;
    border-radius: var(--radius);
  }
  
  /* Page header tablette : titre plus compact */
  .page-title { font-size: var(--fs-lg); }
  .page-subtitle { font-size: var(--fs-sm); }
  
  /* Modals plus larges en tablette */
  .modal { max-width: 90vw; }
  
  /* Row card V6 : reste pleinement utilisable */
      
  /* Forms 3 cols → 2 cols */
    
  /* Templates communication : 2 cols */
  .tpl-grid { grid-template-columns: 1fr 1fr !important; gap: 1rem; }
}

/* ─── MOBILE (≤768px) : V6 row card, Kanban, modales ─── */
@media (max-width: 768px) {
  /* V6 EXPANDABLE ROW : compactage mobile */
                
  /* Le badge stage peut être tronqué (sera revoir avec --short-label) */
  .row-stage-wrap .stage-badge {
    font-size: var(--fs-micro);
    padding: 3px 8px;
  }
  
  /* Détail : 1 colonne sur mobile */
          
  /* Source cell V2 : input + boutons restent compactes */
        
  /* PIPELINE KANBAN : scroll horizontal fluide */
      
  /* AGENDA : vue mois compactée, basculer en jour/semaine recommandé */
      .agenda-event { font-size: var(--fs-micro); padding: 1px 4px; }
  
  /* Tables denses (clients, factures, etc.) : scroll horizontal */
    
  /* (ancien .burger-btn retiré — code mort ; nav mobile = système .mnav-*) */
}

/* ─── SMALL MOBILE (≤480px) : derniers ajustements ─── */
@media (max-width: 480px) {
  /* Row card : encore plus compact */
      .row-chevron { width: 12px; height: 12px; }
    
  /* Sur très petit, le bloc de droite peut wrapper sous le nom */
        
  /* Kanban : largeur de colonnes adaptée petit écran */
    
  /* KPIs : 1 colonne sur très petit */
  .kpi-grid { grid-template-columns: 1fr; }
  
  /* Padding ultra-réduit (la carte garde --card-pad-sm du palier 768 → cohérence) */
  .main { padding: calc(56px + env(safe-area-inset-top) + 1.5rem) 0.5rem 1rem !important; } /* dégage la topbar mobile (56px) + air */
}

/* ════════════════════════════════════════════════════════════════
   SPRINT RESPONSIVE — additions ciblées
   Templates / Pipeline / Clients / Prospection / Agenda / 360px
   ════════════════════════════════════════════════════════════════ */

/* Utilitaire global : masquer sur mobile */
/* ─── #4 TEMPLATES : empêcher boutons de sortir du bloc ─── */
@media (max-width: 768px) {
  .tpl-card {
    overflow: hidden;
    padding: 14px !important;
  }
  .tpl-content {
    word-break: break-word;
    overflow-wrap: anywhere;
  }
  .tpl-head {
    flex-wrap: wrap;
    gap: 6px;
  }
}

/* ─── #3 PROSPECTION : ligne contact + détail expandable ─── */
@media (max-width: 768px) {
  /* La row-card globale ne déborde pas */
  .tbl tr.row-card {
    display: block;
    width: 100%;
  }

  /* Le badge stage prend une largeur minimale tactile */
  .row-stage-wrap {
    flex-shrink: 0;
  }
}

/* En très petit (≤480px), la zone droite passe sous le nom proprement */
/* Suite des règles 768 (déplacées après le 480 pour éviter la nested media query) */
@media (max-width: 768px) {
  
  /* Pill "Ajouté en retour" : reste compacte sur sa propre ligne */
  .src-addback-pill {
    white-space: nowrap;
    width: auto !important;
    max-width: 100%;
    align-self: flex-start;
    font-size: var(--fs-xs);
  }
  
  /* ROW-DETAIL-ACTIONS — disposition compacte mobile :
     - Action principale : pleine largeur (gros bouton tactile)
     - Boutons secondaires + delete : ligne du dessous, compacts à droite */
    /* L'action principale (Réactiver / Avancer / Créer client / etc.) */
        /* Le spacer flex:1 ne sert plus en mobile */
    /* Bouton supprimer : à droite, compact */
  }

/* ─── #6 CLIENTS : tableau → cards mobile (Type + Photo + Nom + Contact) ─── */
@media (max-width: 768px) {
  /* Masquer thead du tableau clients */
  .tbl thead {
    display: none;
  }
  /* Reset table : pas de border-spacing parasite, largeur stricte */
    /* Transformer chaque ligne en card */
  .tbl tr.client-row {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 6px 12px;
    align-items: center;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 12px 14px;
    margin: 0 0 10px 0;
    box-shadow: var(--elev-1);
    width: 100%;
    max-width: 100%;
    box-sizing: border-box;
    cursor: pointer;
    transition: border-color .15s ease;
  }
  .tbl tr.client-row:hover {
    border-color: var(--border-strong);
  }
  /* Tous les <td> enfants : pas de fond, pas de bordure, pas de hover hérité */
  .tbl tbody tr.client-row td,
  .tbl tr.client-row td {
    background: transparent !important;
    background-color: transparent !important;
    border: none !important;
    border-radius: 0 !important;
    box-shadow: none !important;
    -webkit-backdrop-filter: none !important;
    backdrop-filter: none !important;
  }
  /* Masquer colonnes secondaires + case à cocher (sélection multiple peu utile au doigt) */
  .tbl tr.client-row td[data-label="Email"],
  .tbl tr.client-row td.cell-sel,
  .tbl tr.client-row td.cell-go {
    display: none;
  }
  /* Statut : badge sur une 3e ligne pleine largeur (info de pilotage CRM clé) */
  .tbl tr.client-row td[data-label="Statut"] {
    grid-column: 1 / -1;
    padding: 6px 0 0 !important;
    background: transparent !important;
  }
  /* Type pill : occupe la 1ère colonne (étroite) sur toute la hauteur */
  .tbl tr.client-row td[data-label="Type"] {
    grid-row: span 2;
    align-self: center;
    padding: 0 !important;
    background: transparent !important;
  }
  /* Type pill style mobile : un peu plus visible */
  .tbl tr.client-row td[data-label="Type"] .type-pill {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 4px 10px;
    font-size: var(--fs-micro);
    font-weight: var(--fw-bold);
    border-radius: var(--radius-pill);
    min-width: 44px;
  }
  /* Nom + photo : 1ère ligne grille */
  .tbl tr.client-row td[data-label="Nom"] {
    grid-column: 2;
    padding: 0 !important;
    background: transparent !important;
    min-width: 0;
    overflow: hidden;
  }
  /* Contact : 2e ligne grille — affiché seulement si non-vide non-"—" */
  .tbl tr.client-row td[data-label="Contact"] {
    grid-column: 2;
    padding: 0 !important;
    background: transparent !important;
    font-size: var(--fs-xs);
    color: var(--text-muted);
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  /* Si Contact n'est que "—" on le rend invisible (économise une ligne pour les particuliers) */
  .tbl tr.client-row td[data-label="Contact"]:empty,
  .tbl tr.client-row td[data-label="Contact"]:has(>:only-child:empty) {
    display: none;
  }
  /* Logo + nom layout interne */
  .tbl tr.client-row .client-name-cell {
    gap: 10px;
    min-width: 0;
    background: transparent !important;
    padding: 0;
    align-items: center;
  }
  .tbl tr.client-row .client-name-cell-text {
    font-size: var(--fs-base);
    font-weight: var(--fw-semibold);
    color: var(--text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
    max-width: 100%;
  }
  /* Logo client : ROND sur mobile (cohérence avec avatars prospection) */
  .tbl tr.client-row .client-logo,
  .tbl tr.client-row .client-logo-sm,
  .tbl tr.client-row .client-logo-md {
    border-radius: 50% !important;
    width: 32px !important;
    height: 32px !important;
    font-size: var(--fs-micro);
    border: 1px solid var(--glass-border-strong);
  }
  .tbl tbody {
    display: block;
    width: 100%;
    max-width: 100%;
    background: transparent !important;
    box-sizing: border-box;
  }
  /* Card wrap autour de la table : pas de scroll horizontal nécessaire */
  .section .card.card-flat:has(.tbl) {
    padding: 0 !important;
    background: transparent;
    border: none;
    box-shadow: none;
  }
  /* Filtres + recherche : empilés */
  #searchClients { width: 100% !important; }
  #sortClients { width: 100% !important; max-width: 100% !important; }
}

/* ─── TABLES GÉNÉRIQUES → cartes mobile (membres, invitations, sessions, factures) ───
   Étend le pattern .client-row : tables .table-dense + tables .tbl SANS .client-row.
   Chaque <td> doit porter data-label="…" (le libellé s'affiche via ::before). ─── */
@media (max-width: 768px) {
  table.table-dense thead { display: none; }
  table.table-dense, .tbl-cards {
    display: block; width: 100%; max-width: 100%;
    border: none !important; background: transparent !important;
  }
  table.table-dense tbody, .tbl-cards tbody { display: block; width: 100%; }
  table.table-dense tbody tr,
  .tbl-cards tbody tr {
    display: block;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 8px 14px;
    margin: 0 0 10px 0;
    box-shadow: var(--elev-1);
    width: 100%; box-sizing: border-box;
  }
  table.table-dense tbody td,
  .tbl-cards tbody tr td {
    display: flex; justify-content: space-between; align-items: center; gap: 14px;
    text-align: right;
    border: none !important; background: transparent !important;
    padding: 7px 0 !important;
    font-size: var(--fs-base); min-width: 0;
  }
  table.table-dense tbody td + td,
  .tbl-cards tbody tr td + td { border-top: 1px solid var(--glass-border) !important; }
  table.table-dense tbody td::before,
  .tbl-cards tbody tr td::before {
    content: attr(data-label);
    flex: 0 0 42%; text-align: left;
    font-weight: var(--fw-semibold); color: var(--text-secondary); font-size: var(--fs-xs); white-space: nowrap;
  }
  /* Cellule sans libellé (actions/kebab) : pleine largeur, alignée à droite, sans préfixe */
  table.table-dense tbody td:not([data-label]),
  .tbl-cards tbody tr td:not([data-label]) { justify-content: flex-end; }
  table.table-dense tbody td:not([data-label])::before,
  .tbl-cards tbody tr td:not([data-label])::before { content: none; }
  table.table-dense tbody td > *,
  .tbl-cards tbody tr td > * { min-width: 0; }
  /* Cellule d'actions VIDE (ex. pas de menu kebab sur soi-même) : masquée pour ne pas créer un bloc vide */
  table.table-dense tbody td:not([data-label]):not(:has(*)),
  .tbl-cards tbody tr td:not([data-label]):not(:has(*)) { display: none !important; }
  /* Cellule "identité" (Membre) : en-tête pleine largeur (avatar + nom + email), pas en label:valeur */
  table.table-dense tbody td[data-label="Membre"] {
    display: block !important; text-align: left;
    border: none !important;
    padding: 2px 0 11px !important; margin-bottom: 4px;
    border-bottom: 1px solid color-mix(in srgb, var(--border) 60%, transparent) !important;
  }
  table.table-dense tbody td[data-label="Membre"]::before { content: none; }
  table.table-dense td[data-label="Membre"] .cell-id { display: flex; align-items: center; gap: 10px; }
  table.table-dense td[data-label="Membre"] .cell-sub { display: block; font-size: var(--fs-xs); color: var(--text-muted); margin-top: 2px; }
  /* La carte parente ne rogne plus ces tables */
  .card:has(table.table-dense) { overflow: visible !important; }
}

/* ─── #2 AGENDA : grille mois remplacée par liste verticale ─── */
@media (max-width: 768px) {
  /* La grille mois traditionnelle devient inutilisable < 768px : on la cache */
  .agenda-grid {
    display: none !important;
  }
  /* Container liste mobile (rempli par JS) */
  .agenda-mobile-list {
    display: flex !important;
    flex-direction: column;
    gap: 12px;
    margin-top: 1rem;
  }
  .agenda-mobile-day {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 12px 14px;
    box-shadow: var(--elev-1);
  }
  .agenda-mobile-day.is-today {
    border-color: var(--accent);
    background: color-mix(in srgb, var(--accent) 14%, var(--surface));
  }
  .agenda-mobile-day-header {
    display: flex;
    align-items: baseline;
    gap: 10px;
    padding-bottom: 8px;
    margin-bottom: 8px;
    border-bottom: 1px solid var(--glass-border);
  }
  .agenda-mobile-day-num {
    font-size: var(--fs-lg);
    font-weight: var(--fw-bold);
    color: var(--text); /* était #FFFFFF → invisible sur la carte claire */
    line-height: 1;
    min-width: 36px;
  }
  .agenda-mobile-day.is-today .agenda-mobile-day-num {
    color:var(--accent-link);
  }
  .agenda-mobile-day-meta {
    flex: 1;
    min-width: 0;
  }
  .agenda-mobile-day-name {
    font-size: var(--fs-sm);
    font-weight: var(--fw-semibold);
    color: var(--text);
    text-transform: capitalize;
  }
  .agenda-mobile-day-month {
    font-size: var(--fs-micro);
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
  }
  .agenda-mobile-day-empty {
    color: var(--text-muted);
    font-size: var(--fs-sm);
    font-style: italic;
    padding: 4px 0;
  }
  .agenda-mobile-items {
    display: flex;
    flex-direction: column;
    gap: 6px;
  }
  .agenda-mobile-item {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 10px;
    border-radius: var(--radius);
    font-size: var(--fs-sm);
    cursor: pointer;
    transition: filter .12s;
  }
  .agenda-mobile-item:hover { filter: brightness(1.15); }
  .agenda-mobile-item.type-event {
    background: rgba(var(--accent-rgb), 0.28);
    color: var(--text);
    border-left: 0;
  }
  .agenda-mobile-item.type-task {
    background: rgba(var(--accent-rgb), 0.28);
    color: var(--text);
    border-left: 0;
  }
  .agenda-mobile-item.type-birthday {
    background: rgba(236, 72, 153, 0.22);
    color: var(--text);
    border-left: 0;
  }
  .agenda-mobile-item.completed {
    opacity: 0.45;
    text-decoration: line-through;
  }
  .agenda-mobile-item-time {
    font-family: var(--font-data);
    font-size: var(--fs-micro);
    opacity: 0.85;
    flex-shrink: 0;
    min-width: 36px;
  }
  .agenda-mobile-item-title {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  /* Btn "Aujourd'hui" plus visible mobile */
  .agenda-mobile-empty {
    text-align: center;
    padding: 2rem 1rem;
    color: var(--text-muted);
    font-size: var(--fs-sm);
  }
}
/* En desktop : la liste mobile est masquée */
.agenda-mobile-list { display: none; }

/* ─── 360px et moins (Galaxy S8+, vieux Androids) ─── */
@media (max-width: 360px) {
  .main { padding: calc(56px + env(safe-area-inset-top) + 1.5rem) 0.5rem 1rem !important; } /* dégage la topbar mobile (56px) + air */
  .page-title { font-size: var(--fs-lg) !important; }
  .page-subtitle { font-size: var(--fs-xs) !important; }
  
  /* KPIs reste 1 colonne */
  .kpi-grid { grid-template-columns: 1fr; }
  .kpi-value { font-size: var(--fs-lg) !important; }
  
  .modal-title { font-size: var(--fs-md) !important; }
  
  /* (.sidebar drawer retiré — code mort ; nav mobile = .mnav-*) */
  
  /* Templates : 1 col + boutons texte plus court */
  .tpl-content { font-size: var(--fs-xs); }
  
  /* Clients cards : densité +++ */
  .tbl tr.client-row {
    padding: 10px 12px;
    gap: 8px 10px;
  }
  .tbl tr.client-row .client-name-cell-text {
    font-size: var(--fs-sm);
  }
  
  /* Agenda mobile : padding réduit */
  .agenda-mobile-day {
    padding: 10px 12px;
  }
  .agenda-mobile-day-num {
    font-size: var(--fs-lg);
    min-width: 28px;
  }
  
  /* Prospection row : encore plus compact */
      }

/* ════════════════════════════════════════════════════════
   Sidebar — groupes dépliables (déplacé depuis layout.php, Phase 2)
   ════════════════════════════════════════════════════════ */
/* ─── Menu Administratif dépliable (V5-3 refonte) ─── */
/* (bloc .sidebar-group / .sidebar-subnav / .sidebar-sublink retiré — ancienne nav repliable, code mort 2026-06-23) */

/* ════════════════════════════════════════════════════════════
   PHASE 4 — SHELL SAAS
   En-tête de page unifié · carte Plan & sièges (sidebar) ·
   section Abonnement (admin) · accents signature violet→orange.
   ════════════════════════════════════════════════════════════ */

/* ── En-tête de page unifié ── */
.page-header-signature {
  position: relative;
  align-items: flex-end;
  padding-bottom: 0;
  margin-bottom: 2.4rem;
  flex-wrap: wrap;
}
.page-header-signature::after {
  content: none;
}
.page-header-text { min-width: 0; }
.page-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

/* HD04 — une seule bande de mission, compacte et sans effet décoratif. */
body .page-header[data-page-header="hd04"] {
  display: grid;
  width: 100%;
  max-width: none !important;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: end;
  gap: 10px 18px;
  margin: 0 0 12px !important;
  padding: 14px 22px 0;
  border: 0;
  border-bottom: 1px solid var(--border);
  border-radius: 0;
  background: var(--surface);
  box-shadow: none;
}
body .page-header[data-page-header="hd04"] .page-header-context {
  margin: 0 0 5px;
  color: var(--text-muted);
  font-family: var(--font-data);
  font-size: var(--fs-micro);
  font-weight: var(--fw-medium);
  letter-spacing: var(--tracking-label);
  line-height: var(--lh-tight);
  text-transform: uppercase;
}
body .page-header[data-page-header="hd04"] .page-title {
  font-size: clamp(24px, 2.1vw, 34px);
  font-weight: var(--fw-semibold);
  letter-spacing: -.035em;
  line-height: 1.04;
}
body .page-header[data-page-header="hd04"] .page-subtitle {
  max-width: 72ch;
  margin-top: 5px;
  font-size: var(--fs-sm);
  line-height: 1.4;
}
body .page-header[data-page-header="hd04"] .page-actions {
  padding-bottom: 12px;
  gap: 8px;
}
body .page-header[data-page-header="hd04"] .page-actions :is(.btn, button, a) {
  min-height: 34px;
  border-radius: 8px;
  box-shadow: none;
}
body .page-header[data-page-header="hd04"] .page-header-tabs {
  display: flex;
  min-width: 0;
  grid-column: 1 / -1;
  align-items: center;
  gap: 4px;
  min-height: 40px;
  padding: 4px 0 5px;
  overflow-x: auto;
  scrollbar-width: none;
}
body .page-header[data-page-header="hd04"] .page-header-tabs::-webkit-scrollbar { display: none; }
body .page-header[data-page-header="hd04"] .page-header-tabs > [role="group"] { width: auto; }
body .main:not(.main-wide):has(> .page-header[data-page-header="hd04"]) > *:not(.page-header):not(.datepicker-backdrop):not(.datepicker-popover):not([class*="modal"]):not(.toast) {
  max-width: none !important;
  margin-left: 0 !important;
  margin-right: 0 !important;
}
@media (max-width: 1024px) {
  body .page-header[data-page-header="hd04"] { padding-inline: 18px; }
}
@media (max-width: 720px) {
  body .page-header[data-page-header="hd04"] { grid-template-columns: 1fr; padding: 12px 16px 0; }
  body .page-header[data-page-header="hd04"] .page-actions { padding-bottom: 4px; justify-content: flex-start; }
}

/* [DS-4] `.kpi-value.signature` (valeur KPI peinte en dégradé, texte transparent)
   supprimée : aucune page ne l'émettait, et un dégradé décoratif sur du texte est
   exactement ce que la direction artistique proscrit. Le scanner de code mort ne
   l'avait pas vue — le mot « signature » vit ailleurs dans le dépôt (Stripe,
   contract_signatures) et faisait passer le compound pour vivant. */

/* ── Section Abonnement & sièges (admin) ── */
/* [DS-3] Le nom du plan était du texte peint par un dégradé découpé (background-clip).
   Il reprend la même mise en valeur que .kpi-value.accent : une couleur d'accent lisible. */
.sub-detail { font-size: var(--fs-sm); color: var(--text-muted); }
.seat-meter { min-width: 200px; flex: 1; }
.seat-meter-top {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  font-size: var(--fs-xs);
  color: var(--text-secondary);
  margin-bottom: 6px;
  font-variant-numeric: tabular-nums;
}
/* [DS-3] Jauge de sièges : la direction artistique réserve la pilule aux badges de statut,
   aux compteurs et aux jauges — d'où --radius-pill ici et sur le remplissage. */
.seat-bar {
  height: 6px;
  border-radius: var(--radius-pill);
  background: rgba(255, 255, 255, 0.10);
  overflow: hidden;
}
:root[data-theme="light"] .seat-bar { background: rgba(15, 23, 42, 0.10); }
.seat-bar i {
  display: block;
  height: 100%;
  border-radius: var(--radius-pill);
  /* [DS-3] Une jauge garde son aplat d'accent (c'est une donnée, pas un ornement),
     mais perd le dégradé. */
  background: var(--accent);
}
.seat-bar i.seat-bar-full { background: var(--danger); }

/* ── Responsive ── */
@media (max-width: 640px) {
  .page-header-signature { align-items: flex-start; }
  .page-actions { width: 100%; }
  }

/* ════════════════════════════════════════════════════════════
   PHASE 5 — DISPOSITIONS DENSES
   Primitives partagées : lignes de travail, tables denses,
   stats inline, compteurs. Le contenu reste dans la zone main
   (sidebar intouchable — seul l'aurora passe dessous).
   ════════════════════════════════════════════════════════════ */

/* Garde : tout contexte d'empilement du contenu reste sous la sidebar (z 50) */
.main { position: relative; z-index: 1; }

/* Compteur pilule (subnav, filtres, en-têtes de groupe) */
/* [DS-3] La pilule reste légitime ici : c'est un compteur, pas un onglet. En
   revanche son texte était à 10px, sous le plancher de lisibilité, et sa famille
   était écrite en littéral au lieu du token de police de données. */
.count-pill {
  font-family: var(--font-data);
  font-size: var(--fs-micro);
  padding: 1px 7px;
  border-radius: var(--radius-pill);
  background: var(--bg-soft);
  border: 1px solid var(--border);
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}

/* Chips d'en-tête (coins, équipe, période) */
.chip { display: inline-flex; align-items: center; gap: 7px; padding: 5px var(--sp-3); border-radius: var(--radius-pill); font-size: var(--fs-xs); font-weight: var(--fw-semibold); background: var(--m-ctl-bg); border: 1px solid var(--m-ctl-border); color: var(--text-secondary); }
.chip b { font-family: var(--font-data); font-weight: var(--fw-semibold); color: var(--text); font-variant-numeric: tabular-nums; }

/* Stats inline (remplacent les cartes KPI de comptage) */

/* Lignes de travail denses (listes du dashboard) */
.panel-list { padding: 0.35rem 0; }
.panel-list-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 11px 14px 7px; }

/* Table dense (admin, listes structurées) */
.table-dense { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); }
/* [DS-3] 10,5px : sous le plancher de lisibilité (--fs-micro) ET en demi-pixel, donc
   rendu au sous-pixel, variable d'un écran à l'autre. C'est l'en-tête du tableau des
   membres (admin.php), mesuré à 10,5px à l'écran. */
.table-dense th { text-align: left; font-size: var(--fs-micro); font-weight: var(--fw-semibold); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--text-dim); padding: var(--sp-2) var(--sp-4); border-bottom: 1px solid var(--border); white-space: nowrap; }
.table-dense td { padding: 8px 14px; border-bottom: 1px solid color-mix(in srgb, var(--border) 55%, transparent); vertical-align: middle; height: 48px; }
.table-dense tr:last-child td { border-bottom: none; }
.table-dense tbody tr:hover { background: var(--row-hover); }
.table-dense .t-right { text-align: right; }
.cell-id { display: flex; align-items: center; gap: 10px; font-weight: var(--fw-semibold); min-width: 0; }
.cell-sub { display: block; font-family: var(--font-data); font-size: var(--fs-micro); font-weight: var(--fw-regular); color: var(--text-dim); }

/* ════════════════════════════════════════════════════════════
   PHASE 5 — Barre de navigation flottante (remplace la sidebar)
   Pilule de verre centrée en bas, façon maquette.
   ════════════════════════════════════════════════════════════ */
.appnav {
  position: fixed;
  top: 18px;
  bottom: auto;
  left: 50%;
  transform: translateX(-50%);
  z-index: var(--z-navbar);
  max-width: calc(100vw - 32px);
  /* [DS-3] La barre de navigation était la dernière pilule de la coquille. Elle
     prend l'arrondi du système : la pilule reste réservée aux badges de statut,
     aux compteurs et aux jauges. */
  border-radius: var(--radius);
  background: var(--m-nav-bg);
  border: 1px solid var(--m-nav-border);
  box-shadow: var(--elev-2);
  padding: 6px 8px;
  /* Anti-flash : la barre est "persistée" pendant la transition de page */
  view-transition-name: appnav;
  /* Promotion sur sa propre couche compositing → scroll fluide.
     ⚠️ PAS de contain:paint ici : il rognerait les menus déroulants (« Plus », compte…) qui dépassent de la pilule. */
  will-change: transform;
}
/* 🆕 Mode nuit OLED : on neutralise le reflet blanc du haut (inset blanc 0.7 hardcodé ci-dessus,
   moche sur quasi-noir) ; la bordure --glass-border-strong suffit à délimiter + ombre noire profonde. */
:root[data-theme="dark"] .appnav {
  box-shadow: var(--elev-2);
}
/* ── Logo theme-aware : emblème COULEUR en clair, emblème BLANC en nuit (cf. renderLogo).
   Le `display` est piloté ICI (pas en inline) sinon l'inline battrait la classe. ── */
.nop-logo--day { display: inline-block; }
.nop-logo--night { display: none; }
:root[data-theme="dark"] .nop-logo--day { display: none; }
:root[data-theme="dark"] .nop-logo--night { display: inline-block; }
/* Anti-écrasement : chaque item garde sa taille (pas de compression flex) → la pilule ne « compacte »
   plus ses items sur écran étroit ; à la place les labels passent en icônes seules dès ≤1200px (cf. media). */

/* ── Sélecteur de période (graphes dashboard / analytics) ── */
/* [DS-3] Contrôle segmenté : forme carrée (la pilule est réservée aux badges de
   statut) et segment actif SANS fond accent plein — l'accent reste aux actions.
   Chaque segment porte une bordure transparente pour que l'état actif n'ajoute
   aucune épaisseur et ne décale pas ses voisins. */
.period-sel { display:inline-flex; gap:2px; background:var(--bg-soft); border:1px solid var(--border); border-radius: var(--radius); padding:2px; vertical-align:middle; }
.period-sel button { appearance:none; border:1px solid transparent; background:none; font:inherit; font-size:var(--fs-xs); font-weight:var(--fw-semibold); color:var(--text-muted); padding:var(--sp-1) var(--sp-3); border-radius: var(--radius); cursor:pointer; transition:all .15s var(--ease-snappy); white-space:nowrap; min-height: 44px; display: inline-flex; align-items: center; justify-content: center; }
@media (min-width: 641px) { .period-sel button { min-height: auto; display: inline-block; padding: var(--sp-1) var(--sp-3); } }
.period-sel button.on { background:var(--surface-hover); border-color:var(--accent); color:var(--text); }
.period-sel button:not(.on):hover { color:var(--text); }
.period-sel.is-loading { opacity:.5; pointer-events:none; }
@media (max-width: 640px) { /* 🆕 P0 responsive : cibles tactiles 44px (sélecteurs de période) */
  .period-sel button { min-height: 44px; padding-top: var(--sp-3); padding-bottom: var(--sp-3); font-size: var(--fs-sm); }
}

/* ── Bandeau « offre de lancement » + compte à rebours ── */
/* [DS-3] La TEINTE des trois variantes est porteuse de sens (vert = lancement,
   violet = anniversaire, accent = parrainage) : elle reste. Ce qui part, c'est
   l'ornement — le dégradé diagonal, qui faisait varier le fond d'un bord à l'autre
   du même bandeau, et la lueur colorée sous la boîte, qui était une quatrième
   élévation à elle seule. Un bandeau est POSÉ dans le flux de la page : --elev-1. */
.launch-banner { display:flex; align-items:center; justify-content:center; gap:18px; flex-wrap:wrap;
  background:#16A34A; color:#fff; border-radius: var(--radius-lg); padding:var(--sp-4) var(--sp-6); margin:0 0 1.4rem;
  box-shadow:var(--elev-1); }
.launch-banner.cd-ended { display:none; }
.launch-banner .lb-text { font-size:var(--fs-md); font-weight:var(--fw-bold); }
.launch-banner .lb-timer { display:flex; align-items:center; gap:var(--sp-2); }
.launch-banner .lb-unit { background:rgba(255,255,255,.2); border-radius: var(--radius); padding:6px 10px; min-width:54px;
  display:flex; flex-direction:column; align-items:center; line-height:1.05; }
/* Un chiffre de compte à rebours est un nombre d'affichage, pas du texte. */
.launch-banner .lb-unit span { font-size:var(--fs-lg); font-weight: var(--fw-bold); font-variant-numeric:tabular-nums; font-family:var(--font-data); }
.launch-banner .lb-unit small { font-size:var(--fs-micro); opacity:.9; text-transform:uppercase; letter-spacing:.04em; margin-top:2px; }
.launch-banner .lb-sep { font-weight: var(--fw-bold); opacity:.55; font-size:var(--fs-lg); }
@media (max-width:560px){ .launch-banner .lb-text{font-size:var(--fs-base)} .launch-banner .lb-unit{min-width:46px;padding:5px 7px} .launch-banner .lb-unit span{font-size:var(--fs-md)} }
/* Variantes promo (réutilisent .launch-banner) : anniversaire (violet), parrainage (accent) */
.launch-banner.promo-bday { background:#7c3aed; box-shadow:var(--elev-1); }
/* [DS-3] .6em de 16px = 9,6px, sous le plancher de lisibilité. */
.launch-banner.promo-bday sup { font-size:var(--fs-micro); }
/* Encart « remise parrainage » du FILLEUL (partagé billing.php + parrainage.php) */
.ref-encart{display:flex;align-items:center;gap:var(--sp-4);flex-wrap:wrap;padding:var(--sp-4) var(--sp-5);border-radius: var(--radius-lg);border:1px solid color-mix(in srgb,var(--accent) 38%,var(--m-panel-border));background:color-mix(in srgb,var(--accent) 8%,var(--surface))}
.ref-encart .ref-ico{width:40px;height:40px;border-radius: 50%;background:var(--accent);color:var(--on-accent);display:flex;align-items:center;justify-content:center;flex-shrink:0}
.ref-encart .ref-txt{flex:1;min-width:180px}
.ref-encart .ref-h{font-size:var(--fs-base);font-weight:var(--fw-bold);color:var(--accent-link)}
.ref-encart .ref-s{font-size:var(--fs-sm);color:var(--text-secondary);line-height:var(--lh-base);margin-top:1px}
.ref-encart a{margin-left:auto}

.appnav-avatar {
  width: 30px; height: 30px;
  border-radius: 50%;
  background: var(--accent-soft);
  color:var(--accent-link);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: var(--fs-micro);
  font-weight: var(--fw-bold);
  text-transform: uppercase;
  flex-shrink: 0;
  border: 1px solid var(--border);
  overflow: hidden;
}

/* Depuis le passage à la sidebar, la pilule `.appnav` n'est plus rendue : il ne reste
   de cette famille que ce que réemploie le POPOVER ÉQUIPE de la sidebar — `.appnav-group`,
   `.appnav-dropdown*`, `.appnav-dd-*` et `.appnav-team-count`. Le lot d'hygiène annoncé
   ici a été fait (DS-4, 2026-08-08) : les états `.appnav-link.active`, `.appnav-profile*`,
   `.appnav-more-btn/-team-btn.active`, `.appnav-caret` et `.appnav-dd-link.active` sont
   supprimés, faute d'émetteur (le bouton Équipe réellement rendu porte `.sbx-team-btn`,
   stylé dans inc/layout.php). Ce media ne garde donc que l'ancrage des dropdowns. */
@media (max-width: 1200px) {
          /* Cibles tactiles ≥ 44px */
      /* Dropdowns « Plus » / « Équipe » : ancrés au bord droit + largeur bornée → jamais hors écran */
  .appnav-dropdown { left: auto; right: 0; transform: translateY(-6px); max-width: calc(100vw - 24px); }
  .appnav-group.open .appnav-dropdown { transform: translateY(0); }
}
@media (max-width: 720px) {
  .appnav { top: 12px; bottom: auto; max-width: calc(100vw - 20px); }
  .main { padding-top: calc(56px + env(safe-area-inset-top) + 1.5rem); padding-left: 1rem; padding-right: 1rem; padding-bottom: 2rem; } /* 🆕 P0 : ajoute env(safe-area-inset-top) — était 5rem sans inset (encoche iPhone) */
}

/* ════════════════════════════════════════════════════════════
   Barre de nav — menu « Plus » (outils secondaires)
   ════════════════════════════════════════════════════════════ */
.appnav-group { position: relative; display: inline-flex; }

.appnav-dropdown {
  position: absolute;
  top: calc(100% + 10px);
  left: 50%;
  transform: translateX(-50%) translateY(-6px);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  /* [Ciblup V4, 2026-08-10] --elev-2 → --elev-1. C'est un MENU, pas une modale, et la V4 réserve
     l'élévation 2 aux modales et drawers (cf. css/tokens.css §4). L'écart était invisible tant que les
     deux niveaux se jouaient sur 1-2 px de flou ; à la géométrie V4 (50 px de flou à 18 % contre 28 px
     à 5,5 %), un menu de 196 px de large traînait une ombre de modale — vu à la mesure, pas au contrat.
     Repéré en page, sur /suivi : le contrat de jetons ne vérifie que les valeurs, pas leur affectation. */
  box-shadow: var(--elev-1);
  padding: 6px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 196px;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity .16s ease, transform .16s ease, visibility .16s;
  z-index: var(--z-float);
}
.appnav-group.open .appnav-dropdown {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transform: translateX(-50%) translateY(0);
}

/* ════════════════════════════════════════════════════════════
   Barre de nav — popover « Équipe » (disponibilité des membres)
   ════════════════════════════════════════════════════════════ */
.appnav-dropdown-team { min-width: 280px; padding: 10px; overflow: visible; }
/* 🆕 Caret pointant le bouton (carré tourné, bordures haut+gauche = pointe vers le haut) */
.appnav-dropdown-team::before {
  content: ''; position: absolute; top: -6px; left: 50%;
  transform: translateX(-50%) rotate(45deg);
  width: 12px; height: 12px; background: var(--surface);
  border-left: 1px solid var(--border); border-top: 1px solid var(--border);
  border-top-left-radius: var(--radius);
}
/* En-tête : « ÉQUIPE » + « N EN LIGNE » (vert) */
.appnav-dd-head {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  font-size: var(--fs-micro); font-weight: var(--fw-bold); letter-spacing: .12em;
  text-transform: uppercase; color: var(--text-dim);
  padding: 4px 6px 11px;
}
.appnav-dd-online { display: inline-flex; align-items: center; gap: 6px; color: var(--success); letter-spacing: .07em; }
.appnav-dd-online-dot {
  width: 7px; height: 7px; border-radius: 50%; background: var(--success);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--success) 24%, transparent);
}
.appnav-dropdown-team .presence-list { max-height: 300px; padding-right: 2px; }
.appnav-dropdown-team .presence-loading { padding: 6px 12px 10px; }
/* 🆕 Carte membre = carte interne neutre (border + fond doux), avatar plus grand */
.appnav-dropdown-team .presence-item {
  gap: 12px; padding: 11px 12px;
  background: var(--bg-soft); border: 1px solid var(--border);
  border-radius: var(--radius);
}
.appnav-dropdown-team .presence-item.is-me { background: var(--bg-soft); }
.appnav-dropdown-team .presence-item:hover { background: var(--surface-hover); }
.appnav-dropdown-team .presence-avatar { width: 46px; height: 46px; border-radius: 50%; font-size: var(--fs-md); }
.appnav-dropdown-team .presence-dot { width: 14px; height: 14px; bottom: 0; right: 0; border-width: 3px; border-color: var(--bg-soft); }
.appnav-dropdown-team .presence-name { font-size: var(--fs-base); }
.appnav-dropdown-team .presence-status { font-size: var(--fs-xs); margin-top: 2px; }
/* 🆕 Pied « Gérer l'équipe » */
.appnav-dd-foot {
  display: flex; align-items: center; gap: 10px; margin-top: 9px; padding: 11px 12px 6px;
  border-top: 1px solid var(--border);
  color: var(--text-secondary); font-size: var(--fs-sm); font-weight: var(--fw-semibold); text-decoration: none;
  transition: color .15s ease;
}
.appnav-dd-foot:hover { color: var(--text); }
.appnav-dd-foot svg { width: 16px; height: 16px; flex-shrink: 0; opacity: .85; }
.appnav-dd-foot .appnav-dd-foot-label { flex: 1; }
.appnav-dd-foot .appnav-dd-foot-chev { opacity: .55; width: 15px; height: 15px; }

/* Badge « en ligne » sur le bouton Équipe */
.appnav-team-count {
  font-family: var(--font-data);
  font-size: var(--fs-micro);
  font-weight: var(--fw-semibold);
  line-height: 1;
  padding: 2px 6px;
  border-radius: var(--radius-pill);
  background: var(--success-soft);
  color: var(--success);
  margin-left: 1px;
  min-width: 18px;
  text-align: center;
  box-sizing: border-box;
}
/* 🆕 Itér.31 : masqué SANS retirer sa place (évite le saut horizontal du menu au chargement de la présence) */
.appnav-team-count.is-empty { visibility: hidden; }

/* ════════════════════════════════════════════════════════════
   MOUVEMENT — ce qu'il en reste (lot DS-1, 2026-08-08)
   ────────────────────────────────────────────────────────────
   Ce bloc s'appelait « animations douces v3 ». Il portait une
   cascade d'entrée sur TOUT le contenu de page (.main > * montait
   de 18 px, avec un décalage par enfant jusqu'à .62 s), une
   lévitation au survol des cartes, et surtout une SECONDE
   déclaration de .btn — transition sur transform + filter, lift
   au survol, enfoncement au clic — qui écrasait celle du bloc
   PRIMITIVES situé plus haut dans ce même fichier.

   Deux déclarations d'une primitive dans une même feuille, c'est
   le défaut que le lot DS-1 supprime : la seconde gagnait sans
   que rien ne le signale. La transition des boutons vit désormais
   uniquement dans le bloc PRIMITIVES ; le contrat
   tests/design_tokens_contract_test.js (bloc 9) interdit qu'une
   deuxième réapparaisse ici.

   Sur le fond : une console ouverte cinquante fois par jour ne
   rejoue pas une séquence d'entrée à chaque navigation, et rien
   ne lévite au passage de la souris. Il ne reste donc que le
   mouvement qui porte une information — l'ouverture d'un détail,
   le chevron qui pivote, le voile d'une modale — sur une courbe
   unique et sans dépassement.
   ════════════════════════════════════════════════════════════ */
@keyframes nopRise      { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@keyframes nopFade      { from { opacity: 0; } to { opacity: 1; } }

/* Écrans d'authentification : seule arrivée animée du site, parce que
   c'est le seul écran qu'on ne revoit pas cinquante fois par session. */
.auth-card { animation: nopRise 0.24s cubic-bezier(0.22, 1, 0.36, 1) backwards; }

/* Retour d'état des surfaces : la couleur et la bordure changent, la
   surface ne bouge pas (pas de translateY, pas d'ombre qui grossit). */
.tpl-card, .panel {
  transition: background-color 0.15s ease, border-color 0.15s ease;
}

/* Lignes contact : survol = simple fond neutre (PAS de liseré/contour). */
.tbl tbody tr.row-card > td { transition: background 0.15s ease; }
.tbl tbody tr.row-card:hover > td.cell-contact { box-shadow: none; }
/* Le chevron pivote : ici le mouvement EST l'information (ouvert/fermé). */
.row-chevron { transition: transform 0.18s cubic-bezier(0.22, 1, 0.36, 1), color 0.15s ease; }

/* Modale : voile en fondu */
.modal-backdrop.show { animation: nopFade 0.16s ease backwards; }

/* Accessibilité : coupe tout si l'utilisateur préfère moins d'animations */
@media (prefers-reduced-motion: reduce) {
  .auth-card, .modal-backdrop.show { animation: none !important; }
  .row-chevron { transition: color 0.15s ease; }
}

/* ── [DS-5] .sr-only : masquage visuel réservé aux lecteurs d'écran ─────────
   Cette primitive n'avait AUCUN foyer : elle était recopiée trois fois en
   local (taches.php en <style> avec !important, css/conversations.css deux
   fois, scopée à .conversations-search puis à .answer-chat) — et le seul
   consommateur qu'aucune des trois ne couvrait, finder_ia.php:302, affichait
   donc son <h1 class="sr-only">Finder IA</h1> en clair, 42 px, en haut de la
   page. Une classe utilitaire qui vit en trois exemplaires locaux finit
   toujours par manquer là où personne n'a pensé à la recopier ; elle est ici
   déclarée une fois pour tout le site, et les trois copies sont retirées.
   clip + clip-path : le premier pour les moteurs anciens, le second parce que
   `clip` est déprécié. On garde le texte dans le flux d'accessibilité —
   display:none ou visibility:hidden le retireraient AUSSI aux lecteurs
   d'écran, ce qui est exactement l'inverse du but. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  border: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ── B6 Accessibilité : anneau de focus clavier global ──────────────────────
   Plusieurs composants posent outline:none (focus invisible au clavier).
   :focus-visible ne s'active qu'à la navigation clavier (pas à la souris),
   donc on restaure un anneau net sans gêner les clics souris.
   ⚠️ NE JAMAIS remettre de border-radius ici : ce bloc est en fin de fichier et
   :focus-visible a la spécificité d'une classe → un `border-radius:3px` écrasait
   le rayon PROPRE de l'élément au focus clavier (boutons 10px, champs 10px,
   liens de nav 99px passaient à 3px, et en transition:all c'était animé).
   L'outline épouse déjà nativement le rayon de l'élément : rien à compenser.  */
:focus-visible {
  outline: 2px solid var(--accent) !important;
  outline-offset: 2px !important;
}
a:focus:not(:focus-visible),
button:focus:not(:focus-visible),
input:focus:not(:focus-visible),
select:focus:not(:focus-visible),
textarea:focus:not(:focus-visible),
[tabindex]:focus:not(:focus-visible) { outline: none; }

/* ── Modales en PAYSAGE mobile (écran très bas) ─────────────────────────────
   En paysage sur petit appareil, une modale haute déborde verticalement et
   sort de l'écran (boutons d'action inaccessibles). On plafonne la hauteur et
   on rend le contenu défilable. Cible .modal (système v2) ET .modal-overlay
   (variante agenda). max-height en svh pour tenir compte des barres mobiles. */
@media (max-height: 480px) and (orientation: landscape) {
  .modal,
  .modal-backdrop .modal,
  .modal-overlay {
    max-height: 92vh;
    max-height: 92svh;
    overflow-y: auto;
  }
}

/* ════════════════════════════════════════════════════════════
   🆕 Correctifs responsive (revue preview local 2026-06-24)
   ════════════════════════════════════════════════════════════ */
/* Mobile : dégager le bas du contenu des bulles de chat flottantes (Crisp + Feedback). */
@media (max-width: 768px) {
  .main { padding-bottom: calc(88px + env(safe-area-inset-bottom)) !important; }
}
/* Très petit écran : modèles Communication en 1 colonne (au lieu de 2 colonnes serrées). */
@media (max-width: 440px) {
  .tpl-grid { grid-template-columns: 1fr !important; }
}

/* ════════════════════════════════════════════════════════════
   🆕 Pagination « fenêtrée » partagée (helper nopPagerHtml) — Tâches + Suivi
   ════════════════════════════════════════════════════════════ */
.nop-pager {
  display: flex; align-items: center; justify-content: center;
  gap: 6px; flex-wrap: wrap; padding: 4px 0;
}
.nop-pg {
  min-width: 38px; height: 38px; padding: 0 11px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--border); background: var(--surface);
  color: var(--text); font: inherit; font-size: var(--fs-base); font-weight: var(--fw-semibold);
  border-radius: var(--radius); cursor: pointer;
  transition: background .12s ease, border-color .12s ease;
}
.nop-pg:hover:not(:disabled):not(.on) { background: var(--surface-hover); border-color: var(--border-strong); }
.nop-pg.on { background: var(--accent); border-color: var(--accent); color: var(--on-accent); cursor: default; }
.nop-pg:disabled { opacity: .42; cursor: default; }
.nop-pg-nav { font-weight: var(--fw-medium); color: var(--text-muted); }
.nop-pg-ell { min-width: 26px; text-align: center; color: var(--text-muted); user-select: none; }

/* ═══════════════════════════════════════════════════════════════════════════
   Pastilles d'étape de pipeline — lisibilité en thème NUIT
   [Correctif contraste 2026-07-29]

   Les pastilles (.tk-chip dans Tâches, .sv2-chip dans Suivi) sont rendues en JS
   avec un style INLINE : fond = color-mix(teinte 16%, transparent), texte = une
   variante SOMBRE de la teinte, calculée pour la surface CLAIRE. Posée telle
   quelle sur la surface nuit (#18181A), cette variante sombre tombait entre
   1,89:1 et 2,62:1 — les SEPT étapes échouaient AA en nuit, pas seulement une.

   Une bascule nuit existait bien (css/prospection.css:132) mais visait
   .stage-badge, composant qu'aucun PHP/JS n'émet plus : elle ne protégeait rien.

   Ici on éclaircit la teinte exposée par le rendu (--chip-tint) à 75 % + 25 % de
   blanc, sur le même fond : 5,35:1 (Perdu) à 7,90:1 (Stand-by). Générique — toute
   étape ajoutée plus tard est couverte sans y revenir, tant qu'elle pose --chip-tint.

   !important est nécessaire, et suffisant : une déclaration !important d'une
   feuille de style l'emporte sur un style inline non-important (cascade CSS).
   ═══════════════════════════════════════════════════════════════════════════ */
:root[data-theme="dark"] .tk-chip[style*="--chip-tint"],
:root[data-theme="dark"] .sv2-chip[style*="--chip-tint"] {
  color: color-mix(in srgb, var(--chip-tint) 75%, #fff) !important;
}
