/* ===================================================================
   Haria — Espace client (portail)
   Base iOS (typographie système SF Pro, capsules, contrôles segmentés,
   listes à séparateurs encastrés) posée dans une ambiance violette :
   fond lavande dégradé, coque blanche flottante à coins très arrondis,
   aplats et dégradés d'accent, anneaux concentriques.

   Volontairement séparé de admin.css (thème sombre de la console
   interne) : les deux interfaces n'ont ni le même public ni la même
   densité. Aucune page admin ne charge ce fichier.
   =================================================================== */

/* ── Thème clair (défaut) — palette système iOS ───────────────────── */
:root {
  --bg: #f2f2f7;              /* systemGroupedBackground */
  --surface: #ffffff;         /* secondarySystemGroupedBackground */
  --shell: #f4f4f8;           /* coque : un cran plus gris que les cartes */
  --surface-2: rgba(118, 118, 128, 0.09);  /* fill quaternaire */
  --surface-3: rgba(118, 118, 128, 0.16);  /* fill tertiaire */
  --sidebar: rgba(242, 242, 247, 0.82);
  --material: rgba(255, 255, 255, 0.72);   /* barre haute translucide */

  --text: #1c1c1e;                          /* label */
  --text-2: rgba(60, 60, 67, 0.62);         /* secondaryLabel */
  --text-3: rgba(60, 60, 67, 0.36);         /* tertiaryLabel */

  --accent: #6c5ce7;

  /* Palette catégorielle des graphiques. Validée sur la surface des cartes
     (#fbfaff en clair, #1b1a24 en sombre) : bande de clarté, plancher de
     chroma, séparation daltonienne sur TOUS les couples, et contraste >= 3:1.
     L'ordre des slots est le mécanisme de sécurité, pas un choix esthétique —
     ne pas permuter sans repasser le validateur. */
  --card-bg-solid: #fbfaff;  /* teinte moyenne de la carte, pour les anneaux SVG */
  --tip-bg: #1d1b2e;         /* pastille d'infobulle, sombre dans les deux thèmes */
  --viz-1: #6c5ce7;   /* conversations — accent de marque */
  --viz-2: #0d8f62;   /* leads captés */
  --viz-3: #d9532a;   /* conversion */

  /* Rampe ordinale de l'entonnoir : trois pas d'une seule teinte, clarté
     monotone, écarts visibles, extrémité claire qui se détache du fond.
     Les étapes d'un entonnoir sont ordonnées — c'est le seul cas où une rampe
     de valeur est légitime sur des catégories. */
  --fn-1: #4f3ecf;
  --fn-2: #7d6ce6;
  --fn-3: #a396ed;
  --accent-strong: #5e4fdd;
  --accent-deep: #4c3fc7;
  --accent-soft: rgba(108, 92, 231, 0.12);
  --accent-softer: rgba(108, 92, 231, 0.06);
  --ring: rgba(108, 92, 231, 0.28);

  --separator: rgba(60, 60, 67, 0.16);
  --border: rgba(60, 60, 67, 0.13);
  --border-strong: rgba(60, 60, 67, 0.24);

  --danger: #ff3b30;
  --danger-soft: rgba(255, 59, 48, 0.12);
  --success: #34c759;
  --success-soft: rgba(52, 199, 89, 0.14);
  --warn: #ff9500;
  --warn-soft: rgba(255, 149, 0, 0.14);
  --info: #007aff;
  --info-soft: rgba(0, 122, 255, 0.12);

  /* Rayons « continus » façon iOS : généreux sur les cartes, capsules
     sur les commandes. */
  /* Ambiance : halos lavande derrière la coque flottante. */
  --ambient:
    radial-gradient(900px 460px at 4% -6%, #b79dff 0%, rgba(183, 157, 255, 0) 58%),
    radial-gradient(820px 420px at 96% -2%, #cbb6ff 0%, rgba(203, 182, 255, 0) 56%),
    radial-gradient(760px 520px at 50% 106%, #d9caff 0%, rgba(217, 202, 255, 0) 58%),
    #efe9fb;
  /* Fond de carte : blanc qui glisse vers un lavande à peine perceptible. */
  --card-bg: linear-gradient(168deg, #ffffff 0%, #fbfaff 62%, #f7f4ff 100%);
  --card-line: rgba(108, 92, 231, 0.08);
  --track: rgba(108, 92, 231, 0.11);
  /* Dégradé de violets pour les anneaux et répartitions. */
  --ring-1: #6c5ce7;
  --ring-2: rgba(108, 92, 231, 0.55);
  --ring-3: rgba(108, 92, 231, 0.26);
  /* Rampe de la carte de chaleur, du vide au pic. */
  --hm-0: rgba(108, 92, 231, 0.07);
  --hm-1: rgba(108, 92, 231, 0.18);
  --hm-2: rgba(108, 92, 231, 0.34);
  --hm-3: rgba(108, 92, 231, 0.52);
  --hm-4: rgba(108, 92, 231, 0.58);
  --hm-5: rgba(108, 92, 231, 0.82);
  --wm-land: #e4e1ef;         /* terres sans visiteur */
  --wm-pin: #17161d;          /* étiquette posée sur la carte */

  --radius: 24px;
  --radius-sm: 16px;
  --radius-xs: 12px;
  --shadow-card: 0 1px 2px rgba(58, 32, 130, 0.04), 0 10px 30px rgba(58, 32, 130, 0.06);
  --shadow-hover: 0 14px 40px rgba(58, 32, 130, 0.14);
  --shadow-pop: 0 24px 70px rgba(38, 18, 92, 0.22);
  --shadow-accent: 0 8px 20px rgba(108, 92, 231, 0.32);
  --shadow-shell: 0 30px 80px rgba(58, 32, 130, 0.16);
  --shadow-thumb: 0 3px 8px rgba(0, 0, 0, 0.12), 0 1px 1px rgba(0, 0, 0, 0.04);
  --thumb: #ffffff;

  /* SF Pro sur les appareils Apple, Inter ailleurs. */
  --font: -apple-system, BlinkMacSystemFont, "SF Pro Text", "SF Pro Display",
    "Helvetica Neue", "Inter", "Segoe UI", Roboto, sans-serif;

  --sidebar-w: 258px;
  --topbar-h: 64px;
}

/* ── Thème sombre — palette système iOS ───────────────────────────── */
/* Ancré à `:root` : l'attribut n'est posé que sur <html> (portal-shell.js).
   Sans cette ancre, TOUT élément portant data-theme="dark" — un bouton de
   choix, un aperçu — basculait sa propre sous-arborescence en palette sombre,
   et se retrouvait en texte clair sur fond clair. */
:root[data-theme="dark"] {
  --bg: #000000;
  --surface: #1c1c1e;
  --shell: #000000;           /* coque noire : les cartes ressortent */
  --surface-2: rgba(118, 118, 128, 0.24);
  --surface-3: rgba(118, 118, 128, 0.36);
  --sidebar: rgba(28, 28, 30, 0.78);
  --material: rgba(28, 28, 30, 0.72);

  --text: #ffffff;
  --text-2: rgba(235, 235, 245, 0.62);
  --text-3: rgba(235, 235, 245, 0.32);

  --accent: #8b7cf0;

  /* Mêmes teintes, redescendues dans la bande de clarté du fond sombre
     (L 0,48–0,67). Ce n'est pas une inversion automatique : chaque pas a été
     rejoué contre la surface sombre, puis revalidé comme un ensemble. */
  --card-bg-solid: #1b1a24;
  --tip-bg: #2e2c42;
  --viz-1: #8b7cf0;
  --viz-2: #23a878;
  --viz-3: #e0683a;

  /* Sur fond sombre la lecture s'inverse : le plus fort est le plus lumineux. */
  --fn-1: #a396ed;
  --fn-2: #8072e6;
  --fn-3: #6154d2;
  --accent-strong: #7a68ee;
  --accent-deep: #6c5ce7;
  --accent-soft: rgba(139, 124, 240, 0.20);
  --accent-softer: rgba(139, 124, 240, 0.10);
  --ring: rgba(139, 124, 240, 0.35);

  --separator: rgba(84, 84, 88, 0.7);
  --border: rgba(84, 84, 88, 0.5);
  --border-strong: rgba(120, 120, 128, 0.6);

  --danger: #ff453a;
  --danger-soft: rgba(255, 69, 58, 0.20);
  --success: #30d158;
  --success-soft: rgba(48, 209, 88, 0.20);
  --warn: #ff9f0a;
  --warn-soft: rgba(255, 159, 10, 0.20);
  --info: #0a84ff;
  --info-soft: rgba(10, 132, 255, 0.20);

  --ambient:
    radial-gradient(900px 520px at 8% -12%, #2a1b63 0%, rgba(42, 27, 99, 0) 62%),
    radial-gradient(760px 460px at 92% -6%, #1e1747 0%, rgba(30, 23, 71, 0) 60%),
    #08060f;
  --card-bg: linear-gradient(168deg, #1f1f25 0%, #1b1a24 60%, #191826 100%);
  --card-line: rgba(139, 124, 240, 0.12);
  --track: rgba(139, 124, 240, 0.16);
  --ring-1: #8b7cf0;
  --ring-2: rgba(139, 124, 240, 0.6);
  --ring-3: rgba(139, 124, 240, 0.3);
  --hm-0: rgba(139, 124, 240, 0.10);
  --hm-1: rgba(139, 124, 240, 0.22);
  --hm-2: rgba(139, 124, 240, 0.38);
  --hm-3: rgba(139, 124, 240, 0.56);
  --hm-4: rgba(139, 124, 240, 0.62);
  --hm-5: rgba(139, 124, 240, 0.88);
  --wm-land: rgba(235, 235, 245, 0.11);
  --wm-pin: #26252f;

  --shadow-card: 0 1px 2px rgba(0, 0, 0, 0.5);
  --shadow-hover: 0 12px 34px rgba(0, 0, 0, 0.6);
  --shadow-pop: 0 24px 64px rgba(0, 0, 0, 0.75);
  --shadow-accent: 0 8px 22px rgba(108, 92, 231, 0.45);
  --shadow-shell: 0 30px 80px rgba(0, 0, 0, 0.6);
  --shadow-thumb: 0 3px 8px rgba(0, 0, 0, 0.5);
  --thumb: #636366;
}

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

body {
  font-family: var(--font);
  /* Même couleur que la coque : rien d'autre ne doit apparaître, pas même
     pendant le rebond de défilement. */
  background: var(--shell);
  color: var(--text);
  line-height: 1.47;
  letter-spacing: -0.01em;
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  -webkit-tap-highlight-color: transparent;
}

::selection { background: var(--accent-soft); color: var(--text); }

/* Défilement discret, façon barres overlay iOS/macOS. */
* { scrollbar-width: thin; scrollbar-color: var(--border-strong) transparent; }
*::-webkit-scrollbar { width: 8px; height: 8px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb {
  background: var(--border-strong);
  border-radius: 980px;
  border: 2px solid transparent;
  background-clip: content-box;
}

/* ═══════════════════════════════════════════════════════════════════
   COQUE : sidebar + colonne principale
   ═══════════════════════════════════════════════════════════════════ */
/* Panneau blanc flottant sur le fond lavande. `overflow: clip` (et non
   `hidden`) arrondit les angles sans créer de conteneur de défilement :
   la sidebar et la barre haute restent collantes vis-à-vis de la page. */
/* L'espace client occupe tout l'écran : plus de cadre flottant posé sur un
   fond ambiant. Chaque pixel sert à la donnée, et sur un portable de 13
   pouces le tableau de bord y gagne une centaine de pixels utiles.
   Le fond ambiant reste sur la page de connexion (`.auth-shell`), où il n'a
   rien à voler à personne. */
.app {
  display: grid;
  grid-template-columns: var(--sidebar-w) minmax(0, 1fr);
  min-height: 100vh;
  /* --shell reste en retrait des cartes (gris clair / noir) pour les
     détacher : la couleur des cartes, elle, ne bouge pas. */
  background: var(--shell);
  overflow: clip;
}

/* ── Sidebar (matériau translucide, façon iPadOS) ────────────────── */
.sidebar {
  background: var(--shell);
  border-right: 1px solid var(--card-line);
  display: flex;
  flex-direction: column;
  padding: 1rem 0.75rem 1rem;
  position: sticky;
  top: 0;
  height: calc(100vh - 32px);
  overflow-y: auto;
  z-index: 60;
}

/* En-tête du menu : la marque à gauche, la commande de repli à droite. */
.side-head {
  position: relative;
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 0 0.5rem;
  margin-bottom: 1.35rem;
  height: calc(var(--topbar-h) - 1rem);
}
.side-brand {
  display: flex;
  align-items: center;
  gap: 9px;
  text-decoration: none;
  min-width: 0;
  flex: 1;
}

/* Bouton de repli. Déplié : posé à côté du logo, discret jusqu'au survol de
   l'en-tête — il ne doit pas concurrencer la marque. */
.side-collapse {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  flex-shrink: 0;
  border: none;
  border-radius: 9px;
  background: none;
  color: var(--text-3);
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.18s, background 0.15s, color 0.15s, transform 0.25s;
}
.side-collapse svg { width: 18px; height: 18px; }
.side-collapse:hover { background: var(--surface-2); color: var(--text); }
/* Révélé dès qu'on entre dans la barre, pas seulement au-dessus du logo : on
   cherche la commande en arrivant dans le menu, pas en visant son en-tête. */
.sidebar:hover .side-collapse,
.side-collapse:focus-visible { opacity: 1; }
.side-collapse:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ── Menu réduit aux pictogrammes ────────────────────────────────── */
/* L'attribut est posé sur <html> par l'amorce en tête de page : la largeur
   est donc déjà la bonne au premier rendu, sans saut. */
:root[data-sidebar="collapsed"] { --sidebar-w: 76px; }
.app { transition: grid-template-columns 0.24s cubic-bezier(0.32, 0.72, 0, 1); }

/* Le bouton vient se poser SUR le logo et n'apparaît qu'au survol : au repos
   la barre garde son identité, et la commande est là où l'œil la cherche. */
:root[data-sidebar="collapsed"] .side-head { justify-content: center; padding: 0; }
:root[data-sidebar="collapsed"] .side-brand { flex: none; }
:root[data-sidebar="collapsed"] .side-collapse {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border-radius: 12px;
  background: var(--shell);
}
:root[data-sidebar="collapsed"] .sidebar:hover .side-collapse { opacity: 1; }

/* Ce qui n'a plus la place de s'afficher. Les libellés passent en infobulle
   (voir plus bas) : réduire la barre ne doit pas rendre le menu illisible. */
:root[data-sidebar="collapsed"] .logo-text,
:root[data-sidebar="collapsed"] .side-section,
:root[data-sidebar="collapsed"] .side-item .label,
:root[data-sidebar="collapsed"] .side-count,
:root[data-sidebar="collapsed"] .side-sub-name,
:root[data-sidebar="collapsed"] .side-promo { display: none; }

:root[data-sidebar="collapsed"] .side-item,
:root[data-sidebar="collapsed"] .side-sub-item {
  justify-content: center;
  padding-left: 0;
  padding-right: 0;
}
/* Les sections gardent leur respiration : sans leur titre, il faut bien
   quelque chose pour séparer les groupes. */
:root[data-sidebar="collapsed"] .side-sub { margin-top: 1.1rem; }
:root[data-sidebar="collapsed"] .side-sub-item { padding: 0.55rem 0; }
:root[data-sidebar="collapsed"] .side-dot { width: 9px; height: 9px; }

/* Infobulle : le libellé que la barre n'affiche plus. Portée par
   `data-label`, posé par la coque sur chaque entrée. */
:root[data-sidebar="collapsed"] .side-item,
:root[data-sidebar="collapsed"] .side-sub-item { position: relative; overflow: visible; }
:root[data-sidebar="collapsed"] .side-item[data-label]::after,
:root[data-sidebar="collapsed"] .side-sub-item[data-label]::after {
  content: attr(data-label);
  position: absolute;
  left: calc(100% + 6px);
  top: 50%;
  transform: translateY(-50%);
  padding: 5px 9px;
  border-radius: 8px;
  background: var(--wm-pin, #241d4d);
  color: #fff;
  font-size: 0.76rem;
  font-weight: 500;
  white-space: nowrap;
  box-shadow: 0 8px 20px rgba(12, 8, 32, 0.24);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.14s;
  z-index: 60;
}
:root[data-sidebar="collapsed"] .side-item:hover::after,
:root[data-sidebar="collapsed"] .side-sub-item:hover::after { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .app, .side-collapse { transition: none; }
}
.side-brand .logo-mark { width: 28px; height: 28px; object-fit: contain; flex-shrink: 0; }
.side-brand .logo-text {
  font-weight: 700;
  font-size: 1.16rem;
  color: var(--text);
  letter-spacing: -0.028em;
  white-space: nowrap;
}
.side-brand .logo-sub { font-weight: 400; color: var(--text-3); font-size: 0.95rem; }

/* Titre de section : iOS met des majuscules discrètes, sans filet. */
.side-section {
  font-size: 0.695rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-3);
  padding: 0 0.6rem;
  margin: 1.35rem 0 0.4rem;
}

.side-nav { display: flex; flex-direction: column; gap: 2px; }

.side-item {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 0.52rem 0.6rem;
  border-radius: var(--radius-xs);
  text-decoration: none;
  color: var(--text);
  font-size: 0.925rem;
  font-weight: 400;
  font-family: inherit;
  background: none;
  border: none;
  cursor: pointer;
  width: 100%;
  text-align: left;
  transition: background 0.15s, transform 0.1s;
  white-space: nowrap;
}
.side-item svg { width: 19px; height: 19px; flex-shrink: 0; color: var(--accent); }
.side-item span.label { overflow: hidden; text-overflow: ellipsis; }
.side-item:hover { background: var(--surface-2); }
.side-item:active { transform: scale(0.985); }
.side-item:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* Sélection : bloc violet plein à halo, comme la maquette. */
.side-item.active {
  background: linear-gradient(150deg, var(--accent) 0%, var(--accent-deep) 100%);
  color: #fff;
  font-weight: 600;
  box-shadow: var(--shadow-accent);
}
.side-item.active svg { color: #fff; }

.side-count {
  margin-left: auto;
  font-size: 0.755rem;
  font-weight: 600;
  color: var(--text-3);
  font-variant-numeric: tabular-nums;
}
.side-item.active .side-count { color: rgba(255, 255, 255, 0.85); }

/* Sous-liste (widgets du client) */
.side-sub { display: flex; flex-direction: column; gap: 1px; }
.side-sub-item {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 0.45rem 0.6rem;
  border-radius: var(--radius-xs);
  font-size: 0.88rem;
  color: var(--text);
  text-decoration: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: background 0.15s;
}
.side-sub-item:hover { background: var(--surface-2); }
.side-sub-item.active { background: var(--accent-soft); color: var(--accent); font-weight: 600; }
.side-sub-item.active .side-dot { box-shadow: 0 0 0 3px var(--accent-softer); }
.side-dot { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; background: var(--accent); }

.side-spacer { flex: 1; min-height: 1.2rem; }

/* Carte promo bas de sidebar */
.side-promo {
  position: relative;
  overflow: hidden;
  border-radius: 18px;
  padding: 1rem 1rem 1.05rem;
  background: linear-gradient(160deg, #6c5ce7 0%, #4c3fc7 48%, #2b2385 100%);
  color: #fff;
  margin-top: 0.5rem;
}
.side-promo::after {
  content: "";
  position: absolute;
  right: -34px;
  top: -34px;
  width: 110px;
  height: 110px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.10);
}
.side-promo-icon {
  width: 30px;
  height: 30px;
  border-radius: 9px;
  background: rgba(255, 255, 255, 0.18);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 0.6rem;
}
.side-promo-icon svg { width: 17px; height: 17px; }
.side-promo h4 { font-size: 0.9rem; font-weight: 600; letter-spacing: -0.015em; }
.side-promo p { font-size: 0.76rem; color: rgba(255, 255, 255, 0.75); line-height: 1.4; margin: 0.25rem 0 0.8rem; }
.side-promo a {
  display: block;
  text-align: center;
  background: rgba(255, 255, 255, 0.20);
  color: #fff;
  text-decoration: none;
  font-size: 0.815rem;
  font-weight: 600;
  padding: 0.46rem;
  border-radius: 980px;
  position: relative;
  transition: background 0.15s, transform 0.1s;
}
.side-promo a:hover { background: rgba(255, 255, 255, 0.3); }
.side-promo a:active { transform: scale(0.97); }

/* Carte « Votre offre » : remplace le contenu de la carte promo
   (portal-shell.js, initOffre) — jauge des messages du mois. */
.side-offre h4 { margin: 0; }
.offre-jauge {
  position: relative;
  height: 7px;
  border-radius: 99px;
  background: rgba(255, 255, 255, 0.22);
  overflow: hidden;
  margin: 0.65rem 0 0.1rem;
}
.offre-jauge span {
  display: block;
  height: 100%;
  border-radius: 99px;
  background: #fff;
  transition: width 0.6s cubic-bezier(0.22, 1, 0.36, 1);
}
.offre-jauge.presque span { background: #ffd166; }
.offre-jauge.plein span { background: #ff8fa3; }
@media (prefers-reduced-motion: reduce) { .offre-jauge span { transition: none; } }

/* Visite guidée (portal-shell.js, demarrerTutoriel) */
.tuto-voile { position: fixed; inset: 0; z-index: 9000; background: rgba(8, 8, 20, 0.55); }
.tuto-voile.avec-halo { background: transparent; }
.tuto-halo {
  position: fixed;
  z-index: 9001;
  border-radius: 14px;
  pointer-events: none;
  box-shadow: 0 0 0 9999px rgba(8, 8, 20, 0.55), 0 0 0 2px var(--accent, #8b7cf0);
  transition: left 0.3s, top 0.3s, width 0.3s, height 0.3s;
}
.tuto-bulle {
  position: fixed;
  z-index: 9002;
  width: min(320px, calc(100vw - 24px));
  background: var(--card-bg, #fff);
  color: var(--text);
  border: 1px solid var(--card-line, rgba(127, 127, 127, 0.2));
  border-radius: 16px;
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.3);
  padding: 1rem 1.1rem 0.9rem;
}
.tuto-bulle.centre { left: 50% !important; top: 50% !important; transform: translate(-50%, -50%); }
.tuto-pas { margin: 0 0 0.2rem; font-size: 0.72rem; font-weight: 700; letter-spacing: 0.06em; color: var(--accent, #8b7cf0); }
.tuto-bulle h3 { margin: 0 0 0.35rem; font-size: 1rem; font-weight: 800; letter-spacing: -0.02em; color: var(--text); }
.tuto-bulle p { margin: 0; font-size: 0.86rem; line-height: 1.5; color: var(--text-2); }
.tuto-actions { display: flex; gap: 0.5rem; justify-content: flex-end; flex-wrap: wrap; margin-top: 0.9rem; }
.tuto-actions button {
  font-family: inherit;
  font-size: 0.82rem;
  font-weight: 600;
  padding: 0.45rem 0.85rem;
  border-radius: 10px;
  cursor: pointer;
  border: 1px solid var(--border, rgba(127, 127, 127, 0.25));
  background: transparent;
  color: var(--text-2);
}
.tuto-actions .tuto-passer { margin-right: auto; border-color: transparent; }
.tuto-actions .tuto-suiv { background: var(--accent-strong, #6c5ce7); border-color: transparent; color: #fff; }
@media (prefers-reduced-motion: reduce) { .tuto-halo { transition: none; } }
@media print { .tuto-voile, .tuto-halo, .tuto-bulle { display: none !important; } }

/* ── Colonne principale ──────────────────────────────────────────── */
.shell { display: flex; flex-direction: column; min-width: 0; }

/* Barre haute : matériau translucide + hairline, façon barre de navigation. */
.topbar {
  height: var(--topbar-h);
  background: var(--shell);
  border-bottom: 1px solid var(--card-line);
  display: flex;
  align-items: center;
  gap: 0.85rem;
  padding: 0 1.5rem;
  position: sticky;
  top: 0;
  z-index: 50;
}

/* Champ de recherche iOS : fond plein, coins arrondis, pas de bordure. */
.search { position: relative; flex: 1; max-width: 420px; }
.search svg {
  position: absolute;
  left: 11px;
  top: 50%;
  transform: translateY(-50%);
  width: 16px;
  height: 16px;
  color: var(--text-3);
  pointer-events: none;
}
.search input {
  width: 100%;
  height: 42px;
  border: 1px solid var(--card-line);
  background: var(--surface);
  border-radius: 14px;
  padding: 0 2.9rem 0 2.35rem;
  font-family: inherit;
  font-size: 0.9rem;
  color: var(--text);
  box-shadow: 0 2px 10px rgba(58, 32, 130, 0.05);
  transition: box-shadow 0.15s, border-color 0.15s;
}
.search input::placeholder { color: var(--text-3); }
.search input::-webkit-search-cancel-button { -webkit-appearance: none; }
.search input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3.5px var(--ring);
}
.search kbd {
  position: absolute;
  right: 8px;
  top: 50%;
  transform: translateY(-50%);
  font-family: inherit;
  font-size: 0.7rem;
  font-weight: 500;
  color: var(--text-3);
  pointer-events: none;
}

.topbar-actions { margin-left: auto; display: flex; align-items: center; gap: 0.4rem; }

.icon-btn {
  position: relative;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  border: none;
  background: transparent;
  color: var(--accent);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: background 0.15s, transform 0.1s;
}
.icon-btn:hover { background: var(--surface-2); }
.icon-btn:active { transform: scale(0.92); }
.icon-btn svg { width: 18px; height: 18px; }
.icon-btn .dot {
  position: absolute;
  top: 5px;
  right: 6px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--danger);
  border: 2px solid var(--material);
}

.avatar {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: linear-gradient(160deg, var(--accent), var(--accent-deep));
  color: #fff;
  font-size: 0.76rem;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  border: none;
  cursor: pointer;
  font-family: inherit;
  margin-left: 0.25rem;
  transition: transform 0.1s;
}
.avatar:active { transform: scale(0.92); }
/* Photo de profil : elle recouvre le dégradé et masque les initiales.
   Deux verrous plutôt qu'un. `color: transparent` seul laisse remonter le
   texte dès qu'une règle plus spécifique repose une couleur — un thème, un
   survol, un `:focus-visible`, une feuille tierce. `font-size: 0` supprime le
   glyphe lui-même : il n'y a plus rien à recolorer. La taille de police
   n'affecte pas le fond, la photo reste intacte. */
.avatar.has-photo {
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  color: transparent;
  font-size: 0;
}

/* Menu profil : popover iOS (matériau, coins 14, séparateurs pleine largeur) */
.menu {
  position: absolute;
  top: calc(var(--topbar-h) - 10px);
  right: 1.5rem;
  min-width: 232px;
  background: var(--material);
  backdrop-filter: saturate(180%) blur(30px);
  -webkit-backdrop-filter: saturate(180%) blur(30px);
  border: 1px solid var(--separator);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-pop);
  padding: 0;
  overflow: hidden;
  z-index: 80;
}
.menu-head { padding: 0.75rem 0.9rem; border-bottom: 1px solid var(--separator); }
.menu-name { font-size: 0.885rem; font-weight: 600; color: var(--text); word-break: break-all; }
.menu-role { font-size: 0.78rem; color: var(--text-2); }
.menu-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-direction: row-reverse;
  gap: 9px;
  width: 100%;
  padding: 0.68rem 0.9rem;
  border: none;
  background: none;
  border-bottom: 1px solid var(--separator);
  font-family: inherit;
  font-size: 0.9rem;
  color: var(--text);
  text-align: left;
  text-decoration: none;
  cursor: pointer;
  transition: background 0.12s;
}
.menu-item:last-child { border-bottom: none; }
.menu-item:hover { background: var(--surface-2); }
.menu-item svg { width: 17px; height: 17px; color: var(--text-2); }

/* ── Zone de contenu ─────────────────────────────────────────────── */
.page { padding: 1.5rem 1.5rem 3.5rem; max-width: 1520px; width: 100%; }

/* Grand titre iOS */
.page-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 1.35rem;
}
.page-head h1 {
  font-size: 1.95rem;
  font-weight: 700;
  letter-spacing: -0.032em;
  color: var(--text);
  line-height: 1.15;
}
.page-head .sub { font-size: 0.9rem; color: var(--text-2); margin-top: 0.15rem; }

/* En-tête de marque du rapport imprimé : masqué à l'écran, révélé par la
   feuille @media print en bas de fichier. */
.print-head {
  display: none;
  align-items: center;
  gap: 0.8rem;
  padding-bottom: 0.9rem;
  margin-bottom: 1.1rem;
  border-bottom: 1px solid var(--card-line);
}
.print-logo { width: 34px; height: 34px; }
.print-id strong { display: block; font-size: 1rem; letter-spacing: -0.02em; }
.print-id span { font-size: 0.8rem; color: var(--text-2); }
.print-brand { margin-left: auto; font-size: 0.78rem; color: var(--text-3); }
.toolbar { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }

/* ── Réglage replié derrière trois points ────────────────────────── */
/* Pour les commandes qu'on règle une fois et qu'on ne retouche plus : elles
   n'ont pas à occuper la barre en permanence. La valeur retenue, elle, reste
   lisible ailleurs sur la page — un réglage caché dont on ne voit plus l'état
   serait un piège, pas un gain de place. */
.tool-more { position: relative; }
.tool-pop {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  min-width: 200px;
  padding: 0.75rem 0.8rem 0.8rem;
  background: var(--material);
  backdrop-filter: saturate(180%) blur(30px);
  -webkit-backdrop-filter: saturate(180%) blur(30px);
  border: 1px solid var(--separator);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-pop);
  z-index: 80;
  animation: tool-pop-in 160ms cubic-bezier(0.22, 0.61, 0.36, 1);
}
.tool-pop[hidden] { display: none; }
.tool-pop-head {
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-3);
  margin-bottom: 0.5rem;
}
.tool-pop .segmented { display: flex; width: 100%; }
.tool-pop .segmented button { flex: 1; }

@keyframes tool-pop-in {
  from { opacity: 0; transform: translateY(-6px); }
  to { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) { .tool-pop { animation: none; } }

/* Période retenue, sous le titre : la donnée reste annoncée même quand sa
   commande est repliée. */
.period-line { display: inline-flex; align-items: center; gap: 6px; }
.period-line svg { width: 14px; height: 14px; color: var(--text-3); }

/* ── Contrôles ───────────────────────────────────────────────────── */
.chip, .btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  height: 36px;
  padding: 0 0.95rem;
  border: none;
  background: var(--surface-2);
  border-radius: 980px;           /* capsules iOS */
  font-family: inherit;
  font-size: 0.86rem;
  font-weight: 500;
  color: var(--text);
  white-space: nowrap;
}
.chip svg, .btn svg { width: 15px; height: 15px; flex-shrink: 0; }
.chip { color: var(--text-2); }
.btn {
  cursor: pointer;
  text-decoration: none;
  transition: background 0.15s, transform 0.1s, opacity 0.15s;
}
.btn:hover { background: var(--surface-3); }
.btn:active { transform: scale(0.96); }
.btn:disabled { opacity: 0.38; cursor: not-allowed; transform: none; }
/* `.btn`/`.chip` déclarent `display: inline-flex` : sans cette règle, poser
   l'attribut `hidden` sur un bouton (ex. « Retirer » de l'onglet
   Personnalisation) ne le masque pas — la règle d'auteur l'emporte toujours
   sur le `display: none` par défaut de `[hidden]`. Même piège que
   `.wm-pin[hidden]`, voir public/portal-shell.js. */
.chip[hidden], .btn[hidden] { display: none; }
.btn.primary {
  background: linear-gradient(150deg, var(--accent) 0%, var(--accent-deep) 100%);
  color: #fff;
  font-weight: 600;
  box-shadow: var(--shadow-accent);
}
.btn.primary:hover { filter: brightness(1.07); }
.btn.block { width: 100%; height: 48px; font-size: 0.98rem; border-radius: 14px; }
.btn.sm { height: 30px; padding: 0 0.75rem; font-size: 0.81rem; }

select.btn {
  appearance: none;
  padding-right: 2rem;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23888' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round' viewBox='0 0 24 24'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.7rem center;
}

/* Contrôle segmenté iOS : piste grise, pouce blanc ombré. */
.segmented {
  display: inline-flex;
  gap: 0;
  background: var(--surface-2);
  border-radius: 9px;
  padding: 2px;
  position: relative;
}
.segmented button {
  border: none;
  background: none;
  border-radius: 7px;
  padding: 0.3rem 0.8rem;
  font-family: inherit;
  font-size: 0.815rem;
  font-weight: 500;
  color: var(--text);
  cursor: pointer;
  transition: background 0.18s, box-shadow 0.18s, transform 0.1s;
  position: relative;
}
/* Séparateurs fins entre segments inactifs (comme UISegmentedControl) */
.segmented button + button::before {
  content: "";
  position: absolute;
  left: -1px;
  top: 20%;
  height: 60%;
  width: 1px;
  background: var(--separator);
}
.segmented button:active { transform: scale(0.96); }
/* Sans cette règle, le navigateur pose son propre cerclage bleu après un clic
   — hors charte, et jusque dans le thème sombre. */
.segmented button:focus { outline: none; }
.segmented button:focus-visible { outline: 2px solid var(--accent); outline-offset: -1px; border-radius: 7px; }
.segmented button.active,
.segmented button.active + button::before,
.segmented button.active::before {
  background: transparent;
}
.segmented button.active {
  background: var(--thumb);
  box-shadow: var(--shadow-thumb);
  font-weight: 600;
}

/* ═══════════════════════════════════════════════════════════════════
   CARTES (inset grouped iOS : pas de bordure, coins généreux)
   ═══════════════════════════════════════════════════════════════════ */
.card {
  background: var(--card-bg);
  border: 1px solid var(--card-line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
}
.card-pad { padding: 1.2rem 1.3rem 1.35rem; }

.card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 1.15rem 1.3rem 0;
}
.card-head h3 { font-size: 1.045rem; font-weight: 600; letter-spacing: -0.022em; color: var(--text); }
.card-head .sub { font-size: 0.83rem; color: var(--text-2); font-weight: 400; }
.card-more {
  border: none;
  background: none;
  color: var(--accent);
  cursor: pointer;
  font-family: inherit;
  font-size: 0.865rem;
  font-weight: 500;
  padding: 0.1rem 0.2rem;
  text-decoration: none;
  transition: opacity 0.15s;
}
.card-more:hover { opacity: 0.65; }
.card-actions { display: inline-flex; align-items: center; gap: 0.9rem; }

/* Case à cocher : même famille visuelle que les contrôles iOS. */
.check {
  appearance: none;
  -webkit-appearance: none;
  width: 17px;
  height: 17px;
  border-radius: 6px;
  border: 1.5px solid var(--border-strong);
  background: var(--surface);
  cursor: pointer;
  display: inline-grid;
  place-content: center;
  flex-shrink: 0;
  transition: background 0.15s, border-color 0.15s, transform 0.1s;
}
.check:hover { border-color: var(--accent); }
.check:active { transform: scale(0.9); }
.check:checked,
.check:indeterminate { background: var(--accent); border-color: var(--accent); }
.check::after {
  content: "";
  width: 10px;
  height: 10px;
  background: #fff;
  transform: scale(0);
  transition: transform 0.14s cubic-bezier(0.32, 0.72, 0, 1);
  clip-path: polygon(14% 44%, 0 60%, 39% 100%, 100% 18%, 84% 0, 39% 68%);
}
.check:checked::after { transform: scale(1); }
.check:indeterminate::after {
  clip-path: none;
  width: 8px;
  height: 2px;
  border-radius: 2px;
  transform: scale(1);
}
.check:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Colonne de sélection : discrète, elle ne pèse pas sur la lecture. */
th.pick, td.pick { width: 38px; padding-right: 0; }
table.table tbody tr.picked { background: var(--accent-softer); }

/* Barre d'export en tête de l'onglet Leads. Elle change de contenu selon
   qu'une sélection est active ou non, mais garde la même hauteur : rien ne
   saute à l'écran quand on coche une ligne. */
.leads-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.85rem;
  flex-wrap: wrap;
  padding: 1.1rem 1.3rem 0.15rem;
}
.leads-toolbar .btn svg { width: 14px; height: 14px; }
.leads-toolbar .sel-count { font-size: 0.83rem; font-weight: 600; color: var(--text); }
.leads-toolbar .toolbar-right { display: inline-flex; align-items: center; gap: 0.6rem; }

/* ── KPI ─────────────────────────────────────────────────────────── */
.kpi-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0;
  margin-bottom: 1rem;
  overflow: hidden;
  border: 1px solid var(--card-line);
  border-radius: 18px;
  background: var(--card-bg);
  box-shadow: var(--shadow-card);
}
.kpi-grid > .kpi {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-rows: auto auto;
  gap: 0;
  min-width: 0;
  min-height: 96px;
  padding: 0.9rem 1.05rem 0.85rem;
  overflow: hidden;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  transition: background 160ms ease;
}
.kpi-grid > .kpi + .kpi { border-left: 1px solid var(--separator); }
.kpi-grid > .kpi:hover { background: var(--accent-softer); }
.kpi-side { display: contents; }
.kpi-label {
  grid-column: 1;
  grid-row: 1;
  align-self: center;
  min-width: 0;
  overflow: hidden;
  font-size: 0.76rem;
  font-weight: 600;
  color: var(--text-2);
  letter-spacing: -0.006em;
  line-height: 1.2;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.kpi-icon {
  grid-column: 2;
  grid-row: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 27px;
  height: 27px;
  margin-left: 0.7rem;
  border: 1px solid var(--card-line);
  border-radius: 8px;
  background: var(--accent-softer);
  color: var(--accent);
  flex-shrink: 0;
}
.kpi-icon svg { width: 13px; height: 13px; }

.kpi-main {
  grid-column: 1 / -1;
  grid-row: 2;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 0.75rem;
  min-width: 0;
  margin-top: 0.62rem;
}
.kpi-row {
  display: flex;
  align-items: baseline;
  gap: 0.14rem;
  min-width: 0;
}
.kpi-unit { font-size: 0.82rem; font-weight: 600; color: var(--text-2); }
.kpi-value {
  font-size: clamp(1.55rem, 1.8vw, 1.85rem);
  font-weight: 680;
  letter-spacing: -0.045em;
  line-height: 1;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.kpi-sub {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.26rem;
  min-width: 0;
  max-width: 58%;
  margin-bottom: 0.12rem;
  overflow: hidden;
  white-space: nowrap;
  color: var(--text-3);
  font-size: 0.69rem;
  font-weight: 500;
  line-height: 1.1;
  text-align: right;
  text-overflow: ellipsis;
}

.delta {
  display: inline-flex;
  align-items: center;
  white-space: nowrap;
  gap: 2px;
  font-size: 0.775rem;
  font-weight: 600;
  padding: 0.14rem 0.5rem 0.14rem 0.38rem;
  border-radius: 980px;
  font-variant-numeric: tabular-nums;
}
.delta svg { width: 10px; height: 10px; }
.delta.up { background: var(--success-soft); color: var(--success); }
.delta.down { background: var(--danger-soft); color: var(--danger); }
.delta.flat { background: var(--surface-2); color: var(--text-2); }

/* Sous un chiffre KPI, l'écart n'est plus une capsule mais du texte coloré :
   déclaré après les variantes pour l'emporter à spécificité égale. */
.kpi-sub .delta.up,
.kpi-sub .delta.down,
.kpi-sub .delta.flat {
  background: none;
  padding: 0;
  font-size: 0.69rem;
  font-weight: 700;
}
.kpi-sub .delta svg { width: 10px; height: 10px; }

.skel-kpi-label,
.skel-kpi-icon { display: inline-flex; align-items: center; }
.skel-kpi-icon { justify-content: flex-end; }

@media (max-width: 760px) {
  .kpi-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .kpi-grid > .kpi:nth-child(odd) { border-left: 0; }
  .kpi-grid > .kpi:nth-child(n + 3) { border-top: 1px solid var(--separator); }
}
@media (max-width: 360px) {
  .kpi-grid { grid-template-columns: minmax(0, 1fr); }
  .kpi-grid > .kpi + .kpi { border-top: 1px solid var(--separator); border-left: 0; }
}

/* ── Carte de chaleur jour × heure ───────────────────────────────── */
/* Une colonne par jour, une ligne par heure, sur la tranche la plus
   active : on lit d'un coup d'œil quand les visiteurs écrivent. */
.heat-head {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  margin-bottom: 1.05rem;
}
.heat-head h3 { font-size: 1rem; font-weight: 700; letter-spacing: -0.02em; }
.heat-icon {
  width: 30px;
  height: 30px;
  border-radius: 10px;
  background: var(--accent-soft);
  color: var(--accent);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.heat-icon svg { width: 16px; height: 16px; }
.heat-more {
  margin-left: auto;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: transparent;
  color: var(--text-2);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: background 0.15s, color 0.15s, transform 0.1s;
}
.heat-more svg { width: 15px; height: 15px; }
.heat-more:hover { background: var(--surface-2); color: var(--accent); }
.heat-more:active { transform: scale(0.92); }

/* Dans une carte étirée (cf. `.grid-even`) pour s'aligner sur sa voisine, la
   grille remplit maintenant tout le cadre au lieu de laisser un vide sous la
   légende : seule la ligne des jours garde sa hauteur naturelle, les lignes
   d'heures se partagent le reste. `.heat-card` rend la carte flexible pour
   que cet espace existe réellement à distribuer. */
.heat-card { display: flex; flex-direction: column; }
.heat-card .hm-wrap { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.heat-card .hm-wrap .hm { flex: 1; min-height: 0; }

.hm-wrap { position: relative; }
.hm {
  display: grid;
  grid-template-columns: 30px repeat(7, minmax(0, 1fr));
  grid-template-rows: auto;   /* ligne des jours : hauteur naturelle */
  grid-auto-rows: 1fr;        /* lignes d'heures : le reste, à parts égales */
  gap: 5px;
  align-items: stretch;
}
.hm-corner { height: 1px; }
.hm-day {
  font-size: 0.72rem;
  font-weight: 500;
  color: var(--text-2);
  text-align: center;
}
.hm-hour {
  display: flex;
  align-items: center;   /* la ligne s'agrandit ; le libellé reste centré */
  font-size: 0.68rem;
  color: var(--text-3);
  font-variant-numeric: tabular-nums;
}
.hm-cell {
  height: 100%;
  min-height: 14px;
  border-radius: 7px;
  background: var(--hm-0);
  transition: transform 0.12s ease, box-shadow 0.12s ease;
  animation: hm-in 320ms cubic-bezier(0.22, 0.61, 0.36, 1) backwards;
  animation-delay: calc(var(--i, 0) * 10ms);
}
/* La case survolée se soulève : le lecteur voit la cible répondre. L'anneau
   est à la couleur de la surface — un espaceur, pas un contour de donnée. */
.hm-cell:hover,
.hm-cell:focus-visible {
  transform: scale(1.12);
  box-shadow: 0 0 0 2px var(--card-bg-solid), 0 4px 12px rgba(12, 8, 32, 0.16);
  outline: none;
}
.hm-tip { z-index: 8; }
.hm-cell.l1 { background: var(--hm-1); }
.hm-cell.l2 { background: var(--hm-2); }
.hm-cell.l3 { background: var(--hm-3); }
.hm-cell.l4 { background: var(--hm-4); }
.hm-cell.l5 { background: var(--hm-5); }
@keyframes hm-in {
  from { opacity: 0; transform: scale(0.86); }
  to { opacity: 1; transform: none; }
}

.hm-foot {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
  margin-top: 0.85rem;
  font-size: 0.72rem;
  color: var(--text-3);
}
.hm-note { margin-right: auto; color: var(--text-2); }
.hm-scale { display: inline-flex; align-items: center; gap: 4px; }
.hm-key { width: 12px; height: 12px; border-radius: 4px; display: inline-block; }
.hm-key.l1 { background: var(--hm-1); }
.hm-key.l2 { background: var(--hm-2); }
.hm-key.l3 { background: var(--hm-3); }
.hm-key.l4 { background: var(--hm-4); }
.hm-key.l5 { background: var(--hm-5); }

/* ── Carte du monde ──────────────────────────────────────────────── */
/* Panneau de chiffres à gauche, carte à droite : les pays qui parlent au
   chatbot se colorent, les trois premiers portent une étiquette. */
.map-card {
  display: grid;
  grid-template-columns: 190px minmax(0, 1fr);
  gap: 1.1rem;
  align-items: center;
}
.map-stats { display: flex; flex-direction: column; gap: 1.2rem; }
.map-stat-label { font-size: 0.8rem; color: var(--text-2); }
.map-stat-value {
  font-size: 1.75rem;
  font-weight: 700;
  letter-spacing: -0.03em;
  line-height: 1.05;
  margin-top: 0.3rem;
  font-variant-numeric: tabular-nums;
}
.map-stat-sub { font-size: 0.8rem; color: var(--text-3); margin-top: 0.25rem; }

.wm { position: relative; }
/* Calque des étiquettes : il épouse le SVG au pixel près (le SVG est en
   `display:block; height:auto`), ce qui fait des pourcentages `left`/`top` des
   épingles des pourcentages DU DESSIN — et non de la carte, qui peut être plus
   haute que lui quand la mise en page lui impose une hauteur. */
.wm-frame { position: relative; }
/* `overflow` par défaut (masqué) : les tracés qui frôlent le cadre ne
   débordent pas de la carte. */
.wm-svg { display: block; width: 100%; height: auto; }
.wm-c {
  fill: var(--wm-land);
  /* --card-bg est un dégradé : inutilisable comme contour. La couleur de
     surface joue le même rôle, un cheveu entre deux pays. */
  stroke: var(--surface);
  stroke-width: 0.5;
  transition: fill 0.2s;
}
.wm-c.l1 { fill: var(--hm-2); }
.wm-c.l2 { fill: var(--hm-4); }
.wm-c.l3 { fill: var(--accent); }

/* Survol : le pays visé fonce d'un cran et se détache du reste. Seuls les
   pays porteurs de données sont survolables — les autres n'ont rien à dire,
   ils ne réagissent donc pas. */
.wm-c[data-code] { cursor: pointer; transition: fill 0.14s; }
.wm-c[data-code]:hover, .wm-c.on { fill: var(--accent-deep); outline: none; }
.wm-c[data-code]:focus-visible { fill: var(--accent-deep); }

/* Étiquette volante : même dessin que les épingles fixes, mais repositionnée
   sur le pays survolé.
   `.wm-pin.wm-hover` et non `.wm-hover` : `.wm-pin` est déclarée PLUS BAS
   dans ce fichier et lui donne l'animation d'entrée des épingles fixes. À
   spécificité égale c'est la dernière qui l'emporte, donc l'étiquette de
   survol héritait de `reveal-up` — dont le `transform: translateY(14px)`
   écrase le centrage `translate(-50%, …)`. Résultat : à chaque première
   entrée sur un pays, elle apparaissait décalée en bas à droite, y restait le
   temps du `animation-delay`, puis glissait à sa place. Deux classes suffisent
   à trancher, sans dépendre de l'ordre des règles. */
.wm-pin.wm-hover { pointer-events: none; animation: none; z-index: 3; }
/* `.wm-pin` déclare `display: inline-flex` : une règle d'auteur, qui l'emporte
   TOUJOURS sur le `display: none` par défaut de l'attribut `hidden` (une
   feuille de l'agent utilisateur), quelle que soit la spécificité comparée.
   Sans cette ligne, poser `hidden` sur l'infobulle ne changeait rien à
   l'écran : elle restait affichée après le départ du curseur. */
.wm-hover[hidden] { display: none; }
/* Pendant le survol, les épingles fixes reculent pour laisser lire la bulle
   du pays visé — deux étiquettes superposées ne se lisent ni l'une ni l'autre. */
.wm.wm-hovering .wm-pin:not(.wm-hover) { opacity: 0.12; }
.wm .wm-pin:not(.wm-hover) { transition: opacity 0.16s; }

.wm-pin {
  position: absolute;
  transform: translate(-50%, calc(-100% - 10px));
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 5px 10px 5px 6px;
  border-radius: 12px;
  background: var(--wm-pin);
  border: 1px solid rgba(255, 255, 255, 0.09);
  color: #fff;
  white-space: nowrap;
  box-shadow: 0 10px 24px rgba(12, 8, 32, 0.28);
  animation: reveal-up 420ms cubic-bezier(0.22, 0.61, 0.36, 1) backwards;
  animation-delay: 260ms;
}
/* Pointe dirigée vers le pays. Sur les pays du haut de la carte,
   l'étiquette passe sous le point pour ne pas déborder de la carte. */
.wm-pin::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 100%;
  width: 9px;
  height: 9px;
  margin-left: -4.5px;
  margin-top: -4px;
  border-radius: 2px;
  background: var(--wm-pin);
  transform: rotate(45deg);
}
.wm-pin.below { transform: translate(-50%, 10px); }
.wm-pin.below::after { top: auto; bottom: 100%; margin-top: 0; margin-bottom: -4px; }
.wm-flag {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.12);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 0.85rem;
  line-height: 1;
}
.wm-pin-txt { display: flex; flex-direction: column; line-height: 1.15; }
.wm-pin-name { font-size: 0.66rem; color: rgba(255, 255, 255, 0.66); }
.wm-pin-val { font-size: 0.78rem; font-weight: 600; }
.wm-empty {
  position: absolute;
  inset: auto 0 42%;
  text-align: center;
  font-size: 0.85rem;
  color: var(--text-3);
}

/* ── Grille principale ───────────────────────────────────────────── */
.grid-main {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 368px;
  gap: 0.9rem;
  align-items: start;
}
.col { display: flex; flex-direction: column; gap: 0.9rem; min-width: 0; }

/* Rangée de la carte de chaleur et de la carte du monde. */
.grid-wide {
  display: grid;
  grid-template-columns: 340px minmax(0, 1fr);
  gap: 0.9rem;
  align-items: start;
}

/* Rythme vertical entre rangées de cartes : le même écart que sous la ligne
   d'indicateurs, quel que soit l'ordre des rangées dans la page — elles sont
   interchangeables. Porté par le sélecteur d'adjacence plutôt que par un
   `margin-top` fixe, qui laissait un bord à bord dès qu'on permutait. */
.grid-main + .grid-wide,
.grid-wide + .grid-main,
.grid-main + .grid-main,
.grid-wide + .grid-wide {
  margin-top: 0.9rem;
}

/* Chiffre de tête de la carte Activité, sur sa propre ligne sous le titre. */
.chart-figure-row {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  flex-wrap: wrap;
  margin-top: 0.35rem;
}
.chart-figure-row .chart-total { margin-top: 0; }
.chart-figure-row .chart-meta { display: inline-flex; align-items: center; gap: 0.4rem; margin-top: 0; }

/* ── Courbe de tendance multi-séries ─────────────────────────────── */
/* Marques fines, grille en filets pleins, lavis à 16 % sous le trait : la
   donnée est la seule chose autorisée à être forte. */
.tc-plot { position: relative; margin-top: 0.4rem; }
.tc-plot svg { width: 100%; display: block; overflow: visible; }

/* Grille pointillée, comme sur la référence. Je l'avais passée en trait plein
   plus tôt dans le projet (un pointillé se lit parfois comme un seuil) ; ici
   c'est un choix de style assumé, et l'opacité basse enlève l'ambiguïté. */
.tc-grid { stroke: var(--separator); stroke-width: 1; stroke-dasharray: 2 4; opacity: 0.7; }
/* Verticales : présentes mais presque effacées, elles situent les dates sans
   quadriller le tracé. */
.tc-vgrid { stroke: var(--separator); stroke-width: 1; opacity: 0.32; }
.tc-tick {
  font-size: 10px;
  fill: var(--text-3);
  opacity: 0.85;
  font-variant-numeric: tabular-nums;
  dominant-baseline: middle;
}

.tc-line { fill: none; stroke-width: 1.7; stroke-linejoin: round; stroke-linecap: round; }
.tc-s1 { stroke: var(--viz-1); }
.tc-s2 { stroke: var(--viz-2); }
.tc-s3 { stroke: var(--viz-3); }

/* Anneau à la couleur de la surface : le point reste lisible là où il croise
   une autre courbe. C'est un espaceur, pas un contour de donnée. */
.tc-dot { fill: var(--card-bg-solid); stroke-width: 2.2; transition: opacity 0.12s; }
.tc-dot.tc-s1 { stroke: var(--viz-1); }
.tc-dot.tc-s2 { stroke: var(--viz-2); }
.tc-dot.tc-s3 { stroke: var(--viz-3); }

.tc-cursor {
  stroke: var(--border-strong);
  stroke-width: 1;
  opacity: 0.6;
  transition: opacity 0.12s;
}

/* Légende : la pastille porte l'identité, le texte reste en encre de texte. */
/* Légende centrée sous le tracé, sans encadré : chaque série est signalée par
   un court trait de sa couleur, comme sur la référence. */
.tc-legend {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.3rem 1.6rem;
  margin-top: 0.9rem;
}
.tc-leg {
  display: inline-flex;
  align-items: center;
  gap: 0.42rem;
  font-size: 0.78rem;
  color: var(--text-2);
  white-space: nowrap;
}
/* Trait court plutôt que pastille : il rappelle la forme de la marque. */
.tc-swatch { width: 14px; height: 2.5px; border-radius: 2px; flex-shrink: 0; }
.tc-k1 { background: var(--viz-1); }
.tc-k2 { background: var(--viz-2); }
.tc-k3 { background: var(--viz-3); }
/* Dans l'infobulle, la clé est un trait court : à cette densité, un carré
   plein pèse comme de la donnée alors qu'il fait un travail d'étiquette. */
.tooltip .t-key.tc-k1, .tooltip .t-key.tc-k2, .tooltip .t-key.tc-k3 {
  width: 12px;
  height: 2.5px;
  border-radius: 2px;
}

/* Bandeau de dates sous le tracé : la carte doit l'inclure, sinon elle
   fabrique une barre de défilement d'un pixel. */
.tc-x {
  display: flex;
  justify-content: space-between;
  font-size: 0.715rem;
  color: var(--text-3);
  margin-top: 0.35rem;
}

@media (max-width: 640px) {
  .card-analytics { padding: 1.25rem 1.15rem 1.2rem; border-radius: 20px; }
  /* La commande passe sous le titre plutôt que de le comprimer. */
  .tc-head { align-items: flex-start; }
  .tc-period { width: 100%; max-width: none; }
  .tc-figure .chart-total { font-size: 1.8rem; }
}

/* Entête de la carte : titre à gauche, légende à droite, qui repasse dessous
   quand la carte se resserre. */
/* ── Carte analytique ────────────────────────────────────────────── */
/* Variante de `.card` : rayon plus généreux, padding plus large, ombre plus
   diffuse. Les valeurs restent dérivées des jetons du portail — on module,
   on ne crée pas une seconde identité. */
.card-analytics {
  padding: 1.75rem 1.9rem 1.6rem;
  border-radius: 26px;
  border: 1px solid var(--card-line);
  box-shadow: 0 15px 40px rgba(30, 25, 70, 0.05);
  overflow: hidden;
}

/* En-tête compact : identité à gauche, commande de période à droite. */
.tc-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem 1.5rem;
  flex-wrap: wrap;
  margin-bottom: 1.15rem;
}
.tc-ident { min-width: 0; }
.tc-ident h3 {
  font-size: 1.06rem;
  font-weight: 600;
  letter-spacing: -0.024em;
  line-height: 1.2;
  color: var(--text);
}
.tc-sub {
  display: block;
  margin-top: 0.16rem;
  font-size: 0.815rem;
  font-weight: 400;
  color: var(--text-3);
  line-height: 1.35;
}
/* Le sélecteur reprend le composant existant, en plus discret : rectangle
   arrondi plutôt que capsule, texte en encre secondaire. La classe est
   doublée parce que `.select` est déclaré plus bas dans la feuille et
   gagnerait à spécificité égale — c'est plus lisible qu'un `!important`. */
/* Commandes de l'en-tête : période + accès à la vue détaillée. */
.tc-controls { display: inline-flex; align-items: center; gap: 0.4rem; flex-shrink: 0; }
.tc-expand {
  width: 32px;
  height: 32px;
  border-radius: 11px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-2);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  text-decoration: none;
  transition: background 0.14s, color 0.14s, border-color 0.14s;
}
.tc-expand svg { width: 14px; height: 14px; }
.tc-expand:hover { background: var(--surface-2); color: var(--accent); border-color: var(--border-strong); }

.tc-period.tc-period {
  height: 32px;
  border-radius: 11px;
  font-size: 0.815rem;
  font-weight: 500;
  color: var(--text-2);
  flex-shrink: 0;
}

/* Chiffre de tête : compact, aligné avec l'en-tête. */
.tc-figure {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  flex-wrap: wrap;
  margin-bottom: 0.9rem;
}
.tc-figure .chart-total { font-size: 2.15rem; font-weight: 600; margin-top: 0; }
.tc-figure .chart-meta { margin-top: 0; gap: 0.4rem; font-size: 0.795rem; }
.tc-vs { color: var(--text-3); }

/* ── Graphique en aires ──────────────────────────────────────────── */
.chart-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 1.5rem; flex-wrap: wrap; }
.chart-figure { min-width: 0; }
.chart-total {
  font-size: 2.3rem;
  font-weight: 700;
  letter-spacing: -0.042em;
  line-height: 1.08;
  color: var(--text);
  margin-top: 0.35rem;
}
.chart-meta { display: flex; align-items: center; gap: 0.5rem; margin-top: 0.5rem; font-size: 0.8rem; color: var(--text-2); }
.chart-plot { position: relative; flex: 1; min-width: 260px; }
.chart-plot svg { display: block; width: 100%; height: 168px; overflow: visible; }
.chart-x {
  display: flex;
  justify-content: space-between;
  font-size: 0.72rem;
  color: var(--text-3);
  margin-top: 0.35rem;
  padding-left: 2.1rem;
}

/* Infobulle : petit matériau flottant */
.tooltip {
  position: absolute;
  pointer-events: none;
  background: var(--tip-bg);
  border-radius: 13px;
  box-shadow: 0 10px 30px rgba(10, 8, 30, 0.28);
  padding: 0.52rem 0.72rem;
  font-size: 0.78rem;
  color: rgba(255, 255, 255, 0.66);
  white-space: nowrap;
  opacity: 0;
  transform: translateY(3px);
  transition: opacity 0.13s, transform 0.13s;
  z-index: 5;
}
.tooltip.on { opacity: 1; transform: none; }
.tooltip .t-date {
  font-weight: 600;
  color: rgba(255, 255, 255, 0.95);
  margin-bottom: 0.28rem;
  font-size: 0.78rem;
}
.tooltip .t-row { display: flex; align-items: center; gap: 7px; line-height: 1.55; }
.tooltip .t-key { width: 12px; height: 3px; border-radius: 2px; flex-shrink: 0; }
/* La valeur mène, le nom de la série suit : le lecteur a déjà la série,
   il vient chercher le nombre. */
.tooltip .t-val { font-weight: 700; color: #fff; font-variant-numeric: tabular-nums; }

/* Répartition (sous-carte du graphique) */
.split {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 1rem;
  margin-top: 1.25rem;
  padding: 1.05rem 1.15rem 1.15rem;
  background: var(--accent-softer);
  border: 1px solid var(--card-line);
  border-radius: 18px;
}
.split-title { grid-column: 1 / -1; display: flex; align-items: center; justify-content: space-between; }
.split-title h4 { font-size: 0.92rem; font-weight: 600; color: var(--text); letter-spacing: -0.015em; }
.split-item { min-width: 0; }
.split-val {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 1.25rem;
  font-weight: 700;
  letter-spacing: -0.03em;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.split-val svg { width: 15px; height: 15px; color: var(--text-2); }
.split-label { font-size: 0.775rem; color: var(--text-2); margin-bottom: 0.5rem; }
.split-bar { height: 5px; border-radius: 980px; background: var(--track); overflow: hidden; }
.split-bar > span { display: block; height: 100%; border-radius: 980px; }

/* ── Cartes-statistique ──────────────────────────────────────────── */
/* Hiérarchie « stat first » : intitulé discret, valeur en grand, phrase
   de contexte, puis un visuel de support minimal. Volontairement plat :
   ni piste, ni cadre, ni graduation — la donnée porte la carte. */
.stat-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-bottom: 0.5rem;
}
.stat-eyebrow { font-size: 0.815rem; font-weight: 500; color: var(--text-2); letter-spacing: -0.008em; }
.stat-line { display: flex; align-items: baseline; gap: 0.5rem; flex-wrap: wrap; }
.stat-value {
  font-size: 1.9rem;
  font-weight: 700;
  letter-spacing: -0.04em;
  line-height: 1.1;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.stat-goal { font-size: 0.85rem; font-weight: 500; color: var(--text-3); }
.stat-caption { font-size: 0.8rem; color: var(--text-3); margin-top: 0.3rem; }

/* Activité par jour : intensité codée par l'opacité, sans piste ni axe. */
.daybars { display: flex; align-items: flex-end; gap: 0.5rem; margin-top: 1.25rem; }
.daycol { flex: 1; display: flex; flex-direction: column; gap: 0.5rem; min-width: 0; }
.daybar-slot { height: 54px; display: flex; align-items: flex-end; }
.daybar {
  width: 100%;
  max-width: 26px;
  margin: 0 auto;
  border-radius: 7px;
  background: var(--accent);
  transition: transform 0.16s cubic-bezier(0.32, 0.72, 0, 1), filter 0.16s;
  transform-origin: bottom;
}
.daycol:hover .daybar { transform: scaleY(1.06); filter: brightness(1.06); }
.dayname { font-size: 0.7rem; text-align: center; color: var(--text-3); }
.daycol.peak .dayname { color: var(--accent); font-weight: 600; }

/* ── Pastille d'aide « i » ───────────────────────────────────────── */
/* Hors flux, dans le coin haut-droit de la carte : elle n'entre jamais
   en concurrence avec le titre ni avec le chiffre. */
.has-info { position: relative; }
.info-dot {
  position: absolute;
  top: 0.95rem;
  right: 1rem;
  width: 18px;
  height: 18px;
  padding: 0;
  border-radius: 50%;
  border: 1px solid var(--border-strong);
  background: transparent;
  color: var(--text-3);
  font-family: inherit;
  font-size: 0.67rem;
  font-weight: 700;
  line-height: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: help;
  transition: color 0.15s, border-color 0.15s, background 0.15s;
}
.info-dot:hover,
.info-dot:focus-visible {
  color: var(--accent);
  border-color: var(--accent);
  background: var(--accent-soft);
  outline: none;
}
.info-pop {
  position: absolute;
  top: calc(100% + 0.5rem);
  right: -0.25rem;
  width: 258px;
  max-width: 74vw;
  padding: 0.65rem 0.75rem;
  border-radius: 13px;
  border: 1px solid var(--border);
  background: var(--card-bg);
  box-shadow: var(--shadow-hover);
  font-size: 0.765rem;
  font-weight: 400;
  line-height: 1.45;
  letter-spacing: -0.004em;
  color: var(--text-2);
  text-align: left;
  white-space: normal;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-3px);
  transition: opacity 0.16s, transform 0.16s, visibility 0.16s;
  pointer-events: none;
  z-index: 40;
}
.info-dot:hover .info-pop,
.info-dot:focus-visible .info-pop {
  opacity: 1;
  visibility: visible;
  transform: none;
}

/* ── Réglage en pied de carte (valeur moyenne d'un client) ───────── */
.stat-setting {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem 0.75rem;
  flex-wrap: wrap;
  margin-top: 1.2rem;
  padding-top: 0.85rem;
  border-top: 1px solid var(--separator);
  font-size: 0.795rem;
  color: var(--text-3);
}
.stat-setting-label { min-width: 0; }
.stat-setting b {
  color: var(--text);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.stat-setting-form {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  width: 100%;
}
.value-input {
  flex: 1;
  min-width: 0;
  /* Alignée sur .btn.sm : les trois éléments de la ligne font la même hauteur. */
  height: 30px;
  padding: 0 0.6rem;
  border: none;
  background: var(--surface-2);
  border-radius: 10px;
  font-family: inherit;
  font-size: 0.85rem;
  font-variant-numeric: tabular-nums;
  color: var(--text);
  transition: box-shadow 0.15s;
}
.value-input::placeholder { color: var(--text-3); }
.value-input:focus { outline: none; box-shadow: 0 0 0 3px var(--ring); }
/* Les flèches natives du champ nombre alourdissent une carte de 32 px. */
.value-input::-webkit-outer-spin-button,
.value-input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.value-input { -moz-appearance: textfield; appearance: textfield; }
.stat-setting-msg { flex-basis: 100%; font-size: 0.755rem; }
.stat-setting-msg.err { color: var(--danger); }

/* Progression vers l'objectif : une capsule fine, un repère, rien d'autre. */
.meter {
  position: relative;
  height: 8px;
  border-radius: 980px;
  background: var(--track);
  margin-top: 1.15rem;
}
.meter-fill {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  border-radius: 980px;
  background: linear-gradient(90deg, var(--accent) 0%, var(--accent-deep) 100%);
  transition: width 0.5s cubic-bezier(0.32, 0.72, 0, 1);
}
.meter-target {
  position: absolute;
  top: -5px;
  bottom: -5px;
  width: 2px;
  border-radius: 2px;
  background: var(--text);
  opacity: 0.28;
}
.meter-legend {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-top: 0.75rem;
  font-size: 0.795rem;
  color: var(--text-3);
}
.link-more {
  border: none;
  background: none;
  padding: 0;
  font-family: inherit;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--accent);
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  transition: opacity 0.15s;
}
.link-more:hover { opacity: 0.65; }

/* Anneaux concentriques (répartition des échanges) */
.rings { display: flex; align-items: center; gap: 1.4rem; flex-wrap: wrap; }
.rings > svg { width: 168px; height: 168px; flex-shrink: 0; }
.ring-legend { display: flex; flex-direction: column; gap: 0.85rem; flex: 1; min-width: 150px; }
.ring-item { min-width: 0; }
.ring-label {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 0.8rem;
  color: var(--text-2);
  margin-bottom: 0.15rem;
}
.ring-key { width: 9px; height: 9px; border-radius: 3px; flex-shrink: 0; }
.ring-val {
  display: flex;
  align-items: baseline;
  gap: 7px;
  font-size: 1.28rem;
  font-weight: 700;
  letter-spacing: -0.032em;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.ring-pct { font-size: 0.815rem; font-weight: 500; color: var(--text-3); }

/* ── Liste (style « inset grouped » iOS : séparateurs encastrés) ─── */
.list { display: flex; flex-direction: column; }
.list-item {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.6rem 0;
  min-width: 0;
  text-decoration: none;
  color: inherit;
  position: relative;
}
.list-item + .list-item::before {
  content: "";
  position: absolute;
  top: 0;
  left: 44px;              /* encastré sous l'avatar, comme UITableView */
  right: 0;
  height: 1px;
  background: var(--separator);
}
.list-item:last-child { padding-bottom: 0; }
.list-item:first-child { padding-top: 0.2rem; }
.list-avatar {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--accent-soft);
  color: var(--accent);
  font-size: 0.76rem;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.list-main { min-width: 0; flex: 1; display: flex; flex-direction: column; }
.list-name { font-size: 0.895rem; font-weight: 500; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.list-meta { font-size: 0.775rem; color: var(--text-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.list-time { font-size: 0.775rem; color: var(--text-3); white-space: nowrap; flex-shrink: 0; }

/* ── Tableau présenté comme une liste iOS ────────────────────────── */
.table-wrap { overflow-x: auto; padding: 0 1.3rem 0.4rem; }
table.table { width: 100%; border-collapse: collapse; font-size: 0.9rem; }
table.table th {
  text-align: left;
  font-size: 0.735rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-3);
  padding: 0.85rem 0.75rem;
  border-bottom: 1px solid var(--separator);
  white-space: nowrap;
}
table.table td {
  padding: 0.85rem 0.75rem;
  border-bottom: 1px solid var(--separator);
  color: var(--text-2);
  vertical-align: middle;
}
table.table tr:last-child td { border-bottom: none; }
table.table td.num { font-variant-numeric: tabular-nums; }
table.table td.strong { color: var(--text); font-weight: 500; }
table.table tbody tr.clickable { cursor: pointer; transition: background 0.12s; }
table.table tbody tr.clickable:hover { background: var(--surface-2); }
table.table tbody tr.clickable:active { background: var(--surface-3); }
/* Chevron de navigation en fin de ligne (accessoire iOS) */
td.chevron { width: 22px; padding-left: 0; text-align: right; color: var(--text-3); }
td.chevron svg { width: 15px; height: 15px; }

.cell-widget { display: flex; align-items: center; gap: 0.7rem; min-width: 0; }
.cell-icon {
  width: 34px;
  height: 34px;
  border-radius: 10px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-weight: 600;
  font-size: 0.86rem;
  flex-shrink: 0;
}
.cell-name { font-weight: 500; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 260px; }
.mono { font-variant-numeric: tabular-nums; font-size: 0.83rem; color: var(--text-3); }

.badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 0.755rem;
  font-weight: 500;
  padding: 0.16rem 0.6rem;
  border-radius: 980px;
}
.badge::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.badge.ok { background: var(--success-soft); color: var(--success); }
.badge.off { background: var(--surface-2); color: var(--text-2); }
.badge.warn { background: var(--warn-soft); color: var(--warn); }

/* ── États ───────────────────────────────────────────────────────── */
.empty { text-align: center; color: var(--text-3); font-size: 0.9rem; padding: 2.5rem 1rem; }
.skeleton {
  background: linear-gradient(90deg, var(--surface-2) 25%, var(--surface-3) 37%, var(--surface-2) 63%);
  background-size: 400% 100%;
  animation: shimmer 1.3s ease infinite;
  border-radius: 6px;
  color: transparent !important;
}
@keyframes shimmer { 0% { background-position: 100% 0; } 100% { background-position: -100% 0; } }

/* Barres de squelette : mêmes gabarits que le contenu réel, pour que
   l'arrivée des données ne décale rien. */
.skel-bar { display: inline-block; border-radius: 6px; }
.skel-card, .skel-row { pointer-events: none; }
.skel-row .list-main { display: flex; flex-direction: column; flex: 1; min-width: 0; }
.skel-plot { position: absolute; left: 0; right: 0; top: 0; height: 168px; border-radius: 14px; }

/* État vide : une icône, une phrase, une action — plutôt qu'un constat. */
.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: 2.1rem 1.2rem 2.3rem;
}
/* Version illustrée : réservée au premier écran d'un client (rien n'est
   encore arrivé). Ailleurs, le pictogramme suffit — une illustration à chaque
   liste filtrée vide deviendrait du décor. */
.empty-state.with-art { padding: 2.6rem 1.2rem 2.8rem; }
.empty-art { width: 220px; max-width: 72%; height: auto; margin-bottom: 1.2rem; }
.empty-state.with-art .empty-title { font-size: 1.05rem; }
.empty-icon {
  width: 46px;
  height: 46px;
  border-radius: 16px;
  background: var(--accent-soft);
  color: var(--accent);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 0.85rem;
}
.empty-icon svg { width: 21px; height: 21px; }
.empty-title { font-size: 0.95rem; font-weight: 600; color: var(--text); letter-spacing: -0.015em; }
.empty-text {
  font-size: 0.85rem;
  color: var(--text-2);
  line-height: 1.45;
  max-width: 34ch;
  margin-top: 0.3rem;
}
.empty-action { margin-top: 0.95rem; }

/* ── Entrée en cascade ───────────────────────────────────────────── */
/* Chaque bloc monte à son tour ; --reveal-i est posé par Portal.reveal(). */
@keyframes reveal-up {
  from { opacity: 0; transform: translateY(14px); }
  to { opacity: 1; transform: none; }
}
.reveal {
  animation: reveal-up 520ms cubic-bezier(0.22, 0.61, 0.36, 1) both;
  animation-delay: calc(var(--reveal-i, 0) * 55ms);
}

/* Pré-état du lazy reveal (Portal.revealOnScroll) : le bloc attend, invisible,
   que l'observateur le déclare entrant. La classe n'est posée ni en mouvement
   réduit ni sans IntersectionObserver : rien ne peut rester caché. */
.reveal-pending { opacity: 0; }

/* Lignes de tableau : même montée, décalage plus court et plafonné — vingt
   lignes à 55 ms feraient attendre une seconde avant de voir la dernière. */
@keyframes row-in {
  from { opacity: 0; transform: translateY(7px); }
  to { opacity: 1; transform: none; }
}
.row-in {
  animation: row-in 380ms cubic-bezier(0.22, 0.61, 0.36, 1) both;
  animation-delay: calc(var(--row-i, 0) * 26ms);
}

/* Nuage de sujets : les pastilles arrivent dans l'ordre du classement, du
   sujet dominant à la queue. */
@keyframes kw-in {
  from { opacity: 0; transform: scale(0.86); }
  to { opacity: 1; transform: none; }
}
.kw {
  animation: kw-in 340ms cubic-bezier(0.34, 1.32, 0.64, 1) both;
  animation-delay: calc(var(--i, 0) * 42ms);
}

/* Carte du monde : le décor se pose en gris, puis les pays actifs prennent
   leur couleur l'un après l'autre. La donnée arrive APRÈS le fond, l'œil va
   donc droit aux pays qui comptent. */
@keyframes wm-in {
  from { opacity: 0; transform: scale(0.985); }
  to { opacity: 1; transform: none; }
}
.wm-enter .wm-svg {
  animation: wm-in 620ms cubic-bezier(0.22, 0.61, 0.36, 1) both;
  transform-origin: 50% 50%;
}
.wm-enter .wm-c.l1,
.wm-enter .wm-c.l2,
.wm-enter .wm-c.l3 {
  fill: var(--hm-0);
  transition: fill 520ms ease;
  transition-delay: calc(320ms + var(--i, 0) * 60ms);
}
.wm-enter.wm-lit .wm-c.l1 { fill: var(--hm-2); }
.wm-enter.wm-lit .wm-c.l2 { fill: var(--hm-4); }
.wm-enter.wm-lit .wm-c.l3 { fill: var(--accent); }
/* Les épingles posées d'avance attendent que leur pays soit allumé. */
.wm-enter .wm-pin:not(.wm-hover) { animation-delay: 620ms; }

/* ── Bascule de thème (View Transitions) ─────────────────────────── */
/* Les deux instantanés restent fixes : seul le cercle animé côté JS sur
   ::view-transition-new(root) dévoile le nouveau thème. */
::view-transition-old(root),
::view-transition-new(root) {
  animation: none;
  mix-blend-mode: normal;
}
::view-transition-old(root) { z-index: 0; }
::view-transition-new(root) { z-index: 1; }

@media (prefers-reduced-motion: reduce) {
  .skeleton { animation: none; }
  .reveal, .row-in, .kw { animation: none; }
  .hm-cell { animation: none; }
  .wm-enter .wm-svg { animation: none; }
  .wm-enter .wm-c { transition: none; }
}
.hint { font-size: 0.79rem; color: var(--text-3); }

/* ── Onglets ─────────────────────────────────────────────────────── */
/* Traités comme un contrôle segmenté iOS plutôt qu'un soulignement web. */
.tabs {
  display: inline-flex;
  gap: 0;
  background: var(--surface-2);
  border-radius: 9px;
  padding: 2px;
  margin-bottom: 0.9rem;
}
.tab-btn {
  padding: 0.34rem 1.05rem;
  border: none;
  background: none;
  border-radius: 7px;
  font-family: inherit;
  font-size: 0.855rem;
  font-weight: 500;
  color: var(--text);
  cursor: pointer;
  transition: background 0.18s, box-shadow 0.18s, transform 0.1s;
}
.tab-btn:active { transform: scale(0.97); }
.tab-btn.active {
  background: var(--thumb);
  box-shadow: var(--shadow-thumb);
  font-weight: 600;
}

/* ── Pagination ──────────────────────────────────────────────────── */
.pagination {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
  padding: 0.9rem 1.3rem 1.15rem;
  font-size: 0.82rem;
  color: var(--text-3);
}

/* ── Modale : feuille iOS (grabber + coins hauts arrondis) ───────── */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.32);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 200;
  padding: 1rem;
}
.modal-card {
  background: var(--surface);
  border: none;
  border-radius: 22px;
  box-shadow: var(--shadow-pop);
  max-width: 620px;
  width: 100%;
  max-height: 84vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  animation: sheet-in 0.28s cubic-bezier(0.32, 0.72, 0, 1);
}
@keyframes sheet-in {
  from { opacity: 0; transform: translateY(18px) scale(0.98); }
  to { opacity: 1; transform: none; }
}
.modal-grabber {
  width: 36px;
  height: 5px;
  border-radius: 980px;
  background: var(--surface-3);
  margin: 0.55rem auto 0;
  flex-shrink: 0;
}
.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.75rem 1.15rem 0.85rem;
  border-bottom: 1px solid var(--separator);
}
.modal-header h3 { font-size: 1rem; font-weight: 600; letter-spacing: -0.02em; }
/* Bouton « OK » textuel, comme les feuilles iOS */
.modal-done {
  border: none;
  background: none;
  color: var(--accent);
  font-family: inherit;
  font-size: 0.93rem;
  font-weight: 600;
  cursor: pointer;
  padding: 0.2rem 0.3rem;
  transition: opacity 0.15s;
}
.modal-done:hover { opacity: 0.65; }
.modal-body { padding: 1.2rem 1.3rem; overflow-y: auto; display: flex; flex-direction: column; gap: 0.45rem; }

/* ── Fiche d'un lead ─────────────────────────────────────────────── */
/* Structure des CRM de closing : en-tête d'identité, fil d'événements à
   gauche, caractéristiques à droite, chaque volet avec ses onglets. La
   feuille occupe presque tout l'écran — c'est un dossier, pas une alerte. */
.lead-sheet {
  max-width: 1240px;
  width: 96vw;
  height: 88vh;
  max-height: 88vh;
  border-radius: 20px;
}

.lead-head {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.7rem 0.9rem 0.7rem 1rem;
  border-bottom: 1px solid var(--separator);
  flex-shrink: 0;
}
.lead-avatar { width: 32px; height: 32px; font-size: 0.78rem; flex-shrink: 0; }
.lead-head h3 {
  font-size: 1.02rem;
  font-weight: 700;
  letter-spacing: -0.022em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.lead-nav { display: inline-flex; gap: 0.3rem; }
.lead-actions { display: inline-flex; gap: 0.3rem; margin-left: auto; }
/* Boutons ronds de l'en-tête, comme les commandes d'une fiche CRM. */
.lead-round {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: transparent;
  color: var(--text-2);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: background 0.14s, color 0.14s, border-color 0.14s;
}
.lead-round svg { width: 14px; height: 14px; }
.lead-round:hover:not(:disabled) { background: var(--surface-2); color: var(--text); }
.lead-round:disabled { opacity: 0.32; cursor: default; }
.lead-round.done { background: var(--accent); border-color: var(--accent); color: #fff; }

/* Deux volets séparés par un filet vertical, chacun avec son défilement
   propre : le panneau de droite ne descend pas avec le fil de gauche. */
.lead-panes {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 348px;
}
.lead-main, .lead-aside { display: flex; flex-direction: column; min-height: 0; min-width: 0; }
.lead-aside { border-left: 1px solid var(--separator); }

.lead-tabs {
  display: flex;
  gap: 0.15rem;
  padding: 0 0.6rem;
  border-bottom: 1px solid var(--separator);
  flex-shrink: 0;
  overflow-x: auto;
  scrollbar-width: none;
}
.lead-tabs::-webkit-scrollbar { display: none; }
.lead-tab {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.72rem 0.6rem;
  border: none;
  background: none;
  font-family: inherit;
  font-size: 0.84rem;
  font-weight: 500;
  color: var(--text-3);
  cursor: pointer;
  white-space: nowrap;
  transition: color 0.14s;
}
.lead-tab:hover { color: var(--text-2); }
.lead-tab.active { color: var(--accent); font-weight: 600; }
/* Le soulignement de l'onglet actif, posé sur le filet du bandeau. */
.lead-tab.active::after {
  content: "";
  position: absolute;
  left: 0.6rem;
  right: 0.6rem;
  bottom: -1px;
  height: 2px;
  border-radius: 2px 2px 0 0;
  background: var(--accent);
}

.lead-scroll { flex: 1; min-height: 0; overflow-y: auto; padding: 0.85rem 0.9rem 1.1rem; }
.lead-aside .lead-scroll { padding: 0.35rem 0.9rem 1.1rem; }

/* ── Carte d'événement ───────────────────────────────────────────── */
.ev {
  border: 1px solid var(--card-line);
  border-radius: 13px;
  background: var(--surface);
  padding: 0.7rem 0.85rem;
  margin-bottom: 0.55rem;
  transition: border-color 0.14s, box-shadow 0.14s;
}
.ev:hover { border-color: var(--border-strong); box-shadow: var(--shadow-card); }
.ev-top { display: flex; align-items: center; gap: 0.6rem; }
.ev-icon {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--surface-2);
  color: var(--text-2);
}
.ev-icon svg { width: 13px; height: 13px; }
/* Étape acquise : la pastille prend la couleur, le reste ne bouge pas. */
.ev.ok .ev-icon { background: var(--accent-soft); color: var(--accent); }
.ev-title {
  flex: 1;
  min-width: 0;
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--text);
  line-height: 1.35;
}
/* Le complément du titre reste en encre secondaire, comme « avec X par Y ». */
.ev-title em { font-style: normal; font-weight: 400; color: var(--text-2); }
.ev-when {
  font-size: 0.7rem;
  color: var(--text-3);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.01em;
  flex-shrink: 0;
}

/* Volet secondaire : ce que la carte détaille, derrière un liseré d'accent. */
.ev-detail {
  margin: 0.6rem 0 0 2.1rem;
  padding-left: 0.7rem;
  border-left: 2px solid var(--accent-soft);
}
.ev-line { display: flex; align-items: center; gap: 0.55rem; flex-wrap: wrap; font-size: 0.815rem; }
.ev-strong { font-weight: 600; color: var(--text); }
.ev-muted { color: var(--text-2); }
.ev-quote { font-size: 0.845rem; color: var(--text); line-height: 1.45; font-style: italic; }
.ev-pill {
  font-size: 0.715rem;
  font-weight: 600;
  color: var(--text-2);
  background: var(--surface-2);
  border-radius: 980px;
  padding: 0.12rem 0.55rem;
  white-space: nowrap;
}
.ev-pill.ok { color: var(--accent); background: var(--accent-soft); }
/* Dans le panneau, la pastille s'aligne sur le bord des autres valeurs. */
.info-value .ev-pill, .info-value .wtag { vertical-align: middle; }
.info-value .wtag { max-width: 100%; padding: 0.14rem 0.55rem 0.14rem 0.4rem; font-size: 0.775rem; }

/* ── Panneau de droite ───────────────────────────────────────────── */
.fold { padding: 0.9rem 0 1rem; border-bottom: 1px solid var(--separator); }
.fold:last-child { border-bottom: none; }
.fold-head {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  width: 100%;
  padding: 0 0 0.55rem;
  border: none;
  background: none;
  font-family: inherit;
  font-size: 0.865rem;
  font-weight: 600;
  letter-spacing: -0.014em;
  color: var(--text);
  cursor: pointer;
  text-align: left;
}
.fold-chev {
  display: inline-flex;
  color: var(--text-3);
  transform: rotate(90deg);
  transition: transform 0.16s;
}
.fold-chev svg { width: 13px; height: 13px; }
.fold.closed .fold-chev { transform: none; }
.fold.closed .fold-body { display: none; }

/* Grille à deux colonnes : tous les libellés partent du même bord, toutes
   les valeurs aussi. C'est cet alignement qui fait tenir le panneau — en
   fer à droite, chaque valeur commençait à un endroit différent et le bord
   gauche partait en dents de scie. */
.fold-body {
  display: grid;
  /* 126 px : la largeur du plus long libellé (« Délai de capture ») à cette
     graisse. En dessous, il se tronquait. */
  grid-template-columns: 126px minmax(0, 1fr);
  align-items: center;
  row-gap: 0.1rem;
  column-gap: 0.75rem;
}
.info { display: contents; }
.info-label {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.32rem 0;
  font-size: 0.795rem;
  color: var(--text-2);
  min-width: 0;
}
/* Icône d'un cran en retrait du libellé : elle situe la ligne, elle ne la
   dispute pas. */
.info-label svg { width: 13px; height: 13px; flex-shrink: 0; color: var(--text-3); }
.info-label > span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.info-value {
  padding: 0.32rem 0;
  font-size: 0.83rem;
  font-weight: 500;
  color: var(--text);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  /* Chasse fixe : ces valeurs forment une colonne, les chiffres doivent
     s'aligner verticalement d'une ligne à l'autre. */
  font-variant-numeric: tabular-nums;
}
.lead-link { color: var(--accent); font-weight: 600; text-decoration: none; letter-spacing: -0.005em; }
.lead-link:hover { text-decoration: underline; }
.lead-muted { color: var(--text-3); font-weight: 400; }

/* Cellule pays du tableau des leads : pays en clair, ville en sous-texte
   quand elle est connue (dépend de la collecte de ville, souvent inactive). */
.lead-geo { display: flex; flex-direction: column; line-height: 1.3; }
.lead-geo-main { font-size: 0.87rem; white-space: nowrap; }
.lead-geo-sub { font-size: 0.73rem; color: var(--text-3); }
/* Nombre de messages : chiffre centré, tabulaire pour s'aligner en colonne. */
.lead-msgcount { text-align: center; font-variant-numeric: tabular-nums; color: var(--text-2); }

/* Questions posées : les messages du visiteur, dans l'ordre. */
.qasked { list-style: none; padding-top: 0.5rem; }
.qasked li {
  display: flex;
  gap: 0.6rem;
  padding: 0.55rem 0;
  border-bottom: 1px solid var(--separator);
  font-size: 0.835rem;
  line-height: 1.45;
}
.qasked li:last-child { border-bottom: none; }
.qasked-n {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  flex-shrink: 0;
  background: var(--surface-2);
  color: var(--text-3);
  font-size: 0.7rem;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.qasked-text { color: var(--text); min-width: 0; }

/* Conversation : les bulles du portail, inchangées. */
.lead-thread { display: flex; flex-direction: column; gap: 0.45rem; }

@media (max-width: 900px) {
  .lead-sheet { width: 100vw; height: 100vh; max-height: 100vh; border-radius: 0; }
  /* Les deux volets s'empilent : le panneau de détails passe en premier,
     c'est le numéro qu'on vient chercher sur un téléphone. */
  .lead-panes { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto auto; }
  .lead-aside { border-left: none; border-bottom: 1px solid var(--separator); order: -1; }
  .lead-aside .lead-scroll { max-height: 40vh; }
}

/* Bulles de conversation façon Messages */
.msg-bubble {
  max-width: 78%;
  padding: 0.55rem 0.9rem;
  border-radius: 19px;
  font-size: 0.925rem;
  line-height: 1.4;
  white-space: pre-wrap;
  word-wrap: break-word;
}
.msg-bubble.user { align-self: flex-end; background: var(--accent); color: #fff; border-bottom-right-radius: 6px; }
.msg-bubble.assistant { align-self: flex-start; background: var(--surface-2); color: var(--text); border-bottom-left-radius: 6px; }

/* ── Connexion ───────────────────────────────────────────────────── */
.auth-shell {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
  background: var(--ambient);
  background-attachment: fixed;
}
.auth-card {
  width: 100%;
  max-width: 400px;
  background: var(--card-bg);
  border: 1px solid var(--card-line);
  border-radius: 26px;
  box-shadow: var(--shadow-shell);
  padding: 2.1rem 1.9rem 1.9rem;
}
.auth-brand { display: flex; align-items: center; gap: 9px; margin-bottom: 1.5rem; }
.auth-brand .logo-mark { width: 30px; height: 30px; object-fit: contain; }
.auth-brand .logo-text { font-weight: 700; font-size: 1.16rem; letter-spacing: -0.028em; }
.auth-brand .logo-sub { font-weight: 400; color: var(--text-3); font-size: 0.95rem; }
.auth-card h1 { font-size: 1.55rem; font-weight: 700; letter-spacing: -0.032em; }
.auth-desc { font-size: 0.9rem; color: var(--text-2); margin: 0.3rem 0 1.5rem; }

.field { margin-bottom: 0.85rem; }
.field label { display: block; font-size: 0.8rem; font-weight: 500; color: var(--text-2); margin-bottom: 0.35rem; }
.field input {
  width: 100%;
  height: 46px;
  padding: 0 0.9rem;
  border: none;
  background: var(--surface-2);
  border-radius: 12px;
  font-family: inherit;
  font-size: 0.95rem;
  color: var(--text);
  transition: box-shadow 0.15s, background 0.15s;
}
.field input::placeholder { color: var(--text-3); }
.field input:focus { outline: none; box-shadow: 0 0 0 3.5px var(--ring); }

/* Autofill Chrome/Safari : la feuille UA impose un fond clair opaque par-dessus
   notre style (champs tout blancs en thème sombre). La transition très longue
   neutralise la couleur imposée ; on repeint texte et caret avec le thème. */
.field input:-webkit-autofill,
.field input:-webkit-autofill:hover,
.field input:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--text);
  caret-color: var(--text);
  transition: background-color 5999s ease-in-out 0s;
}

.field textarea {
  width: 100%;
  padding: 0.7rem 0.9rem;
  border: none;
  background: var(--surface-2);
  border-radius: 12px;
  font-family: inherit;
  font-size: 0.92rem;
  line-height: 1.45;
  color: var(--text);
  resize: vertical;
  transition: box-shadow 0.15s, background 0.15s;
}
.field textarea::placeholder { color: var(--text-3); }
.field textarea:focus { outline: none; box-shadow: 0 0 0 3.5px var(--ring); }
.field-hint { display: block; margin-top: 0.35rem; font-size: 0.755rem; color: var(--text-3); line-height: 1.4; }

/* ═══════════════════════════════════════════════════════════════════
   PERSONNALISATION DU WIDGET (onglet de la fiche widget)
   ═══════════════════════════════════════════════════════════════════ */

/* Formulaire à gauche, aperçu qui suit le défilement à droite : on règle et
   on voit le résultat sans quitter des yeux ni l'un ni l'autre. */
.wcfg {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 340px;
  gap: 0.9rem;
  align-items: start;
}
.wcfg-form > .card + .card { margin-top: 0.9rem; }
.wcfg-aside { position: sticky; top: 1.5rem; }
.wcfg-row { display: grid; grid-template-columns: 1fr 1fr; gap: 0.75rem; }
.wcfg-opt { font-weight: 400; color: var(--text-3); }

/* Sélecteur de couleur : la pastille native, la valeur en clair à côté —
   sans elle on ne peut pas relire ni recopier une couleur de marque. */
.wcfg-color { display: flex; align-items: center; gap: 0.6rem; }
.wcfg-color input[type="color"] {
  width: 46px;
  height: 46px;
  padding: 4px;
  border: none;
  border-radius: 12px;
  background: var(--surface-2);
  cursor: pointer;
}
.wcfg-color input[type="color"]::-webkit-color-swatch-wrapper { padding: 0; }
.wcfg-color input[type="color"]::-webkit-color-swatch { border: none; border-radius: 8px; }
.wcfg-hex {
  font-size: 0.85rem;
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
  text-transform: uppercase;
}

.wcfg-delay { display: flex; align-items: center; gap: 0.6rem; }
.wcfg-delay input { width: 100px; }
.wcfg-unit { font-size: 0.85rem; color: var(--text-2); }

/* Barre d'enregistrement : le message vit à gauche des boutons, il ne
   déplace donc jamais la mise en page en apparaissant. */
.wcfg-save {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.6rem;
  margin-top: 0.9rem;
  flex-wrap: wrap;
}
.wcfg-msg { margin-right: auto; font-size: 0.82rem; color: var(--text-2); }
.wcfg-msg.ok { color: var(--success); }
.wcfg-msg.err { color: var(--danger); }
.wcfg-msg.warn { color: var(--warn); }

/* ── Bascule illustrée ───────────────────────────────────────────── */
/* Un cran au-dessus du contrôle segmenté ordinaire, pour les deux réglages
   qui décrivent un RENDU : un pictogramme montre le coin de l'écran ou le
   soleil/la lune plus vite qu'un libellé, et le pouce glisse d'une option à
   l'autre au lieu de sauter. Sa position et sa largeur viennent du JS (les
   libellés n'ont pas la même longueur) — d'où `--x` et `--w`. */
.wtoggle {
  position: relative;
  display: inline-flex;
  gap: 2px;
  padding: 3px;
  background: var(--surface-2);
  border-radius: 12px;
  max-width: 100%;
}
.wtoggle::before {
  content: "";
  position: absolute;
  top: 3px;
  bottom: 3px;
  left: 0;
  width: var(--w, 0);
  transform: translateX(var(--x, 0));
  border-radius: 9px;
  background: var(--thumb);
  box-shadow: var(--shadow-thumb);
  /* Tant que le JS n'a pas mesuré (vue encore masquée), pas de pouce plutôt
     qu'un pouce de travers. */
  opacity: 0;
  transition: transform 0.3s cubic-bezier(0.32, 0.72, 0, 1),
              width 0.3s cubic-bezier(0.32, 0.72, 0, 1),
              opacity 0.2s;
}
.wtoggle.ready::before { opacity: 1; }

.wtoggle button {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  min-width: 0;
  padding: 0.42rem 0.85rem;
  border: none;
  background: none;
  border-radius: 9px;
  font-family: inherit;
  font-size: 0.845rem;
  font-weight: 500;
  color: var(--text-2);
  cursor: pointer;
  white-space: nowrap;
  transition: color 0.2s, transform 0.1s;
}
.wtoggle button svg { width: 16px; height: 16px; flex-shrink: 0; transition: color 0.2s, transform 0.3s; }
.wtoggle button span { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.wtoggle button:hover { color: var(--text); }
.wtoggle button:active { transform: scale(0.97); }
.wtoggle button:focus { outline: none; }
.wtoggle button:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* Option retenue : le texte passe à la couleur d'accent, le pictogramme aussi.
   Contraste franc avec l'option au repos, qui reste lisible (--text-2) au lieu
   du gris pâle du contrôle segmenté. */
.wtoggle button.active { color: var(--accent); font-weight: 600; }
.wtoggle button.active svg { color: var(--accent); }
/* La lune se lève quand on choisit le sombre : le seul mouvement de la paire,
   assez discret pour ne pas distraire. */
.wtoggle button.active [data-icon="moon"] svg { transform: rotate(-18deg); }

@media (prefers-reduced-motion: reduce) {
  .wtoggle::before,
  .wtoggle button svg { transition: none; }
}

/* Étroit : les deux options se partagent la largeur plutôt que de déborder. */
@media (max-width: 560px) {
  .wtoggle { display: flex; width: 100%; }
  .wtoggle button { flex: 1 1 0; }
}

/* ═══════════════════════════════════════════════════════════════════
   GLOBE — vue « Globe » de l'analyse de données
   ═══════════════════════════════════════════════════════════════════ */

/* Colonne de chiffres à gauche, globe à droite qui prend toute la place
   restante : c'est lui le sujet, la colonne l'accompagne. */
.globe-layout {
  display: grid;
  grid-template-columns: 320px minmax(0, 1fr);
  gap: 0.9rem;
  /* Le globe s'aligne sur la colonne de gauche plutôt que de garder une
     hauteur fixe : quand la liste « Visites par emplacement » s'allonge
     (plus de villes), les deux colonnes finissent au même niveau. */
  align-items: stretch;
}
.globe-rail { display: flex; flex-direction: column; gap: 0.9rem; }
/* Les tuiles s'empilent : la colonne est trop étroite pour une grille. */
.globe-rail .globe-kpis { display: grid; grid-template-columns: 1fr 1fr; gap: 0.6rem; }
.globe-rail .globe-kpis .tile { padding: 0.8rem 0.85rem 0.9rem; }
.globe-rail .globe-kpis .tile-value { font-size: 1.4rem; }

.globe-card {
  position: relative;
  overflow: hidden;
  /* Hauteur pilotée par le grid stretch ci-dessus (= celle de la colonne de
     gauche). Les bornes ne servent qu'aux cas extrêmes : un rail très court
     ne doit pas écraser le globe, un rail très long ne doit pas le pousser
     hors de l'écran. */
  min-height: 460px;
  max-height: calc(100vh - 160px);
  display: flex;
  flex-direction: column;
  /* Pas de carte ici : le globe flotte directement sur la page — c'est lui
     l'objet, un cadre autour n'aurait fait que le rapetisser visuellement.
     Le fond « mer » du globe (dessiné par le canevas) joue déjà ce rôle. */
  background: none;
  border: none;
  box-shadow: none;
  border-radius: 0;
}
/* L'analyse de données porte `body.dashboard-view`, dont la règle
   `.dashboard-view .card` (plus spécifique que `.globe-card`, déclarée plus
   bas) venait de lui refaire un cadre blanc. On ré-ancre le sans-cadre avec
   un composé `.card.globe-card` qui la bat, quel que soit l'ordre. */
.dashboard-view .card.globe-card {
  background: none;
  border: none;
  box-shadow: none;
  border-radius: 0;
}
.globe-stage {
  position: relative;
  flex: 1;
  min-height: 0;
  /* Teintes du globe, lues par le canevas : elles suivent donc le thème du
     portail sans que le JS ait à connaître la palette.
     Le globe est en gris — mer claire, terres un ton plus soutenu — pour que
     la couleur d'accent ne serve qu'à une chose : signaler les pays d'où
     viennent des visiteurs. */
  --gl-sea-light: #f6f7f9;
  --gl-sea: #e8eaef;
  --gl-land: #b4bac6;
  --gl-active: var(--accent);
  opacity: 0;
  transition: opacity 0.5s;
}
.globe-stage.ready { opacity: 1; }
:root[data-theme="dark"] .globe-stage {
  --gl-sea-light: #2a2e37;
  --gl-sea: #1e222a;
  --gl-land: #5a616e;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .globe-stage {
    --gl-sea-light: #2a2e37;
    --gl-sea: #1e222a;
    --gl-land: #5a616e;
  }
}

.gl-canvas { display: block; width: 100%; height: 100%; cursor: grab; touch-action: none; }
.globe-stage.dragging .gl-canvas { cursor: grabbing; }
.globe-stage.pointing .gl-canvas { cursor: pointer; }

/* Infobulle ancrée au point survolé, jamais au curseur : elle ne tremble pas
   quand la main bouge de quelques pixels sur une cible immobile. */
.gl-tip {
  position: absolute;
  transform: translate(-50%, calc(-100% - 14px));
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 7px 11px;
  border-radius: 12px;
  background: var(--wm-pin, #241d4d);
  border: 1px solid rgba(255, 255, 255, 0.1);
  color: #fff;
  white-space: nowrap;
  box-shadow: 0 12px 28px rgba(12, 8, 32, 0.34);
  pointer-events: none;
  z-index: 3;
}
.gl-tip[hidden] { display: none; }
.gl-tip.below { transform: translate(-50%, 14px); }
.gl-tip.flip { transform: translate(-88%, calc(-100% - 14px)); }
.gl-tip.below.flip { transform: translate(-88%, 14px); }
.gl-tip-title { font-size: 0.82rem; font-weight: 600; }
.gl-tip-sub { font-size: 0.68rem; color: rgba(255, 255, 255, 0.66); }
.gl-tip-sub:empty { display: none; }
.gl-tip-val { font-size: 0.72rem; color: rgba(255, 255, 255, 0.9); margin-top: 2px; }

.gl-hint {
  position: absolute;
  left: 50%;
  bottom: 0.5rem;
  transform: translateX(-50%);
  font-size: 0.73rem;
  color: var(--text-3);
  pointer-events: none;
  transition: opacity 0.25s;
}
.globe-stage.dragging .gl-hint, .globe-stage.pointing .gl-hint { opacity: 0; }
.gl-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  font-size: 0.85rem;
  color: var(--text-3);
}

.globe-legend {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0 1.2rem 0.95rem;
  font-size: 0.76rem;
  color: var(--text-3);
  flex-shrink: 0;
}
.globe-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 4px var(--accent-softer);
  flex-shrink: 0;
}

/* Sous 1100 px, le globe passe sous la colonne : côte à côte, aucun des deux
   n'aurait la place de se lire. */
@media (max-width: 1100px) {
  .globe-layout { grid-template-columns: minmax(0, 1fr); align-items: stretch; }
  .globe-card { min-height: clamp(400px, 70vh, 620px); max-height: 620px; }
}

/* Sur papier, un globe qu'on ne peut pas tourner n'a pas d'intérêt. */
@media print {
  .globe-layout { display: block; }
  .globe-card { display: none; }
}

/* Le fil d'activité occupe la largeur : il n'a pas de voisin, et une carte à
   moitié vide sur la droite lirait comme un bloc manquant. */
.grid-feed { grid-template-columns: minmax(0, 1fr); }

/* ── Qualité des réponses (migration 018) ────────────────────────── */
/* Un chiffre, une barre, deux comptes. Pas de note sur cinq : le visiteur a
   cliqué un pouce, on ne lui invente pas une moyenne. */
.qual { display: flex; flex-direction: column; gap: 0.4rem; padding: 0.4rem 0 0.2rem; }
.qual-score {
  font-size: 2.1rem;
  font-weight: 700;
  letter-spacing: -0.03em;
  line-height: 1;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.qual-sub { font-size: 0.82rem; color: var(--text-2); }
.qual-bar {
  height: 8px;
  border-radius: 980px;
  background: var(--danger-soft);
  overflow: hidden;
  margin-top: 0.35rem;
}
.qual-bar span { display: block; height: 100%; background: var(--success); border-radius: 980px; }
.qual-legend { display: flex; gap: 0.9rem; font-size: 0.76rem; margin-top: 0.15rem; }
.qual-up { color: var(--success); font-weight: 600; }
.qual-down { color: var(--text-3); }

/* ── Période : la date, et les boutons au survol ─────────────────── */
/* Ce qu'on lit tout le temps, c'est la plage analysée ; ce qu'on touche une
   fois par semaine, c'est le sélecteur. L'un occupe donc la place, l'autre
   vient par-dessus au survol — même encombrement, deux états. */
.period {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: flex-end;
  min-width: 178px;
  height: 34px;
}
.period-label {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  height: 34px;
  padding: 0 0.85rem;
  border: none;
  border-radius: 980px;
  background: var(--surface-2);
  color: var(--text-2);
  font-family: inherit;
  font-size: 0.83rem;
  font-weight: 500;
  white-space: nowrap;
  cursor: pointer;
  transition: opacity 0.16s, background 0.16s;
}
.period-label:hover { background: var(--surface-3); }
.period-label svg { width: 14px; height: 14px; color: var(--text-3); }
.period .segmented {
  position: absolute;
  right: 0;
  top: 0;
  opacity: 0;
  transform: scale(0.97);
  transform-origin: right center;
  pointer-events: none;
  transition: opacity 0.16s, transform 0.16s;
}
/* `:focus-within` fait le clavier, `.open` le tactile — où le survol n'existe
   pas et où la commande resterait sinon inatteignable. */
.period:hover .period-label,
.period:focus-within .period-label,
.period.open .period-label { opacity: 0; }
.period:hover .segmented,
.period:focus-within .segmented,
.period.open .segmented {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}
@media (prefers-reduced-motion: reduce) {
  .period-label, .period .segmented { transition: none; }
}
/* À l'impression, la commande n'a pas lieu d'être : seule la plage reste. */
@media print {
  .period .segmented { display: none; }
  .period-label { opacity: 1 !important; background: none; padding-left: 0; }
}

/* ── Mode présentation ───────────────────────────────────────────── */
/* Montrer ses chiffres en réunion, sans la coque de l'application. Rien n'est
   masqué à l'impression qui ne le soit ici : c'est le même travail de tri,
   fait une fois pour le papier et repris pour l'écran. */
:root[data-present] .sidebar,
:root[data-present] .side-backdrop,
:root[data-present] .topbar,
:root[data-present] .footer,
:root[data-present] .toolbar { display: none; }
:root[data-present] .app { grid-template-columns: minmax(0, 1fr); }
:root[data-present] .page { padding: 2.2rem 3vw 3rem; max-width: none; }
:root[data-present] .page-head h1 { font-size: clamp(2rem, 3.4vw, 2.9rem); }
/* Les chiffres grossissent, le reste ne bouge pas : c'est la lecture à trois
   mètres qu'on vise, pas une maquette différente. */
:root[data-present] .kpi { min-height: 7.4rem; }
:root[data-present] .kpi-value { font-size: 2.2rem; }
:root[data-present] .kpi-label { font-size: 1.12rem; }
:root[data-present] .stat-value { font-size: 2.6rem; }
:root[data-present] .chart-total { font-size: 2.6rem; }

.present-btn { display: inline-flex; align-items: center; gap: 0.35rem; }
.present-btn svg { width: 14px; height: 14px; }

.present-exit {
  position: fixed;
  top: 1rem;
  right: 1rem;
  z-index: 260;
  display: none;
  align-items: center;
  gap: 0.45rem;
  padding: 0.45rem 0.9rem;
  border: none;
  border-radius: 980px;
  background: var(--material);
  backdrop-filter: saturate(180%) blur(30px);
  -webkit-backdrop-filter: saturate(180%) blur(30px);
  box-shadow: var(--shadow-pop);
  color: var(--text-2);
  font-family: inherit;
  font-size: 0.82rem;
  cursor: pointer;
}
:root[data-present] .present-exit { display: inline-flex; }
.present-exit kbd {
  font-family: inherit;
  font-size: 0.68rem;
  border: 1px solid var(--separator);
  border-radius: 5px;
  padding: 0.05rem 0.3rem;
}
@media print {
  .present-exit { display: none !important; }
}

/* ── Palette de recherche (⌘K) ───────────────────────────────────── */
/* Une fenêtre posée haut dans l'écran, pas au centre : on la lit en gardant
   la page derrière en vue, et le regard n'a pas à redescendre après la
   frappe. */
.pal-overlay {
  position: fixed;
  inset: 0;
  z-index: 300;
  background: rgba(0, 0, 0, 0.32);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 11vh 1rem 1rem;
}
.pal {
  width: 100%;
  max-width: 620px;
  background: var(--surface);
  border-radius: 18px;
  box-shadow: var(--shadow-pop);
  overflow: hidden;
  animation: sheet-in 0.22s cubic-bezier(0.32, 0.72, 0, 1);
}
.pal-head {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  padding: 0.85rem 1rem;
  border-bottom: 1px solid var(--separator);
  color: var(--text-3);
}
.pal-head svg { width: 17px; height: 17px; flex-shrink: 0; }
.pal-input {
  flex: 1;
  border: none;
  background: none;
  font-family: inherit;
  font-size: 1rem;
  color: var(--text);
  outline: none;
}
.pal-esc {
  font-size: 0.68rem;
  font-family: inherit;
  color: var(--text-3);
  border: 1px solid var(--separator);
  border-radius: 6px;
  padding: 0.1rem 0.35rem;
}
.pal-body { max-height: 58vh; overflow-y: auto; padding-bottom: 0.4rem; }
.pal-group {
  padding: 0.7rem 1rem 0.3rem;
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-3);
}
.pal-item {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.55rem 1rem;
  text-decoration: none;
  color: inherit;
}
/* `.on` et non `:hover` seul : la sélection suit aussi les flèches du
   clavier, et les deux doivent se voir de la même façon. */
.pal-item:hover, .pal-item.on { background: var(--accent-softer); }
.pal-ico {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  flex-shrink: 0;
  border-radius: 8px;
  background: var(--surface-2);
  color: var(--text-2);
}
.pal-ico svg { width: 14px; height: 14px; }
.pal-txt { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.pal-title {
  font-size: 0.87rem;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.pal-sub { font-size: 0.74rem; color: var(--text-3); }
.pal-when { font-size: 0.72rem; color: var(--text-3); white-space: nowrap; }
.pal-hint { padding: 1.3rem 1rem; font-size: 0.83rem; color: var(--text-3); text-align: center; }

/* ── Fil d'activité (tableau de bord) ────────────────────────────── */
/* Volontairement sans cadre autour de chaque ligne : c'est une liste qu'on
   parcourt, pas une série d'objets. Le seul relief est la pastille de
   gauche, et elle n'est pleine que pour un contact laissé — le seul des deux
   événements qui appelle une action. */
.feed { list-style: none; display: flex; flex-direction: column; }
.feed-row a {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.6rem 0.2rem;
  border-bottom: 1px solid var(--separator);
  text-decoration: none;
  color: inherit;
}
.feed-row:last-child a { border-bottom: none; }
.feed-row a:hover .feed-title { color: var(--accent); }
.feed-dot {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  flex-shrink: 0;
  border-radius: 50%;
  background: var(--surface-2);
  color: var(--text-3);
}
.feed-dot.lead { background: var(--accent); color: #fff; }
.feed-dot svg { width: 14px; height: 14px; }
.feed-txt { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.feed-title {
  font-size: 0.87rem;
  font-weight: 500;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  transition: color 0.15s;
}
.feed-sub { font-size: 0.74rem; color: var(--text-3); }
.feed-when { font-size: 0.74rem; color: var(--text-3); white-space: nowrap; flex-shrink: 0; }

/* ── Cloche : panneau des alertes ────────────────────────────────── */
.bell-menu { min-width: 330px; max-width: 92vw; }
.bell-item {
  display: flex;
  align-items: flex-start;
  gap: 0.65rem;
  padding: 0.7rem 0.9rem;
  border-bottom: 1px solid var(--separator);
  text-decoration: none;
  color: inherit;
}
.bell-item:last-child { border-bottom: none; }
.bell-item:hover { background: var(--surface-2); }
/* Non lue : un liseré, pas un fond coloré — la liste reste lisible quand
   tout est neuf, ce qui est le cas le plus fréquent. */
.bell-item.fresh { box-shadow: inset 2px 0 0 var(--accent); }
.bell-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  flex-shrink: 0;
  border-radius: 9px;
  background: var(--accent-soft);
  color: var(--accent);
}
.bell-icon svg { width: 15px; height: 15px; }
.bell-txt { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.bell-title { font-size: 0.85rem; font-weight: 600; color: var(--text); }
.bell-sub {
  font-size: 0.76rem;
  color: var(--text-2);
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
.bell-when { font-size: 0.7rem; color: var(--text-3); white-space: nowrap; flex-shrink: 0; }
.bell-empty { padding: 1.1rem 0.95rem; font-size: 0.8rem; color: var(--text-3); }

/* Colonne e-mail : bornée et coupée proprement. Une adresse longue ne doit pas
   écraser les colonnes voisines — et la date, elle, ne se coupe jamais en
   trois lignes. */
.cell-mail { max-width: 220px; }
.cell-mail a {
  display: inline-block;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  vertical-align: bottom;
}
.cell-date { white-space: nowrap; }

/* ── Relance d'un lead (migration 016) ───────────────────────────── */
/* Dans la fiche : une date à côté du statut. Le statut dit quoi faire, la
   date dit quand — les deux se lisent sur la même ligne. */
.lead-relance {
  flex: 1;
  min-width: 0;
  padding: 0.34rem 0.6rem;
  border: 1px solid var(--card-line);
  border-radius: 9px;
  background: var(--surface-2);
  color: var(--text);
  font-family: inherit;
  font-size: 0.83rem;
}
.lead-relance:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
.lead-relance-clear {
  border: none;
  background: none;
  color: var(--text-3);
  font: inherit;
  font-size: 0.76rem;
  cursor: pointer;
  padding: 0.2rem 0.3rem;
}
.lead-relance-clear:hover { color: var(--danger); }

/* Dans la liste : une pastille près du nom. C'est la seule information du
   tableau qui réclame une action aujourd'hui — elle se voit sans lire la
   ligne, et vire au rouge quand la date est passée. */
.lead-relance-chip {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  margin-left: 0.45rem;
  padding: 0.1rem 0.42rem 0.1rem 0.3rem;
  border-radius: 980px;
  font-size: 0.7rem;
  font-weight: 600;
  white-space: nowrap;
  background: var(--surface-3);
  color: var(--text-2);
}
.lead-relance-chip svg { width: 11px; height: 11px; }
.lead-relance-chip.now { background: var(--warn-soft); color: var(--warn); }
.lead-relance-chip.late { background: var(--danger-soft); color: var(--danger); }

/* ── Intégrations ────────────────────────────────────────────────── */
/* Une carte par connecteur, en colonne large : les logos identifient les
   services, puis le texte explique ce qu'ils font concrètement. */
.int-family { margin-bottom: 1.6rem; }
.int-family-head { margin: 0 0.2rem 0.7rem; }
.int-family-head h2 {
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--text-3);
}
.int-family-head .sub { display: block; margin-top: 0.15rem; }
.int-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(420px, 1fr)); gap: 0.7rem; }

.int {
  display: flex;
  align-items: flex-start;
  gap: 0.85rem;
  padding: 1rem 1.1rem;
  background: var(--card-bg, var(--surface));
  border: 1px solid var(--card-line);
  border-radius: 16px;
  transition: border-color 0.16s, transform 0.16s;
}
.int:hover { transform: translateY(-1px); }
/* Branchée : un liseré à gauche, pas un fond vert. La carte reste lisible, et
   l'œil repère les connecteurs actifs en balayant la colonne. */
.int.on { box-shadow: inset 3px 0 0 var(--success); }
.int.soon { opacity: 0.72; }
.int-glyph {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  flex-shrink: 0;
  border-radius: 11px;
  background: var(--accent-soft);
  color: var(--accent);
}
.int-glyph svg { width: 18px; height: 18px; }
.int-logos {
  display: flex;
  align-items: center;
  min-width: 38px;
  padding-right: 0.2rem;
  flex-shrink: 0;
}
.int-logo {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  margin-right: -9px;
  border: 1px solid var(--card-line);
  border-radius: 11px;
  background: #fff;
  box-shadow: 0 2px 7px rgba(15, 23, 42, 0.08);
}
.int-logo:last-child { margin-right: 0; }
.int-logo img {
  display: block;
  width: 21px;
  height: 21px;
  object-fit: contain;
}
.int-txt { flex: 1; min-width: 0; }
.int-name {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--text);
}
.int-tagline { font-size: 0.84rem; font-weight: 500; color: var(--accent); margin-top: 1px; }
.int-desc { font-size: 0.81rem; color: var(--text-2); line-height: 1.5; margin-top: 0.35rem; }
.int-requires { font-size: 0.76rem; color: var(--text-3); margin-top: 0.35rem; font-style: italic; }
.int-cta { flex-shrink: 0; padding-top: 0.15rem; }
.int-soon { font-size: 0.76rem; color: var(--text-3); white-space: nowrap; }

.int-pill {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-size: 0.68rem;
  font-weight: 600;
  padding: 0.12rem 0.5rem;
  border-radius: 980px;
  background: var(--surface-3);
  color: var(--text-2);
}
.int-pill svg { width: 10px; height: 10px; }
.int-pill.on { background: var(--success-soft); color: var(--success); }
.int-pill.off { background: var(--warn-soft); color: var(--warn); }
.int-pill.soft { background: var(--surface-2); color: var(--text-3); }

/* Fenêtre de configuration */
.int-card { max-width: 520px; }
.int-modal-desc { font-size: 0.84rem; color: var(--text-2); line-height: 1.5; margin-bottom: 0.4rem; }
.int-actions { display: flex; align-items: center; gap: 0.5rem; margin-top: 0.6rem; }
.int-spacer { flex: 1; }

/* Journal des envois */
.int-log { list-style: none; display: flex; flex-direction: column; }
.int-log-row {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.5rem 0.1rem;
  border-bottom: 1px solid var(--separator);
  font-size: 0.81rem;
}
.int-log-row:last-child { border-bottom: none; }
.int-log-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex-shrink: 0;
  background: var(--success);
}
.int-log-row.ko .int-log-dot { background: var(--danger); }
.int-log-name { font-weight: 600; color: var(--text); }
.int-log-event { font-size: 0.72rem; color: var(--text-3); }
.int-log-detail {
  flex: 1;
  min-width: 0;
  color: var(--text-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.int-log-when { color: var(--text-3); white-space: nowrap; font-size: 0.75rem; }

@media (max-width: 720px) {
  .int-grid { grid-template-columns: minmax(0, 1fr); }
  .int { flex-wrap: wrap; }
  .int-logos { min-width: 38px; }
  .int-cta { width: 100%; }
}

/* ── Aide & support : demandes d'assistance ──────────────────────── */
/* Le formulaire à gauche, le fil des demandes à droite. Ouvrir une demande est
   l'action principale de la page : elle reste visible pendant qu'on relit ce
   qu'on a déjà envoyé. */
.tk-layout {
  display: grid;
  grid-template-columns: 380px minmax(0, 1fr);
  gap: 0.9rem;
  align-items: start;
}
.tk-form { position: sticky; top: 0.9rem; }
.tk-send { display: flex; align-items: center; gap: 0.7rem; margin-top: 0.4rem; }
.tk-list-col { display: flex; flex-direction: column; gap: 0.6rem; min-width: 0; }
.tk-list-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.2rem 0.2rem 0.1rem;
}
.tk-list-head h3 { font-size: 0.95rem; font-weight: 600; }

/* Une demande = une carte dépliable. Fermée, elle tient sur une ligne : objet,
   date, état. Ouverte, elle devient le fil complet. */
.tk-card { overflow: hidden; }
.tk-head {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  width: 100%;
  padding: 0.85rem 1rem;
  background: none;
  border: none;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}
.tk-head:hover { background: var(--surface-2); }
.tk-head-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.tk-subject {
  font-size: 0.92rem;
  font-weight: 600;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tk-meta { font-size: 0.76rem; color: var(--text-3); }
.tk-chevron { display: inline-flex; color: var(--text-3); transition: transform 0.18s; }
.tk-chevron svg { width: 16px; height: 16px; transform: rotate(90deg); }
.tk-card.open .tk-chevron { transform: rotate(180deg); }

.tk-status {
  flex-shrink: 0;
  font-size: 0.72rem;
  font-weight: 600;
  padding: 0.16rem 0.55rem;
  border-radius: 980px;
}
.tk-accent { background: var(--accent-soft); color: var(--accent); }
.tk-warn { background: var(--warn-soft); color: var(--warn); }
.tk-success { background: var(--success-soft); color: var(--success); }
.tk-neutral { background: var(--surface-3); color: var(--text-2); }

/* Le fil n'est pas masqué par `hidden` mais par une hauteur nulle : la carte
   s'ouvre et se ferme d'un mouvement, sans saut. */
.tk-body {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.24s cubic-bezier(0.32, 0.72, 0, 1);
}
.tk-card.open .tk-body { grid-template-rows: 1fr; }
/* `min-height: 0` autant qu'`overflow` : sans lui, le contenu impose sa
   hauteur minimale et la rangée ne retombe jamais à zéro. */
.tk-inner { overflow: hidden; min-height: 0; }
.tk-card.open .tk-body {
  border-top: 1px solid var(--separator);
}

.tk-msg { padding: 0.85rem 1rem; border-bottom: 1px solid var(--separator); }
.tk-msg:last-of-type { border-bottom: none; }
/* La réponse de Haria se distingue par un liseré, pas par une bulle : c'est un
   courrier, pas une messagerie instantanée. */
.tk-msg.haria { background: var(--accent-softer); box-shadow: inset 3px 0 0 var(--accent); }
.tk-msg-who {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--text-2);
  margin-bottom: 0.25rem;
}
.tk-msg-when { font-size: 0.72rem; font-weight: 400; color: var(--text-3); }
.tk-msg-body { font-size: 0.88rem; color: var(--text); white-space: pre-wrap; line-height: 1.5; }

.tk-reply { display: flex; gap: 0.5rem; align-items: flex-end; padding: 0.8rem 1rem 0.9rem; }
/* Hors d'un `.field`, un textarea reprend la police du navigateur (du
   monospace) : on lui redonne celle du portail. */
.tk-reply textarea {
  flex: 1;
  resize: vertical;
  min-height: 62px;
  padding: 0.6rem 0.8rem;
  border: none;
  border-radius: 12px;
  background: var(--surface-2);
  color: var(--text);
  font-family: inherit;
  font-size: 0.88rem;
  line-height: 1.45;
}
.tk-reply textarea:focus { outline: 2px solid var(--accent); outline-offset: 1px; }

@media (max-width: 1000px) {
  .tk-layout { grid-template-columns: minmax(0, 1fr); }
  .tk-form { position: static; }
}

/* ── Confirmation flottante ──────────────────────────────────────── */
.toast-host {
  position: fixed;
  left: 50%;
  bottom: 22px;
  transform: translateX(-50%);
  z-index: 9999;
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: center;
  pointer-events: none;
}
.toast {
  padding: 9px 16px;
  border-radius: 980px;
  background: var(--wm-pin, #241d4d);
  color: #fff;
  font-size: 0.82rem;
  font-weight: 500;
  white-space: nowrap;
  box-shadow: 0 10px 26px rgba(12, 8, 32, 0.28);
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 0.2s, transform 0.2s;
}
.toast.show { opacity: 1; transform: none; }
.toast.err { background: var(--danger); }
@media (prefers-reduced-motion: reduce) { .toast { transition: opacity 0.2s; } }

/* ── Suivi commercial des leads (statut, note) ───────────────────── */
/* Le statut se lit comme une pastille colorée fermée, et redevient un menu
   déroulant ordinaire à l'usage — pas de composant sur mesure à maintenir. */
.lead-status {
  appearance: none;
  -webkit-appearance: none;
  border: 1px solid transparent;
  border-radius: 980px;
  padding: 0.32rem 1.7rem 0.32rem 0.75rem;
  font-family: inherit;
  font-size: 0.78rem;
  font-weight: 600;
  cursor: pointer;
  background-color: var(--surface-2);
  color: var(--text-2);
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='11' height='11' fill='none' stroke='%23888' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round' viewBox='0 0 24 24'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.6rem center;
  background-size: 10px;
  transition: background-color 0.15s, color 0.15s;
}
.lead-status:disabled { opacity: 0.55; cursor: default; }
.lead-status:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.lead-status[data-tone="accent"] { background-color: var(--accent-soft); color: var(--accent); }
.lead-status[data-tone="success"] { background-color: var(--success-soft); color: var(--success); }
.lead-status[data-tone="warn"] { background-color: var(--warn-soft); color: var(--warn); }
.lead-status[data-tone="danger"] { background-color: var(--danger-soft); color: var(--danger); }
/* Dans le tableau : plus compacte, elle partage la ligne avec le nom. */
.lead-status.sm { padding: 0.24rem 1.5rem 0.24rem 0.6rem; font-size: 0.74rem; }

/* Bloc « Suivi commercial » de la fiche : même esprit que les autres cartes
   de réglage du portail (fond, libellé, zone de sauvegarde). */
.lead-crm {
  padding: 0.9rem 1rem 1rem;
  margin: 0 0 0.9rem;
  border-radius: 14px;
  background: var(--surface-2);
}
.lead-crm-row { display: flex; align-items: center; justify-content: space-between; gap: 0.6rem; margin-bottom: 0.7rem; }
.lead-crm-label { font-size: 0.78rem; font-weight: 600; color: var(--text-2); }
.lead-crm textarea {
  width: 100%;
  min-height: 64px;
  padding: 0.55rem 0.7rem;
  border: none;
  border-radius: 10px;
  background: var(--card-bg);
  color: var(--text);
  font-family: inherit;
  font-size: 0.85rem;
  line-height: 1.45;
  resize: vertical;
}
.lead-crm textarea::placeholder { color: var(--text-3); }
.lead-crm textarea:focus { outline: none; box-shadow: 0 0 0 3px var(--ring); }
.lead-crm-save {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.5rem;
  margin-top: 0.5rem;
}
.lead-crm-msg { margin-right: auto; font-size: 0.76rem; color: var(--text-3); }
.lead-crm-msg.err { color: var(--danger); }
.lead-crm-msg.ok { color: var(--success); }
/* Migration non appliquée côté base : on explique plutôt que de masquer. */
.lead-crm.disabled textarea, .lead-crm.disabled select { pointer-events: none; opacity: 0.6; }

/* ── Choix du style ──────────────────────────────────────────────── */
/* Trois vignettes plutôt qu'une liste déroulante : un style se choisit à
   l'œil. Chaque vignette dessine en CSS pur la silhouette de son rendu —
   rayons, relief, en-tête — sans image à charger. */
.wcfg-styles { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.6rem; }
.wstyle {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.3rem;
  padding: 0.75rem;
  border: 1.5px solid var(--card-line);
  border-radius: 14px;
  background: var(--surface-2);
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  transition: border-color 0.16s, background 0.16s, transform 0.1s;
}
.wstyle:hover { border-color: var(--accent); }
.wstyle:active { transform: scale(0.98); }
.wstyle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.wstyle.active { border-color: var(--accent); background: var(--accent-softer); }
.wstyle-name { font-size: 0.86rem; font-weight: 600; color: var(--text); }
.wstyle-desc { font-size: 0.74rem; line-height: 1.35; color: var(--text-3); }

/* Silhouette : un rectangle blanc surmonté d'une barre de couleur, décliné
   selon le style. C'est ce qui distingue les trois d'un coup d'œil. */
.wstyle-art {
  width: 100%;
  height: 46px;
  margin-bottom: 0.25rem;
  background: #fff;
  border-top: 13px solid var(--accent);
  border-radius: 9px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
/* Épuré : pas de bandeau coloré, un simple filet sous le titre. */
.wstyle-art.epure {
  border-top: none;
  border-radius: 4px;
  box-shadow: none;
  border: 1px solid var(--card-line);
  background:
    linear-gradient(var(--card-line), var(--card-line)) 0 13px / 100% 1px no-repeat,
    linear-gradient(var(--text-3), var(--text-3)) 6px 6px / 40% 3px no-repeat,
    #fff;
}
/* Immersif : bandeau haut en dégradé avec la pastille de profil au centre. */
.wstyle-art.immersif {
  border-radius: 16px;
  border-top: none;
  background:
    radial-gradient(circle at 50% 11px, #fff 0 5px, transparent 5px),
    linear-gradient(150deg, var(--accent) 0%, var(--accent-deep) 100%) top / 100% 26px no-repeat,
    #fff;
  box-shadow: 0 5px 16px rgba(0, 0, 0, 0.16);
}

/* ── Sélecteurs d'image ──────────────────────────────────────────── */
/* La vignette EST le champ : on voit ce qui est en place, et les deux actions
   possibles tiennent à côté. L'input[type=file] reste caché — il n'est pas
   stylable proprement et son libellé natif n'est pas traduisible. */
.wimg { display: flex; align-items: center; gap: 0.7rem; }
.wimg-thumb {
  width: 56px;
  height: 56px;
  flex-shrink: 0;
  border-radius: 12px;
  background: var(--surface-2) center / cover no-repeat;
  border: 1px solid var(--card-line);
}
.wimg-thumb.round { border-radius: 50%; background-size: 62%; }
/* Vide : une trame discrète plutôt qu'un carré gris, pour qu'on comprenne
   qu'il manque quelque chose sans que ça ressemble à une image cassée. */
.wimg-thumb[data-empty="1"] {
  background-image: repeating-linear-gradient(
    45deg, var(--separator) 0 1px, transparent 1px 7px
  );
  background-size: auto;
}
.wimg-side { display: flex; flex-direction: column; gap: 0.35rem; align-items: flex-start; }

/* ── Bibliothèque d'icônes ───────────────────────────────────────── */
/* Sous chaque sélecteur d'image : de quoi habiller le widget sans avoir de
   fichier sous la main. Les icônes sont dessinées aux couleurs du client,
   elles se lisent donc comme un aperçu et pas comme un catalogue. */
.wart-label {
  display: block;
  margin: 0.75rem 0 0.45rem;
  font-size: 0.76rem;
  color: var(--text-3);
}
/* Cinq icônes tiennent sur une ligne dans une colonne de formulaire : au-delà
   elles passent à la ligne et la section double de hauteur pour rien. */
.wart { display: flex; flex-wrap: wrap; gap: 0.45rem; }
.wart-item {
  width: 40px;
  height: 40px;
  padding: 0;
  border-radius: 50%;
  border: 2px solid transparent;
  background: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: transform 0.14s, border-color 0.14s;
}
.wart-item svg { width: 34px; height: 34px; border-radius: 50%; display: block; }
.wart-item:hover { transform: translateY(-2px); }
/* Sélectionnée : un anneau, pas un fond — l'icône elle-même porte déjà la
   couleur de marque, un aplat de plus la rendrait illisible. */
.wart-item.active { border-color: var(--accent); }
.wart-item:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ── Fenêtre de cadrage ──────────────────────────────────────────── */
.crop-card { max-width: 360px; }
.crop-card .modal-body { gap: 0.9rem; align-items: stretch; }
/* Le cadre montre EXACTEMENT ce que le widget affichera : ce qui déborde est
   coupé ici comme là-bas. La trame en damier se voit à travers les logos
   transparents — sans elle, on ne distingue pas le vide du blanc. */
.crop-stage {
  position: relative;
  width: 100%;
  aspect-ratio: 1;
  align-self: center;
  max-width: 260px;
  border-radius: 18px;
  overflow: hidden;
  cursor: grab;
  touch-action: none;
  background:
    repeating-conic-gradient(var(--surface-2) 0% 25%, var(--surface) 0% 50%) 0 0 / 18px 18px;
  box-shadow: inset 0 0 0 1px var(--card-line);
}
.crop-stage.round { border-radius: 50%; }
.crop-stage.dragging { cursor: grabbing; }
.crop-stage canvas { display: block; width: 100%; height: 100%; }
.crop-zoom { display: flex; align-items: center; gap: 0.6rem; color: var(--text-3); }
.crop-zoom input { flex: 1; accent-color: var(--accent); }
.crop-hint { font-size: 0.76rem; color: var(--text-3); text-align: center; margin: -0.4rem 0 0; }
.crop-actions { display: flex; align-items: center; gap: 0.4rem; }
.crop-spacer { flex: 1; }
/* Le bouton « Appliquer » de l'en-tête sert au tactile (pouce en haut) ;
   celui du bas au clavier et à la souris. Un seul des deux à l'écran. */
@media (min-width: 560px) {
  .crop-card .modal-header .modal-done { display: none; }
}
@media (max-width: 559px) {
  .crop-actions [data-crop="ok"] { display: none; }
}

/* ── Aperçu du widget ────────────────────────────────────────────── */
/* Scène volontairement claire, quel que soit le thème du portail : c'est le
   site du visiteur qu'on simule, pas l'espace client. Les valeurs suivent
   celles de THEMES / STYLES dans public/widget.js — un aperçu qui ne
   correspondrait pas au rendu réel serait pire que pas d'aperçu du tout. */
.wprev {
  position: relative;
  background: #eef0f4;
  border-radius: 16px;
  padding: 1.1rem 1rem 4.4rem;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.65rem;
}
.wprev.left { align-items: flex-start; }

.wprev-panel {
  width: 100%;
  max-width: 286px;
  border-radius: 16px;
  overflow: hidden;
  background: #fff;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.2);
}

/* En-tête : rangée avatar + identité + croix. Le style « immersif » l'empile
   et le centre, « épuré » lui retire son aplat — comme dans le widget. */
.wprev-head {
  position: relative;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0.7rem 0.85rem;
  color: #fff;
  transition: background 0.2s;
}
.wprev-avatar {
  width: 30px;
  height: 30px;
  flex-shrink: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.22) center / cover no-repeat;
}
.wprev-avatar[data-empty="1"]::after {
  content: "";
  display: block;
  width: 100%;
  height: 100%;
  border-radius: inherit;
  background: currentColor;
  opacity: 0.35;
  -webkit-mask: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M20 2H4a2 2 0 0 0-2 2v18l4-4h14a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2z'/%3E%3C/svg%3E") center / 56% no-repeat;
  mask: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M20 2H4a2 2 0 0 0-2 2v18l4-4h14a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2z'/%3E%3C/svg%3E") center / 56% no-repeat;
}
.wprev-id { min-width: 0; flex: 1; }
.wprev-name {
  display: block;
  font-size: 0.84rem;
  font-weight: 600;
  line-height: 1.25;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.wprev-status { display: block; font-size: 0.66rem; opacity: 0.8; }
.wprev-x { font-size: 1rem; opacity: 0.75; line-height: 1; }

.wprev-body {
  background: linear-gradient(180deg, #f8f9fc 0%, #ffffff 100%);
  padding: 0.75rem;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}
.wprev-row { display: flex; align-items: flex-start; gap: 6px; max-width: 88%; }
.wprev-row.user { align-self: flex-end; }
.wprev-msgavatar {
  width: 22px;
  height: 22px;
  flex-shrink: 0;
  border-radius: 50%;
  background: var(--accent) center / cover no-repeat;
}
.wprev-bubble {
  background: #f4f5f7;
  border: 1px solid rgba(0, 0, 0, 0.04);
  border-radius: 15px;
  padding: 0.5rem 0.75rem;
  font-size: 0.76rem;
  line-height: 1.4;
  color: #1d1d1f;
}
/* Couleur posée en JS (celle du client). */
.wprev-bubble.user { border-color: transparent; }

.wprev-chips { display: flex; flex-direction: column; align-items: flex-end; gap: 5px; margin-top: 0.2rem; }
.wprev-chips[hidden] { display: none; }
.wprev-chip {
  border: 1px solid var(--accent);
  border-radius: 13px;
  padding: 0.3rem 0.65rem;
  font-size: 0.7rem;
  background: #fff;
  max-width: 100%;
  word-break: break-word;
}

.wprev-teaser {
  background: #fff;
  color: #1d1d1f;
  border: 1px solid rgba(0, 0, 0, 0.06);
  border-radius: 14px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.14);
  padding: 0.55rem 0.8rem;
  font-size: 0.78rem;
  max-width: 240px;
}
.wprev-teaser[hidden] { display: none; }

/* Barre de saisie factice : elle montre le rayon du champ et la forme du
   bouton d'envoi, deux marqueurs forts du style. */
.wprev-input {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 9px 10px;
  border-top: 1px solid #f0f0f2;
  background: #fff;
}
.wprev-input span {
  flex: 1;
  padding: 7px 12px;
  border: 1px solid #e8e8ee;
  border-radius: 18px;
  background: #f8f9fc;
  font-size: 0.7rem;
  color: #b0b0b8;
}
.wprev-input em { width: 26px; height: 26px; border-radius: 50%; flex-shrink: 0; }

/* Bouton d'action (lien du client) : aperçu au-dessus de la saisie, comme
   dans le widget. La couleur reste posée par le script (couleur du client). */
.wprev-cta {
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0.35rem 0.4rem 0;
  padding: 7px 10px;
  border-radius: 18px;
  font-size: 0.68rem;
  font-weight: 600;
  color: #fff;
}
.wprev-cta::after { content: "\2197"; margin-left: 5px; opacity: 0.75; font-size: 0.9em; }
.wprev-cta[hidden] { display: none; }

/* Le bouton flottant : c'est lui qui matérialise le côté choisi. */
.wprev-launcher {
  position: absolute;
  bottom: 1.1rem;
  right: 1rem;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background-position: center, center;
  background-repeat: no-repeat, no-repeat;
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.24);
  transition: left 0.25s, right 0.25s, border-radius 0.2s;
}
.wprev.left .wprev-launcher { right: auto; left: 1rem; }
.wprev-launcher svg { width: 22px; height: 22px; }
.wprev-caption { margin-top: 0.6rem; font-size: 0.73rem; color: var(--text-3); text-align: center; }

/* ── Aperçu : thème sombre du widget ─────────────────────────────── */
.wprev[data-wtheme="dark"] { background: #2a2b33; }
.wprev[data-wtheme="dark"] .wprev-panel { background: #17181e; box-shadow: 0 12px 32px rgba(0, 0, 0, 0.5); }
.wprev[data-wtheme="dark"] .wprev-body { background: linear-gradient(180deg, #131418 0%, #17181e 100%); }
.wprev[data-wtheme="dark"] .wprev-bubble { background: #25262e; color: #e7e7ee; border-color: rgba(255, 255, 255, 0.06); }
.wprev[data-wtheme="dark"] .wprev-chip { background: transparent; }
.wprev[data-wtheme="dark"] .wprev-input { background: #17181e; border-top-color: rgba(255, 255, 255, 0.08); }
.wprev[data-wtheme="dark"] .wprev-input span { background: #1f2027; border-color: rgba(255, 255, 255, 0.1); color: #75767f; }
.wprev[data-wtheme="dark"] .wprev-teaser { background: #25262e; color: #e7e7ee; border-color: rgba(255, 255, 255, 0.1); }

/* ── Aperçu : style « épuré » ────────────────────────────────────── */
/* L'en-tête perd son aplat, les bulles de l'assistant leur cadre. */
.wprev[data-style="epure"] .wprev-panel { border-radius: 10px; box-shadow: 0 4px 14px rgba(0, 0, 0, 0.14); }
.wprev[data-style="epure"] .wprev-head { background: #fff; color: #1f2024; border-bottom: 1px solid #f0f0f2; }
.wprev[data-style="epure"] .wprev-avatar { display: none; }
.wprev[data-style="epure"] .wprev-status { color: #8b8c96; opacity: 1; }
.wprev[data-style="epure"] .wprev-body { background: #fff; gap: 0.7rem; padding: 0.8rem; }
.wprev[data-style="epure"] .wprev-row { max-width: 100%; }
.wprev[data-style="epure"] .wprev-msgavatar { display: none; }
.wprev[data-style="epure"] .wprev-bubble { background: none; border: none; padding: 0; }
.wprev[data-style="epure"] .wprev-bubble.user { padding: 0.5rem 0.75rem; border-radius: 9px; }
.wprev[data-style="epure"] .wprev-chips { align-items: stretch; }
.wprev[data-style="epure"] .wprev-chip { border-radius: 7px; background: none; text-align: left; }
.wprev[data-style="epure"] .wprev-input span { border-radius: 9px; }
.wprev[data-style="epure"] .wprev-input em { border-radius: 7px; }
.wprev[data-style="epure"] .wprev-launcher { border-radius: 16px; box-shadow: 0 4px 14px rgba(0, 0, 0, 0.18); }

.wprev[data-wtheme="dark"][data-style="epure"] .wprev-head { background: #17181e; color: #e7e7ee; border-bottom-color: rgba(255, 255, 255, 0.08); }
.wprev[data-wtheme="dark"][data-style="epure"] .wprev-body { background: #17181e; }
.wprev[data-wtheme="dark"][data-style="epure"] .wprev-bubble { background: none; }

/* ── Aperçu : style « immersif » ─────────────────────────────────── */
/* En-tête empilé et centré autour de la photo de profil, bulles en cartes
   avec une pointe vers leur auteur, saisie posée en carte. */
.wprev[data-style="immersif"] .wprev-panel { border-radius: 24px; box-shadow: 0 16px 40px rgba(0, 0, 0, 0.24); }
.wprev[data-style="immersif"] .wprev-head { flex-direction: column; text-align: center; gap: 7px; padding: 1rem 0.85rem 0.9rem; }
.wprev[data-style="immersif"] .wprev-avatar { width: 46px; height: 46px; box-shadow: 0 5px 14px rgba(0, 0, 0, 0.2); }
.wprev[data-style="immersif"] .wprev-id { flex: none; width: 100%; }
.wprev[data-style="immersif"] .wprev-name { font-size: 0.9rem; font-weight: 700; }
.wprev[data-style="immersif"] .wprev-x { position: absolute; top: 10px; right: 12px; }
.wprev[data-style="immersif"] .wprev-body { padding: 0.85rem 0.75rem; gap: 0.5rem; }
.wprev[data-style="immersif"] .wprev-bubble {
  border: none;
  border-radius: 17px;
  border-end-start-radius: 5px;
  box-shadow: 0 3px 12px rgba(0, 0, 0, 0.08);
}
.wprev[data-style="immersif"] .wprev-bubble.user { border-end-start-radius: 17px; border-end-end-radius: 5px; }
.wprev[data-style="immersif"] .wprev-chip { border-radius: 15px; font-weight: 500; }
.wprev[data-style="immersif"] .wprev-input { border-top: none; padding: 8px 11px 11px; }
.wprev[data-style="immersif"] .wprev-input span {
  border-radius: 19px;
  border-color: transparent;
  background: #fff;
  box-shadow: 0 3px 12px rgba(0, 0, 0, 0.09);
}
.wprev[data-style="immersif"] .wprev-launcher { box-shadow: 0 12px 30px rgba(0, 0, 0, 0.3); }

.wprev[data-wtheme="dark"][data-style="immersif"] .wprev-bubble { background: #22232b; }
.wprev[data-wtheme="dark"][data-style="immersif"] .wprev-input span { background: #22232b; }

@media (max-width: 700px) {
  .wcfg-styles { grid-template-columns: 1fr; }
}

/* Sous 1000 px, l'aperçu passe sous le formulaire plutôt que de l'écraser. */
@media (max-width: 1000px) {
  .wcfg { grid-template-columns: minmax(0, 1fr); }
  .wcfg-aside { position: static; }
}
@media (max-width: 560px) {
  .wcfg-row { grid-template-columns: 1fr; }
}

/* ── Pied de page ────────────────────────────────────────────────── */
.footer {
  margin-top: 2.5rem;
  padding-top: 1.2rem;
  text-align: center;
  font-size: 0.79rem;
  color: var(--text-3);
}
.footer a { color: var(--accent); text-decoration: none; }
.footer a:hover { text-decoration: underline; }


/* ═══════════════════════════════════════════════════════════════════
   ANALYSE DE DONNÉES + PAGES LEADS / CONVERSATIONS
   ═══════════════════════════════════════════════════════════════════ */

/* ── Onglets de l'analyse ────────────────────────────────────────── */
/* Les six sections d'analyse vivaient dans la barre de gauche ; elles sont
   devenues un sommaire horizontal en haut de la page. La barre latérale
   garde ainsi une entrée unique, et la place libérée reste disponible pour
   les prochaines fonctionnalités. */
.antabs {
  display: flex;
  gap: 0.25rem;
  padding: 3px;
  /* La rangée épouse ses onglets : elle se lit comme un contrôle, pas comme
     une bande d'en-tête, et deux onglets ne s'étirent pas sur la largeur. */
  width: fit-content;
  max-width: 100%;
  margin-bottom: 1.35rem;
  background: var(--surface-2);
  border-radius: 12px;
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.antabs::-webkit-scrollbar { display: none; }

.antab {
  flex: 1 1 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  padding: 0.46rem 0.85rem;
  border-radius: 9px;
  font-size: 0.845rem;
  font-weight: 500;
  color: var(--text-2);
  text-decoration: none;
  white-space: nowrap;
  transition: background 0.18s, color 0.18s, box-shadow 0.18s, transform 0.1s;
}
.antab svg { width: 16px; height: 16px; flex-shrink: 0; color: var(--accent); }
.antab:hover { color: var(--text); }
.antab:active { transform: scale(0.97); }
.antab:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* Onglet ouvert : la même capsule violette que l'entrée sélectionnée de la
   barre de gauche, pour que la bascule se lise du premier coup d'œil. */
.antab.active {
  background: linear-gradient(150deg, var(--accent) 0%, var(--accent-deep) 100%);
  box-shadow: var(--shadow-accent);
  color: #fff;
  font-weight: 600;
}
.antab.active svg { color: #fff; }

/* Sous 1100 px, les libellés complets ne tiennent plus : la rangée défile
   au doigt et l'onglet actif est ramené dans le champ de vision. */
@media (max-width: 1100px) {
  .antab { flex: 0 0 auto; }
}

/* ── Barre de filtres ────────────────────────────────────────────── */
/* Une rangée de commandes capsule, alignée sur la barre d'outils des
   en-têtes de page : recherche, sélecteurs, actions. */
.filters {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  flex-wrap: wrap;
  padding: 0.95rem 1.3rem;
  border-bottom: 1px solid var(--separator);
}
.filters .grow { flex: 1; min-width: 160px; }
.filters-right { margin-left: auto; display: inline-flex; align-items: center; gap: 0.55rem; flex-wrap: wrap; }

.select {
  appearance: none;
  -webkit-appearance: none;
  height: 34px;
  padding: 0 2rem 0 0.85rem;
  border: 1px solid var(--border);
  background-color: var(--surface);
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238e8e93' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.6rem center;
  background-size: 13px;
  border-radius: 980px;
  font-family: inherit;
  font-size: 0.845rem;
  font-weight: 500;
  color: var(--text);
  cursor: pointer;
  max-width: 230px;
  text-overflow: ellipsis;
  transition: box-shadow 0.15s, border-color 0.15s;
}
.select:hover { border-color: var(--border-strong); }
.select:focus { outline: none; box-shadow: 0 0 0 3.5px var(--ring); }

.input-inline {
  height: 34px;
  width: 100%;
  padding: 0 0.9rem;
  border: 1px solid var(--border);
  background: var(--surface);
  border-radius: 980px;
  font-family: inherit;
  font-size: 0.87rem;
  color: var(--text);
  transition: box-shadow 0.15s, border-color 0.15s;
}
.input-inline::placeholder { color: var(--text-3); }
.input-inline:focus { outline: none; box-shadow: 0 0 0 3.5px var(--ring); border-color: transparent; }

/* ── En-tête de section analytique ───────────────────────────────── */
.section-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin: 0 0 0.9rem;
}
.section-head h2 {
  font-size: 1.32rem;
  font-weight: 700;
  letter-spacing: -0.032em;
  display: flex;
  align-items: center;
  gap: 0.55rem;
}
.section-head h2 svg { width: 19px; height: 19px; color: var(--accent); }
.section-head p { font-size: 0.86rem; color: var(--text-2); margin-top: 0.22rem; max-width: 60ch; }

/* Rangée de petites tuiles (métriques secondaires) */
.tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(168px, 1fr));
  gap: 0.9rem;
  margin-bottom: 0.9rem;
}
.tile { padding: 1rem 1.15rem 1.05rem; }
.tile-label { font-size: 0.79rem; color: var(--text-2); display: flex; align-items: center; gap: 0.4rem; }
.tile-label svg { width: 14px; height: 14px; color: var(--accent); }
.tile-value {
  font-size: 1.62rem;
  font-weight: 700;
  letter-spacing: -0.032em;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  margin-top: 0.42rem;
  line-height: 1.1;
}
.tile-sub { font-size: 0.76rem; color: var(--text-3); margin-top: 0.28rem; }

/* ── Barres horizontales classées ────────────────────────────────── */
.hbars { display: flex; flex-direction: column; gap: 0.85rem; margin-top: 0.3rem; }
.hbar { display: flex; align-items: center; gap: 0.7rem; }
.hbar-rank {
  width: 21px;
  height: 21px;
  border-radius: 7px;
  background: var(--surface-2);
  color: var(--text-3);
  font-size: 0.72rem;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  font-variant-numeric: tabular-nums;
}
.hbar-body { flex: 1; min-width: 0; }
.hbar-head { display: flex; align-items: baseline; justify-content: space-between; gap: 0.7rem; margin-bottom: 0.32rem; }
.hbar-label {
  font-size: 0.875rem;
  color: var(--text);
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.hbar-val {
  font-size: 0.83rem;
  font-weight: 600;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  flex-shrink: 0;
}
.hbar-sub { color: var(--text-3); font-weight: 400; margin-left: 0.4rem; }
.hbar-track { display: block; height: 7px; border-radius: 980px; background: var(--track); overflow: hidden; }
.hbar-fill {
  display: block;
  height: 100%;
  border-radius: 980px;
  background: linear-gradient(90deg, var(--accent) 0%, var(--accent-strong) 100%);
}

/* ── Colonnes (jour de semaine, heures) ──────────────────────────── */
.cols { display: flex; align-items: flex-end; gap: 0.4rem; margin-top: 1rem; }
.cols.dense { gap: 2px; }
.colcell { flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 0.32rem; }
.colslot { display: flex; align-items: flex-end; width: 100%; }
.colbar {
  display: block;
  width: 100%;
  border-radius: 7px;
  background: var(--accent);
  transition: opacity 0.2s;
}
.cols.dense .colbar { border-radius: 3px; }
.colname { font-size: 0.7rem; color: var(--text-3); white-space: nowrap; }
.colval { font-size: 0.7rem; color: var(--text-3); font-variant-numeric: tabular-nums; height: 0.95rem; }
.colcell.peak .colname { color: var(--accent); font-weight: 600; }
.colcell.peak .colval { color: var(--text); font-weight: 600; }

/* ── Entonnoir de conversion ─────────────────────────────────────── */
/* Dans une rangée à hauteurs égales, l'entonnoir occupe la carte entière et
   ce sont les raccords qui absorbent la hauteur en trop : la silhouette
   s'allonge au lieu de laisser un blanc sous la dernière étape. */
/* Surtitre de l'entonnoir : les visites du site, hors échelle. */
.funnel-head {
  display: flex;
  align-items: baseline;
  gap: 0.55rem;
  flex-wrap: wrap;
  margin-top: 0.9rem;
  padding-bottom: 0.9rem;
  border-bottom: 1px solid var(--separator);
}
.funnel-head-main { font-size: 1.15rem; font-weight: 700; letter-spacing: -0.022em; color: var(--text); }
.funnel-head-sub { font-size: 0.815rem; color: var(--text-2); }

.funnel { margin-top: 0.9rem; display: flex; flex-direction: column; }
.grid-even > .card > .funnel { flex: 1; }
.grid-even > .card > .funnel > .funnel-gap { flex: 1; }
/* Bande centrée, largeur proportionnelle à l'étape : c'est le rétrécissement
   qui raconte l'entonnoir. Pas de piste derrière — une piste pleine largeur
   redonnerait à chaque étape l'apparence d'un bloc plein et effacerait la
   forme, seule chose que ce graphique doit montrer. */
.funnel-meta { display: flex; align-items: baseline; justify-content: space-between; gap: 0.8rem; margin-bottom: 0.2rem; }
.funnel-label { font-size: 0.875rem; font-weight: 500; color: var(--text); }
.funnel-val {
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.funnel-pct { font-size: 0.76rem; font-weight: 500; color: var(--text-3); margin-left: 0.45rem; }
.funnel-band {
  height: 40px;
  border-radius: 13px;
  margin: 0 auto;
  background: var(--fn, var(--accent));
  transition: width 0.7s cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* Le raccord relie la bande à la suivante : un trapèze découpé aux deux
   largeurs, qui matérialise ce qui se perd entre les étapes. */
.funnel-gap {
  position: relative;
  min-height: 30px;
  max-height: 96px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.funnel-taper {
  position: absolute;
  inset: 0;
  background: var(--accent);
  opacity: 0.16;
  clip-path: polygon(
    calc(50% - var(--a) / 2) 0%,
    calc(50% + var(--a) / 2) 0%,
    calc(50% + var(--b) / 2) 100%,
    calc(50% - var(--b) / 2) 100%
  );
}
/* Fond à la couleur de la carte : le taux d'abandon reste lisible par-dessus
   le trapèze, sans qu'on ait à contourer le texte. */
.funnel-drop {
  position: relative;
  font-size: 0.735rem;
  color: var(--text-2);
  background: var(--card-bg-solid);
  padding: 0.1rem 0.6rem;
  border-radius: 980px;
  font-variant-numeric: tabular-nums;
}
.funnel-hint { font-size: 0.755rem; color: var(--text-3); margin: -0.1rem 0 0.5rem; }

/* ── Relevés chiffrés en pied de carte ───────────────────────────── */
/* Trois valeurs de même nature, séparées par un filet vertical. Aucune barre :
   des longueurs presque identiques ne mesureraient rien et donneraient
   l'illusion d'une comparaison. */
.mini-stats {
  display: flex;
  gap: 1.4rem;
  flex-wrap: wrap;
  border-top: 1px solid var(--separator);
  padding-top: 0.95rem;
}
.mini-stat {
  display: flex;
  flex-direction: column;
  gap: 0.18rem;
  padding-left: 0.9rem;
  border-left: 1px solid var(--separator);
}
.mini-stat:first-child { padding-left: 0; border-left: none; }
.mini-stat-label { font-size: 0.755rem; color: var(--text-3); }
.mini-stat-value {
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--text);
  letter-spacing: -0.018em;
}

/* ── Nuage de sujets ─────────────────────────────────────────────── */
.kw-cloud { display: flex; flex-wrap: wrap; gap: 0.45rem; margin-top: 0.85rem; }
.kw {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.3rem 0.7rem;
  border-radius: 980px;
  color: var(--text);
  line-height: 1.25;
  border: 1px solid var(--card-line);
}
.kw-n { font-size: 0.7rem; font-weight: 600; color: var(--accent); font-variant-numeric: tabular-nums; }

/* ── Liste de questions ──────────────────────────────────────────── */
.qlist { display: flex; flex-direction: column; margin-top: 0.4rem; }
.qitem {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  padding: 0.72rem 0;
  border-bottom: 1px solid var(--separator);
}
.qitem:last-child { border-bottom: none; }
.qitem-text { flex: 1; min-width: 0; font-size: 0.885rem; color: var(--text); line-height: 1.4; }
.qitem-count {
  font-size: 0.74rem;
  font-weight: 600;
  color: var(--accent);
  background: var(--accent-soft);
  border-radius: 980px;
  padding: 0.16rem 0.55rem;
  white-space: nowrap;
  flex-shrink: 0;
}

/* ── Pastille widget dans les tableaux transverses ───────────────── */
.wtag {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.78rem;
  color: var(--text-2);
  background: var(--surface-2);
  border-radius: 980px;
  padding: 0.16rem 0.6rem 0.16rem 0.4rem;
  max-width: 190px;
}
.wtag .side-dot { width: 7px; height: 7px; }
.wtag span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Extrait de message dans une ligne de tableau */
.snippet {
  display: block;
  max-width: 460px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text);
  font-weight: 500;
}
.snippet-sub {
  display: block;
  max-width: 460px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 0.775rem;
  color: var(--text-3);
  margin-top: 0.15rem;
  font-weight: 400;
}

/* Bandeau d'information (données tronquées, aide contextuelle) */
.notice {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  padding: 0.7rem 0.95rem;
  border-radius: 14px;
  background: var(--warn-soft);
  color: var(--text-2);
  font-size: 0.8rem;
  margin-bottom: 0.9rem;
}
.notice svg { width: 15px; height: 15px; color: var(--warn); flex-shrink: 0; margin-top: 1px; }
.notice.info { background: var(--accent-softer); }
.notice.info svg { color: var(--accent); }

/* Entête de fiche lead dans la modale de conversation */
.sheet-lead {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.7rem 0.85rem;
  border-radius: 14px;
  background: var(--accent-softer);
  border: 1px solid var(--card-line);
  margin-bottom: 0.6rem;
}
.sheet-lead .list-avatar { flex-shrink: 0; }
.sheet-lead-main { min-width: 0; flex: 1; }
.sheet-lead-name { font-size: 0.9rem; font-weight: 600; color: var(--text); }
.sheet-lead-meta { font-size: 0.78rem; color: var(--text-2); }

/* Résumé en une phrase, en tête d'une conversation ouverte.
   Volontairement à part des bulles : ce n'est pas un message du fil, c'est ce
   qu'on lit AVANT de décider s'il vaut la peine d'être lu. */
.conv-summary {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  padding: 0.7rem 0.9rem;
  margin-bottom: 0.7rem;
  border-radius: 14px;
  background: var(--accent-softer);
  border: 1px solid var(--accent-soft);
}
.conv-summary svg { width: 16px; height: 16px; color: var(--accent); flex-shrink: 0; margin-top: 2px; }
.conv-summary p {
  font-size: 0.875rem;
  line-height: 1.45;
  color: var(--text);
  font-style: italic;
}
/* `display: flex` l'emporterait sur l'attribut `hidden` : sans cette règle,
   le bloc resterait visible et vide tant qu'aucune phrase n'est arrivée. */
.conv-summary[hidden] { display: none; }

/* Posé entre l'en-tête et le fil : il garde la gouttière de la modale et ne
   défile pas avec les messages. */
.modal-card > .conv-summary { margin: 0 1.3rem 0.2rem; }
/* Fiche lead : aligné sur la gouttière de l'en-tête, au-dessus des volets. */
.lead-sheet > .conv-summary { margin: 0.7rem 1rem 0; }

/* Attente : une barre qui respire plutôt qu'un mot. La phrase peut ne jamais
   venir (pas de clé, appel en échec) — le bloc disparaît alors sans avoir
   promis quoi que ce soit. */
.conv-summary.loading { border-color: transparent; }
.conv-summary-bar {
  display: block;
  height: 0.8rem;
  width: 62%;
  border-radius: 999px;
  background: var(--accent-soft);
  animation: convSummaryPulse 1.3s ease-in-out infinite;
}
@keyframes convSummaryPulse {
  0%, 100% { opacity: 0.45; }
  50% { opacity: 0.9; }
}
@media (prefers-reduced-motion: reduce) {
  .conv-summary-bar { animation: none; }
}

/* Danger discret (suppression RGPD) */
.btn.danger { color: var(--danger); }
.btn.danger:hover { background: var(--danger-soft); }

/* Deux colonnes égales pour les cartes d'analyse */
.grid-2 {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
  gap: 0.9rem;
  align-items: start;
}
.grid-2 + .grid-2, .grid-2 + .card, .card + .grid-2 { margin-top: 0.9rem; }

/* Rangée à hauteurs égales : chaque colonne se cale sur la plus haute, et la
   carte seule d'une colonne occupe toute la hauteur. Son dernier bloc se pose
   alors sur le bord bas, comme un pied de carte, plutôt que de laisser un
   grand vide sous le contenu. */
.grid-even { align-items: stretch; }
/* Deux formes de rangée : la carte seule d'une colonne (tableau de bord),
   et la carte posée directement dans la grille (pages d'analyse). */
.grid-even .col > .card:only-child,
.grid-even > .card {
  display: flex;
  flex-direction: column;
}
.grid-even .col > .card:only-child { flex: 1; }

/* Carte « remplisseuse » : elle absorbe la hauteur restante de sa colonne, de
   sorte que les deux colonnes se terminent au même trait quel que soit le
   nombre de lignes. Son corps défile plutôt que d'allonger la page, et son
   pied — la pagination — reste ancré en bas, hors du défilement. */
.grid-even .col > .card-fill {
  /* `flex-basis: 0` est le point clé : la carte ne compte pas sa propre
     hauteur dans celle de la colonne. La rangée se cale donc sur l'autre
     colonne, puis cette carte reçoit tout ce qui reste. Avec `flex: 1` seul,
     elle poussait la colonne à la hauteur de son tableau et les deux
     colonnes se désalignaient dès qu'il y avait beaucoup de lignes. */
  flex: 1 1 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
/* Les onglets entrent dans la carte : ils en sont l'en-tête, pas un élément
   posé à côté sur le fond de page. */
.card-tabs {
  padding: 0.85rem 1rem 0;
  flex-shrink: 0;
}
.card-tabs .tabs { margin-bottom: 0.85rem; }
.card-scroll {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
}
/* Le tableau porte déjà ses filets : le pied s'en sépare par le sien. */
.card-fill > div:last-child:not(:empty) {
  flex-shrink: 0;
  border-top: 1px solid var(--separator);
}
.card-fill .pagination { margin: 0; padding: 0.75rem 1rem; }
.card-fill .table-wrap { overflow: visible; }
/* L'en-tête du tableau reste visible pendant le défilement. */
.card-fill .table thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--card-bg-solid);
}
/* Bloc de pied : `auto` absorbe la hauteur en trop, le `padding` garantit un
   écart minimum avec le contenu quand la carte n'est pas étirée (colonne
   unique sur mobile). */
.grid-even > .card > .card-foot { margin-top: auto; padding-top: 0.9rem; }

/* ═══════════════════════════════════════════════════════════════════
   DASHBOARD CLIENT — cockpit commercial
   La structure de la page ne change pas. Une seule surface porte la marque ;
   les cartes de données redeviennent calmes, nettes et hiérarchisées.
   ═══════════════════════════════════════════════════════════════════ */
.dashboard-view {
  --dash-card: rgba(255, 255, 255, 0.94);
  --dash-card-solid: #ffffff;
  --dash-line: rgba(40, 30, 80, 0.09);
  --dash-line-strong: rgba(40, 30, 80, 0.15);
  --dash-subtle: rgba(91, 76, 150, 0.045);
  --dash-ink: #181426;
  --dash-muted: #777184;
  --viz-1: #5d4ce6;
  --viz-2: #8964ed;
  --viz-3: #b17ae8;
  --activity-grid: rgba(103, 79, 190, 0.11);
  --activity-glow: rgba(117, 82, 223, 0.12);
}
:root[data-theme="dark"] .dashboard-view {
  --dash-card: rgba(29, 28, 36, 0.96);
  --dash-card-solid: #1d1c24;
  --dash-line: rgba(255, 255, 255, 0.08);
  --dash-line-strong: rgba(255, 255, 255, 0.14);
  --dash-subtle: rgba(255, 255, 255, 0.035);
  --dash-ink: #f8f7fb;
  --dash-muted: rgba(235, 235, 245, 0.58);
  --viz-1: #a89cff;
  --viz-2: #c09aff;
  --viz-3: #dda9f5;
  --activity-grid: rgba(187, 157, 255, 0.13);
  --activity-glow: rgba(139, 92, 246, 0.18);
}

.dashboard-view .shell {
  background:
    radial-gradient(700px 360px at 72% -80px, var(--accent-softer), transparent 68%),
    var(--shell);
}
.dashboard-view .page {
  max-width: 1480px;
  padding: 1.8rem clamp(1.15rem, 2.2vw, 2.2rem) 4rem;
}
.dashboard-view .page-head { margin-bottom: 1.05rem; }
.dashboard-view .page-eyebrow,
.dashboard-view .section-kicker {
  display: block;
  margin-bottom: 0.3rem;
  color: var(--accent);
  font-size: 0.66rem;
  font-weight: 750;
  letter-spacing: 0.11em;
  line-height: 1;
  text-transform: uppercase;
}
.dashboard-view .page-head h1 {
  font-size: clamp(1.9rem, 2.5vw, 2.35rem);
  font-weight: 750;
  letter-spacing: -0.048em;
}
.dashboard-view .period-line { margin-top: 0.32rem; }
.dashboard-view .page-head .btn,
.dashboard-view .page-head .icon-btn {
  border: 1px solid var(--dash-line);
  background: var(--dash-card);
  box-shadow: 0 1px 2px rgba(31, 23, 60, 0.04);
}

/* Résumé exécutif : seule surface expressive du dashboard. */
.executive-brief {
  position: relative;
  isolation: isolate;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: stretch;
  gap: clamp(1.5rem, 5vw, 5rem);
  min-height: 176px;
  margin-bottom: 1rem;
  padding: clamp(1.45rem, 2.4vw, 2rem) clamp(1.4rem, 2.7vw, 2.3rem);
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.11);
  border-radius: 22px;
  background:
    linear-gradient(112deg, rgba(255, 255, 255, 0.055), transparent 38%),
    linear-gradient(135deg, #171329 0%, #211748 56%, #35206c 100%);
  box-shadow: 0 20px 55px rgba(45, 29, 100, 0.22), inset 0 1px 0 rgba(255, 255, 255, 0.08);
  color: #fff;
}
.executive-brief::after {
  content: "";
  position: absolute;
  z-index: -1;
  inset: 0;
  opacity: 0.2;
  background-image: linear-gradient(rgba(255,255,255,.06) 1px, transparent 1px);
  background-size: 100% 42px;
  mask-image: linear-gradient(90deg, transparent 35%, #000 100%);
}
.brief-glow {
  position: absolute;
  z-index: -1;
  top: -145px;
  right: -80px;
  width: 400px;
  height: 400px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(157, 129, 255, 0.34), transparent 68%);
}
.brief-copy { align-self: center; min-width: 0; }
.brief-kicker {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  margin-bottom: 1.2rem;
  color: rgba(255, 255, 255, 0.52);
  font-size: 0.72rem;
}
.brief-live { display: inline-flex; align-items: center; gap: 0.42rem; color: #bdf4ce; }
.brief-live > span {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #58db83;
  box-shadow: 0 0 0 4px rgba(88, 219, 131, 0.12), 0 0 16px rgba(88, 219, 131, 0.5);
}
.brief-live.off { color: #ffc5c1; }
.brief-live.off > span { background: #ff6b63; box-shadow: 0 0 0 4px rgba(255, 107, 99, 0.13); }
.brief-live b { font-size: inherit; font-weight: 650; }
.brief-update::before { content: "·"; margin-right: 0.65rem; }
.brief-copy h2 {
  max-width: 780px;
  font-size: clamp(1.45rem, 2.3vw, 2.15rem);
  font-weight: 720;
  letter-spacing: -0.045em;
  line-height: 1.1;
  text-wrap: balance;
}
.brief-copy p {
  max-width: 720px;
  margin-top: 0.62rem;
  color: rgba(255, 255, 255, 0.64);
  font-size: clamp(0.79rem, 1vw, 0.88rem);
  line-height: 1.55;
}
.brief-impact {
  position: relative;
  z-index: 1;
  display: flex;
  min-width: 210px;
  /* L'écart suffit à séparer les deux colonnes : le filet vertical qui vivait
     ici a été retiré (comme le grand cercle du fond), la carte respire sans
     être quadrillée. */
  padding-left: clamp(1.5rem, 3vw, 3rem);
  flex-direction: column;
  justify-content: center;
  align-items: flex-start;
}
.brief-impact-label {
  color: rgba(255, 255, 255, 0.48);
  font-size: 0.68rem;
  font-weight: 650;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.brief-impact strong {
  margin-top: 0.4rem;
  font-size: clamp(1.8rem, 3.1vw, 2.65rem);
  font-weight: 700;
  letter-spacing: -0.055em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.brief-impact-trend { margin-top: 0.75rem; color: rgba(255, 255, 255, 0.58); font-size: 0.72rem; }
.brief-impact-trend .delta { color: #9ce9b5; background: rgba(73, 204, 115, 0.14); }
.brief-impact-trend .delta.down { color: #ffaaa5; background: rgba(255, 91, 82, 0.14); }
.brief-impact-trend .delta.flat { color: rgba(255, 255, 255, 0.62); background: rgba(255, 255, 255, 0.08); }

/* Réglage « Valeur moyenne d'un client » : l'ancienne carte « Pipeline
   récupéré » a quitté le tableau de bord, le montant unitaire se règle
   désormais sous la valeur qu'il alimente. Fond sombre oblige, le formulaire
   a ses propres couleurs. */
.brief-value-setting {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.45rem 0.75rem;
  width: 100%;
  margin-top: 1.1rem;
  padding-top: 0.9rem;
  border-top: 1px solid rgba(255, 255, 255, 0.12);
  font-size: 0.72rem;
  color: rgba(255, 255, 255, 0.55);
}
.brief-value-setting .stat-setting-label b { color: #fff; }
.brief-value-setting .link-more { color: rgba(255, 255, 255, 0.72); }
.brief-value-setting .link-more:hover { color: #fff; opacity: 1; }
.brief-value-setting .stat-setting-msg { color: rgba(255, 255, 255, 0.6); }
.brief-value-setting .stat-setting-msg.err { color: #ffaaa5; }
.brief-value-setting .value-input {
  height: 32px;
  background: rgba(255, 255, 255, 0.09);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.16);
  color: #fff;
}
.brief-value-setting .value-input::placeholder { color: rgba(255, 255, 255, 0.4); }
.brief-value-setting .value-input:focus {
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.3), 0 0 0 3px rgba(255, 255, 255, 0.14);
}

/* Thème clair : le résumé garde sa mise en page et son rôle de surface
   expressive, mais quitte le violet profond pour une lavande claire à
   encre violette — le contraste vient des textes sombres, pas du fond. */
:root[data-theme="light"] .executive-brief {
  border-color: rgba(93, 76, 230, 0.18);
  background:
    linear-gradient(112deg, rgba(255, 255, 255, 0.65), transparent 40%),
    linear-gradient(135deg, #efeaff 0%, #e7ddfd 55%, #dbcefb 100%);
  box-shadow: 0 20px 55px rgba(93, 76, 230, 0.13), inset 0 1px 0 rgba(255, 255, 255, 0.75);
  color: #241b4d;
}
:root[data-theme="light"] .executive-brief::after {
  opacity: 0.45;
  background-image: linear-gradient(rgba(93, 76, 230, 0.12) 1px, transparent 1px);
}
:root[data-theme="light"] .brief-glow {
  background: radial-gradient(circle, rgba(124, 98, 245, 0.16), transparent 68%);
}
:root[data-theme="light"] .brief-kicker { color: rgba(36, 27, 77, 0.55); }
:root[data-theme="light"] .brief-live { color: #0c7a43; }
:root[data-theme="light"] .brief-live > span {
  background: #1fa75c;
  box-shadow: 0 0 0 4px rgba(31, 167, 92, 0.14), 0 0 12px rgba(31, 167, 92, 0.35);
}
:root[data-theme="light"] .brief-live.off { color: #b3261e; }
:root[data-theme="light"] .brief-live.off > span {
  background: #e5484d;
  box-shadow: 0 0 0 4px rgba(229, 72, 77, 0.14);
}
:root[data-theme="light"] .brief-copy p { color: rgba(36, 27, 77, 0.68); }
:root[data-theme="light"] .brief-impact-label { color: rgba(36, 27, 77, 0.52); }
:root[data-theme="light"] .brief-impact-trend { color: rgba(36, 27, 77, 0.6); }
:root[data-theme="light"] .brief-impact-trend .delta { color: #0c7a43; background: rgba(31, 167, 92, 0.14); }
:root[data-theme="light"] .brief-impact-trend .delta.down { color: #b3261e; background: rgba(229, 72, 77, 0.12); }
:root[data-theme="light"] .brief-impact-trend .delta.flat { color: rgba(36, 27, 77, 0.62); background: rgba(36, 27, 77, 0.08); }
:root[data-theme="light"] .brief-value-setting { border-top-color: rgba(36, 27, 77, 0.12); color: rgba(36, 27, 77, 0.56); }
:root[data-theme="light"] .brief-value-setting .stat-setting-label b { color: #241b4d; }
:root[data-theme="light"] .brief-value-setting .link-more { color: rgba(36, 27, 77, 0.72); }
:root[data-theme="light"] .brief-value-setting .link-more:hover { color: #241b4d; }
:root[data-theme="light"] .brief-value-setting .stat-setting-msg.err { color: #b3261e; }
:root[data-theme="light"] .brief-value-setting .value-input {
  background: rgba(255, 255, 255, 0.65);
  box-shadow: inset 0 0 0 1px rgba(36, 27, 77, 0.2);
  color: #241b4d;
}
:root[data-theme="light"] .brief-value-setting .value-input::placeholder { color: rgba(36, 27, 77, 0.4); }
:root[data-theme="light"] .brief-value-setting .value-input:focus {
  box-shadow: inset 0 0 0 1px rgba(93, 76, 230, 0.45), 0 0 0 3px rgba(93, 76, 230, 0.16);
}

/* Surfaces analytiques : moins de lavande et de relief, davantage de précision. */
.dashboard-view .card {
  border: 1px solid var(--dash-line);
  border-radius: 18px;
  background: var(--dash-card);
  box-shadow: 0 1px 2px rgba(26, 18, 55, 0.035), 0 8px 24px rgba(26, 18, 55, 0.035);
}
.dashboard-view .card-head h3,
.dashboard-view .tc-ident h3,
.dashboard-view .heat-head h3,
.dashboard-view .attention-head h3 { font-weight: 680; letter-spacing: -0.028em; }
.dashboard-view .card-head .sub,
.dashboard-view .tc-sub { color: var(--dash-muted); }
.dashboard-view .grid-wide,
.dashboard-view .grid-main,
.dashboard-view .col { gap: 1rem; }
.dashboard-view .grid-main + .grid-wide,
.dashboard-view .grid-wide + .grid-main,
.dashboard-view .grid-main + .grid-main,
.dashboard-view .grid-wide + .grid-wide { margin-top: 1rem; }

/* Le rail KPI est volontairement commun à toutes les pages du portail. */
.dashboard-view .kpi-grid { border-color: var(--dash-line); background: var(--dash-card); }
.dashboard-view .kpi-grid > .kpi {
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
}
.dashboard-view .kpi-grid > .kpi + .kpi { border-left: 1px solid var(--dash-line); }
.dashboard-view .kpi-grid > .kpi:hover { background: var(--accent-softer); }
.dashboard-view .kpi-label { color: var(--dash-muted); }

@media (max-width: 760px) {
  .dashboard-view .kpi-grid > .kpi:nth-child(odd) { border-left: 0; }
  .dashboard-view .kpi-grid > .kpi:nth-child(n + 3) { border-top: 1px solid var(--dash-line); }
}
@media (max-width: 360px) {
  .dashboard-view .kpi-grid > .kpi + .kpi { border-top: 1px solid var(--dash-line); border-left: 0; }
}

.dashboard-view .stat-value { font-size: clamp(2rem, 3vw, 2.65rem); font-weight: 680; }
.dashboard-view .card-analytics { padding: 1.45rem 1.55rem 1.35rem; border-radius: 18px; box-shadow: none; }

/* Activité : panneau monochrome violet, précis et légèrement technique. */
.dashboard-view .activity-card {
  position: relative;
  isolation: isolate;
  padding: 1.25rem 1.35rem 1.05rem;
  overflow: hidden;
  border-color: rgba(103, 79, 190, 0.16);
  background:
    linear-gradient(145deg, var(--activity-glow), transparent 34%),
    var(--dash-card);
  box-shadow: 0 16px 42px rgba(43, 28, 91, 0.08), inset 0 1px 0 rgba(255, 255, 255, 0.65);
}
.dashboard-view .activity-card::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: 0 0 auto;
  height: 2px;
  background: linear-gradient(90deg, var(--viz-1), var(--viz-2) 46%, transparent 88%);
  opacity: 0.82;
}
.dashboard-view .activity-card::after {
  content: "";
  position: absolute;
  z-index: -1;
  top: 0;
  right: 0;
  width: 44%;
  height: 46%;
  opacity: 0.32;
  background-image: radial-gradient(circle, var(--activity-grid) 1px, transparent 1px);
  background-size: 14px 14px;
  mask-image: linear-gradient(225deg, #000, transparent 72%);
  pointer-events: none;
}
:root[data-theme="dark"] .dashboard-view .activity-card {
  border-color: rgba(178, 145, 255, 0.16);
  box-shadow: 0 18px 46px rgba(0, 0, 0, 0.28), inset 0 1px 0 rgba(255, 255, 255, 0.04);
}
.dashboard-view .activity-card > * { position: relative; z-index: 1; }
.dashboard-view .activity-card .tc-head {
  align-items: flex-start;
  margin-bottom: 0;
  padding-bottom: 1rem;
  border-bottom: 1px solid var(--activity-grid);
}
.dashboard-view .tc-kicker {
  display: inline-flex;
  align-items: center;
  gap: 0.38rem;
  margin-bottom: 0.42rem;
  color: var(--viz-1);
  font-size: 0.61rem;
  font-weight: 750;
  letter-spacing: 0.1em;
  line-height: 1;
  text-transform: uppercase;
}
.dashboard-view .tc-kicker > span {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--viz-2);
  box-shadow: 0 0 0 4px var(--activity-glow), 0 0 12px var(--viz-2);
}
.dashboard-view .activity-card .tc-ident h3 {
  font-size: 1.08rem;
  font-weight: 720;
  letter-spacing: -0.035em;
}
.dashboard-view .activity-card .tc-sub { margin-top: 0.2rem; font-size: 0.75rem; }
.dashboard-view .activity-card .tc-controls {
  gap: 0;
  padding: 3px;
  border: 1px solid var(--activity-grid);
  border-radius: 12px;
  background: rgba(105, 81, 186, 0.045);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
}
.dashboard-view .activity-card .tc-period.tc-period {
  height: 29px;
  border: 0;
  border-radius: 9px;
  background-color: transparent;
  color: var(--text-2);
  font-size: 0.72rem;
}
.dashboard-view .activity-card .tc-expand {
  width: 29px;
  height: 29px;
  border: 0;
  border-left: 1px solid var(--activity-grid);
  border-radius: 0 9px 9px 0;
  background: transparent;
  color: var(--viz-1);
}
.dashboard-view .activity-card .tc-expand:hover { background: var(--activity-glow); color: var(--viz-1); }
.dashboard-view .activity-card .tc-figure {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: end;
  gap: 1.25rem;
  margin: 0;
  padding: 1rem 0 0.85rem;
}
.dashboard-view .activity-card .tc-primary-metric { min-width: 0; }
.dashboard-view .activity-card .tc-metric-label {
  display: block;
  margin-bottom: 0.3rem;
  color: var(--text-3);
  font-size: 0.64rem;
  font-weight: 650;
  letter-spacing: 0.055em;
  text-transform: uppercase;
}
.dashboard-view .activity-card .tc-figure .chart-total {
  display: inline-block;
  font-size: clamp(2.15rem, 3.2vw, 2.75rem);
  font-weight: 680;
  letter-spacing: -0.06em;
}
.dashboard-view .activity-card .chart-meta {
  display: inline-flex;
  margin: 0 0 0.18rem 0.55rem;
  vertical-align: baseline;
}
.dashboard-view .activity-card .chart-meta .delta {
  padding: 0.15rem 0.42rem 0.15rem 0.32rem;
  background: var(--activity-glow);
  color: var(--viz-1);
  font-size: 0.66rem;
}
.dashboard-view .activity-card .chart-meta .delta.down,
.dashboard-view .activity-card .chart-meta .delta.flat { background: var(--activity-glow); color: var(--viz-2); }
.dashboard-view .activity-card .tc-vs { color: var(--text-3); font-size: 0.68rem; }
.dashboard-view .activity-card .tc-snapshot {
  display: grid;
  grid-template-columns: repeat(2, minmax(92px, 1fr));
  overflow: hidden;
  border: 1px solid var(--activity-grid);
  border-radius: 12px;
  background: rgba(105, 81, 186, 0.035);
}
.dashboard-view .activity-card .tc-snapshot > div { padding: 0.68rem 0.8rem 0.62rem; }
.dashboard-view .activity-card .tc-snapshot > div + div { border-left: 1px solid var(--activity-grid); }
.dashboard-view .activity-card .tc-snapshot span {
  display: block;
  color: var(--text-3);
  font-size: 0.61rem;
  white-space: nowrap;
}
.dashboard-view .activity-card .tc-snapshot strong {
  display: block;
  margin-top: 0.26rem;
  color: var(--text);
  font-size: 1rem;
  font-weight: 680;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
}
.dashboard-view .activity-card .tc-visual {
  position: relative;
  margin: 0 -0.25rem;
  padding: 0.25rem 0.25rem 0.05rem;
  border-top: 1px solid var(--activity-grid);
}
.dashboard-view .activity-card .tc-plot { margin-top: 0.35rem; }
.dashboard-view .activity-card .tc-grid {
  stroke: var(--activity-grid);
  stroke-dasharray: 1 5;
  opacity: 0.85;
}
.dashboard-view .activity-card .tc-vgrid { stroke: var(--activity-grid); opacity: 0.42; }
.dashboard-view .activity-card .tc-tick { fill: var(--text-3); opacity: 0.72; }
.dashboard-view .activity-card .tc-line { filter: drop-shadow(0 2px 3px var(--activity-glow)); }
.dashboard-view .activity-card .tc-s1 { stroke-width: 2.3; }
.dashboard-view .activity-card .tc-s2 { stroke-width: 1.9; opacity: 0.9; }
.dashboard-view .activity-card .tc-s3 { stroke-width: 1.65; opacity: 0.78; }
.dashboard-view .activity-card .tc-dot { fill: var(--dash-card-solid); stroke-width: 2.6; }
.dashboard-view .activity-card .tc-cursor { stroke: var(--viz-2); opacity: 0.34; stroke-dasharray: 3 4; }
.dashboard-view .activity-card .tc-x {
  margin-top: 0.18rem;
  color: var(--text-3);
  font-size: 0.66rem;
}
.dashboard-view .activity-card .tc-legend {
  justify-content: flex-start;
  gap: 0.45rem;
  margin-top: 0.72rem;
  padding-left: 2.1rem;
}
.dashboard-view .activity-card .tc-leg {
  gap: 0.38rem;
  padding: 0.27rem 0.52rem;
  border: 1px solid var(--activity-grid);
  border-radius: 8px;
  background: rgba(105, 81, 186, 0.035);
  color: var(--text-2);
  font-size: 0.67rem;
}
.dashboard-view .activity-card .tc-swatch { width: 13px; height: 2px; }
.dashboard-view .activity-card .tc-k2 { opacity: 0.82; }
.dashboard-view .activity-card .tc-k3 { opacity: 0.68; }
.dashboard-view .activity-card .tooltip {
  padding: 0.6rem 0.72rem;
  border: 1px solid rgba(190, 163, 255, 0.18);
  border-radius: 10px;
  background: rgba(25, 18, 50, 0.94);
  box-shadow: 0 16px 34px rgba(25, 14, 62, 0.3);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
}
.dashboard-view .tc-legend { margin-top: 0.75rem; }

@media (max-width: 720px) {
  .dashboard-view .activity-card { padding: 1.1rem 1rem 1rem; }
  .dashboard-view .activity-card .tc-head { gap: 0.8rem; }
  .dashboard-view .activity-card .tc-controls { width: 100%; }
  .dashboard-view .activity-card .tc-period.tc-period { flex: 1; width: auto; }
  .dashboard-view .activity-card .tc-figure { grid-template-columns: minmax(0, 1fr); gap: 0.85rem; }
  .dashboard-view .activity-card .tc-snapshot { width: 100%; }
  .dashboard-view .activity-card .tc-legend { padding-left: 0; }
}
/* Analyse de données : la page porte body.dashboard-view et hérite du langage
   cockpit. Deux rappels spécifiques : le sommaire d'onglets se présente comme
   une carte (aligné sur les boutons de la barre haute), et le sélecteur de
   série vit dans la tête de la carte Activité. */
.dashboard-view .antabs {
  border: 1px solid var(--dash-line);
  background: var(--dash-card);
  box-shadow: 0 1px 2px rgba(31, 23, 60, 0.04);
}
.dashboard-view .activity-card .tc-controls .segmented {
  border: 0;
  background: transparent;
  padding: 0;
}
.dashboard-view .activity-card .tc-controls .segmented button {
  padding: 0.34rem 0.74rem;
  font-size: 0.72rem;
}

/* En-têtes des cartes d'analyse : les pages posent leurs cartes en card-pad,
   l'en-tête n'a donc rien à porter en haut — un seul écart de référence sous
   le titre, plus de padding au cas par cas en inline. */
.dashboard-view .card-head { padding: 0 0 0.9rem; }

/* Même rythme vertical que le dashboard entre les cartes d'une section
   (le rail KPI porte déjà son 1rem bas). */
.dashboard-view .an-view > .card + .card,
.dashboard-view .an-view > .card + .grid-2,
.dashboard-view .an-view > .grid-2 + .grid-2,
.dashboard-view .an-view > .grid-2 + .card { margin-top: 1rem; }

.dashboard-view .heat-icon { border: 1px solid var(--card-line); background: var(--accent-softer); }
.dashboard-view .hm-cell { border-radius: 5px; }
.dashboard-view .map-stat-value { font-weight: 670; }

/* File d'actions : trois lignes franches, sans fabriquer une seconde grille de KPI.
   La carte occupe la colonne étroite à côté d'Activité (l'ancien emplacement de
   « Pipeline récupéré ») : les lignes s'empilent et se partagent la hauteur. */
.attention-card { padding: 1.3rem 1.35rem 1.35rem; }
.attention-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.8rem;
  margin-bottom: 1rem;
}
.attention-head h3 { font-size: 1.02rem; line-height: 1.25; color: var(--text); }
.attention-total {
  display: inline-flex;
  align-items: center;
  min-height: 27px;
  padding: 0.25rem 0.68rem;
  border-radius: 999px;
  background: var(--warn-soft);
  color: var(--warn);
  font-size: 0.7rem;
  font-weight: 700;
  white-space: nowrap;
}
.attention-total.clear { background: var(--success-soft); color: var(--success); }
.attention-total.partial { background: var(--surface-2); color: var(--text-2); }
.attention-list {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: 0.65rem;
}
.attention-item {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 0.72rem;
  flex: 1 1 auto;
  min-width: 0;
  padding: 0.82rem 0.85rem;
  border: 1px solid transparent;
  border-radius: 13px;
  background: var(--dash-subtle);
  color: inherit;
  text-decoration: none;
  transition: background 150ms ease, border-color 150ms ease, transform 150ms ease;
}
.attention-item:hover {
  transform: translateY(-1px);
  border-color: var(--dash-line-strong);
  background: var(--surface-2);
}
.attention-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 10px;
  background: var(--success-soft);
  color: var(--success);
  flex-shrink: 0;
}
.attention-item.needs-action .attention-icon.relance { background: var(--warn-soft); color: var(--warn); }
.attention-item.needs-action .attention-icon.conversation,
.attention-item.needs-action .attention-icon.integration { background: var(--danger-soft); color: var(--danger); }
.attention-item.unavailable { opacity: 0.62; }
.attention-item.unavailable .attention-icon { background: var(--surface-2); color: var(--text-3); }
.attention-icon svg { width: 15px; height: 15px; }
.attention-copy { display: flex; min-width: 0; flex-direction: column; gap: 0.16rem; }
.attention-copy strong { font-size: 0.8rem; font-weight: 650; color: var(--text); }
.attention-copy span {
  color: var(--dash-muted);
  font-size: 0.69rem;
  line-height: 1.35;
}
.attention-count {
  min-width: 20px;
  color: var(--text);
  font-size: 1rem;
  font-weight: 700;
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.attention-item.clear .attention-count { color: var(--text-3); }
.attention-go { display: inline-flex; color: var(--text-3); }
.attention-go svg { width: 13px; height: 13px; }

.dashboard-view .feed-row a {
  margin: 0 -0.45rem;
  padding: 0.64rem 0.45rem;
  border-radius: 10px;
  transition: background 140ms ease;
}
.dashboard-view .feed-row a:hover { background: var(--dash-subtle); }
.dashboard-view .feed-row:not(:last-child) a { border-bottom-color: var(--dash-line); border-radius: 10px 10px 0 0; }
.dashboard-view .feed-dot { border-radius: 9px; }

@media (max-width: 820px) {
  .executive-brief { grid-template-columns: minmax(0, 1fr); gap: 1.3rem; }
  /* Empilée, la colonne de droite passe dessous : c'est le MÊME séparateur,
     couché — retiré lui aussi pour que les deux mises en page se ressemblent. */
  .brief-impact {
    min-width: 0;
    padding: 1.15rem 0 0;
  }
}
@media (max-width: 560px) {
  .dashboard-view .page { padding-top: 1.2rem; }
  .executive-brief { min-height: 0; padding: 1.3rem 1.2rem; border-radius: 18px; }
  .brief-kicker { align-items: flex-start; flex-direction: column; gap: 0.2rem; margin-bottom: 0.9rem; }
  .brief-update::before { content: none; }
  .brief-copy h2 { font-size: 1.45rem; }
  .brief-impact { align-items: flex-start; }
  .attention-head { flex-direction: column; }
  .attention-card { padding: 1.1rem; }
}
@media (prefers-reduced-motion: reduce) {
  .dashboard-view .kpi,
  .attention-item { transition: none; }
}

@media (max-width: 720px) {
  .filters { padding: 0.8rem 1rem; }
  .select { max-width: 100%; flex: 1; }
  .snippet, .snippet-sub { max-width: 210px; }
}

/* ═══════════════════════════════════════════════════════════════════
   RESPONSIVE
   ═══════════════════════════════════════════════════════════════════ */
.side-toggle {
  display: none;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  border: none;
  background: transparent;
  color: var(--accent);
  cursor: pointer;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.side-toggle:active { transform: scale(0.92); }
.side-backdrop { display: none; }

@media (max-width: 1150px) {
  .grid-main { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 1180px) {
  .grid-wide { grid-template-columns: minmax(0, 1fr); }
  .map-card { grid-template-columns: minmax(0, 1fr); gap: 1rem; }
  .map-stats { flex-direction: row; gap: 2rem; }
}

@media (max-width: 900px) {
  .app {
    grid-template-columns: minmax(0, 1fr);
  }
  /* La barre est un tiroir sur mobile : elle s'ouvre en entier ou pas du
     tout. Le repli n'a rien à y faire. */
  .side-collapse { display: none; }
  /* Le tiroir garde sa largeur propre (`.sidebar` en position fixe) : il faut
     seulement remettre le contenu déplié. */
  :root[data-sidebar="collapsed"] .side-head { justify-content: flex-start; padding: 0 0.5rem; }
  :root[data-sidebar="collapsed"] .logo-text,
  :root[data-sidebar="collapsed"] .side-section,
  :root[data-sidebar="collapsed"] .side-item .label,
  :root[data-sidebar="collapsed"] .side-count,
  :root[data-sidebar="collapsed"] .side-sub-name { display: revert; }
  :root[data-sidebar="collapsed"] .side-promo { display: block; }
  :root[data-sidebar="collapsed"] .side-item,
  :root[data-sidebar="collapsed"] .side-sub-item { justify-content: flex-start; }
  :root[data-sidebar="collapsed"] .side-item[data-label]::after,
  :root[data-sidebar="collapsed"] .side-sub-item[data-label]::after { content: none; }
  .sidebar {
    position: fixed;
    left: 0;
    top: 0;
    height: 100vh;
    width: 272px;
    transform: translateX(-100%);
    transition: transform 0.32s cubic-bezier(0.32, 0.72, 0, 1);
    box-shadow: var(--shadow-pop);
  }
  .sidebar.open { transform: none; }
  .side-backdrop {
    display: block;
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.32);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.25s;
    z-index: 55;
  }
  body.side-open .side-backdrop { opacity: 1; pointer-events: auto; }
  .side-toggle { display: inline-flex; }
  .topbar { padding: 0 0.9rem; gap: 0.5rem; }
  .search { max-width: none; }
  .search kbd { display: none; }
  .page { padding: 1.1rem 0.9rem 3rem; }
  .menu { right: 0.9rem; }
}

@media (max-width: 560px) {
  .page-head h1 { font-size: 1.65rem; }
  .kpi-grid > .kpi { min-height: 92px; padding: 0.82rem 0.85rem 0.78rem; }
  .kpi-label { font-size: 0.7rem; }
  .kpi-icon { width: 25px; height: 25px; margin-left: 0.45rem; }
  .kpi-value { font-size: 1.6rem; }
  .kpi-main { gap: 0.45rem; margin-top: 0.55rem; }
  .kpi-sub { max-width: 52%; font-size: 0.64rem; }
  .kpi-sub .delta.up, .kpi-sub .delta.down, .kpi-sub .delta.flat { font-size: 0.64rem; }
  .chart-total { font-size: 1.95rem; }
  .toolbar { width: 100%; }
}

/* ═══════════════════════════════════════════════════════════════════
   IMPRESSION — le même tableau de bord en rapport de marque (bouton
   « Rapport PDF » → impression → « Enregistrer en PDF »).
   La coque de l'application disparaît : il ne reste que l'en-tête de
   marque, les chiffres et les cartes, sur fond blanc.
   ═══════════════════════════════════════════════════════════════════ */
@media print {
  /* Palette claire imposée, même si le client lit son espace en sombre. */
  :root,
  :root[data-theme="dark"] {
    --shell: #ffffff;
    --surface: #ffffff;
    --surface-2: rgba(118, 118, 128, 0.09);
    --surface-3: rgba(118, 118, 128, 0.16);
    --card-bg: #ffffff;
    --card-line: rgba(60, 60, 67, 0.16);
    --border: rgba(60, 60, 67, 0.16);
    --border-strong: rgba(60, 60, 67, 0.3);
    --separator: rgba(60, 60, 67, 0.18);
    --text: #1c1c1e;
    --text-2: rgba(60, 60, 67, 0.68);
    --text-3: rgba(60, 60, 67, 0.45);
    --accent: #6c5ce7;
    --accent-soft: rgba(108, 92, 231, 0.12);
    --track: rgba(108, 92, 231, 0.14);
    --ambient: #ffffff;
    --shadow-card: none;
    --shadow-shell: none;
    --shadow-hover: none;
  }

  @page { margin: 13mm; }

  body {
    background: #fff;
    /* Les aplats de couleur (badges, courbe, anneaux) doivent sortir. */
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }

  /* Chrome de l'application : hors sujet sur un rapport. */
  .sidebar,
  .side-backdrop,
  .topbar,
  .toolbar,
  .footer,
  .menu,
  .page-head,
  .card-actions,
  .card-more,
  .link-more,
  .empty-action,
  td.chevron,
  table.table th:last-child { display: none !important; }

  .app {
    display: block;
    margin: 0;
    border-radius: 0;
    min-height: 0;
    box-shadow: none;
    background: #fff;
    overflow: visible;
  }
  .page { padding: 0; max-width: none; }
  .page-head { margin-bottom: 0.6rem; }
  .page-head h1 { font-size: 1.35rem; }

  .print-head { display: flex !important; }

  .card {
    background: #fff;
    border: 1px solid var(--card-line);
    box-shadow: none;
    break-inside: avoid;
  }
  .kpi-grid {
    grid-template-columns: repeat(4, 1fr);
    gap: 4mm;
    overflow: visible;
    border: 0;
    background: none;
    box-shadow: none;
  }
  .kpi-grid > .kpi,
  .kpi-grid > .kpi + .kpi {
    min-height: 4.7rem;
    padding: 0.85rem 0.9rem 0.9rem;
    border: 1px solid var(--card-line);
    border-radius: 14px;
    background: #fff;
  }
  .kpi-label { font-size: 0.8rem; }
  .kpi-value { font-size: 1.6rem; }
  /* Assez petit pour tenir « ↑ +36,4 % vs période précédente » sur une
     seule ligne dans une colonne de rapport. */
  .kpi-sub { font-size: 0.62rem; }
  .kpi-sub .delta.up, .kpi-sub .delta.down, .kpi-sub .delta.flat { font-size: 0.62rem; }
  .kpi-icon { width: 28px; height: 28px; border-radius: 9px; }
  .kpi-icon svg { width: 14px; height: 14px; }

  /* Une grille ne se coupe pas proprement entre deux pages : le rapport
     déroule les cartes en pleine largeur, l'une sous l'autre. */
  .grid-main, .col { display: block; }

  /* Carte de chaleur resserrée : elle tient ainsi sous le graphique au
     lieu de partir seule sur la page suivante. */
  .hm { gap: 6px; }
  .hm-cell { height: 26px; border-radius: 8px; }
  .hm-day, .hm-hour { font-size: 0.7rem; }
  .hm-foot { margin-top: 0.7rem; font-size: 0.72rem; }
  .heat-more { display: none; }
  .grid-wide { display: block; }
  .grid-wide .card { margin-bottom: 5mm; }
  .map-card { grid-template-columns: 170px minmax(0, 1fr); }
  .wm-pin { box-shadow: none; }
  .grid-main .card { margin-bottom: 5mm; }
  .table-wrap { overflow: visible; }

  /* Pages d'analyse : les commandes de filtre ne servent à rien sur papier,
     et les grilles se déroulent en pleine largeur. */
  .filters, .leads-toolbar, .segmented, .notice { display: none !important; }
  .antabs { display: none !important; }
  .info-dot, .stat-setting-form,
  .brief-value-setting .link-more { display: none !important; }
  .grid-2 { display: block; }
  .grid-2 > .card { margin-bottom: 5mm; }
  .tiles { grid-template-columns: repeat(4, 1fr); gap: 4mm; }
  .tile { padding: 0.85rem 0.9rem 0.9rem; }
  .tile-value { font-size: 1.5rem; }
  .hbar-fill, .funnel-band { transition: none !important; }

  /* Rien ne clignote ni ne glisse sur une feuille de papier. */
  .reveal, .row-in, .kw { animation: none !important; }
  /* Un bloc jamais entré dans l'écran doit quand même s'imprimer. */
  .reveal-pending { opacity: 1 !important; }
  .wm-enter .wm-svg { animation: none !important; }
  .wm-enter .wm-c, .colbar, .funnel-band { transition: none !important; }
  .skeleton { animation: none !important; }
  .hm-cell { animation: none !important; }

  /* Le résumé reste dans le rapport ; la file d'actions, purement
     opérationnelle, n'a pas de sens dans un document exporté. */
  .dashboard-view .executive-brief {
    min-height: 0;
    margin-bottom: 5mm;
    padding: 7mm;
    border-radius: 14px;
    box-shadow: none;
  }
  .dashboard-view .kpi {
    display: grid;
    min-height: 4.7rem;
    padding: 0.85rem 0.9rem 0.9rem;
    transform: none;
  }
  .dashboard-view .kpi-grid > .kpi,
  .dashboard-view .kpi-grid > .kpi + .kpi {
    border: 1px solid var(--card-line);
    border-radius: 14px;
    background: #fff;
  }
  .dashboard-view .kpi-label { font-size: 0.8rem; }
  .dashboard-view .kpi-value { font-size: 1.6rem; }
  .dashboard-view .attention-card { display: none !important; }
}
