/* ============================================================
   Jenna's World — CRM · LA feuille de style (un seul fichier depuis le 28/09,
   mission CRM + bot : « un seul CSS, journal.css est la vérité des jetons »).

   Trois fichiers ont été fondus ici DANS LEUR ORDRE DE CHARGEMENT, pour que
   la cascade reste exactement celle d'avant :
     1. style.css  — design system v8 « Daylight » (27/08) : jetons de base,
        composants, pages Gallery / Sets / Profil / Voice & Style ;
     2. m4.css     — presets Voice & Style, aperçu persona ;
     3. journal.css (10/09, piste « Journal ») — les jetons Telegram qui
        REDÉFINISSENT ceux de style.css, la barre latérale, Today,
        Conversations, Fans, la barre d'onglets mobile.
   Les règles des pages retirées le 28/09 (Broadcasts, Channel, Lists,
   Automations, Referrals, Team, Scripts, Her rhythm, bundles, cloche,
   réponses rapides) ont été enlevées : chaque sélecteur restant vise une
   classe ou un id encore présent dans index.html ou app.js. crm.css (jamais
   chargé) est supprimé. Une règle nouvelle va en bas, dans la partie
   « Journal » : c'est elle qui a le dernier mot.
   ============================================================ */

/* ==================== [style.css — fondu le 28/09] ==================== */
/* ============================================================
   Jenna's World — CRM · Design System v8 « Daylight »
   REFONTE COMPLÈTE (27/08/2026) — direction « Motoko 2026 »

   Principes :
   - CLAIR PAR DÉFAUT — papier #f5f5f5, cartes blanches, encre #111.
     Le thème sombre chaleureux reste disponible ([data-theme="dark"]).
   - Élévation par FOND, pas par ombre : les ombres sont quasi nulles.
   - Un seul accent : l'encre (noir neutre). Aucune couleur criarde,
     aucun glow, aucun dégradé décoratif, aucun emoji comme icône.
   - Grille 8px, rayons 10/14/18px, Inter, chiffres tabulaires,
     marges généreuses.
   ============================================================ */

/* ============================================================
   1. TOKENS — clair par défaut
   ============================================================ */
:root,
[data-theme="light"] {
  /* Surfaces : papier → carte → creux */
  --bg: #f5f4f2;
  --panel: #ffffff;
  --surface: #faf9f7;
  --surface-2: #f1efec;
  --elevated: #ffffff;

  /* Encre : 4 niveaux */
  --text: #14120f;
  --text1: #14120f;
  --text2: #6e6862;
  --text3: #9a938b;

  /* Hairlines — presque invisibles, juste de quoi poser la carte */
  --border: rgba(20, 18, 15, 0.08);
  --border-strong: rgba(20, 18, 15, 0.15);
  --row-border: rgba(20, 18, 15, 0.06);
  --line-tint: rgba(20, 18, 15, 0.065);

  /* Accent unique — l'encre */
  /* Accent UNIQUE : bleu Telegram. Il ne sert qu'aux actions, aux liens
     et aux repères actifs — tout le reste reste gris chaud. */
  --accent: #229ed9;
  --accent-hover: #157cb0;
  --accent-active: #126b99;
  --accent-bright: #229ed9;
  --accent-solid: #229ed9;
  --accent-solid-hover: #1c8dc4;
  --accent-grad: #229ed9;
  --accent-grad-hover: #1c8dc4;
  --on-accent: #ffffff;
  --accent-soft: rgba(34, 158, 217, 0.1);
  --accent-wash: rgba(34, 158, 217, 0.055);
  --accent-ring: rgba(34, 158, 217, 0.4);
  --accent-line: rgba(34, 158, 217, 0.3);
  --accent-border-soft: rgba(34, 158, 217, 0.24);
  --accent-border-hover: rgba(34, 158, 217, 0.42);
  --accent-glow: transparent;
  --halo: transparent;
  --btn-primary-glow: none;
  --logo-shadow: none;

  /* Sémantique — sourde, toujours doublée d'un libellé */
  --ok: #17795e;   --ok-soft: rgba(23, 121, 94, 0.09);
  --warn: #8a5a12; --warn-soft: rgba(138, 90, 18, 0.09);
  --warn-border: rgba(138, 90, 18, 0.2);
  --err: #b3261e;  --err-soft: rgba(179, 38, 30, 0.08);

  /* Remplissages génériques */
  --hover-fill: rgba(20, 18, 15, 0.045);
  --tint: rgba(20, 18, 15, 0.02);
  --tint-2: rgba(20, 18, 15, 0.035);
  --chip-bg: rgba(20, 18, 15, 0.045);
  --chip-hover: rgba(20, 18, 15, 0.08);
  --btn-ghost-hover: rgba(20, 18, 15, 0.045);
  --file-btn-bg: rgba(20, 18, 15, 0.045);
  --file-btn-hover: rgba(20, 18, 15, 0.08);
  --file-btn-border: rgba(20, 18, 15, 0.14);
  --track-bg: rgba(20, 18, 15, 0.07);
  --step-bg: rgba(20, 18, 15, 0.025);
  --step-hover: rgba(20, 18, 15, 0.05);
  --code-bg: rgba(20, 18, 15, 0.05);
  --code-text: #423c35;
  --overlay: rgba(24, 24, 24, 0.34);

  /* Chat — bulles blanches / grises, aucune couleur */
  --bubble-in: #f1efec;
  --bubble-out: #ffffff;
  --bubble-out-border: rgba(20, 18, 15, 0.1);

  /* Surfaces translucides */
  --topbar-bg: rgba(245, 244, 242, 0.85);
  --sidebar-bg: #f5f4f2;
  --pop-bg: rgba(255, 255, 255, 0.98);
  --toast-bg: #f2f1ef;
  --toast-text: #121215;

  /* Ombres — quasi inexistantes : l'élévation vient du fond */
  --shadow-sm: 0 1px 2px rgba(20, 18, 15, 0.03);
  --shadow-md: 0 1px 2px rgba(20, 18, 15, 0.04), 0 4px 12px rgba(20, 18, 15, 0.04);
  --shadow-lg: 0 2px 6px rgba(20, 18, 15, 0.05), 0 12px 32px rgba(20, 18, 15, 0.07);
  --shadow-float: 0 4px 12px rgba(20, 18, 15, 0.07), 0 20px 48px rgba(20, 18, 15, 0.1);

  /* Chart — nuances d'encre uniquement */
  --seg-dm: #229ed9;
  --seg-subs: #7fc7e6;
  --seg-channel: #d6d2cc;
  --scroll-thumb: rgba(20, 18, 15, 0.14);
  --scroll-thumb-hover: rgba(20, 18, 15, 0.26);

  /* Géométrie */
  --r-xs: 10px;
  --r-sm: 12px;
  --r: 16px;
  --r-lg: 18px;
  --sidebar-w: 256px;
  --topbar-h: 56px;   /* 20/10 (audit UI prod, défaut 1) : 72 → 56 px ; la carte de la créatrice garde ses 72 px (.brand) */
  --gutter: 32px;
  --ease: 0.16s cubic-bezier(0.4, 0, 0.2, 1);

  /* ------------------------------------------------------------
     Base 8 px (idée 14) — le RYTHME DE LA PAGE
     ------------------------------------------------------------
     Ces paliers gouvernent la STRUCTURE : marge sous un en-tête de
     page, écart entre deux panneaux, gouttière d'une grille de
     cartes. C'est là que les pages divergeaient (20, 22, 24, 30 px
     selon l'écran) — pas dans le détail des composants.

     Ils ne gouvernent PAS la micro-typographie interne (l'écart de
     3 px entre une puce et son libellé, le padding d'un badge) :
     forcer ces valeurs-là sur 8 px déformerait des composants déjà
     validés. Le thème reste aéré : on a arrondi le rythme dominant
     de 20 px VERS LE HAUT (24 px), jamais vers le bas.
     ------------------------------------------------------------ */
  --sp-1: 8px;
  --sp-2: 16px;
  --sp-3: 24px;   /* rythme par défaut entre deux blocs d'une page */
  --sp-4: 32px;
  --sp-6: 48px;
  --sp-8: 64px;

  color-scheme: light;
}

/* ---------- Thème SOMBRE chaleureux (optionnel) ---------- */
[data-theme="dark"] {
  --bg: #121215;
  --panel: #1a1a1e;
  --surface: #212126;
  --surface-2: #2a2a30;
  --elevated: #32323a;

  --text: #f3f1ee;
  --text1: #f3f1ee;
  --text2: #a5a09a;
  --text3: #78736d;

  --border: rgba(255, 252, 246, 0.075);
  --border-strong: rgba(255, 252, 246, 0.15);
  --row-border: rgba(255, 252, 246, 0.055);
  --line-tint: rgba(255, 252, 246, 0.06);

  --accent: #229ed9;
  --accent-hover: #6ec3ea;
  --accent-active: #8ed2ef;
  --accent-bright: #229ed9;
  --accent-solid: #229ed9;
  --accent-solid-hover: #35abe0;
  --accent-grad: #229ed9;
  --accent-grad-hover: #35abe0;
  --on-accent: #ffffff;
  --accent-soft: rgba(34, 158, 217, 0.16);
  --accent-wash: rgba(34, 158, 217, 0.08);
  --accent-ring: rgba(34, 158, 217, 0.45);
  --accent-line: rgba(34, 158, 217, 0.34);
  --accent-border-soft: rgba(34, 158, 217, 0.26);
  --accent-border-hover: rgba(34, 158, 217, 0.44);
  --accent-glow: transparent;
  --halo: transparent;
  --btn-primary-glow: none;
  --logo-shadow: none;

  --ok: #6ec99a;   --ok-soft: rgba(110, 201, 154, 0.13);
  --warn: #e0b45f; --warn-soft: rgba(224, 180, 95, 0.12);
  --warn-border: rgba(224, 180, 95, 0.28);
  --err: #e88b7f;  --err-soft: rgba(232, 139, 127, 0.13);

  --hover-fill: rgba(255, 252, 246, 0.055);
  --tint: rgba(255, 252, 246, 0.025);
  --tint-2: rgba(255, 252, 246, 0.045);
  --chip-bg: rgba(255, 252, 246, 0.055);
  --chip-hover: rgba(255, 252, 246, 0.1);
  --btn-ghost-hover: rgba(255, 252, 246, 0.07);
  --file-btn-bg: rgba(255, 252, 246, 0.06);
  --file-btn-hover: rgba(255, 252, 246, 0.11);
  --file-btn-border: rgba(255, 252, 246, 0.16);
  --track-bg: rgba(255, 252, 246, 0.08);
  --step-bg: rgba(255, 252, 246, 0.035);
  --step-hover: rgba(255, 252, 246, 0.07);
  --code-bg: rgba(255, 252, 246, 0.06);
  --code-text: #c8c8d0;
  --overlay: rgba(8, 8, 10, 0.7);

  --bubble-in: #26262c;
  --bubble-out: #163243;
  --bubble-out-border: rgba(34, 158, 217, 0.3);

  --topbar-bg: rgba(18, 18, 21, 0.82);
  --sidebar-bg: #121215;
  --pop-bg: rgba(50, 50, 58, 0.97);
  --toast-bg: #14120f;
  --toast-text: #ffffff;

  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
  --shadow-md: 0 2px 10px rgba(0, 0, 0, 0.34);
  --shadow-lg: 0 10px 34px rgba(0, 0, 0, 0.44);
  --shadow-float: 0 18px 52px rgba(0, 0, 0, 0.52);

  --seg-dm: #229ed9;
  --seg-subs: #4a7f96;
  --seg-channel: #3a3a42;
  --scroll-thumb: rgba(255, 252, 246, 0.13);
  --scroll-thumb-hover: rgba(255, 252, 246, 0.24);

  color-scheme: dark;
}

/* ============================================================
   2. BASE
   ============================================================ */
*,
*::before,
*::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scrollbar-color: var(--scroll-thumb) transparent;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI",
    system-ui, sans-serif;
  font-size: 14px;
  font-weight: 500;
  line-height: 1.55;
  letter-spacing: -0.006em;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-variant-numeric: tabular-nums;
}

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

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--scroll-thumb);
  border-radius: 99px;
  border: 3px solid transparent;
  background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover { background: var(--scroll-thumb-hover); background-clip: content-box; }

a { color: var(--accent); text-decoration: none; transition: color var(--ease); }
a:hover { color: var(--accent-hover); }

h1, h2, h3, h4 {
  margin: 0;
  font-weight: 650;
  letter-spacing: -0.022em;
  color: var(--text);
  text-wrap: balance;
}
h1 { font-size: 32px; }

p { margin: 0 0 12px; }
p:last-child { margin-bottom: 0; }

code {
  font-family: ui-monospace, "SF Mono", "JetBrains Mono", Menlo, monospace;
  font-size: 12px;
  background: var(--code-bg);
  color: var(--code-text);
  padding: 2px 6px;
  border-radius: 6px;
}
/* 20/10 (audit UI prod, défaut 4) : échelle unique 12 / 14 / 18 / 32 px ; <small> valait « smaller »
   du navigateur (11,67 px sous un texte de 14, 10 px sous 12) : ramené à la plus petite marche. */
small { font-size: 12px; }
/* 20/10 (audit UI prod, lot 3) : un contrôle sans font-size explicite retombait sur le défaut du
   navigateur, 13,33 px (recherche des Sets, curseur de la Galerie, Save de tête des Sets, lignes de
   l'écran Fans, cases de Voice & Style). Base de l'échelle pour tous ; les règles de classe gardent
   leurs 12 ou 18 px, le placeholder suit le champ. */
input, select, textarea, button { font-family: inherit; font-size: 14px; }

img { max-width: 100%; }

/* Focus visible unifié */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--accent-ring);
  outline-offset: 2px;
  border-radius: var(--r-xs);
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ---------- Utilitaires ---------- */
.hidden { display: none !important; }
.muted { color: var(--text2); }
.small { font-size: 12px; }
.error-text { color: var(--err); font-size: 14px; margin: 8px 0 0; }
.ok-text { color: var(--ok); font-size: 14px; }

/* ============================================================
   3. SHELL — sidebar + main + topbar
   ============================================================ */
.app {
  display: grid;
  grid-template-columns: var(--sidebar-w) minmax(0, 1fr);
  min-height: 100vh;
}

/* ---------- Sidebar façon Notion ---------- */
.sidebar {
  position: fixed;
  top: 0;
  left: 0;
  width: var(--sidebar-w);
  height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--sidebar-bg);
  border-right: 1px solid var(--border);
  z-index: 60;
  overflow-y: auto;
  overscroll-behavior: contain;
}

.brand {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 0 18px;
  height: 72px;
  flex: none;
}

.brand-name {
  font-size: 14px;
  font-weight: 650;
  letter-spacing: -0.02em;
  line-height: 1.2;
}
.brand-sub {
  font-size: 12px;
  font-weight: 500;
  color: var(--text3);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin-top: 2px;
}

.nav {
  flex: 1;
  padding: 4px 12px 16px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.nav-link {
  display: flex;
  align-items: center;
  gap: 11px;
  height: 40px;
  padding: 0 12px;
  border: 1px solid transparent;
  border-radius: var(--r);
  color: var(--text2);
  font-size: 14px;
  font-weight: 500;
  letter-spacing: -0.012em;
  transition: background var(--ease), color var(--ease), border-color var(--ease);
}
.nav-link:hover { background: var(--hover-fill); color: var(--text); }
/* Actif = carte blanche posée sur le papier (référence), pas une pastille colorée. */
.nav-link.active {
  background: var(--panel);
  border-color: var(--border);
  color: var(--text);
  font-weight: 600;
  box-shadow: var(--shadow-sm);
}
.nav-ico {
  flex: none;
  width: 18px;
  height: 18px;
  display: grid;
  place-items: center;
  color: var(--text3);
  transition: color var(--ease);
}
.nav-ico svg { width: 17px; height: 17px; display: block; }
.nav-link:hover .nav-ico { color: var(--text2); }
.nav-link.active .nav-ico { color: var(--accent); }

/* Groupe « Advanced » repliable */

.sidebar-footer {
  padding: 12px 12px 16px;
  border-top: 1px solid var(--border);
  margin-top: auto;
  position: sticky;
  bottom: 0;
  background: var(--sidebar-bg);
}
.sidebar-footer .btn { justify-content: flex-start; }

/* ---------- Main ---------- */
.main {
  grid-column: 2;
  min-width: 0;
  padding: calc(var(--topbar-h) + 8px) var(--gutter) 88px;
}

.page { max-width: 1240px; }
/* `backwards` et non `both` : avec `both`, l'image finale de `pageIn`
   (transform) restait appliquée pour toujours, ce qui faisait de la section
   un BLOC CONTENEUR pour les `position: fixed` qu'elle contient. Les
   modales AI Offers (#offer-modal, #offer-fan-modal) se retrouvaient donc
   enfermées dans la hauteur de la page : carte coupée, voile partiel et
   bouton « Save offer » hors écran. `backwards` garde l'animation d'entrée
   et rend `transform: none` une fois terminée. */
.page.fade-in { animation: pageIn 0.26s cubic-bezier(0.22, 0.61, 0.36, 1) backwards; }
@keyframes pageIn {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: none; }
}
.fade-in .stat-card { animation: cardIn 0.32s cubic-bezier(0.22, 0.61, 0.36, 1) both; }
.fade-in .stat-card:nth-child(2) { animation-delay: 0.03s; }
.fade-in .stat-card:nth-child(3) { animation-delay: 0.06s; }
.fade-in .stat-card:nth-child(4) { animation-delay: 0.09s; }
.fade-in .stat-card:nth-child(n+5) { animation-delay: 0.12s; }
@keyframes cardIn {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: none; }
}

/* ---------- Page header ---------- */
.page-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--sp-2) var(--sp-3);
  flex-wrap: wrap;
  margin: 0 0 var(--sp-3);      /* 20 -> 24 */
}
.page h2 {
  flex: 1 1 260px;
  min-width: 0;
  font-size: 18px;
  font-weight: 640;
  letter-spacing: -0.024em;
  display: flex;
  flex-direction: column;
  gap: 3px;
}
/* Le titre principal vit dans le header fixe : les en-têtes de section
   internes restent discrets, et la période y est masquée (pilotée en haut). */
.page-head-slim h2 { font-size: 18px; font-weight: 620; }

/* Les actions du header restent sur UNE ligne (jamais d'empilement). */
.page-head > .btn-group,
.page-head > .btn { flex: 0 0 auto; flex-wrap: nowrap; }
.page-sub {
  display: block;
  font-size: 14px;
  font-weight: 450;
  color: var(--text2);
  letter-spacing: -0.006em;
}
.btn-group {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

/* ---------- Topbar = header de page (titre + période + ⌘K + cloche) ---------- */
.topbar {
  position: fixed;
  top: 0;
  left: var(--sidebar-w);
  right: 0;
  height: var(--topbar-h);
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 0 var(--gutter);
  background: var(--bg);
  z-index: 50;
}
.topbar-title {
  flex: none;
  margin: 0;
  font-size: 32px;
  font-weight: 700;
  letter-spacing: -0.035em;
  color: var(--text);
  white-space: nowrap;
}

/* Sélecteur de période — pilules, l'active en carte blanche */
.topbar-period {
  display: flex;
  align-items: center;
  gap: 2px;
  flex: none;
}
.period-btn {
  border: 1px solid transparent;
  background: transparent;
  color: var(--text2);
  font-family: inherit;
  font-size: 14px;
  font-weight: 500;
  letter-spacing: -0.01em;
  height: 36px;
  padding: 0 16px;
  border-radius: 99px;
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--ease), color var(--ease), border-color var(--ease);
}
.period-btn:hover { color: var(--text); background: var(--hover-fill); }
.period-btn-active {
  background: var(--panel);
  border-color: var(--border);
  color: var(--text);
  font-weight: 600;
}
.period-btn-active:hover { background: var(--panel); }

/* Actions à droite */
.topbar-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-left: auto;
  min-width: 0;
}

.month-rev {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 40px;
  padding: 0 14px;
  border-radius: 99px;
  background: var(--panel);
  border: 1px solid var(--border);
  color: var(--text2);
  font-size: 14px;
  font-weight: 550;
  white-space: nowrap;
}
.bell, .theme-toggle, .sidebar-toggle {
  width: 40px;
  height: 40px;
  flex: none;
  display: grid;
  place-items: center;
  border-radius: 99px;
  border: 1px solid var(--border);
  background: var(--panel);
  color: var(--text2);
  cursor: pointer;
  position: relative;
  padding: 0;
  font-size: 14px;
  line-height: 1;
  transition: background var(--ease), color var(--ease), border-color var(--ease);
}
.bell:hover, .theme-toggle:hover, .sidebar-toggle:hover {
  background: var(--surface);
  border-color: var(--border-strong);
  color: var(--text);
}
.bell svg { width: 17px; height: 17px; }

.sidebar-toggle { display: none; position: fixed; top: 16px; left: 16px; z-index: 70; }
.sidebar-overlay { display: none; }

/* ---------- Panneau notifications ---------- */

/* ============================================================
   4. SURFACES — panels, banners, grilles
   ============================================================ */
.panel {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: var(--sp-3);
  margin-bottom: var(--sp-3);   /* 20 -> 24 : rythme unique entre blocs */
  box-shadow: var(--shadow-sm);
}
.panel h3 {
  font-size: 14px;
  font-weight: 640;
  letter-spacing: -0.018em;
  margin: 0 0 16px;
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.two-col {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--sp-3);             /* 20 -> 24 */
  align-items: start;
}
.two-col > .panel {
  margin-bottom: var(--sp-3);
  /* Un enfant de grille refuse par défaut de devenir plus étroit que son
     contenu (`min-width: auto`) : un tableau large faisait donc déborder la
     PAGE de quelques pixels (déjà 1 px avant l'harmonisation, 3 px après).
     `min-width: 0` autorise le panneau à se réduire ; le tableau défile
     alors dans son panneau au lieu de pousser la page. */
  min-width: 0;
}
.two-col > .panel > .table-wrap,
.two-col > .panel { overflow-x: auto; }
/* Une seule colonne réellement visible → pas de moitié d'écran vide. */
.two-col:has(> .panel.hidden) { grid-template-columns: minmax(0, 780px); }

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 16px;
  align-items: start;
}

/* « More details » repliable du dashboard */
.dash-more { margin-top: var(--sp-1); }   /* 4 -> 8 */
.dash-more summary {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 16px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--r);
  cursor: pointer;
  list-style: none;
  font-size: 14px;
  font-weight: 600;
  color: var(--text2);
  user-select: none;
  transition: background var(--ease), color var(--ease);
}
.dash-more summary::-webkit-details-marker { display: none; }
.dash-more summary:hover { background: var(--surface); color: var(--text); }
.dash-more summary::after {
  content: "";
  margin-left: auto;
  width: 7px;
  height: 7px;
  border-right: 1.6px solid currentColor;
  border-bottom: 1.6px solid currentColor;
  transform: rotate(45deg) translate(-2px, -2px);
  opacity: 0.6;
  transition: transform var(--ease);
}
.dash-more[open] summary::after { transform: rotate(225deg) translate(-2px, -2px); }
.dash-more-count { font-weight: 450; color: var(--text3); }
.dash-more[open] > .panel { margin-top: 16px; }

/* ============================================================
   5. HERO + ONBOARDING (dashboard)
   ============================================================ */
/* Salutation : du texte posé sur le papier, aucune carte — l'air fait
   le travail. C'est le seul endroit où l'app parle à la première
   personne : date du jour, bonjour, puis une nouvelle du jour. */

@keyframes heroIn {
  from { opacity: 0; transform: translateY(5px); }
  to { opacity: 1; transform: none; }
}

.onboarding-card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: 18px 20px;
  margin-bottom: var(--sp-3);   /* 20 -> 24 */
  box-shadow: var(--shadow-sm);
}

/* ---------- Boutique encore vide : le parcours en trois étapes ----------
   Rien n'a été vendu : c'est le moment de dire quoi faire, pas d'aligner
   des zéros. Le parcours prend la place que prendraient les chiffres. */
.dash-empty {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: 28px 28px 26px;
  margin-bottom: 24px;
  box-shadow: var(--shadow-sm);
  animation: heroIn 0.5s 0.04s cubic-bezier(0.22, 0.61, 0.36, 1) both;
}

/* ---------- Cartes KPI encore endormies ----------
   Regroupées hors de la grille principale : un libellé, ce qui les
   remplira, et un tiret. Aucun « 0 » ne crie sur la page. */
   /* -6 -> 0 */

.quiet-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(276px, 1fr));
  gap: 10px;
}
.quiet-card {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 13px 16px;
  border-radius: var(--r-sm);
  background: var(--surface);
  border: 1px solid var(--border);
  transition: border-color var(--ease), background var(--ease);
}
.quiet-card:hover { border-color: var(--border-strong); background: var(--panel); }
.quiet-ico {
  flex: none;
  width: 18px;
  height: 18px;
  display: grid;
  place-items: center;
  color: var(--text3);
}
.quiet-ico svg { width: 17px; height: 17px; display: block; }
.quiet-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.quiet-label {
  font-size: 14px;
  font-weight: 550;
  color: var(--text2);
  letter-spacing: -0.012em;
}
.quiet-hint {
  font-size: 12px;
  font-weight: 450;
  color: var(--text3);
  line-height: 1.45;
}
.quiet-dash {
  flex: none;
  font-size: 18px;
  font-weight: 500;
  color: var(--text3);
  opacity: 0.55;
}

/* ============================================================
   6. KPI CARDS + CHARTS
   ============================================================ */
.stats-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(232px, 1fr));
  gap: var(--sp-2);
  margin-bottom: var(--sp-3);
}
.stat-card {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: 20px 20px 18px;
  box-shadow: var(--shadow-sm);
  transition: border-color var(--ease);
}
/* Micro-interaction : la carte se « réveille » — la bordure se précise,
   l'icône reprend de l'encre. Aucun mouvement brusque, aucune ombre. */
.stat-card:hover { border-color: var(--border-strong); }
.stat-card:hover .stat-icon { color: var(--text); }
.stat-card .stat-value { transition: letter-spacing var(--ease); }
/* Ligne du haut : libellé à gauche, icône fine à droite (référence). */
.stat-top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 16px;
}
.stat-icon {
  flex: none;
  width: 20px;
  height: 20px;
  display: grid;
  place-items: center;
  color: var(--text3);
}
.stat-icon svg { width: 18px; height: 18px; display: block; }
.stat-label {
  font-size: 14px;
  font-weight: 550;
  color: var(--text2);
  letter-spacing: -0.012em;
  min-width: 0;
}
.stat-value {
  font-size: 32px;
  font-weight: 620;
  letter-spacing: -0.038em;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
  color: var(--text);
}
.stat-trend {
  margin-top: 10px;
  font-size: 12px;
  font-weight: 450;
  color: var(--text3);
}
.stat-trend.up, .stat-trend.down {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 8px;
  border-radius: 99px;
  font-weight: 600;
}
.stat-trend.up { color: var(--ok); background: var(--ok-soft); }
.stat-trend.down { color: var(--err); background: var(--err-soft); }

/* ---------- Feed d'activité récente (dashboard) ---------- */

/* Entrée en cascade : le feed se remplit, il n'apparaît pas d'un bloc. */

@keyframes rowIn {
  from { opacity: 0; transform: translateY(4px); }
  to { opacity: 1; transform: none; }
}

/* ---------- Bar chart (HTML/CSS pur) ---------- */
.chart {
  display: flex;
  align-items: flex-end;
  gap: 6px;
  height: 190px;
  padding: 12px 4px 30px;
  position: relative;
}
.chart-lg { height: 230px; }
.chart .empty-state { margin: auto; padding: 0; border: 0; background: none; }
.chart .empty-state .empty-ico { width: 44px; height: 44px; margin-bottom: 6px; }
.chart .empty-state .empty-title { font-size: 14px; }
.chart .empty-state .empty-desc { font-size: 12px; }

/* ---------- Aperçu de graphique (aucune donnée) ----------
   Plutôt qu'un cadre vide : la silhouette pâle des barres à venir, et
   une légende posée au centre. Les barres ne portent aucun chiffre —
   elles ne décrivent rien, elles montrent seulement la forme. */
.chart-is-ghost { display: block; height: 210px; padding: 12px 4px 24px; }
/* Les barres occupent la moitié basse et s'effacent en montant ; la légende
   a la moitié haute pour elle seule — aucun texte ne passe sur une barre. */
.chart-ghost {
  position: absolute;
  inset: 48% 4px 24px;
  display: flex;
  align-items: flex-end;
  gap: 6px;
  -webkit-mask-image: linear-gradient(to top, #000 0%, rgba(0, 0, 0, 0.3) 100%);
  mask-image: linear-gradient(to top, #000 0%, rgba(0, 0, 0, 0.3) 100%);
}
.chart-ghost-bars {
  display: flex;
  align-items: flex-end;
  gap: 6px;
  width: 100%;
  height: 100%;
}
.ghost-bar {
  flex: 1;
  border-radius: 7px 7px 3px 3px;
  background: var(--line-tint);
}
.chart-ghost-note {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 48%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 5px;
  text-align: center;
  padding: 0 24px;
}
.chart-ghost-title {
  font-size: 14px;
  font-weight: 600;
  letter-spacing: -0.012em;
  color: var(--text2);
}
.chart-ghost-desc {
  font-size: 12px;
  font-weight: 450;
  color: var(--text3);
  max-width: 46ch;
  line-height: 1.55;
}

/* ---------- Aperçu du feed d'activité (aucune donnée) ---------- */

.bar {
  position: relative;
  flex: 1;
  min-width: 8px;
  border-radius: 6px 6px 3px 3px;
  background: var(--accent-solid);
  opacity: 0.9;
  transition: opacity var(--ease), filter var(--ease);
  align-self: flex-end;
}
.bar:hover { opacity: 1; }
.bar .tip {
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%);
  background: var(--elevated);
  border: 1px solid var(--border);
  color: var(--text);
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
  padding: 4px 8px;
  border-radius: 8px;
  box-shadow: var(--shadow-md);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--ease);
  z-index: 5;
}
.bar:hover .tip { opacity: 1; }
.bar .day {
  position: absolute;
  top: calc(100% + 7px);
  left: 50%;
  transform: translateX(-50%);
  font-size: 12px;
  font-weight: 500;
  color: var(--text3);
  white-space: nowrap;
}

.seg-dm { background: var(--seg-dm); }
.seg-subs { background: var(--seg-subs); }
.seg-channel { background: var(--seg-channel); }

.legend {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin-top: 10px;
  padding-top: 12px;
  border-top: 1px solid var(--row-border);
}
.legend-item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--text2);
}
.dot { width: 9px; height: 9px; border-radius: 3px; display: inline-block; }

/* ---------- Barres horizontales ---------- */

/* ============================================================
   7. BOUTONS
   ============================================================ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  height: 38px;
  padding: 0 16px;
  border-radius: 99px;
  border: 1px solid var(--border);
  background: var(--panel);
  color: var(--text);
  font-family: inherit;
  font-size: 14px;
  font-weight: 550;
  letter-spacing: -0.01em;
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--ease), border-color var(--ease),
              color var(--ease), transform var(--ease), box-shadow var(--ease);
}
.btn:hover { background: var(--surface); border-color: var(--border-strong); }
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: 0.45; cursor: not-allowed; transform: none; }

/* Primaire = pilule d'encre pleine (bouton « Sign in » de la référence). */
.btn-primary {
  background: var(--accent-solid);
  border-color: transparent;
  color: var(--on-accent);
  font-weight: 600;
  box-shadow: none;
}
.btn-primary:hover { background: var(--accent-solid-hover); border-color: transparent; }
.btn-primary:disabled { box-shadow: none; }

.btn-ghost {
  background: transparent;
  border-color: var(--border);
  color: var(--text2);
}
.btn-ghost:hover { background: var(--btn-ghost-hover); color: var(--text); }

.btn-danger {
  background: transparent;
  border-color: var(--err-soft);
  color: var(--err);
}
.btn-danger:hover { background: var(--err-soft); border-color: var(--err); }

.btn-sm { height: 32px; padding: 0 13px; font-size: 12px; border-radius: 99px; }
.btn-block { width: 100%; }

.row-actions { display: flex; gap: 6px; flex-wrap: wrap; }

/* ============================================================
   8. BADGES + TAGS
   ============================================================ */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 8px;
  border-radius: 99px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: -0.002em;
  background: var(--chip-bg);
  color: var(--text2);
  white-space: nowrap;
  vertical-align: middle;
}
.badge-active, .badge.purple { background: var(--accent-soft); color: var(--accent); }
.badge.green, .badge-ok { background: var(--ok-soft); color: var(--ok); }
.badge.red { background: var(--err-soft); color: var(--err); }
.badge.warn { background: var(--warn-soft); color: var(--warn); }
.badge.gray { background: var(--chip-bg); color: var(--text3); }
.badge-draft { background: var(--warn-soft); color: var(--warn); }
.badge-inuse { background: var(--ok-soft); color: var(--ok); }

.tag {
  display: inline-block;
  padding: 2px 8px;
  margin: 0 4px 4px 0;
  border-radius: 99px;
  background: var(--chip-bg);
  border: 1px solid var(--border);
  color: var(--text2);
  font-size: 12px;
}

/* ============================================================
   9. TABLES
   ============================================================ */
.table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}
.table th {
  text-align: left;
  padding: 0 12px 10px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.045em;
  text-transform: uppercase;
  color: var(--text3);
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
.table td {
  padding: 11px 12px;
  border-bottom: 1px solid var(--row-border);
  color: var(--text2);
  vertical-align: middle;
}
.table td b { color: var(--text); font-weight: 600; }
.table tr:last-child td { border-bottom: 0; }
.table tbody tr { transition: background var(--ease); }
.table tbody tr:hover { background: var(--tint); }
tr[onclick] { cursor: pointer; }

/* ============================================================
   10. FORMULAIRES
   ============================================================ */
.form-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
  margin-bottom: 16px;
}
.form-grid label,
.form-grid > .full {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 12px;
  font-weight: 550;
  color: var(--text2);
  min-width: 0;
}
.form-grid label.full,
.form-grid .full { grid-column: 1 / -1; }
/* « ≈ $3.90 » sous un prix saisi en Stars (set, post Channel) — même
   lecture que sur la page Offres : elle raisonne en dollars, la facture
   reste en Stars (demande de la propriétaire du 13/09). */

input[type="text"],
input[type="password"],
input[type="number"],
input[type="email"],
select,
textarea {
  width: 100%;
  min-width: 0;
  height: 40px;
  padding: 0 12px;
  border-radius: var(--r-sm);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  font-family: inherit;
  font-size: 14px;
  font-weight: 500;
  transition: border-color var(--ease), box-shadow var(--ease), background var(--ease);
}
textarea {
  height: auto;
  min-height: 76px;
  padding: 10px 12px;
  line-height: 1.55;
  resize: vertical;
}
input::placeholder, textarea::placeholder { color: var(--text3); font-weight: 450; }
input:hover, select:hover, textarea:hover { border-color: var(--border-strong); }
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-ring);
  background: var(--panel);
}
input:disabled, select:disabled, textarea:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  background: var(--tint);
}

select,
.period-select,
.test-fan-select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 32px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2371717c' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
  background-size: 15px;
  cursor: pointer;
}

input[type="checkbox"] {
  width: 16px;
  height: 16px;
  min-width: 16px;
  accent-color: var(--accent-solid);
  cursor: pointer;
}
.form-grid label:has(> input[type="checkbox"]) {
  flex-direction: row;
  align-items: center;
  gap: 8px;
  color: var(--text2);
  font-size: 14px;
}

.form-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 4px;
}

input[type="file"] {
  font-size: 12px;
  color: var(--text2);
  height: auto;
  padding: 8px;
  cursor: pointer;
}
input[type="file"]::file-selector-button {
  margin-right: 10px;
  padding: 6px 12px;
  border-radius: var(--r-xs);
  border: 1px solid var(--file-btn-border);
  background: var(--file-btn-bg);
  color: var(--text);
  font-family: inherit;
  font-size: 12px;
  font-weight: 550;
  cursor: pointer;
  transition: background var(--ease);
}
input[type="file"]::file-selector-button:hover { background: var(--file-btn-hover); }

/* ============================================================
   11. ÉTATS VIDES
   ============================================================ */
.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  text-align: center;
  padding: 44px 24px;
  color: var(--text2);
}
/* Un état vide doit être accueillant : icône fine dans un halo doux,
   une phrase humaine, et toujours une porte de sortie (le CTA). */
.empty-state .empty-ico {
  width: 52px;
  height: 52px;
  display: grid;
  place-items: center;
  border-radius: 99px;
  background: var(--surface-2);
  color: var(--text3);
  margin-bottom: 10px;
  transition: color var(--ease), background var(--ease);
}
.empty-state .empty-ico svg { width: 22px; height: 22px; }
.empty-state:hover .empty-ico { color: var(--text2); background: var(--surface); }
.empty-state .empty-title {
  font-size: 14px;
  font-weight: 640;
  letter-spacing: -0.018em;
  color: var(--text);
}
.empty-state .empty-desc {
  font-size: 14px;
  color: var(--text2);
  max-width: 46ch;
  line-height: 1.6;
}
.empty-state .empty-cta { margin-top: 16px; }
.chart-empty { padding: 20px; }
td > .empty-state { padding: 32px 16px; }

/* ============================================================
   12. GALERIE
   ============================================================ */
.gal-toolbar {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 20px;
}
.gal-toolbar #gal-search { flex: 1; min-width: 180px; max-width: 320px; height: 36px; }
.gal-toolbar #gal-sort { width: auto; min-width: 150px; height: 36px; margin-left: auto; }

/* ---------- Curseur de taille des vignettes ----------
   Un seul réglage, discret, à droite du tri : il pilote --gal-size,
   la variable que lit la grille. Les deux thèmes suivent tout seuls. */
.gal-size-ctl {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  height: 36px;
  padding: 0 12px 0 13px;
  border: 1px solid var(--border);
  border-radius: 99px;
  background: var(--panel);
}
.gal-size-ctl label {
  font-size: 12px;
  font-weight: 500;
  color: var(--text2);
  white-space: nowrap;
  cursor: default;
}
.gal-size-ctl input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  width: 96px;
  height: 16px;
  padding: 0;
  margin: 0;
  border: 0;
  background: transparent;
  cursor: ew-resize;
}
.gal-size-ctl input[type="range"]::-webkit-slider-runnable-track {
  height: 3px;
  border-radius: 99px;
  background: var(--track-bg);
}
.gal-size-ctl input[type="range"]::-moz-range-track {
  height: 3px;
  border-radius: 99px;
  background: var(--track-bg);
}
.gal-size-ctl input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 13px;
  height: 13px;
  margin-top: -5px;
  border-radius: 50%;
  background: var(--accent-solid);
  border: 2px solid var(--panel);
  box-shadow: 0 0 0 1px var(--accent-border-soft);
  transition: transform var(--ease);
}
.gal-size-ctl input[type="range"]::-moz-range-thumb {
  width: 13px;
  height: 13px;
  border-radius: 50%;
  background: var(--accent-solid);
  border: 2px solid var(--panel);
  box-shadow: 0 0 0 1px var(--accent-border-soft);
}
.gal-size-ctl input[type="range"]:hover::-webkit-slider-thumb { transform: scale(1.15); }
.gal-size-ctl input[type="range"]:focus-visible { outline: none; }
.gal-size-ctl input[type="range"]:focus-visible::-webkit-slider-thumb { box-shadow: 0 0 0 3px var(--accent-ring); }
.gal-size-ctl input[type="range"]:focus-visible::-moz-range-thumb { box-shadow: 0 0 0 3px var(--accent-ring); }

/* Filtres segmentés */
.gal-seg {
  display: inline-flex;
  align-items: center;
  gap: 2px;
}
.gal-seg-btn {
  border: 1px solid transparent;
  background: transparent;
  color: var(--text2);
  font-family: inherit;
  font-size: 14px;
  font-weight: 500;
  padding: 0 14px;
  height: 36px;
  border-radius: 99px;
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--ease), color var(--ease), border-color var(--ease);
}
.gal-seg-btn:hover { color: var(--text); background: var(--hover-fill); }
.gal-seg-btn.gal-seg-active {
  background: var(--panel);
  border-color: var(--border);
  color: var(--text);
  font-weight: 600;
}

/* Grille média — le contenu est le héros.
   --gal-size = largeur mini d'une vignette, pilotée par #gal-size
   (valeur par défaut = la taille historique, 272px). L'écart suit la
   taille : à petites vignettes, une gouttière de 20px ferait des trous. */
.gal-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(var(--gal-size, 272px), 1fr));
  gap: clamp(10px, calc(var(--gal-size, 272px) * 0.072), 20px);
}
.gal-grid > .empty-state { grid-column: 1 / -1; }

.gal-card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
  transition: border-color var(--ease), box-shadow var(--ease);
}
.gal-card:hover {
  border-color: var(--border-strong);
  box-shadow: var(--shadow-md);
}
.gal-card-off { opacity: 0.55; }
.gal-card-off:hover { opacity: 0.8; }

/* Ratio portrait 3:4 : c'est le format des photos de créatrice — un 4:3
   coupait systématiquement les visages. */
.gal-media {
  position: relative;
  display: block;
  aspect-ratio: 3 / 4;
  background: var(--surface-2);
  overflow: hidden;
}
.gal-thumb {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform 0.4s cubic-bezier(0.22, 0.61, 0.36, 1);
}
.gal-thumb-ph {
  display: grid;
  place-items: center;
  color: var(--text3);
  background: var(--surface-2);
}
.gal-thumb-ph svg { width: 34px; height: 34px; }
.gal-card:hover .gal-thumb { transform: scale(1.025); }

/* ---------- Vignette VIDÉO : la vraie première image du fichier ----------
   Le <video> muet sert d'affiche. `pointer-events: none` est essentiel :
   le clic doit atteindre la carte (ouvrir l'édition), pas le lecteur. */
.gal-thumb-video {
  position: relative;
  display: block;
  width: 100%;
  height: 100%;
  background: var(--surface-2);
}
.gal-thumb-video > video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  pointer-events: none;
  background: var(--surface-2);
}
/* Pastille « vidéo » — repère discret, pas une icône décorative. */
.gal-vid-play {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  z-index: 2;
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: rgba(18, 18, 22, 0.55);
  color: #fff;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  pointer-events: none;
  transition: background var(--ease);
}
.gal-vid-play svg { width: 22px; height: 22px; }
.gal-card:hover .gal-vid-play { background: var(--accent-solid); }
/* Durée « m:ss » — remplie par app.js sur `loadedmetadata`. */
.gal-vid-dur {
  position: absolute;
  right: 8px;
  bottom: 8px;
  z-index: 2;
  padding: 2px 7px;
  border-radius: 99px;
  background: rgba(0, 0, 0, 0.66);
  color: #fff;
  font-size: 12px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  pointer-events: none;
}

.gal-card-lib { cursor: pointer; }
/* Le nom de fichier vit SOUS la photo, sur la carte blanche :
   plus lisible qu'un voile noir, et fidèle à la référence. */
.gal-lib-caption {
  padding: 13px 15px 14px;
  border-top: 1px solid var(--border);
  background: var(--panel);
}
.gal-lib-name {
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
  letter-spacing: -0.012em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.gal-lib-desc {
  font-size: 12px;
  color: var(--text3);
  margin-top: 2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ---------- LES TAGS, SOUS LA PHOTO (13/09) ----------
   Propriétaire : « les tags, ça sert à ça ! je vois qu'en plus on les voit
   pas dans les photos et dans les sets ». Ils vivaient dans le formulaire
   d'édition et dans la lightbox — invisibles en parcourant la grille, alors
   que ce sont EUX qui décident ce que le bot retrouve quand un fan réclame
   « fishnet » ou « kitchen ». Quatre pastilles au plus, le reste se compte :
   la carte ne grandit que d'une ligne, jamais de deux. */
.gal-lib-tags {
  display: flex;
  flex-wrap: nowrap;
  overflow: hidden;
  gap: 4px;
  margin-top: 7px;
}
.gal-tag {
  flex: none;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 12px;
  line-height: 1.5;
  padding: 2px 7px;
  border-radius: 99px;
  color: var(--text2);
  background: var(--chip-bg);
}
/* Le compte des tags restants est POUSSÉ À DROITE : la ligne occupe toute la
   largeur de la carte au lieu de s'arrêter au hasard, et le « +3 » tombe à la
   même place d'une carte à l'autre (règle propriétaire : « soit tu retires
   l'espace, soit tu mets du contenu »). */
.gal-tag-more { color: var(--text3); margin-left: auto; }
/* La pastille écartée par la mesure disparaît vraiment (la règle globale
   `.hidden` ne l'emporte pas toujours sur un enfant de flex). */
.gal-lib-tags .gal-tag.hidden { display: none; }
/* Sans tag, le bot ne sait pas ce que montre la photo — et ne l'enverra
   jamais en cadeau (`_teaser_undescribed`). Ça se dit, ça ne se devine pas. */
.gal-tag-none { color: var(--warn, var(--text3)); background: transparent; padding-left: 0; }
/* TAGS TENUS À LA MAIN (21/09) — la pastille de SES mots. Teintée accent :
   dans une grille de tags automatiques gris, on repère d'un coup d'oeil les
   photos qu'elle a taguées elle-même. */
.gal-tag-mine {
  color: var(--accent, var(--text2));
  background: var(--accent-soft, var(--chip-bg));
  font-weight: 600;
}
/* La ligne d'état sous le champ Tags de la fiche : la marque, ce qu'elle
   change, et la sortie. Elle n'apparaît que sur un article déjà tenu à la
   main ou que l'on vient de retoucher. */
.gal-tags-mark {
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px;
  margin: -6px 0 0; font-size: 12px;
}
.gal-tags-mark .btn { margin-left: auto; }
.gal-grid.gal-dense .gal-lib-tags { margin-top: 5px; }
.gal-grid.gal-dense .gal-tag { font-size: 12px; padding: 1px 6px; }

/* La lecture du modèle sous l'état du fan (13/09) : « Slow lane · here to
   talk, not to buy ». Une ligne discrète — c'est une explication, pas une
   alarme ; l'état au-dessus garde la couleur. */

/* Le pied de la cloche : « Show everything » (13/09). Discret, pleine
   largeur, il dit combien de lignes dorment derrière — rien n'est supprimé,
   c'est juste ailleurs. */

/* Actions au survol — pas de reflow, révélation d'opacité */
.gal-actions-hover {
  position: absolute;
  top: 10px;
  right: 10px;
  display: flex;
  gap: 6px;
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity var(--ease), transform var(--ease);
  z-index: 3;
}
.gal-card-lib:hover .gal-actions-hover,
.gal-card-lib:focus-within .gal-actions-hover { opacity: 1; transform: none; }
.gal-actions-hover .btn {
  height: 28px;
  padding: 0 9px;
  font-size: 12px;
  border-radius: var(--r-xs);
  background: rgba(20, 20, 24, 0.82);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border-color: rgba(255, 255, 255, 0.16);
  color: #fff;
}
.gal-actions-hover .btn:hover { background: rgba(38, 38, 44, 0.94); border-color: rgba(255, 255, 255, 0.3); }
.gal-actions-hover .btn-danger { color: #ff8f85; }
.gal-actions-hover .btn-danger:hover { background: rgba(180, 40, 32, 0.85); color: #fff; }

/* ---------- Vue resserrée (curseur vers la gauche) ----------
   Sous ~200px de large, la carte garde la photo comme héros : le pied
   maigrit, la description passe à la trappe (le nom du fichier reste,
   tronqué), et les repères posés sur l'image rétrécissent avec elle. */
.gal-grid.gal-dense .gal-lib-caption { padding: 8px 10px 9px; }
.gal-grid.gal-dense .gal-lib-name { font-size: 12px; }
.gal-grid.gal-dense .gal-lib-desc { display: none; }
.gal-grid.gal-dense .gal-actions-hover { top: 6px; right: 6px; gap: 4px; }
.gal-grid.gal-dense .gal-actions-hover .btn { height: 24px; padding: 0 7px; font-size: 12px; }
.gal-grid.gal-dense .gal-vid-play { width: 32px; height: 32px; }
.gal-grid.gal-dense .gal-vid-play svg { width: 16px; height: 16px; }
.gal-grid.gal-dense .gal-vid-dur { right: 5px; bottom: 5px; padding: 1px 5px; font-size: 12px; }
.gal-grid.gal-dense .gal-thumb-ph svg { width: 24px; height: 24px; }

.gal-type {
  position: absolute;
  top: 10px;
  left: 10px;
  z-index: 2;
  padding: 2px 8px;
  border-radius: 99px;
  background: rgba(0, 0, 0, 0.6);
  color: #fff;
  font-size: 12px;
  font-weight: 600;
}
.gal-zoom {
  position: absolute;
  bottom: 10px;
  right: 10px;
  z-index: 3;
  opacity: 0;
  transition: opacity var(--ease);
  background: rgba(0, 0, 0, 0.6);
  border-radius: 99px;
  padding: 4px 8px;
  font-size: 12px;
  color: #fff;
}
.gal-card:hover .gal-zoom { opacity: 1; }

/* Corps de carte (variante vendable) */
.gal-body { padding: 12px 14px 14px; display: flex; flex-direction: column; gap: 6px; }
.gal-status-row { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.gal-title { font-size: 14px; font-weight: 600; color: var(--text); }
.gal-meta { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 12px; color: var(--text3); }
.gal-price { color: var(--accent); font-weight: 650; }
.gal-badge-free { background: var(--ok-soft); color: var(--ok); padding: 2px 8px; border-radius: 99px; font-size: 12px; font-weight: 600; }
.gal-sales, .gal-extra, .gal-date { font-size: 12px; color: var(--text3); }
.gal-actions { display: flex; gap: 6px; flex-wrap: wrap; }
.gal-card-lib .gal-body { display: none; }

.gal-loadmore-wrap { grid-column: 1 / -1; display: flex; justify-content: center; padding: 12px 0 4px; }

/* Sets */

/* ============================================================
   13. MODALE GALERIE (import + carte d'édition)
   ============================================================ */
body.gal-modal-open { overflow: hidden; }

.gal-modal {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 40px 24px;
  overflow-y: auto;
}
.gal-modal::before {
  content: "";
  position: fixed;
  inset: 0;
  background: var(--overlay);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.gal-modal-form {
  position: relative;
  width: 100%;
  max-width: 940px;
  background: var(--elevated);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: 26px 28px 22px;
  box-shadow: var(--shadow-float);
  animation: modalIn 0.22s cubic-bezier(0.22, 0.61, 0.36, 1) both;
  margin: auto;
}
@keyframes modalIn {
  from { opacity: 0; transform: translateY(14px) scale(0.985); }
  to { opacity: 1; transform: none; }
}
#item-form-wrap.gal-import-mode .gal-modal-form { max-width: 560px; }

.gal-modal-head { margin-bottom: 20px; }
/* En mode édition, ce titre est le NOM DU FICHIER : il peut être long,
   il s'ellipse plutôt que de casser la mise en page de la modale. */
.gal-modal-head h3 {
  font-size: 18px;
  font-weight: 640;
  letter-spacing: -0.022em;
  margin-bottom: 5px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.gal-form-sub { font-size: 14px; margin: 0; }

/* Croix de fermeture (import / édition). C'est la SEULE sortie « annuler »
   avec le bouton Cancel : un clic sur le voile ne ferme plus la fenêtre,
   pour ne jamais perdre une saisie en cours. Même dessin que .of-modal-x. */
#item-form-wrap .gal-modal-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
}
#item-form-wrap .gal-modal-head-text { min-width: 0; }
.gal-modal-x {
  flex: none;
  width: 32px;
  height: 32px;
  display: grid;
  place-items: center;
  border: 1px solid var(--border);
  border-radius: var(--r-xs);
  background: var(--surface);
  color: var(--text2);
  font-size: 14px;
  cursor: pointer;
  transition: background var(--ease), color var(--ease);
}
.gal-modal-x:hover { background: var(--hover-fill); color: var(--text); }
.gal-modal-x:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.gal-modal-media { display: flex; flex-direction: column; gap: 10px; }

/* Bascule import / édition */
#item-form-wrap.gal-import-mode .gal-edit-card { display: none; }
#item-form-wrap.gal-edit-mode .gal-modal-media { display: none; }

/* row-reverse → l'action primaire (Save/Import) se retrouve à DROITE ;
   `flex-start` pousse donc le groupe vers le bord droit de la modale. */
#item-form-wrap .gal-form-actions {
  margin-top: 22px;
  padding-top: 18px;
  border-top: 1px solid var(--border);
  flex-direction: row-reverse;
  justify-content: flex-start;
}

/* ---------- Carte d'édition : photo à gauche, infos à droite ---------- */
.gal-edit-card {
  display: grid;
  grid-template-columns: minmax(0, 400px) minmax(0, 1fr);
  gap: 24px;
  align-items: start;
}
.gal-edit-media { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
/* Ligne méta sous le titre : type + numéro. Le nom du fichier est
   remonté en en-tête de la carte (demande propriétaire). */
.gal-filename {
  font-size: 12px;
  font-weight: 550;
  color: var(--text3);
  letter-spacing: 0.02em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Cadre média de la carte d'édition — TOUS les ratios.
   Le cadre a une hauteur souple ; l'image se contente d'y tenir
   (`contain` + auto) : jamais recadrée, jamais déformée, toujours
   centrée. Le fond est un gris papier doux, pas du noir : un
   paysage dans un cadre portrait ne produit plus de barres noires. */
.gal-edit-photo {
  position: relative;
  min-height: 300px;
  height: 46vh;
  max-height: 520px;
  border-radius: var(--r);
  overflow: hidden;
  background: var(--surface-2);
  border: 1px solid var(--border);
  /* FLEX et non grid : sur une grille à ligne `auto`, la hauteur en %
     de l'enfant dépend de la ligne, qui dépend de l'enfant — le
     navigateur abandonne et l'image débordait (donc se faisait rogner).
     En flex, le cadre a une hauteur définie et `max-height:100%` tient. */
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 8px;
}
/* width/height 100% + `contain` : la SEULE combinaison qui tient pour
   tous les ratios. Avec `width:auto`, `max-height:100%` ne contraignait
   pas la hauteur et un portrait débordait (donc se faisait rogner par
   l'overflow du cadre). Ici l'image tient toujours, jamais rognée,
   jamais déformée, centrée sur un gris papier. */
/* L'image tient dans le cadre quel que soit son ratio — portrait,
   paysage ou carré : jamais rognée, jamais déformée, toujours centrée. */
.gal-edit-photo img,
.gal-edit-photo video {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  min-width: 0;
  min-height: 0;
  object-fit: contain;
  display: block;
  border-radius: var(--r-xs);
  background: none;
}
/* Le LECTEUR de la carte d'édition : contrôles natifs du navigateur, fond
   noir (une vidéo n'est pas une photo sur papier), largeur confortable dès
   l'ouverture — sans quoi il apparaît en 300x150 avant les métadonnées. */
.gal-edit-photo video {
  width: 100%;
  height: 100%;
  background: #000;
}
.gal-edit-ph { color: var(--text3); font-size: 14px; padding: 24px; text-align: center; }

.gal-edit-nav {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
}
.gal-edit-arrow {
  width: 32px;
  height: 32px;
  display: grid;
  place-items: center;
  border-radius: 99px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text2);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  padding: 0;
  transition: background var(--ease), color var(--ease), border-color var(--ease);
}
.gal-edit-arrow:hover:not(:disabled) {
  background: var(--accent-soft);
  border-color: var(--accent-border-soft);
  color: var(--accent);
}
.gal-edit-arrow:disabled { opacity: 0.3; cursor: not-allowed; }
.gal-edit-count {
  font-size: 12px;
  font-weight: 550;
  color: var(--text3);
  font-variant-numeric: tabular-nums;
  min-width: 60px;
  text-align: center;
}

.gal-edit-info { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.gal-edit-heading {
  font-size: 14px;
  font-weight: 620;
  letter-spacing: -0.018em;
  word-break: break-word;
  margin: 0;
}
.gal-edit-heading:empty { display: none; }
.gal-edit-info .gal-text-details { display: flex; flex-direction: column; gap: 16px; }
.gal-edit-info .form-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); margin-bottom: 0; }

/* Bloc « Auto » : UN SEUL cadre — le champ EST le cadre, le bouton est dedans.
   (10/09, propriétaire : « on dirait qu'on peut écrire dessus […] il prend trop
   d'espace pour rien ».) Avant : un libellé bleu, puis un champ et un bouton
   FANTÔME de même bordure, même hauteur et mêmes coins posés côte à côte —
   deux cadres vides que l'œil lit comme deux cases à remplir, sur trois lignes.
   Maintenant : une seule ligne, une seule bordure, et un bouton PLEIN qui ne
   peut plus passer pour un champ. */
/* ÉTAT PAR DÉFAUT (10/09, propriétaire : « ou sinon faire juste un bouton
   write it ou auto et c'est tout ») : un bouton, un lien discret, rien
   d'autre — pas de cadre, pas de champ vide qui attend qu'on le remplisse.
   L'indication ne sert qu'une fois de temps en temps ; elle se déplie à la
   demande (et d'office sur une vidéo, que le modèle ne peut pas regarder). */
.gal-ai-row {
  display: flex;
  align-items: center;
  gap: 12px;
}
.gal-ai-row > #ai-hint { display: none; }
.gal-ai-hint-toggle {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  font-size: 12px;
  color: var(--text3);
  cursor: pointer;
}
.gal-ai-hint-toggle:hover { color: var(--accent); }

/* ÉTAT DÉPLIÉ : le champ EST le cadre, le bouton est dedans, le lien s'efface. */

/* Le cadre s'allume quand on écrit DANS le champ : c'est lui qui a le focus,
   pas le div — d'où :focus-within (l'anneau du champ, lui, est neutralisé,
   sinon il redessinerait une deuxième boîte à l'intérieur de la première). */

#ai-gen { flex: none; white-space: nowrap; }

/* Interrupteur */
.gal-switch { position: relative; display: inline-block; width: 38px; height: 22px; flex: none; }
.gal-switch input { opacity: 0; width: 0; height: 0; position: absolute; }
.gal-switch-slider {
  position: absolute;
  inset: 0;
  background: var(--track-bg);
  border-radius: 99px;
  cursor: pointer;
  transition: background var(--ease);
}
.gal-switch-slider::before {
  content: "";
  position: absolute;
  left: 3px;
  top: 3px;
  width: 16px;
  height: 16px;
  border-radius: 99px;
  background: #fff;
  transition: transform var(--ease);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
}
.gal-switch input:checked + .gal-switch-slider { background: var(--accent-solid); }
.gal-switch input:checked + .gal-switch-slider::before { transform: translateX(16px); }

/* ---------- Dropzone ---------- */
.gal-dropzone {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 30px 20px;
  border-radius: var(--r);
  border: 1.5px dashed var(--border-strong);
  background: var(--surface);
  cursor: pointer;
  text-align: center;
  transition: border-color var(--ease), background var(--ease);
  overflow: hidden;
}
.gal-dropzone:hover { border-color: var(--accent); background: var(--accent-wash); }
.gal-dropzone input[type="file"] {
  position: absolute;
  inset: 0;
  opacity: 0;
  cursor: pointer;
  width: 100%;
  height: 100%;
  padding: 0;
}
.gal-dropzone-drag { border-color: var(--accent); background: var(--accent-soft); }
.gal-dropzone-locked { opacity: 0.55; cursor: not-allowed; border-style: solid; }
.gal-dropzone-locked input { pointer-events: none; }
.gal-dropzone-square { aspect-ratio: 4 / 3; padding: 20px; }
.gal-dropzone-square .gal-dz-icon { width: 46px; height: 46px; }
.gal-dropzone-square .gal-dz-title { font-size: 14px; }

.gal-dz-icon {
  width: 42px;
  height: 42px;
  display: grid;
  place-items: center;
  border-radius: 99px;
  background: var(--accent-soft);
  color: var(--accent);
}
.gal-dz-icon svg { width: 20px; height: 20px; }
.gal-dz-title { font-size: 14px; font-weight: 600; color: var(--text); }
.gal-dz-sub { font-size: 12px; color: var(--text3); text-align: center; margin: 0; }
.gal-dz-sub b { color: var(--text2); }
.gal-dz-file {
  font-size: 12px;
  color: var(--accent);
  font-weight: 550;
  word-break: break-all;
}

.gal-dz-files { display: flex; flex-direction: column; gap: 6px; max-height: 210px; overflow-y: auto; }
.gal-dz-label { font-size: 12px; font-weight: 600; color: var(--text3); }
.gal-dz-file-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 9px;
  border-radius: var(--r-xs);
  background: var(--surface);
  border: 1px solid var(--border);
}
.gal-dz-file-item img,
.gal-dz-vid {
  width: 34px;
  height: 34px;
  flex: none;
  border-radius: 6px;
  object-fit: cover;
  background: var(--surface-2);
  display: grid;
  place-items: center;
  font-size: 14px;
}
.gal-dz-file-meta { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.gal-dz-file-name {
  font-size: 12px;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.gal-dz-file-size { font-size: 12px; color: var(--text3); }
.gal-dz-x, .gal-dz-clear {
  flex: none;
  border: 0;
  background: transparent;
  color: var(--text3);
  cursor: pointer;
  font-size: 14px;
  font-family: inherit;
  padding: 4px 6px;
  border-radius: 6px;
  transition: background var(--ease), color var(--ease);
}
.gal-dz-x:hover, .gal-dz-clear:hover { background: var(--err-soft); color: var(--err); }
.gal-dz-clear { align-self: flex-start; font-size: 12px; }

/* Bloc avancé */

/* ---------- Lightbox ---------- */
.gal-lightbox {
  position: fixed;
  inset: 0;
  z-index: 210;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 40px 24px;
}
.gal-lb-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(6, 6, 8, 0.86);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
.gal-lb-card {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(300px, 0.65fr);
  max-width: 1080px;
  width: 100%;
  max-height: calc(100vh - 80px);
  background: var(--elevated);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  overflow: hidden;
  box-shadow: var(--shadow-float);
  animation: modalIn 0.22s cubic-bezier(0.22, 0.61, 0.36, 1) both;
}
.gal-lb-close {
  position: absolute;
  top: 12px;
  right: 12px;
  z-index: 4;
  width: 32px;
  height: 32px;
  display: grid;
  place-items: center;
  border-radius: 99px;
  border: 1px solid var(--border);
  background: rgba(20, 20, 24, 0.75);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  color: #fff;
  font-size: 14px;
  cursor: pointer;
  transition: background var(--ease);
}
.gal-lb-close:hover { background: rgba(50, 50, 56, 0.95); }
.gal-lb-media { background: var(--surface-2); display: grid; place-items: center; min-height: 300px; padding: 10px; }
.gal-lb-media img,
.gal-lb-media video { max-width: 100%; max-height: calc(100vh - 80px); width: auto; height: auto; object-fit: contain; display: block; border-radius: var(--r-xs); }
/* Un lecteur vidéo sans largeur intrinsèque connue resterait minuscule le
   temps des métadonnées : on lui donne un plancher confortable. */
.gal-lb-media video { min-width: min(560px, 100%); background: #000; }
.gal-lb-ph { display: grid; place-items: center; color: var(--text3); padding: 40px; }
.gal-lb-ph svg { width: 46px; height: 46px; }
.gal-lb-body { padding: 26px 24px; display: flex; flex-direction: column; gap: 12px; overflow-y: auto; }
.gal-lb-body h3 { font-size: 18px; font-weight: 640; letter-spacing: -0.02em; }
.gal-lb-desc { margin: 0; line-height: 1.6; }
.gal-lb-tags { margin: 0; }
.gal-lb-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: auto; padding-top: 12px; }

/* ============================================================
   14. AI OFFERS
   ============================================================ */

.offer-picker-count { font-size: 12px; font-weight: 600; color: var(--accent); }
.offer-picker-actions { display: flex; gap: 6px; flex-wrap: wrap; }

.offer-media-picker {
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-height: 340px;
  overflow-y: auto;
  padding: 6px;
  border-radius: var(--r-sm);
  background: var(--surface);
  border: 1px solid var(--border);
}

.offer-media-empty { padding: 24px; text-align: center; color: var(--text3); font-size: 14px; }

.offer-pack-note {
  padding: 12px 14px;
  border-radius: var(--r-sm);
  background: var(--accent-wash);
  border: 1px solid var(--accent-border-soft);
  font-size: 14px;
  color: var(--text2);
  line-height: 1.6;
}
.offer-pack-note b { color: var(--accent); }

/* ============================================================
   15. INBOX — un vrai chat
   ============================================================ */
/* Inspiration shadcn « mail » : trois colonnes — la liste, la
   conversation, puis la fiche du fan. La conversation garde toute sa
   largeur, les métadonnées ne l'écrasent plus. */
.inbox-layout {
  display: grid;
  grid-template-columns: minmax(240px, 300px) minmax(0, 1fr) minmax(240px, 300px);
  gap: 16px;
  height: calc(100vh - var(--topbar-h) - 130px);
  min-height: 520px;
}
.inbox-details {
  padding: 20px;
  overflow-y: auto;
}
.inbox-details h3 { margin-bottom: 14px; }
.inbox-details-empty { line-height: 1.6; }
/* Dans la colonne, la fiche s'empile verticalement (plus en bandeau). */
.inbox-details .fan-context {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 14px;
  padding: 0;
  background: none;
  border: 0;
  font-size: 14px;
}
.inbox-details .fan-chip {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 3px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--row-border);
}
.inbox-details .fan-chip:last-child { border-bottom: 0; padding-bottom: 0; }
.inbox-details .fan-status {
  flex-direction: row;
  flex-wrap: wrap;
  gap: 6px;
  margin-left: 0;
}
.inbox-details .fan-recent { flex-basis: auto; white-space: normal; padding-top: 0; border-top: 0; }
.inbox-layout > .panel { margin-bottom: 0; display: flex; flex-direction: column; min-height: 0; }

.inbox-convs { padding: 14px 10px 10px; }
.inbox-convs h3 { padding: 0 8px; margin-bottom: 10px; }
.conv-list { flex: 1; overflow-y: auto; display: flex; flex-direction: column; gap: 2px; padding-right: 2px; }

.conv-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 10px;
  border-radius: var(--r-sm);
  cursor: pointer;
  transition: background var(--ease);
  border-left: 2px solid transparent;
}
.conv-item:hover { background: var(--hover-fill); }
.conv-item.active { background: var(--accent-soft); border-left-color: var(--accent); }
.conv-item.followup { border-left-color: var(--warn); }
.conv-item.done { opacity: 0.55; }
.conv-item.active.followup { border-left-color: var(--accent); }

.conv-avatar {
  flex: none;
  width: 38px;
  height: 38px;
  display: grid;
  place-items: center;
  border-radius: 99px;
  background: var(--accent-grad);
  color: #fff;
  font-size: 14px;
  font-weight: 650;
}
.conv-main { flex: 1; min-width: 0; }
.conv-name {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.conv-item.active .conv-name { color: var(--accent); }
.conv-preview {
  font-size: 12px;
  color: var(--text3);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  margin-top: 1px;
}

/* ---------- Fil de discussion ---------- */
.inbox-thread { padding: 0; overflow: hidden; }
.thread-head {
  flex: none;
  padding: 15px 20px;
  border-bottom: 1px solid var(--border);
  font-size: 14px;
  font-weight: 620;
  letter-spacing: -0.016em;
  color: var(--text);
}
.fan-context {
  flex: none;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 14px;
  padding: 12px 20px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  font-size: 12px;
  color: var(--text2);
}
.fan-chip { display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.fan-chip b { color: var(--text); font-weight: 600; }
.fan-status { gap: 6px; margin-left: auto; }
.fan-status .btn.active-status {
  background: var(--accent-soft);
  border-color: var(--accent-border-soft);
  color: var(--accent);
  font-weight: 620;
}
/* Rappel des derniers échanges : UNE ligne — le fil complet est juste
   en dessous, inutile de le répéter sur trois lignes. */
.fan-recent {
  flex-basis: 100%;
  line-height: 1.6;
  padding-top: 8px;
  border-top: 1px solid var(--row-border);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.txt-fan { color: var(--text2); }
.txt-creator { color: var(--accent); }

.thread-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 20px;
  background: var(--bg);
}
.thread-body > .muted { margin: auto; }

.bubble {
  position: relative;
  width: fit-content;
  max-width: min(68%, 560px);
  padding: 9px 13px 7px;
  border-radius: 16px;
  font-size: 14px;
  font-weight: 450;
  line-height: 1.5;
  word-break: break-word;
  animation: bubbleIn 0.2s ease both;
}
.bubble-text { display: block; white-space: pre-wrap; }
@keyframes bubbleIn {
  from { opacity: 0; transform: translateY(4px); }
  to { opacity: 1; transform: none; }
}
.bubble.user {
  align-self: flex-start;
  background: var(--bubble-in);
  border: 1px solid var(--border);
  border-bottom-left-radius: 5px;
  color: var(--text);
}
.bubble.assistant {
  align-self: flex-end;
  background: var(--bubble-out);
  border: 1px solid var(--bubble-out-border);
  border-bottom-right-radius: 5px;
  color: var(--text);
}
.bubble + .bubble { margin-top: 2px; }
.bubble.user + .bubble.assistant,
.bubble.assistant + .bubble.user { margin-top: 8px; }
.bubble-time {
  display: block;
  margin-top: 4px;
  font-size: 12px;
  font-weight: 500;
  color: var(--text3);
  letter-spacing: 0.01em;
}
.bubble.assistant .bubble-time { text-align: right; color: var(--accent-bright); opacity: 0.75; }
.bubble.user .bubble-time { text-align: left; }

/* ---------- Zone de saisie ---------- */
.reply-box {
  flex: none;
  display: flex;
  align-items: flex-end;
  gap: 10px;
  padding: 14px 20px;
  border-top: 1px solid var(--border);
  background: var(--panel);
}
.reply-box textarea {
  flex: 1;
  min-height: 44px;
  max-height: 140px;
  border-radius: var(--r);
  background: var(--surface);
  resize: none;
}
.reply-box .btn { flex: none; height: 44px; padding: 0 20px; border-radius: var(--r); }
/* 13/10 (tour 62, `vente_manuelle`) : le panneau « Sell a set » sous la zone de saisie. */
.paid-panel { flex: none; padding: 10px 20px 12px; border-top: 1px solid var(--border); background: var(--panel); max-height: 45vh; overflow: auto; }
.paid-head { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
.paid-head .btn { margin-left: auto; }
.paid-panel label input { margin-left: 6px; width: 12em; }
.paid-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 6px 0; border-bottom: 1px solid var(--border); }
.paid-list { margin: 4px 0 6px; padding-left: 18px; }
#reply-msg { padding: 0 20px 10px; margin: 0; flex: none; }
#reply-msg:empty { display: none; }

/* ---------- Réponses rapides ---------- */

/* ---------- Broadcasts ---------- */

/* ============================================================
   16. LOGIN
   ============================================================ */
/* La page d'accueil est la première chose que voit la propriétaire : papier
   chaud, une seule carte posée au centre, beaucoup d'air autour. Fond plat —
   un lavis en dégradé produisait des bandes visibles à ces opacités. */
.login-screen {
  position: fixed;
  inset: 0;
  z-index: 300;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 28px;
  padding: 24px;
  background: var(--bg);
  overflow: hidden;
}
.login-card {
  position: relative;
  width: 100%;
  max-width: 392px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: 44px 40px 40px;
  text-align: center;
  box-shadow: var(--shadow-md);
  animation: modalIn 0.3s cubic-bezier(0.22, 0.61, 0.36, 1) both;
}
.login-logo {
  width: 56px;
  height: 56px;
  margin: 0 auto 22px;
  display: grid;
  place-items: center;
  border-radius: var(--r-lg);
  background: var(--accent-solid);
  color: var(--on-accent);
}
.login-logo svg { width: 28px; height: 28px; }
.login-card h1 {
  font-size: 18px;
  font-weight: 680;
  letter-spacing: -0.035em;
  margin: 0 0 8px;
}
.login-sub {
  margin: 0 0 32px;
  font-size: 14px;
  font-weight: 450;
  line-height: 1.55;
  color: var(--text2);
}
.login-card form { display: flex; flex-direction: column; gap: 8px; text-align: left; }
.login-label {
  font-size: 12px;
  font-weight: 550;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text3);
}
/* Champ : l'icône vit DANS le champ, le texte respire à sa droite. */
.login-field { position: relative; }
.login-field-ico {
  position: absolute;
  left: 15px;
  top: 50%;
  transform: translateY(-50%);
  display: grid;
  place-items: center;
  width: 18px;
  height: 18px;
  color: var(--text3);
  pointer-events: none;
  transition: color var(--ease);
}
.login-field-ico svg { width: 17px; height: 17px; display: block; }
.login-field:focus-within .login-field-ico { color: var(--accent); }
.login-card input {
  width: 100%;
  height: 50px;
  padding-left: 42px;
  text-align: left;
  background: var(--surface);
  border-radius: var(--r);
  font-size: 14px;
}
.login-card .btn {
  margin-top: 10px;
  height: 50px;
  font-size: 14px;
  border-radius: var(--r);
}
.login-foot {
  margin: 0;
  max-width: 392px;
  text-align: center;
  font-size: 12px;
  color: var(--text3);
  animation: modalIn 0.3s 0.08s cubic-bezier(0.22, 0.61, 0.36, 1) both;
}
.login-card .error-text { margin: 14px 0 0; text-align: center; }
.login-hint {
  padding: 10px 12px;
  margin-bottom: 16px;
  border-radius: var(--r-sm);
  background: var(--warn-soft);
  border: 1px solid var(--warn-border);
  color: var(--warn);
  font-size: 12px;
  text-align: left;
}

/* ============================================================
   17. TOASTS / OVERLAYS / 404
   ============================================================ */
.toast {
  position: fixed;
  left: 50%;
  bottom: 28px;
  transform: translateX(-50%);
  z-index: 400;
  max-width: min(90vw, 460px);
  padding: 12px 18px;
  border-radius: var(--r);
  background: var(--toast-bg);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  border: 1px solid var(--border);
  color: var(--text);
  font-size: 14px;
  font-weight: 550;
  box-shadow: var(--shadow-lg);
  animation: toastIn 0.24s cubic-bezier(0.22, 0.61, 0.36, 1) both;
}
@keyframes toastIn {
  from { opacity: 0; transform: translate(-50%, 14px); }
  to { opacity: 1; transform: translate(-50%, 0); }
}

.session-expired-overlay {
  position: fixed;
  inset: 0;
  z-index: 350;
  display: grid;
  place-items: center;
  padding: 24px;
  background: var(--overlay);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
.session-expired-card {
  width: 100%;
  max-width: 380px;
  background: var(--elevated);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: 30px 28px;
  text-align: center;
  box-shadow: var(--shadow-float);
}
.session-expired-icon {
  font-size: 18px;
  width: 52px;
  height: 52px;
  margin: 0 auto 14px;
  display: grid;
  place-items: center;
  border-radius: 99px;
  background: var(--accent-soft);
}
.session-expired-card h3 { font-size: 18px; margin-bottom: 6px; }
.session-expired-card p { font-size: 14px; color: var(--text2); margin-bottom: 20px; }

.notfound-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  text-align: center;
  padding: 90px 24px;
}
.notfound-icon {
  font-size: 18px;
  width: 60px;
  height: 60px;
  display: grid;
  place-items: center;
  border-radius: 99px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  margin-bottom: 8px;
}
.notfound-state h2 { font-size: 18px; }
.notfound-state p { color: var(--text2); }
.notfound-state .btn { margin-top: 12px; }

/* ---------- Panneau « Voice & Style » mis en avant ---------- */

/* ============================================================
   18. RESPONSIVE
   ============================================================ */
@media (max-width: 1180px) {
  .two-col { grid-template-columns: minmax(0, 1fr); }
  .gal-lb-card { grid-template-columns: minmax(0, 1fr); max-height: calc(100vh - 60px); overflow-y: auto; }
  .gal-lb-media img { max-height: 46vh; }
}

@media (max-width: 1280px) {
  /* Pas la place pour trois colonnes : la fiche du fan passe en bandeau
     sous l'en-tête du fil, comme avant. */
  .inbox-layout { grid-template-columns: minmax(230px, 290px) minmax(0, 1fr); }
  .inbox-details { grid-column: 1 / -1; max-height: 240px; }
  .inbox-details .fan-context { flex-direction: row; flex-wrap: wrap; gap: 8px 18px; }
  .inbox-details .fan-chip { flex-direction: row; align-items: center; gap: 6px; padding-bottom: 0; border-bottom: 0; }
}

@media (max-width: 1024px) {
  .gal-edit-card { grid-template-columns: minmax(0, 1fr); }
  .gal-edit-media { max-width: 380px; }
  .inbox-layout { grid-template-columns: minmax(220px, 280px) minmax(0, 1fr); }
}

@media (max-width: 860px) {
  :root { --sidebar-w: 260px; }
  .app { grid-template-columns: minmax(0, 1fr); }
  .sidebar {
    transform: translateX(-100%);
    transition: transform 0.24s cubic-bezier(0.4, 0, 0.2, 1);
    box-shadow: var(--shadow-lg);
  }
  body.sidebar-open .sidebar { transform: none; }
  .sidebar-overlay {
    display: block;
    position: fixed;
    inset: 0;
    background: var(--overlay);
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--ease);
    z-index: 55;
  }
  body.sidebar-open .sidebar-overlay { opacity: 1; pointer-events: auto; }
  .sidebar-toggle { display: grid; transition: opacity var(--ease); }
  /* Tiroir ouvert : le hamburger se superposerait au logo de la marque.
     On l'efface — l'overlay et les liens de nav referment le tiroir. */
  body.sidebar-open .sidebar-toggle { opacity: 0; pointer-events: none; }
  .main { grid-column: 1; padding: calc(var(--topbar-h) + 8px) 18px 60px; }
  .topbar { left: 0; padding: 0 18px 0 62px; }
  .page-head { align-items: flex-start; }
  .form-grid { grid-template-columns: minmax(0, 1fr); }
  .gal-edit-info .form-grid { grid-template-columns: minmax(0, 1fr); }
  .inbox-layout { grid-template-columns: minmax(0, 1fr); height: auto; }
  .inbox-convs { max-height: 320px; }
  .inbox-thread { min-height: 520px; }
  
  
  .table { display: block; overflow-x: auto; white-space: nowrap; }
  .gal-modal { padding: 20px 14px; }
  .gal-modal-form { padding: 20px 18px 18px; }
  /* 20/10 (audit UI prod, défaut 1) : `.theme-toggle { right: 16px; bottom: 16px; }` retiré — reste d'un
     bouton flottant ; sur le bouton en position: relative, il le remontait de 16 px au-dessus de la barre. */
  .month-rev { max-width: 150px; overflow: hidden; text-overflow: ellipsis; }
}

@media (max-width: 560px) {
  .stats-grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; }
  .stat-card { padding: 14px; }
  .stat-value { font-size: 18px; }
  .page h2 { font-size: 18px; }
  
  
  .gal-grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; }
  .bubble { max-width: 86%; }
}

/* En-tête interne réduit à sa phrase d'explication (le titre est en haut). */
.page-head h2.page-head-subonly {
  font-size: 0;
  gap: 0;
}
.page-head h2.page-head-subonly .page-sub { font-size: 14px; }

/* Vignettes en brouillon : atténuées, mais toujours lisibles. */
.gal-card-off { opacity: 0.78; }
.gal-card-off:hover { opacity: 1; }

/* …SAUF dans la bibliothèque : un média importé y arrive TOUJOURS en
   brouillon (aucun prix, aucune vente tant qu'il n'est pas dans une offre).
   L'atténuer ferait croire à un contenu « éteint » ou déjà classé : la
   galerie est neutre, c'est l'offre qui décide Locked / Free preview. */
.gal-card-lib.gal-card-off,
.gal-card-lib.gal-card-off:hover { opacity: 1; }

/* Inbox — avatars en bleu DOUX : quatre pastilles pleines côte à côte
   pesaient trop lourd dans une colonne calme. */
.conv-avatar {
  background: var(--accent-soft);
  color: var(--accent);
  font-weight: 620;
}
.conv-item.active .conv-avatar { background: var(--accent-solid); color: var(--on-accent); }

/* Fil vide : une phrase plutôt qu'un grand blanc. */
.thread-body:empty::before {
  content: "Pick someone on the left — the whole conversation shows up here.";
  margin: auto;
  max-width: 32ch;
  text-align: center;
  color: var(--text3);
  font-size: 14px;
  line-height: 1.6;
}


/* ============================================================
   OVERVIEW — cartes KPI (pyramide inversée) et skeletons
   ------------------------------------------------------------
   Quatre cartes, titrées comme des questions, chacune portant son
   contexte : variation, mini-tendance, cible. Tokens du thème
   uniquement (accent #229ed9 inchangé), clair et sombre.
   ============================================================ */
.stats-grid#stats-cards {
  /* Quatre KPI sur une ligne en grand écran, deux en tablette : l'œil ne
     doit jamais avoir à descendre pour lire ce qui compte le plus. */
  grid-template-columns: repeat(auto-fit, minmax(248px, 1fr));
}
/* MAQUETTES 28/09 (point 4) : les quatre tuiles d'Analytics sur UNE ligne.
   L'auto-fill à 232 px en rangeait trois et laissait « Messages » seul en
   dessous à 1 280 px. Deux par deux en tablette, une par une au téléphone. */
.stats-grid#analytics-cards { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 1100px) { .stats-grid#analytics-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 480px) { .stats-grid#analytics-cards { grid-template-columns: minmax(0, 1fr); } }
.kpi-card {
  display: flex;
  flex-direction: column;
  gap: 10px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: 18px 20px 16px;
  box-shadow: var(--shadow-sm);
  transition: border-color var(--ease), box-shadow var(--ease);
  min-width: 0;
}
.kpi-card:hover { border-color: var(--border-strong); }

/* Le titre est une QUESTION : « Sales today vs yesterday ». Petit, en
   capitales espacées — le chiffre reste la vedette. */
.kpi-question {
  font-size: 12px;
  font-weight: 650;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text2);
  line-height: 1.35;
}
.kpi-row { display: flex; align-items: flex-end; justify-content: space-between; gap: 12px; }
.kpi-value {
  font-size: 32px;
  font-weight: 700;
  letter-spacing: -0.025em;
  line-height: 1.1;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  min-width: 0;
  /* Le titre d'une offre peut être long : il se coupe proprement plutôt
     que de déformer la carte. */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.kpi-value-muted { color: var(--text3); font-weight: 600; }
.kpi-unit { font-size: 14px; font-weight: 600; color: var(--text2); margin-left: 6px; letter-spacing: 0; }

/* Verdict d'un coup d'œil : flèche + couleur sémantique, jamais d'emoji. */
.kpi-foot { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.kpi-delta {
  display: inline-flex; align-items: center; gap: 3px;
  padding: 2px 7px;
  border-radius: 99px;
  font-size: 12px; font-weight: 650;
  font-variant-numeric: tabular-nums;
}
.kpi-delta.up { color: var(--ok); background: var(--ok-soft); }
.kpi-delta.down { color: var(--err); background: var(--err-soft); }
.kpi-delta.flat { color: var(--text2); background: var(--surface-2); }
.kpi-arrow { font-size: 12px; line-height: 1; }
.kpi-since, .kpi-sub { font-size: 12px; color: var(--text3); }

/* Sparkline : la forme de la tendance, pas des chiffres à lire. */
.kpi-spark { flex: none; overflow: visible; }
.kpi-spark-line { fill: none; stroke: var(--accent); stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.kpi-spark-area { fill: var(--accent-wash); stroke: none; }
.kpi-spark-flat line { stroke: var(--border-strong); stroke-width: 1.5; stroke-linecap: round; }

/* Progression vers la cible mensuelle : une barre fine, pas une jauge. */
.kpi-target { display: flex; align-items: center; gap: 9px; }
.kpi-target-bar {
  flex: 1; height: 4px; min-width: 40px;
  border-radius: 99px;
  background: var(--surface-2);
  overflow: hidden;
}
.kpi-target-bar span {
  display: block; height: 100%;
  border-radius: 99px;
  background: var(--accent);
  transition: width 0.5s var(--ease);
}
.kpi-target-txt { font-size: 12px; color: var(--text3); white-space: nowrap; }

/* Carte sans donnée : elle EXPLIQUE et propose la suite (jamais un 0 muet). */
.kpi-card-empty { justify-content: flex-start; }
.kpi-empty-note { margin: 0; font-size: 12px; color: var(--text2); line-height: 1.45; }
.kpi-card-empty .btn { align-self: flex-start; margin-top: 2px; }

/* ---------- Skeletons (Apple HIG : squelette, pas spinner) ---------- */
.skel {
  display: block;
  border-radius: var(--r-sm);
  background: linear-gradient(90deg,
              var(--surface-2) 25%,
              color-mix(in srgb, var(--surface-2) 55%, var(--panel)) 37%,
              var(--surface-2) 63%);
  background-size: 400% 100%;
  animation: skel-shimmer 1.4s ease-in-out infinite;
}
.skel-line { height: 11px; width: 100%; }
.skel-value { height: 28px; width: 55%; margin: 2px 0; }
.skel-w40 { width: 40%; }
.skel-w60 { width: 60%; }
.kpi-card-skel { gap: 12px; }
@keyframes skel-shimmer {
  0% { background-position: 100% 50%; }
  100% { background-position: 0 50%; }
}
@media (prefers-reduced-motion: reduce) {
  .skel { animation: none; }
  .kpi-target-bar span { transition: none; }
}
/* Valeur TEXTE (le titre d'une offre) : plus petite qu'un nombre et sur deux
   lignes au besoin — « Sunset balcony set » doit se lire en entier. */
.kpi-value-text {
  font-size: 18px;
  font-weight: 660;
  letter-spacing: -0.012em;
  line-height: 1.28;
  white-space: normal;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* ============================================================
   CUSTOMERS — profils fans et file « à réactiver »
   ------------------------------------------------------------
   Tokens existants uniquement (accent #229ed9 inchangé), clair et sombre.
   Une carte par fan : identité à gauche, les trois chiffres qui décident au
   milieu, l'état à droite. Dépliée, elle donne la note et l'action.
   ============================================================ */
.cust-search {
  min-width: 240px;
  height: 34px;
  padding: 0 12px;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--panel);
  color: var(--text);
  font-size: 14px;
}
.cust-search:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-ring);
}
.cust-search::placeholder { color: var(--text3); }

/* ---------- À réactiver : la seule section qui demande une action ---------- */

/* ---------- Résumé ---------- */
.cust-summary {
  display: flex; gap: var(--sp-3); flex-wrap: wrap;
  margin: var(--sp-3) 0 var(--sp-2);   /* 22/12 -> 24/16 */
  font-size: 14px; color: var(--text2);
}
.cust-summary b { color: var(--text); font-weight: 680; }

/* ---------- Les profils ---------- */
.cust-grid { display: flex; flex-direction: column; gap: 8px; }

/* Les trois chiffres qui décident, alignés d'une ligne à l'autre. */

/* ---------- Fiche dépliée : la note et l'action ---------- */

.cust-notes-lbl {
  font-size: 12px; font-weight: 650; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--text2);
}
.cust-notes {
  width: 100%; resize: vertical;
  padding: 9px 11px;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--panel); color: var(--text);
  font: inherit; font-size: 14px; line-height: 1.5;
}
.cust-notes:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-ring); }

.skel-avatar { width: 34px; height: 34px; border-radius: 50%; flex: none; }

@media (max-width: 860px) {
  
  
  
  .cust-search { min-width: 0; width: 100%; }
}
/* Le tri de Customers a sa PROPRE classe : `.period-select` est masquée dans
   les en-têtes de page (le sélecteur de période vit dans la topbar). */
.cust-sort {
  height: 34px;
  padding: 0 30px 0 11px;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--panel);
  color: var(--text);
  font: inherit; font-size: 14px;
  cursor: pointer;
}
.cust-sort:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-ring); }

/* État vide de « à réactiver » : compact — c'est une bonne nouvelle, pas un
   panneau à remplir. */

/* ============================================================
   MICRO-INTERACTIONS (Apple HIG) — toast « Undo » et ligne retirée
   ============================================================ */
/* Le toast garde son apparence ; il gagne une action quand une suppression
   peut encore être annulée. */
.toast.toast-undo {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 10px 10px 10px 18px;
}
.toast-msg { flex: 1; min-width: 0; }
.toast-action {
  flex: none;
  padding: 5px 12px;
  border: 1px solid var(--accent-border-soft);
  border-radius: var(--r-sm);
  background: var(--accent-soft);
  color: var(--accent);
  font: inherit;
  font-size: 12px;
  font-weight: 680;
  cursor: pointer;
  transition: background var(--ease), border-color var(--ease);
}
.toast-action:hover { background: var(--accent); color: #fff; border-color: var(--accent); }
.toast-action:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--accent-ring); }

/* La ligne supprimée s'efface immédiatement — « Undo » la ramène. Elle est
   MASQUÉE, pas retirée du DOM : le retour est instantané et sans re-rendu. */
.row-removing {
  display: none !important;
}

/* ---------- Validation à la frappe (idée 12) ---------- */
.field-error {
  display: block;
  margin-top: 5px;
  font-size: 12px;
  line-height: 1.4;
  color: var(--err);
}
.field-error:empty { display: none; }
input.is-invalid,
textarea.is-invalid,
select.is-invalid {
  border-color: var(--err);
}
input.is-invalid:focus,
textarea.is-invalid:focus,
select.is-invalid:focus {
  box-shadow: 0 0 0 3px var(--err-soft);
}

@media (prefers-reduced-motion: reduce) {
  .toast { animation: none; }
}

/* Un <form> posé directement dans une page n'a pas de marge : son dernier
   élément (souvent une ligne d'état) touchait le panneau suivant à 11 px.
   Il prend le pas standard, comme un panneau. */
.page > form { margin-bottom: var(--sp-3); }
.page > form:last-child { margin-bottom: 0; }

/* ============================================================
   MOBILE — ergonomie au pouce (idée 13, audit à 390 px)
   ------------------------------------------------------------
   Tout est enfermé dans une media query : le desktop ne bouge pas.
   Trois problèmes mesurés à 390 px, trois familles de correctifs :
     1. des cibles tactiles à 32-38 px de haut (Apple HIG : 44 px) ;
     2. deux pages qui débordaient horizontalement (Overview 94 px,
        Gallery 121 px) — donc du contenu inatteignable au pouce ;
     3. des textes à 10,5-11,5 px, illisibles sur petit écran.
   ============================================================ */
@media (max-width: 860px) {

  /* ---------- 1. Cibles tactiles : 44 px de haut minimum ----------
     On agit sur la HAUTEUR, jamais sur la couleur ni le rayon. Les
     boutons gardent donc exactement leur apparence, ils deviennent
     seulement atteignables au pouce. */
  .btn,
  .btn-sm,
  .btn-lg,
  select,
  .cust-sort,
  .of-tool-sel,
  .period-select,
  .gal-seg-btn,
  .cust-search,
  input[type="text"],
  input[type="search"],
  input[type="number"],
  input[type="password"] {
    min-height: 44px;
  }
  /* Un bouton « petit » reste petit VISUELLEMENT (même fonte, même
     rayon) : c'est sa zone de contact qui grandit. */
  .btn-sm { padding: 0 16px; }

  /* Les puces de fermeture et autres carrés minuscules (✕ des quick
     replies, croix de modale) : même règle, en largeur aussi. */
  .of-modal-x,
  .gal-modal-x,
  .chip-x {
    min-width: 44px;
    min-height: 44px;
  }

  /* Une ligne de liste entière est cliquable : elle doit offrir la
     même surface confortable. */
  .cust-main,
  .conv-item,
  .of-tr > td {
    min-height: 44px;
  }

  /* ---------- 2. Rien ne doit déborder de l'écran ----------
     Gallery : la barre de filtres faisait 493 px de large — les deux
     derniers filtres étaient hors de portée. Elle défile désormais
     horizontalement, avec accroche, et sans barre de défilement
     visible (le geste suffit, c'est la convention mobile). */
  .gal-filters,
  .gal-seg {
    display: flex;
    flex-wrap: nowrap;
    max-width: 100%;
    overflow-x: auto;
    scroll-snap-type: x proximity;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .gal-filters::-webkit-scrollbar,
  .gal-seg::-webkit-scrollbar { display: none; }
  .gal-seg-btn { flex: none; scroll-snap-align: start; }

  /* Overview : le graphique (30 barres à 8 px minimum + gouttières)
     mesurait 414 px et poussait la PAGE entière. Il défile maintenant
     DANS son panneau — les 30 jours restent lisibles et atteignables
     au lieu d'être écrasés à 2 px de large. */
  .chart {
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }
  .chart::-webkit-scrollbar { display: none; }
  .chart .bar { min-width: 10px; }

  /* Filet de sécurité : aucune page ne pousse le document. */
  .page { max-width: 100%; overflow-x: clip; }

  /* Les interrupteurs on/off (AI Offers, Galerie) : on N'AGRANDIT PAS la
     pastille — lui donner 44 px de côté la transformait en gros rond bleu
     et cassait sa forme de curseur. On lui ajoute une zone de contact
     INVISIBLE autour : l'apparence ne bouge pas, le pouce a ses 44 px. */
  .gal-switch,
  .of-sw { position: relative; }
  .gal-switch::after,
  .of-sw::after {
    content: "";
    position: absolute;
    left: 50%;
    top: 50%;
    width: 44px;
    height: 44px;
    transform: translate(-50%, -50%);
  }

  /* Les gestes posés sur une vignette de la Galerie (Edit, Delete)
     faisaient 41 px de large : quelques pixels manquaient. */
  .gal-actions .btn,
  .gal-actions-hover .btn { min-width: 44px; }

  /* ---------- 3. Lisibilité : plancher à 12 px ---------- */
  .onboarding-num,
  .cust-fig-sub,
  .of-t-sub,
  .of-next,
  .kpi-target-txt,
  .cust-handle { font-size: 12px; }
  /* Ces pages portent leurs styles dans un <style> propre à la page :
     il faut la même spécificité pour que le plancher s'applique. */
  #page-offers .of-t-sub,
  #page-offers .of-next,
  #page-crm .kpi-question,
  #page-customers .cust-state,
  #page-customers .cust-fig-sub { font-size: 12px; }

  /* ---------- 4. La barre du haut tient dans l'écran ----------
     Mesuré à 390 px : son contenu faisait 805 px. La recherche, la
     cloche et le bouton de thème étaient POUSSÉS HORS DE L'ÉCRAN et
     devenaient inatteignables (la barre ne défile pas). On enlève ce
     qui fait doublon, on garde tous les gestes. */
  /* Le compteur « 900 ★ this month » est déjà la première carte KPI
     de l'Overview : inutile de le répéter dans une barre à l'étroit. */
  .month-rev { display: none; }
  /* Les pastilles de période quittent la barre — le <select> de la
     page reprend son rôle (les pastilles ne faisaient que le piloter).
     La propriétaire garde donc le choix de la période, à portée de
     pouce et non collé au bord haut de l'écran. */
  .topbar-period { display: none !important; }
  

  /* ---------- 5. Les actions principales restent au pouce ----------
     Sur un en-tête de page, le bouton d'action passait à droite, loin
     du pouce, et se retrouvait parfois coupé. En mobile il prend
     toute la largeur, sous le titre. */
  .page-head { align-items: stretch; }
  .page-head .btn-group {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-1);
    width: 100%;
  }
  .page-head .btn-group > * { flex: 1 1 auto; }
}

/* ============================================================
   SCRIPTS — vue « séquence » (idée 6)
   ------------------------------------------------------------
   Un script se lit de haut en bas comme le fan va le vivre :
   étapes numérotées, pauses en liaison, posts payants distingués
   des messages gratuits. Tokens existants uniquement (accent
   #229ed9 inchangé), clair et sombre.
   ============================================================ */

/* ---------- En-tête : identité à gauche, résultats à droite ---------- */

/* Trois chiffres alignés : « runs » n'est pas « sales ». */

/* ---------- La séquence ---------- */

/* Étiquettes : « free » se tait, le prix parle. */

/* L'étape payante est le moment qui compte : un filet d'accent la marque. */

/* La pause RELIE deux étapes : c'est un trait, pas une étape. */

/* ---------- Pied : date + gestes ---------- */

/* ============================================================
   AI OFFERS — places de la semaine (rareté honnête, mission 9)
   ------------------------------------------------------------
   La puce n'apparaît QUE si la propriétaire a fixé une limite ;
   les chiffres viennent des ventes réelles des 7 derniers jours.
   ============================================================ */
.of-slots {
  display: block;
  margin-top: 4px;
  font-size: 12px;
  color: var(--text3);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
/* Complet : le ton change, la couleur reste celle du thème (pas d'alerte
   rouge — c'est une bonne nouvelle commerciale, pas une erreur). */
.of-slots-full {
  color: var(--accent);
  font-weight: 620;
}

/* ==================== [m4.css — fondu le 28/09] ==================== */
/* ============================================================
   Jenna's World — composants secondaires (v7 « Charcoal Rose »)
   Scripts, presets Voice & Style, Lists, Referrals, aperçu persona.
   Aucune couleur en dur : tout vient des tokens de style.css.
   ============================================================ */

/* ---------- Éditeur d'étapes (page Scripts) ---------- */

/* ---------- Referrals ---------- */

/* ============================================================
   Voice & Style — presets
   ============================================================ */

.preset-card {
  position: relative;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--r);
  padding: 18px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  box-shadow: var(--shadow-sm);
  transition: border-color var(--ease), background var(--ease), transform var(--ease);
}
.preset-card:hover {
  background: var(--surface);
  border-color: var(--border-strong);
  transform: translateY(-1px);
}

.preset-card > * { position: relative; }

.preset-emojis { display: flex; flex-direction: column; gap: 4px; font-size: 14px; }

/* Aperçu des règles : dégradé de fin de zone pour que la coupe se lise
   comme « il y a la suite » et non comme un texte tronqué. */

/* ---------- Progression de la fiche créatrice ---------- */

/* ---------- Statut du persona ---------- */

/* ---------- Fiche créatrice sectionnée ---------- */

/* ---------- Aperçu du persona ---------- */
.preview-block { margin-bottom: 14px; }
.preview-block h4 {
  margin: 0 0 8px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.045em;
  text-transform: uppercase;
  color: var(--text3);
}
.preview-block pre, .preview-full pre {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  padding: 14px;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 12px;
  line-height: 1.65;
  color: var(--text2);
  white-space: pre-wrap;
  word-break: break-word;
  max-height: 280px;
  overflow-y: auto;
  margin: 0;
}
.preview-full summary {
  cursor: pointer;
  font-size: 12px;
  font-weight: 550;
  color: var(--accent);
  margin-bottom: 10px;
  user-select: none;
}

/* ============================================================
   Lists — cartes d'audience
   ============================================================ */

.list-card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--r);
  padding: 18px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  box-shadow: var(--shadow-sm);
  transition: border-color var(--ease), background var(--ease), transform var(--ease);
}
.list-card:hover {
  background: var(--surface);
  border-color: var(--border-strong);
  transform: translateY(-1px);
}
.list-card h4 { font-size: 14px; font-weight: 620; letter-spacing: -0.016em; }
.list-card .muted { font-size: 12px; }

/* ==================== [journal.css — fondu le 28/09] ==================== */
/* ============================================================
   Jenna's World — REFONTE CRM 10/09, piste « Journal » aux couleurs de
   Telegram (décision propriétaire du 10/09 : « le journal me paraît bien,
   mais aux couleurs de Telegram »). Chargé APRÈS style.css et m4.css :
   il redéfinit les jetons (palette, polices) et ne stylise que ce qui a
   été refait — barre latérale (fiche créatrice), page Today, Conversations
   à deux volets, Fans en tableau, barre d'onglets mobile. Le reste du
   dashboard hérite de la palette par les jetons.
   ============================================================ */

/* ---------- Jetons : palette Telegram, clair ---------- */
:root,
[data-theme="light"] {
  --bg: #eef3f7;
  --panel: #ffffff;
  --surface: #f5f8fa;
  --surface-2: #e9eff4;
  --elevated: #ffffff;
  --text: #0f1419;
  --text1: #0f1419;
  --text2: #5f6f7e;
  --text3: #8a98a6;
  --border: rgba(15, 20, 25, 0.08);
  --border-strong: rgba(15, 20, 25, 0.16);
  --row-border: rgba(15, 20, 25, 0.06);
  --line-tint: rgba(15, 20, 25, 0.065);
  --accent: #229ed9;
  --accent-hover: #1c8dc4;
  --accent-active: #177bab;
  --accent-bright: #2aabee;
  --accent-solid: #2aabee;
  --accent-solid-hover: #229ed9;
  --accent-grad: #2aabee;
  --accent-grad-hover: #229ed9;
  --on-accent: #ffffff;
  --accent-soft: rgba(42, 171, 238, 0.12);
  --accent-wash: rgba(42, 171, 238, 0.07);
  --accent-ring: rgba(42, 171, 238, 0.35);
  --accent-line: rgba(42, 171, 238, 0.3);
  --accent-border-soft: rgba(42, 171, 238, 0.28);
  --accent-border-hover: rgba(42, 171, 238, 0.45);
  --ok: #2e9e4f;   --ok-soft: rgba(46, 158, 79, 0.12);
  --warn: #b8700c; --warn-soft: rgba(224, 147, 42, 0.16);
  --warn-border: rgba(224, 147, 42, 0.3);
  --err: #d1434b;  --err-soft: rgba(209, 67, 75, 0.1);
  --info: #7c5cd6; --info-soft: rgba(124, 92, 214, 0.12);
  --hover-fill: rgba(15, 20, 25, 0.045);
  --tint: rgba(15, 20, 25, 0.02);
  --tint-2: rgba(15, 20, 25, 0.035);
  --chip-bg: rgba(15, 20, 25, 0.06);
  --chip-hover: rgba(15, 20, 25, 0.1);
  --btn-ghost-hover: rgba(15, 20, 25, 0.045);
  --track-bg: rgba(15, 20, 25, 0.07);
  --code-bg: rgba(15, 20, 25, 0.05);
  --code-text: #3b4a58;
  --bubble-in: #ffffff;
  --bubble-out: #effdde;
  --bubble-out-border: transparent;
  --chat-bg: #dfe9f0;
  --topbar-bg: rgba(238, 243, 247, 0.9);
  --sidebar-bg: #ffffff;
  --pop-bg: rgba(255, 255, 255, 0.98);
  --toast-bg: #17212b;
  --toast-text: #ffffff;
  --seg-dm: #2aabee;
  --seg-subs: #8ed0f5;
  --seg-channel: #c9d6e0;
  --scroll-thumb: rgba(15, 20, 25, 0.14);
  --scroll-thumb-hover: rgba(15, 20, 25, 0.26);
  --font-body: "Instrument Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  --font-display: "Bricolage Grotesque", "Instrument Sans", -apple-system, system-ui, sans-serif;
}

/* ---------- Jetons : palette Telegram, sombre (Telegram Desktop) ---------- */
[data-theme="dark"] {
  --bg: #0e1621;
  --panel: #17212b;
  --surface: #1e2c3a;
  --surface-2: #242f3d;
  --elevated: #2b3a4b;
  --text: #f5f5f5;
  --text1: #f5f5f5;
  --text2: #a3b0bd;
  --text3: #708294;
  --border: rgba(255, 255, 255, 0.08);
  --border-strong: rgba(255, 255, 255, 0.16);
  --row-border: rgba(255, 255, 255, 0.06);
  --line-tint: rgba(255, 255, 255, 0.06);
  --accent: #5eb5f7;
  --accent-hover: #7cc4f9;
  --accent-active: #9ad2fb;
  --accent-bright: #5eb5f7;
  --accent-solid: #2aabee;
  --accent-solid-hover: #3fb6f2;
  --accent-grad: #2aabee;
  --accent-grad-hover: #3fb6f2;
  --on-accent: #ffffff;
  --accent-soft: rgba(94, 181, 247, 0.16);
  --accent-wash: rgba(94, 181, 247, 0.08);
  --accent-ring: rgba(94, 181, 247, 0.45);
  --accent-line: rgba(94, 181, 247, 0.34);
  --accent-border-soft: rgba(94, 181, 247, 0.26);
  --accent-border-hover: rgba(94, 181, 247, 0.44);
  --ok: #5ec78a;   --ok-soft: rgba(94, 199, 138, 0.14);
  --warn: #e6b45a; --warn-soft: rgba(230, 180, 90, 0.14);
  --warn-border: rgba(230, 180, 90, 0.3);
  --err: #f07178;  --err-soft: rgba(240, 113, 120, 0.14);
  --info: #a48cf0; --info-soft: rgba(164, 140, 240, 0.16);
  --hover-fill: rgba(255, 255, 255, 0.05);
  --tint: rgba(255, 255, 255, 0.025);
  --tint-2: rgba(255, 255, 255, 0.04);
  --chip-bg: rgba(255, 255, 255, 0.08);
  --chip-hover: rgba(255, 255, 255, 0.12);
  --btn-ghost-hover: rgba(255, 255, 255, 0.06);
  --track-bg: rgba(255, 255, 255, 0.1);
  --code-bg: rgba(255, 255, 255, 0.07);
  --code-text: #cfd8e0;
  --bubble-in: #182533;
  --bubble-out: #2b5278;
  --bubble-out-border: transparent;
  --chat-bg: #0e1621;
  --topbar-bg: rgba(14, 22, 33, 0.9);
  --sidebar-bg: #17212b;
  --pop-bg: rgba(23, 33, 43, 0.98);
  --toast-bg: #2b3a4b;
  --toast-text: #ffffff;
  --seg-dm: #2aabee;
  --seg-subs: #5eb5f7;
  --seg-channel: #3d4f61;
  --scroll-thumb: rgba(255, 255, 255, 0.16);
  --scroll-thumb-hover: rgba(255, 255, 255, 0.28);
}

/* ---------- Typographie : Instrument Sans pour lire, Bricolage pour titrer ---------- */
body { font-family: var(--font-body); }
h1, h2, h3, h4, .brand-name, .big-num, .today-brief { font-family: var(--font-display); }
.topbar-title { font-family: var(--font-display); font-weight: 600; }
.today-h h3, .inbox-details h3, .panel > h3 { font-family: var(--font-body); }
.btn, input, select, textarea, .filter-chip { font-family: var(--font-body); }

/* ---------- Barre latérale : la créatrice en tête, six entrées ---------- */
.who-card { gap: 12px; padding: 0 16px; cursor: default; }
.who-avatar {
  width: 36px; height: 36px; flex: none;
  border-radius: 50%;
  background: var(--accent-solid);
  color: #fff;
  display: grid; place-items: center;
  font: 600 14px/1 var(--font-display);
}
.who-txt { min-width: 0; }
.who-sub { text-transform: none; letter-spacing: 0; font-size: 12px; margin-top: 1px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* MAQUETTES 28/09 (point 3) : la santé du bot en un point, sur toutes les
   pages ; sur téléphone le bouton de menu porte le rouge (la carte est dans
   le tiroir). */
.who-bot { font-size: 12px; color: var(--text3); margin-top: 1px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.who-dot { display: inline-block; width: 7px; height: 7px; border-radius: 50%; margin-right: 4px; vertical-align: 1px; background: #2e9e5b; }
.who-dot.warn { background: #c9741c; }
.who-dot.ko { background: #d64545; }
.sidebar-toggle.bot-alert::after { content: ""; position: absolute; top: 6px; right: 6px; width: 9px; height: 9px; border-radius: 50%; background: #d64545; border: 2px solid var(--panel); }

/* 20/10 (audit UI prod, défaut 5) : `.nav-sub` retiré d'Analytics et de Voice & Style, deux pages de premier
   niveau dont l'icône était cachée et le texte décalé ; elles ont l'icône et le retrait des autres entrées. */

/* ---------- Puces d'état (Today, Conversations, Fans) ---------- */
.chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 9px;
  border-radius: 99px;
  /* MAQUETTES 28/09 (point 6) : à 11,5 px « Warned » se lisait « Wamed »
     (le « rn » se colle en « m ») — 12 px et un peu d'air entre les lettres. */
  font-size: 12px; font-weight: 550; line-height: 1.2; letter-spacing: 0.015em;
  white-space: nowrap;
  vertical-align: middle;
}
.chip::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: none; }
.chip.t-ok { color: var(--ok);   background: var(--ok-soft); }
.chip.t-warn { color: var(--warn); background: var(--warn-soft); }
.chip.t-err { color: var(--err);  background: var(--err-soft); }

.chip.t-info { color: var(--info); background: var(--info-soft); }
.chip.t-mute { color: var(--text3); background: var(--chip-bg); }
.chip.t-neu { color: var(--text2); background: var(--chip-bg); }
.filter-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.filter-chip {
  border: 1px solid var(--border);
  background: var(--panel);
  color: var(--text2);
  border-radius: 99px;
  padding: 6px 12px;
  font-size: 12px; font-weight: 500; line-height: 1.2;
  cursor: pointer;
  transition: background var(--ease), color var(--ease), border-color var(--ease);
}
.filter-chip:hover { border-color: var(--border-strong); color: var(--text); }
.filter-chip.on { background: var(--accent-solid); border-color: var(--accent-solid); color: #fff; }
.filter-chip i { font-style: normal; opacity: 0.7; margin-left: 5px; }

/* ---------- Today : accueil « Compteur », les $ d'abord ---------- */
.today-h { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin: 0 0 8px; }
.today-h h3 { font-size: 12px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text3); }
.money-strip {
  display: grid; grid-template-columns: repeat(3, 1fr);
  background: var(--panel); border: 1px solid var(--border); border-radius: 14px;
  margin: 4px 0 16px; overflow: hidden;
}
.money-tile {
  padding: 18px 20px;
  border-left: 1px solid var(--border);
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 2px 12px; align-items: center;
  min-width: 0;
}
.money-tile:first-child { border-left: 0; }
.money-tile .eyebrow { grid-column: 1 / -1; font-size: 12px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--text3); font-weight: 600; }
.money-tile .money { font-family: var(--font-display); font-size: 32px; font-weight: 600; line-height: 1.1; letter-spacing: -0.03em; white-space: nowrap; }
.money-tile .money small { font-family: var(--font-body); font-size: 14px; font-weight: 500; color: var(--text3); margin-left: 8px; letter-spacing: 0; }
/* Le sous-titre passe SOUS la courbe, sur toute la largeur : à 225 px il
   repartait à la ligne dès qu'il portait ventes + acheteurs + comparaison,
   et la troisième tuile ne s'alignait plus avec les deux autres. */
.money-tile .money-sub { grid-column: 1 / -1; color: var(--text2); font-size: 12px; line-height: 1.4; }
.money-tile .money-spark { grid-column: 2; grid-row: 2; align-self: center; }
.money-tile .money-spark svg { width: 96px; height: 34px; }
.money-tile .money-goal { grid-column: 1 / -1; margin-top: 4px; } /* tour 520 : la barre de l'objectif du mois */
.money-strip .kpi-card { grid-column: 1 / -1; }
.up { color: var(--ok); font-weight: 600; }
.down { color: var(--err); font-weight: 600; }
.today-chart { margin-bottom: 16px; }
.today-chart svg { width: 100%; height: auto; display: block; }
.money-bars rect { fill: var(--accent-solid); opacity: 0.5; }
.money-bars rect.hi { opacity: 1; }
.money-bars text { font: 12px var(--font-body); fill: var(--text3); }
.money-bars line { stroke: var(--border); }
.money-bars .avg { stroke: var(--text); stroke-width: 1.2; stroke-dasharray: 3 3; opacity: 0.5; }
.money-bars .lab { font: 600 12px var(--font-body); fill: var(--text); }
.money-bars rect.money-z { fill: var(--text3); opacity: 0.3; }   /* jour sans vente */
.chart-note { margin-left: 8px; font-size: 12px; font-weight: 500; letter-spacing: 0; text-transform: none; color: var(--text3); }
.chart-note:empty { display: none; }
/* Survol du graphique : infobulle maison, instantanée et stylée — celle du
   <title> SVG mettait une seconde à venir et sortait sans style (propriétaire,
   10/09). La cible est la colonne entière, pas la barre. */
.money-chart { position: relative; }
.money-bars { touch-action: pan-y; }
.money-bars .money-col { fill: var(--accent-solid); opacity: 0; transition: opacity 90ms linear; }
.money-bars .money-col.on { opacity: 0.09; }
.money-bars rect.money-b { transition: opacity 90ms linear; }
.money-bars rect.money-b.on { opacity: 1; }
.money-tip {
  position: absolute; left: 0; top: 0;
  transform: translate(-50%, calc(-100% - 10px));
  display: grid; justify-items: center; gap: 2px;
  padding: 7px 11px 8px;
  background: var(--elevated);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: var(--shadow-md);
  white-space: nowrap;
  pointer-events: none;
  z-index: 6;
}
.money-tip[hidden] { display: none; }
.money-tip.side { transform: translate(0, -2px); }            /* barre trop haute : à côté */
.money-tip.side-left { transform: translate(-100%, -2px); }
.money-tip b { font-size: 12px; font-weight: 600; letter-spacing: 0.07em; text-transform: uppercase; color: var(--text3); }
.money-tip em {
  font-style: normal; font-family: var(--font-display);
  font-size: 18px; font-weight: 600; letter-spacing: -0.02em;
  color: var(--text); font-variant-numeric: tabular-nums;
}
.money-tip i { font-style: normal; font-size: 12px; color: var(--text3); }
.money-tip i .up, .money-tip i .down { font-size: 12px; }
.today-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; align-items: start; margin-bottom: 16px; }
.sales-list { display: flex; flex-direction: column; }
.sale-row {
  display: grid; grid-template-columns: 48px 108px minmax(0, 1fr) auto;
  gap: 10px; align-items: baseline;
  padding: 9px 0; border-top: 1px solid var(--row-border);
  font-size: 14px;
}
.sale-row:first-child { border-top: 0; }
/* Une vente mène à la conversation, un set à sa fiche : les lignes se
   comportent comme des liens (couleur du texte gardée, fond au survol). */
a.sale-row { color: inherit; text-decoration: none; }
.sale-row-link { margin: 0 -8px; padding-left: 8px; padding-right: 8px; border-radius: 8px; }
.sale-row-link:hover { background: var(--hover-fill); }
.sale-row-link:focus-visible { outline: 2px solid var(--accent-ring); outline-offset: -2px; }
.sets-table tr.row-link { cursor: pointer; }
.sets-table tr.row-link:hover td { background: var(--hover-fill); }
.sale-row time { color: var(--text3); font-size: 12px; font-variant-numeric: tabular-nums; }
.sale-row b { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sale-row span { color: var(--text2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sale-row em { font-style: normal; font-weight: 600; white-space: nowrap; }
.sale-row em small, .num small { color: var(--text3); font-weight: 500; margin-left: 6px; font-size: 12px; }
.sets-table td { height: 42px; }
.sets-table td.set { display: flex; align-items: center; gap: 9px; font-weight: 600; height: 42px; }
.sets-table td.set span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 180px; }
.sets-table .thumb { width: 30px; height: 30px; border-radius: 6px; object-fit: cover; background: var(--surface-2); flex: none; display: inline-block; }
.sets-table .num { text-align: right; white-space: nowrap; }
.queue-empty { padding: 14px 0; color: var(--text2); font-size: 14px; }

/* ---------- Conversations : deux volets, la fiche en tiroir ---------- */
.page-inbox .inbox-layout {
  grid-template-columns: minmax(280px, 340px) minmax(0, 1fr);
  position: relative;
}
.page-inbox .inbox-convs { padding: 12px 8px 8px; max-height: none; }
.conv-filters { padding: 0 4px 10px; position: sticky; top: 0; z-index: 2; background: var(--panel); }
/* 13/10 (tour 61, `inbox_gestes`) — recherche, audiences, non-lus, épingle. */
.conv-search { width: 100%; min-width: 0; margin-bottom: 10px; }
.conv-audiences { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; margin-top: 8px; }
.conv-aud-label { font-size: 12px; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; color: var(--text3); margin-right: 4px; }
.conv-aud {
  border: 0; background: transparent; color: var(--text2);
  border-radius: 99px; padding: 4px 10px;
  font-size: 12px; font-weight: 500; line-height: 1.2; cursor: pointer;
  font-family: var(--font-body);
  transition: background var(--ease), color var(--ease);
}
.conv-aud:hover { background: var(--hover-fill); color: var(--text); }
.conv-aud.on { background: var(--accent-soft); color: var(--accent); }
.conv-aud i { font-style: normal; opacity: 0.7; margin-left: 5px; }
/* 14/10 (tour 157, `porteurs`) — les fils qui portent l'argent. */
.conv-porteurs { padding: 0 4px 10px; border-bottom: 1px solid var(--border, rgba(0,0,0,.08)); margin-bottom: 8px; }
/* 20/10 (UI prod défauts 6 à 8) — « Top spenders » est un filtre de la liste :
   le montant sur chaque ligne, ses faits en aperçu, 3 fans puis « See all N » sous 600 px. */
.conv-spend { flex: none; font-size: 12px; font-weight: 600; color: var(--text2); font-variant-numeric: tabular-nums; }
.conv-spend + .conv-time { margin-left: 8px; }
.conv-name .conv-spend { margin-left: auto; }
.conv-item.active .conv-spend { color: #fff; }
.conv-preview-top { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.conv-see-all { display: none; margin: 8px 4px; align-self: flex-start; }
@media (max-width: 600px) {
  .conv-item.conv-over { display: none; }
  .conv-see-all { display: inline-flex; }
}
.thread-relecture { padding: 16px; border-bottom: 0; margin: 0; }
.conv-porteurs summary { cursor: pointer; font-size: 14px; padding: 4px 0 6px; }
.conv-porteurs summary .muted { font-size: 12px; margin-left: 4px; }
.porteur { padding: 6px 0; border-top: 1px solid var(--border, rgba(0,0,0,.06)); font-size: 12px; }
.porteur-top { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.porteur-top a { font-weight: 600; color: var(--text); }
.porteur-top .btn { margin-left: auto; }
.porteur-facts { margin-top: 2px; font-size: 12px; }
.conv-item.unread .conv-name-txt { font-weight: 700; }
.conv-item.unread .conv-preview { color: var(--text2); }
.conv-preview:has(> .conv-preview-txt) { display: flex; align-items: center; gap: 8px; }
.conv-preview-txt { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.conv-unread {
  flex: none; min-width: 18px; height: 18px; padding: 0 5px;
  display: inline-grid; place-items: center;
  border-radius: 99px; background: var(--accent-solid); color: #fff;
  font-size: 12px; font-weight: 650; font-variant-numeric: tabular-nums;
}
.conv-pin { flex: none; display: inline-flex; color: var(--accent); }
.conv-pin svg { width: 13px; height: 13px; }
mark.conv-hit { background: var(--accent-soft); color: inherit; border-radius: 3px; padding: 0 1px; }
.conv-item.active .conv-unread { background: #fff; color: var(--accent-solid); }
.conv-item.active .conv-pin { color: #fff; }
.conv-item.active mark.conv-hit { background: rgba(255, 255, 255, 0.28); }
.conv-marks { display: contents; }
.conv-item { border-left: 0; border-radius: 10px; padding: 9px 10px; }
.conv-item.active { background: var(--accent-solid); }
.conv-item.active .conv-name,
.conv-item.active .conv-name-txt,
.conv-item.active .conv-preview,
.conv-item.active .conv-preview i,
.conv-item.active .conv-time { color: #fff; }
.conv-item.active .conv-avatar { background: #fff; color: var(--accent-solid); }
.conv-item.active .chip, .conv-item.active .badge { background: rgba(255, 255, 255, 0.22); color: #fff; }
.conv-name { display: flex; align-items: center; gap: 6px; min-width: 0; }
.conv-name-txt { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 0 1 auto; }
.conv-name .chip { max-width: 112px; overflow: hidden; text-overflow: ellipsis; display: inline-block; line-height: 1.5; padding: 2px 8px; }
.conv-name .chip::before { display: none; }
.conv-time { margin-left: auto; flex: none; font-size: 12px; font-weight: 500; color: var(--text3); font-variant-numeric: tabular-nums; }
.conv-preview i { font-style: normal; color: var(--text2); }
.thread-top {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--border);
  flex: none;
}
.thread-top .thread-head {
  flex: 1; min-width: 0;
  padding: 0; border: 0;
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
.thread-top .thread-head b { font-weight: 600; font-size: 14px; }
.thread-top .conv-avatar { width: 30px; height: 30px; font-size: 12px; }
.thread-actions { display: flex; gap: 6px; flex: none; }
.inbox-back { display: none; }
.thread-facts {
  display: flex; flex-wrap: wrap; gap: 6px 22px;
  padding: 8px 16px 10px;
  border-bottom: 1px solid var(--border);
  font-size: 12px; color: var(--text2);
  flex: none;
}
.thread-facts:empty { display: none; }
.thread-facts b { color: var(--text); font-weight: 600; margin-right: 4px; white-space: nowrap; }
.thread-facts span { white-space: nowrap; }
.thread-facts a { margin-left: auto; font-weight: 550; cursor: pointer; }
.page-inbox .thread-body { background: var(--chat-bg); }
.bubble.user { background: var(--bubble-in); border-color: transparent; box-shadow: 0 1px 1px rgba(15, 20, 25, 0.1); }
.bubble.assistant { background: var(--bubble-out); border-color: transparent; box-shadow: 0 1px 1px rgba(15, 20, 25, 0.1); }
[data-theme="dark"] .bubble.assistant { color: #f5f5f5; }
.bubble.assistant .bubble-time { color: var(--text3); opacity: 1; }
[data-theme="dark"] .bubble.assistant .bubble-time { color: #a9c6e0; }
.page-inbox .reply-box textarea { border-radius: 18px; }
.inbox-details {
  position: absolute; top: 0; right: 0; bottom: 0;
  width: min(400px, 100%);
  z-index: 5;
  box-shadow: var(--shadow-lg);
  overflow-y: auto;
  grid-column: auto;
  max-height: none;
}
.inbox-details[hidden] { display: none; }
.details-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 12px; }
.details-top h3 { margin: 0; }
.inbox-details .fan-context { flex-direction: column; }
.inbox-details .fan-chip { flex-direction: column; align-items: flex-start; gap: 3px; padding-bottom: 14px; border-bottom: 1px solid var(--row-border); }

/* ---------- Fans ---------- */
/* Le tableau de la refonte 10/09 a été remplacé le 18/09 par la liste de la
   maquette 14 (voir la section « FANS » en bas de ce fichier). `.fan-cell`
   reste : la page Conversations s'en sert. */
.table-wrap { overflow-x: auto; }
.fan-cell { display: flex; align-items: center; gap: 10px; min-width: 0; }

.page-fans .page-head .btn-group { flex-wrap: nowrap; }

/* ---------- Graphique journalier : les dates ne se marchent plus dessus ---------- */
.chart.chart-dense .bar:nth-child(even) .day { visibility: hidden; }

/* ---------- Barre d'onglets mobile ---------- */
.tabbar { display: none; }

@media (max-width: 1100px) {
  .today-cols { grid-template-columns: minmax(0, 1fr); gap: 26px; }
}

@media (max-width: 860px) {
  .tabbar {
    position: fixed; left: 0; right: 0; bottom: 0;
    height: 62px;
    display: grid; grid-template-columns: repeat(5, 1fr);
    background: var(--panel);
    border-top: 1px solid var(--border);
    z-index: 65;
    padding-bottom: env(safe-area-inset-bottom);
  }
  .tabbar a, .tabbar button {
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
    font: 500 12px var(--font-body);
    color: var(--text3);
    background: none; border: 0; padding: 0; cursor: pointer;
  }
  .tabbar a.active { color: var(--accent); }
  .tabbar svg { width: 20px; height: 20px; }
  .main { padding-bottom: 92px; }
  .sidebar-toggle { display: none; }
  .topbar { padding-left: 18px; }
  .money-strip { grid-template-columns: minmax(0, 1fr); }
  .money-tile { border-left: 0; border-top: 1px solid var(--border); }
  .money-tile:first-child { border-top: 0; }
  .sets-table th:nth-child(3), .sets-table td:nth-child(3), .sets-table th:nth-child(4), .sets-table td:nth-child(4) { display: none; }
  /* Le set ne disparaît plus sur téléphone (« 19:57 · Jan · $24.70 » ne
     disait plus CE QUI a été vendu) : il passe sous le nom du fan. */
  .sale-row { grid-template-columns: 48px minmax(0, 1fr) auto; align-items: center; }
  .sale-row time { grid-column: 1; grid-row: 1 / 3; }
  .sale-row b { grid-column: 2; grid-row: 1; }
  .sale-row span { grid-column: 2; grid-row: 2; font-size: 12px; }
  .sale-row em { grid-column: 3; grid-row: 1 / 3; }
  /* Conversations : la liste OU le fil, jamais les deux empilés */
  .page-inbox .inbox-layout {
    grid-template-columns: minmax(0, 1fr);
    height: calc(100vh - var(--topbar-h) - 110px);
    min-height: 0;
  }
  .page-inbox .inbox-thread { display: none; min-height: 0; }
  .page-inbox .inbox-layout.show-thread .inbox-convs { display: none; }
  .page-inbox .inbox-layout.show-thread .inbox-thread { display: flex; }
  .inbox-back { display: inline-flex; }
  .thread-facts { gap: 4px 14px; }
  .thread-top { flex-wrap: nowrap; }
  .thread-top .thread-head { flex-wrap: nowrap; overflow: hidden; }
  .thread-top .thread-head .chip, .thread-top .thread-count { display: none; }
  /* « About » est dans la ligne des faits. TOUR 53 (01/10) : la règle visait
     « button:last-child », qui est « Why » depuis le 28/09 — le pourquoi était
     introuvable sur téléphone. Elle vise désormais le bouton About lui-même. */
  .thread-actions .btn-about { display: none; }
  .inbox-details { width: 100%; }
}

@media (prefers-reduced-motion: reduce) {
  .filter-chip { transition: none; }
}

/* ============================================================
   ANALYTICS — refonte du 10/09 au soir (propriétaire : « plus
   ergonomique, c'est pas très propre et simple »). Une commande de
   période dans la page, une ligne « all time » à la place de six
   cartes, des panneaux qui disent ce qu'ils couvrent.
   ============================================================ */
#page-analytics .an-tools { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.an-seg { display: inline-flex; align-items: center; gap: 2px; padding: 2px; background: var(--surface-2); border-radius: 99px; }
.an-seg-btn {
  border: 0; background: transparent; color: var(--text2);
  font-family: inherit; font-size: 14px; font-weight: 500; letter-spacing: -0.01em;
  height: 30px; padding: 0 14px; border-radius: 99px; cursor: pointer; white-space: nowrap;
}
.an-seg-btn:hover { color: var(--text); }
.an-seg-on { background: var(--panel); color: var(--text); font-weight: 600; box-shadow: var(--shadow-sm); }

/* Ce qui ne suit pas la période choisie le dit — une ligne au lieu de
   six cartes, et une étiquette sur les panneaux concernés. */
.an-alltime { display: flex; flex-wrap: wrap; align-items: center; margin: -6px 0 16px; font-size: 12px; color: var(--text2); }
.an-alltime b { color: var(--text); font-weight: 600; }
.an-sep { font-style: normal; color: var(--text3); margin: 0 8px; }
.panel-scope {
  margin-left: 6px; padding: 2px 7px; border-radius: 99px;
  background: var(--surface-2); color: var(--text3);
  font-size: 12px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase;
}

/* Jour sans vente : un trait pâle, jamais une barre qu'on prend pour $1. */
.chart .bar-zero { height: 3px; background: var(--text3); opacity: 0.3; }

/* Messages par jour : deux barres jumelles (reçus / envoyés). La paire garde
   la classe .bar pour hériter de l'infobulle et de la date. */
.chart .bar.bar-pair {
  background: none; opacity: 1; height: 100%;
  display: flex; align-items: flex-end; justify-content: center; gap: 2px;
}
.chart .bar-pair .pb { display: block; width: 46%; max-width: 9px; border-radius: 4px 4px 2px 2px; }
.pb-in { background: var(--accent-solid); opacity: 0.85; }
.pb-out { background: var(--ok); opacity: 0.6; }
.an-legend { display: inline-flex; flex-wrap: wrap; gap: 12px; }
.an-legend .legend-item { font-size: 12px; color: var(--text3); gap: 5px; }

#page-analytics .table .num { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
#page-analytics .table tr.row-link { cursor: pointer; }
#page-analytics .table tr.row-link:hover td { background: var(--hover-fill); }
#page-analytics .chart-note { text-transform: none; letter-spacing: 0; }

/* Analytics au doigt : plutôt que de laisser les tableaux déborder sous le
   pouce (ils débordaient de 64 px et 195 px à 360 px de large), on retire les
   colonnes qui ne décident de rien et on garde le fan et ce qu'il dépense, le
   set et ce qu'il rapporte. */
@media (max-width: 860px) {
  #page-analytics .fans-top th:nth-child(4), #page-analytics .fans-top td:nth-child(4) { display: none; }
}
@media (max-width: 520px) {
  #page-analytics .sets-table th:nth-child(5), #page-analytics .sets-table td:nth-child(5) { display: none; }
  #page-analytics .fans-top th:nth-child(2), #page-analytics .fans-top td:nth-child(2) { display: none; }
  #page-analytics .sets-table td.set span { max-width: 110px; }
  #page-analytics .table th, #page-analytics .table td { padding-left: 7px; padding-right: 7px; }
}

/* ---------- Profil créatrice (#/config) « Fiche et onglets », 10/09 23 h 50 ----------
   Choix de la propriétaire parmi huit maquettes : sa fiche résumée à gauche
   (collante), un seul onglet ouvert à droite. Champs de 38 px. */
.page-profile { max-width: 1180px; }
.prof-layout { display: grid; grid-template-columns: 300px minmax(0, 1fr); gap: var(--sp-3); align-items: start; margin: 0; }
.prof-side { position: sticky; top: calc(var(--topbar-h, 72px) + 16px); padding: 26px 22px 22px; margin: 0; text-align: center; border-radius: 20px; }
.prof-avatar {
  width: 96px; height: 96px; margin: 0 auto 14px;
  border-radius: 50%;
  background: linear-gradient(135deg, #2aabee 0%, #7c5cd6 100%);
  color: #fff;
  display: grid; place-items: center;
  font: 600 32px/1 var(--font-display);
}
.prof-name { font: 600 18px/1.1 var(--font-display); letter-spacing: -0.02em; color: var(--text); overflow-wrap: anywhere; }
.prof-meta { color: var(--text2); font-size: 14px; margin-top: 4px; min-height: 18px; }
.prof-ring { width: 74px; height: 74px; margin: 18px auto 6px; border-radius: 50%; background: conic-gradient(var(--accent-solid) 0 0%, var(--track-bg) 0% 100%); display: grid; place-items: center; }
.prof-ring i { width: 58px; height: 58px; border-radius: 50%; background: var(--panel); display: grid; place-items: center; font: 600 14px/1 var(--font-display); font-style: normal; color: var(--text); }
.prof-fill-txt { font-size: 12px; color: var(--text3); }
.prof-state-ok { color: var(--ok); font-weight: 600; }
.prof-state-warn { color: var(--warn); font-weight: 600; }
.prof-side .btn-block { width: 100%; margin-top: 8px; }
.prof-side #prof-save-btn { margin-top: 18px; }
.prof-facts { text-align: left; margin: 18px 0 0; padding: 14px 0 0; border-top: 1px solid var(--row-border); display: grid; gap: 7px; font-size: 14px; }
.prof-facts div { display: flex; justify-content: space-between; gap: 10px; }
.prof-facts dt { color: var(--text3); }
.prof-facts dd { margin: 0; font-weight: 600; color: var(--text); text-align: right; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.prof-mainwrap { min-width: 0; }
.prof-tabs-panel { padding: 0; margin: 0 0 var(--sp-3); border-radius: 20px; overflow: hidden; }
.prof-tabs { display: flex; border-bottom: 1px solid var(--border); padding: 0 10px; overflow-x: auto; scrollbar-width: none; }
.prof-tabs::-webkit-scrollbar { display: none; }
.prof-tab, .details-tab {
  appearance: none; background: none; border: 0; cursor: pointer; white-space: nowrap;
  padding: 16px 16px 14px;
  font: 600 14px/1.2 var(--font-body); color: var(--text2);
  border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.prof-tab:hover, .details-tab:hover { color: var(--text); }
.prof-tab.on, .details-tab.on { color: var(--accent); border-color: var(--accent); }
.prof-tab:focus-visible, .details-tab:focus-visible { outline: 2px solid var(--accent-ring); outline-offset: -2px; border-radius: 6px; }
.prof-tab em { font-style: normal; font-size: 12px; font-weight: 500; color: var(--text3); margin-left: 6px; }
.prof-tab em.done { color: var(--ok); }
.prof-pane { padding: 22px 24px 24px; }
.prof-pane-h { margin: 0 0 16px; color: var(--text2); font-size: 14px; }
.prof-sub { margin: 20px 0 10px; font: 600 12px/1 var(--font-body); letter-spacing: 0.08em; text-transform: uppercase; color: var(--text3); }
.prof-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px 18px; }
.prof-grid label { display: flex; flex-direction: column; gap: 5px; font-size: 12px; font-weight: 550; color: var(--text2); min-width: 0; }
.prof-grid label.full { grid-column: 1 / -1; }
.page-profile input[type="text"], .page-profile input[type="number"], .page-profile input[type="password"], .page-profile select { height: 38px; font-size: 14px; }
.prof-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 14px; color: var(--text); }
.prof-row input[type="number"] { width: 82px; text-align: right; padding-right: 8px; }
.prof-row b { font-weight: 600; }
.prof-hint { margin: 6px 0 0; font-size: 12px; color: var(--text3); line-height: 1.5; }
.prof-hint + .prof-row { margin-top: 18px; }
.prof-pane-foot { display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--row-border); font-size: 14px; color: var(--text3); }
.prof-next { appearance: none; background: none; border: 0; padding: 0; cursor: pointer; font: 600 14px/1.2 var(--font-body); color: var(--accent); }
.prof-next:hover { text-decoration: underline; }
#prof-password .form-actions { margin-top: 16px; }
.prof-panel { padding: 18px 20px; }
.prof-h { display: flex; align-items: baseline; gap: 10px; margin: 0 0 12px; flex-wrap: wrap; }
.prof-h h3 { margin: 0; font: 600 12px/1.3 var(--font-body); letter-spacing: 0.08em; text-transform: uppercase; color: var(--text3); }
.prof-h span { font-size: 12px; color: var(--text3); }
.prof-savebar {
  position: fixed; left: 50%; bottom: 22px; transform: translateX(-50%);
  display: flex; align-items: center; gap: 14px;
  padding: 6px 6px 6px 16px;
  background: var(--toast-bg); color: var(--toast-text);
  border-radius: 99px; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25);
  z-index: 60; font-size: 14px; font-weight: 500;
}

@media (max-width: 1100px) {
  .prof-layout { grid-template-columns: minmax(0, 1fr); }
  .prof-side { position: static; }
}
@media (max-width: 860px) {
  .prof-savebar { bottom: 74px; }
  /* MAQUETTES 28/09 (point 7, propriétaire : « oui ») — sur téléphone la
     fiche prenait tout le premier écran (avatar 96 px, anneau, Save, « What
     the bot reads », voix, délai) avant le premier champ, et Save restait
     800 px plus haut que ce qu'on modifiait. La fiche devient une ligne :
     avatar, nom, ville · heure, « 18 of 25 details » ; l'anneau et les deux
     faits partent (ils sont dans les onglets) ; Save vit dans la barre
     « Unsaved changes » qui suit le défilement. Ordinateur inchangé. */
  .prof-side {
    display: grid; grid-template-columns: 44px minmax(0, 1fr); column-gap: 12px; row-gap: 1px;
    align-items: center; text-align: left; padding: 12px 14px; border-radius: 16px;
  }
  .prof-avatar { width: 44px; height: 44px; margin: 0; font-size: 18px; grid-row: 1 / span 3; }
  .prof-name { font-size: 18px; }
  .prof-meta { margin-top: 0; min-height: 0; font-size: 12px; }
  .prof-ring { display: none; }
  .prof-fill-txt { grid-column: 2; }
  .prof-side #prof-save-btn { display: none; }
  .prof-side #persona-preview-btn { grid-column: 1 / -1; margin-top: 10px; }
  .prof-facts { display: none; }
}
@media (max-width: 520px) {
  .prof-grid { grid-template-columns: minmax(0, 1fr); }
  .prof-pane { padding: 18px 16px 20px; }
}

/* ---------- Voice & Style « la page longue » (11/09) ----------
   Le duel en haut, puis règles / chiffres / vente / automatique. Texte des
   messages à 16 px : c'est lui qu'on vient lire. Aucun bandeau d'emoji. */
.page-voice { max-width: 1040px; }
.vx-wrap { display: flex; flex-direction: column; }
.vx-ask { text-align: center; margin-bottom: 16px; }
.vx-eyebrow { display: block; font: 600 12px/1 var(--font-body); letter-spacing: .09em; text-transform: uppercase; color: var(--text3); margin-bottom: 7px; }
.vx-ask p { margin: 0; font: 600 18px/1.4 var(--font-display); letter-spacing: -.015em; color: var(--text); }
/* Les deux cartes partagent les MÊMES trois lignes (en-tête / messages /
   pied) : une description de voix plus longue que l'autre ne décale plus le
   début des messages. Sans subgrid, on retombe sur deux cartes de hauteur
   égale — l'état d'avant, jamais pire. */
.vx-duel { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); grid-template-rows: auto 1fr auto; gap: 16px; align-items: stretch; position: relative; }
.vx-duel > .vx-card { grid-row: span 3; }
@supports (grid-template-rows: subgrid) {
  .vx-duel > .vx-card { display: grid; grid-template-rows: subgrid; }
}
.vx-vs {
  position: absolute; left: 50%; top: 26px; transform: translateX(-50%);
  z-index: 2; width: 30px; height: 30px; border-radius: 50%;
  background: var(--panel); border: 1px solid var(--border);
  display: grid; place-items: center;
  font: 600 12px/1 var(--font-body); letter-spacing: .04em; text-transform: uppercase; color: var(--text3);
}
.vx-card {
  display: flex; flex-direction: column;
  background: var(--panel); border: 1px solid var(--border); border-radius: 18px; overflow: hidden;
  transition: border-color var(--ease), box-shadow var(--ease);
}
.vx-card.live { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.vx-card header { padding: 15px 20px 13px; border-bottom: 1px solid var(--row-border); }
.vx-card header h2 { margin: 0; font: 600 18px/1.15 var(--font-display); letter-spacing: -.02em; }
.vx-card header p { margin: 6px 0 0; color: var(--text2); font-size: 14px; line-height: 1.5; min-height: 19px; }
/* Les messages sont centrés dans la ligne partagée : quand un côté en a
   moins que l'autre, l'écart se répartit au lieu de creuser un trou en bas. */
.vx-says { padding: 16px 20px 18px; flex: 1; display: flex; flex-direction: column; justify-content: center; gap: 10px; }
.vx-says p { margin: 0; font-size: 14px; line-height: 1.55; color: var(--text); overflow-wrap: anywhere; }
.vx-says p + p { padding-top: 10px; border-top: 1px dashed var(--row-border); }
.vx-says .vx-none { color: var(--text3); font-size: 14px; }
/* 20/10 (UI prod défaut 14) : l'échec de l'exemple, en ligne, avec « Retry ». */
.vx-says .vx-err { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; color: var(--err); font-size: 14px; }
.vx-says .vx-skel { height: 19px; border-radius: 6px; background: var(--surface-2); animation: vxPulse 1.1s ease-in-out infinite; border: 0; }
.vx-says .vx-skel + .vx-skel { border-top: 0; padding-top: 0; }
@keyframes vxPulse { 0%, 100% { opacity: .5; } 50% { opacity: .9; } }
.vx-card footer { display: flex; align-items: center; justify-content: space-between; gap: 10px; min-height: 54px; padding: 11px 16px 11px 20px; border-top: 1px solid var(--row-border); background: var(--tint); }
.vx-another { margin-top: 12px; }
.vx-card footer .small { font-size: 12px; }
.vx-pills { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; justify-content: center; margin: 16px 0 0; }
.vx-pills-l { font-size: 12px; color: var(--text3); }
.vx-pill {
  appearance: none; cursor: pointer;
  border: 1px solid var(--border); background: var(--panel); color: var(--text2);
  border-radius: 99px; padding: 7px 14px;
  font: 600 14px/1.2 var(--font-body);
  display: inline-flex; align-items: center; gap: 7px;
  transition: border-color var(--ease), color var(--ease), background var(--ease);
}
.vx-pill:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.vx-pill.on { background: var(--accent); border-color: var(--accent); color: #fff; }
/* 20/10 (défaut 14) : le survol (collé après un toucher en 390) peignait le texte en bleu sur le bleu. */
.vx-pill.on:hover:not(:disabled) { color: #fff; }
.vx-pill.live { opacity: .55; cursor: default; }
.vx-pill em { font-style: normal; font-size: 12px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--ok); }
.vx-pill-new { border-style: dashed; color: var(--accent); }
.vx-sec { padding: 20px 24px; margin: 20px 0 0; border-radius: 18px; }
.vx-h { display: flex; align-items: baseline; gap: 12px; margin: 0 0 14px; flex-wrap: wrap; }
.vx-h h3 { margin: 0; font: 600 18px/1.2 var(--font-display); letter-spacing: -.02em; }
.vx-h span { font-size: 14px; color: var(--text3); }
.vx-h .btn { margin-left: auto; }

.vx-stats { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 20px; }
.vx-empty { grid-column: 1 / -1; margin: 0; font-size: 14px; color: var(--text3); line-height: 1.55; max-width: 62ch; }
.vx-stat b { display: flex; align-items: baseline; gap: 5px; font: 600 32px/1 var(--font-display); letter-spacing: -.03em; color: var(--text); }
.vx-stat b i { font-style: normal; font: 600 14px/1 var(--font-body); color: var(--text3); }
.vx-stat span { display: block; margin-top: 6px; font-size: 14px; color: var(--text); }
.vx-stat em { display: block; margin-top: 3px; font-style: normal; font-size: 12px; color: var(--text3); }
.vx-sell { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 20px 18px; }
.vx-si-wide { grid-column: 1 / -1; }
.vx-si .t { font-size: 14px; font-weight: 600; color: var(--text); }
.vx-si .d { margin: 3px 0 10px; font-size: 12px; color: var(--text3); line-height: 1.5; min-height: 19px; }
.vx-row { display: flex; align-items: center; gap: 7px; font-size: 14px; color: var(--text2); }
.vx-row input[type="number"] { width: 62px; height: 34px; text-align: right; padding-right: 8px; }
#cfg-everyday-story { height: 38px; }
.seg3 { display: flex; gap: 6px; }
.seg3 button {
  flex: 1; appearance: none; cursor: pointer;
  border: 1px solid var(--border); background: var(--surface); color: var(--text2);
  border-radius: 99px; padding: 8px 4px; font: 600 12px/1.2 var(--font-body);
}
.seg3 button:hover { border-color: var(--border-strong); color: var(--text); }
.seg3 button.on { background: var(--accent); border-color: var(--accent); color: #fff; }
.vx-auto .vauto { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 9px 18px; }
.vauto { list-style: none; margin: 0; padding: 0; display: grid; gap: 7px; }
.vauto li { position: relative; padding-left: 22px; font-size: 14px; color: var(--text2); line-height: 1.45; }
.vauto li::before {
  content: "✓"; position: absolute; left: 0; top: 1px;
  width: 15px; height: 15px; border-radius: 50%;
  background: var(--ok-soft); color: var(--ok);
  font: 700 12px/15px var(--font-body); text-align: center;
}
.warn-text { color: var(--warn); font-weight: 600; }
/* (28/09, maquettes point 7 : la seconde définition de .prof-savebar, copie de
   celle du profil héritée de la fusion des feuilles, est retirée.) */

@media (max-width: 860px) {
  .vx-stats { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .vx-sell { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .vx-auto .vauto { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 620px) {
  /* Empilées : chaque carte reprend ses propres lignes. */
  .vx-duel { grid-template-columns: minmax(0, 1fr); grid-template-rows: none; }
  .vx-duel > .vx-card { display: flex; grid-row: auto; }
  .vx-vs { top: auto; left: auto; right: 18px; transform: none; display: none; }
  .vx-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .vx-sell { grid-template-columns: minmax(0, 1fr); }
  .vx-auto .vauto { grid-template-columns: minmax(0, 1fr); }
  .vx-sec { padding: 18px 16px; }
}

/* ---------- CE QUI MANQUE AU CATALOGUE (11/09) ----------
   L'aperçu de l'accueil, la colonne de Fans, le tableau de Sets. Même
   grammaire que le reste : pas de carte sur chaque chose, le bleu ne sert
   qu'à ce qui demande une décision. */
.lack {
  display: flex; align-items: center; gap: 28px; flex-wrap: wrap;
  background: var(--panel); border: 1px solid var(--border);
  border-radius: 16px; padding: 15px 20px; margin: 0 0 16px;
}
.lack-l {
  font: 600 12px/1.35 var(--font-body); letter-spacing: .09em; text-transform: uppercase;
  color: var(--text3); max-width: 96px;
}
.lack-i {
  display: flex; flex-direction: column; gap: 2px;
  text-decoration: none; color: inherit; border-radius: 8px;
}
.lack-i:hover b { color: var(--accent); }
.lack-i b { font: 600 18px/1.15 var(--font-display); letter-spacing: -.02em; }
.lack-i span { font-size: 12px; color: var(--text3); }
.lack-i em { font-style: normal; font-size: 12px; color: var(--text2); }
.lack-alert b { color: var(--danger, #cf4040); }
.lack-go { margin-left: auto; }
.lack-sec { margin-top: 18px; }
.lack-th { font-weight: 600; white-space: nowrap; }
.lack-short .lack-th { color: var(--accent); }
.lack-bar {
  display: inline-block; vertical-align: middle; width: 160px; max-width: 34vw;
  height: 7px; border-radius: 99px; background: var(--surface-2); overflow: hidden; margin-right: 10px;
}
.lack-bar i { display: block; height: 100%; border-radius: 99px; background: var(--accent); }
.lack-none { color: var(--danger, #cf4040); font-weight: 600; font-size: 14px; }
.lack-foot {
  margin: 0; padding: 14px 20px; border-top: 1px solid var(--row-border);
  background: var(--tint); font-size: 14px; color: var(--text2); line-height: 1.6;
}
.lack-foot b { color: var(--text); font-weight: 600; }
@media (max-width: 620px) {
  .lack { gap: 18px; padding: 14px 16px; }
  .lack-go { margin-left: 0; }
  .lack-bar { width: 70px; }
}

/* ---------- Her rhythm (12/09) : à quelle vitesse elle répond, à qui ----------
   Une page, un réglage principal (trois cartes), les trois groupes d'hommes
   avec leur attente en secondes ou minutes, une vraie rafale rejouée, et six
   moments on/off. Aucun chiffre de coût : elle parle de son naturel. */
.page-rhythm { max-width: 1160px; }

/* Spécificité : style.css pose `input[type="number"] { width: 100% }` et
   `select { width: 100% }` — sans la balise dans le sélecteur, le champ
   s'étirait sur toute la largeur du téléphone et l'unité se tronquait. */

/* ============================================================
   FANS — « UNE SEULE COLONNE » (18/09)
   ------------------------------------------------------------
   Maquette 14, retenue par le propriétaire parmi quinze
   (docs/maquettes-fans/14-fusion-une-colonne.png). Écrit TÉLÉPHONE
   D'ABORD : les règles de base sont celles du petit écran, l'ordinateur
   est la media query. Aucune icône-emoji, le bleu du propriétaire
   (--accent-solid = #2aabee), et les jetons du thème pour le clair comme
   pour le sombre — aucune couleur en dur, les quatre teintes de files
   dérivent des jetons d'état (--err, --warn, --info).
   ============================================================ */

/* ---------- Le bandeau « what's waiting on you » ---------- */
/* 20/10 (audit UI prod, défauts 9 et 10) : le code interne à côté de son libellé, en « Show everything » seulement. */
.code-full { display: none; margin-left: 6px; }
body.crm-full .code-full { display: inline; }
.fanq { padding: 14px 14px 16px; margin-bottom: 14px; }
.fanq-none { margin: 0; color: var(--text2); font-size: 14px; }
.fanq-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px; margin-bottom: 12px; }
.fanq-head h3 {
  margin: 0; font-family: var(--font-display); font-size: 12px; font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--text2);
}
.fanq-head p { margin: 0; font-size: 14px; color: var(--text2); font-variant-numeric: tabular-nums; }
.fanq-head b { color: var(--text); font-weight: 680; }
.fanq-head span { color: var(--text3); }

/* 20/10 (UI prod défaut 11) — les files du bandeau sur une ligne de 14 px, contraste
   normal ; la couleur de la file n'est plus qu'un point. Les injoignables au pied. */
.fanq-line { display: flex; flex-wrap: wrap; gap: 6px 8px; }
.fanq-pill {
  display: inline-flex; align-items: baseline; flex-wrap: wrap; gap: 0 6px;
  padding: 7px 12px; min-height: 36px; text-align: left; cursor: pointer;
  background: var(--panel); color: var(--text); border: 1px solid var(--border); border-radius: 99px;
  font-family: var(--font-body); font-size: 14px; line-height: 1.4;
  transition: background 0.12s, border-color 0.12s;
}
.fanq-pill::before {
  content: ""; flex: none; width: 8px; height: 8px; border-radius: 50%;
  background: var(--border-strong); align-self: center;
}
.fanq-pill:hover { background: var(--hover-fill); }
.fanq-pill:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.fanq-pill.on { border-color: var(--accent-solid); box-shadow: 0 0 0 2px var(--accent-ring); }
.fanq-n { font-weight: 680; color: var(--text); font-variant-numeric: tabular-nums; }
.fanq-lbl { color: var(--text); }
.fanq-usd { color: var(--text2); font-variant-numeric: tabular-nums; }
.fanq-pill.q-err::before { background: var(--err); }
.fanq-pill.q-warn::before, .fanq-pill.q-amber::before { background: var(--warn); }
.fanq-pill.q-info::before { background: var(--info); }
.fanq-foot { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--border); }
.fanq-foot .fanq-pill { border-radius: 10px; }
.fanq .fanq-line + .fanq-none { margin-top: 12px; }

/* TOUR 535 (16/10) — les ventes que la machine retient : une ligne par fan, sans clic. */
.fanh[hidden] { display: none; }
.fanh-rows { display: grid; gap: 6px; }
.fanh-row {
  display: grid; gap: 2px; text-align: left; width: 100%; padding: 8px 10px;
  border: 1px solid var(--row-border); border-left: 3px solid var(--warn); border-radius: 8px;
  background: transparent; color: var(--text); font: inherit; font-size: 14px; cursor: pointer;
}
.fanh-row:hover { background: var(--hover-fill); }
.fanh-row:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.fanh-who { display: flex; flex-wrap: wrap; gap: 4px 10px; align-items: baseline; }
.fanh-who span, .fanh-when { color: var(--text2); font-variant-numeric: tabular-nums; font-size: 12px; }
.fanh-gate code { font-size: 12px; }
.fanh-gate small { display: block; color: var(--text3); font-size: 12px; }

/* ---------- La liste ---------- */
.fanl { padding: 0; overflow: hidden; }
.fanl-head { padding: 13px 14px 0; }
.fanl-head h3 {
  margin: 0; font-family: var(--font-display); font-size: 12px; font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--text2);
}
.fanl-sub { margin: 3px 0 0; font-size: 12px; color: var(--text3); }
.fanl-hint { display: none; }
.page-fans .cust-filters { padding: 10px 14px 11px; }
.fanl-rows { border-top: 1px solid var(--row-border); }
.fanl-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 11px 14px 13px; border-top: 1px solid var(--row-border);
  font-size: 12px; color: var(--text3);
}
.fanl-foot[hidden] { display: none; }

/* ---------- Une ligne ---------- */
.fanrow { border-bottom: 1px solid var(--row-border); }
.fanrow:last-child { border-bottom: 0; }
.fanrow-main {
  display: grid; width: 100%; align-items: center; gap: 1px 10px;
  grid-template-columns: 34px minmax(0, 1fr) auto;
  grid-template-areas: "av name money" "av when chip";
  padding: 10px 14px 11px; background: none; border: 0; cursor: pointer;
  text-align: left; font-family: var(--font-body); color: var(--text);
}
.fanrow-main:hover { background: var(--hover-fill); }
.fanrow-main:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.fanrow.is-open { background: var(--accent-wash); }
.fanrow.is-open .fanrow-main { background: none; border-left: 3px solid var(--accent-solid); padding-left: 11px; }
.fanrow-av {
  grid-area: av; display: grid; place-items: center; width: 34px; height: 34px;
  border-radius: 50%; background: var(--accent-soft); color: var(--accent);
  font-weight: 680; font-size: 14px;
}
.fanrow-id { grid-area: name; min-width: 0; display: flex; align-items: baseline; gap: 8px; }
.fanrow-name {
  font-weight: 640; font-size: 14px; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}
.fanrow-handle { display: none; font-size: 12px; color: var(--text3); white-space: nowrap; }
.fanrow-money { grid-area: money; text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
.fanrow-money b { display: block; font-size: 14px; font-weight: 680; }
.fanrow-money i { font-style: normal; font-size: 12px; color: var(--text3); }
.fanrow-when {
  grid-area: when; min-width: 0; display: flex; flex-wrap: wrap; gap: 0 6px;
  font-size: 12px; color: var(--text2);
}
.fanrow-when span + span::before { content: "·"; margin-right: 6px; color: var(--text3); }
.fanrow-chip { grid-area: chip; justify-self: end; white-space: nowrap; }
.fanrow-act { display: none; grid-area: act; justify-self: end; font-size: 14px; font-weight: 620; color: var(--accent); }
.fanrow-skel { display: flex; align-items: center; gap: 12px; padding: 13px 14px; }
.fanrow-skel .skel-line { flex: 1; }

/* ---------- La fiche, SOUS la ligne (c'est ce qui fait la maquette 14) ---------- */
.fandetail {
  padding: 2px 14px 16px 11px; border-left: 3px solid var(--accent-solid);
  background: var(--accent-wash);
}
.fand-alert {
  border-left: 3px solid var(--err); border-radius: 0 8px 8px 0;
  padding: 9px 12px; margin: 6px 0 12px; background: var(--err-soft);
}
.fand-alert.a-info { border-left-color: var(--info); background: var(--info-soft); }
.fand-alert b { display: block; font-size: 14px; font-weight: 660; color: var(--text); }
.fand-alert span { display: block; margin-top: 2px; font-size: 12px; color: var(--text2); line-height: 1.45; }
.fand-quote {
  margin: 0 0 12px; font-size: 12px; font-style: italic; color: var(--text2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.fand-cols { display: grid; grid-template-columns: minmax(0, 1fr); gap: 14px 22px; }
.fand-col { margin: 0; }
.fand-col h4 {
  margin: 0 0 6px; font-family: var(--font-display); font-size: 12px; font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--text3);
}
.fand-fact {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  padding: 3px 0; border-bottom: 1px solid var(--line-tint);
}
.fand-fact:last-child { border-bottom: 0; }
.fand-fact dt { font-size: 12px; color: var(--text2); }
.fand-fact dd {
  margin: 0; font-size: 12px; color: var(--text); text-align: right;
  white-space: nowrap; font-variant-numeric: tabular-nums;
}
.fand-fact.is-key dd { font-weight: 680; }
.fand-fact dd i { font-style: normal; color: var(--text3); font-size: 12px; }
.fand-fact dd .is-warn { color: var(--warn); font-weight: 640; }
.fand-note { margin-top: 12px; }
.fand-note .cust-notes { width: 100%; }
.fand-acts { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }
.fand-acts .btn-primary { flex: 1 1 100%; justify-content: center; }
.fand-acts .btn-ghost { flex: 1 1 auto; justify-content: center; }

/* Deux colonnes dès le téléphone : « ses dates » en face de « son argent »,
   c'est la lecture de la maquette 14. Les valeurs passent à la ligne au lieu
   de déborder — « 6 days ago · 5 sent » ne tient pas sur 170 px. */
@media (min-width: 380px) {
  .fand-cols { grid-template-columns: 1fr 1fr; gap: 14px 16px; }
  .fand-col-wide { grid-column: 1 / -1; }
  .fand-fact { gap: 6px; }
  .fand-fact dt, .fand-fact dd { font-size: 12px; }
  /* C'est l'INTITULÉ qui passe à la ligne, jamais le fait : « 6 days ago »
     coupé en deux ne se lit plus. */
  .fand-fact dt { min-width: 0; }
  .fand-fact dd { flex: 0 0 auto; }
  .fand-more { display: none; }       /* « · 5 sent » : la place manque */
}
@media (min-width: 560px) {
  .fand-cols { gap: 14px 22px; }
  .fand-more { display: inline; }
  .fand-acts .btn-primary, .fand-acts .btn-ghost { flex: 0 0 auto; }
}
@media (min-width: 640px) {
  .fanl-hint { display: inline; }
}

/* ---------- Ordinateur : tout sur une seule ligne ---------- */
@media (min-width: 900px) {
  .fanq { padding: 16px 18px 18px; }
  .fanl-head { padding: 15px 18px 0; }
  .page-fans .cust-filters { padding: 11px 18px 12px; }
  .fanl-foot { padding: 12px 18px 14px; }
  .fanrow-main {
    grid-template-columns: 34px minmax(0, 1.5fr) 118px minmax(0, 1.1fr) 132px 66px;
    grid-template-areas: "av name money when chip act";
    gap: 12px; padding: 9px 18px; min-height: 54px;
  }
  .fanrow.is-open .fanrow-main { padding-left: 15px; }
  .fanrow-id { flex-direction: column; align-items: flex-start; gap: 0; line-height: 1.25; }
  .fanrow-handle { display: block; }
  .fanrow-money b { font-size: 14px; }
  .fanrow-money i { display: block; }
  .fanrow-when { flex-direction: column; gap: 0; line-height: 1.35; }
  .fanrow-when span + span::before { content: none; }
  .fanrow-act { display: block; }
  .fandetail { padding: 4px 18px 18px 15px; }
  .fand-cols { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px 26px; }
  .fand-col-wide { grid-column: auto; }
  .fand-quote { font-size: 14px; }
}

@media (prefers-reduced-motion: reduce) {
  .fanq-pill, .fanrow-main { transition: none; }
}

/* ---------- 28/09 (mission CRM + bot) : « Her bot » sur Today, onglet « Why » du tiroir ---------- */
.bot-tile { display: grid; gap: 6px; padding: 12px 14px; }
.bot-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.bot-dot { display: inline-block; width: 9px; height: 9px; border-radius: 50%; margin-right: 6px; vertical-align: middle; background: currentColor; opacity: .5; }
.bot-dot.ok { background: #2e9e5b; opacity: 1; }
.bot-dot.ko { background: #d64545; opacity: 1; }
.bot-dot.warn { background: #c9741c; opacity: 1; }
.bot-facts { display: flex; flex-wrap: wrap; gap: 4px 14px; }
.bot-warn { color: #c9741c; font-weight: 600; }
.why-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 8px; }
.why-turn { display: grid; grid-template-columns: 78px 1fr; gap: 8px; padding: 7px 0; border-top: 1px solid var(--border); font-size: 12px; }
.why-turn time { opacity: .7; font-variant-numeric: tabular-nums; font-size: 12px; }
.why-turn > div { display: grid; gap: 3px; min-width: 0; overflow-wrap: anywhere; }
.why-event b { opacity: .8; }
.of-t-never { color: #c9741c; font-weight: 600; }

/* ============================================================
   TOUR 53 (01/10) — le bandeau « why it is not moving » d'une conversation,
   le sort réel des réponses écrites dans le CRM, la file « Waiting for
   money » de Today. Jetons existants seulement (bleu #229ed9 inchangé),
   clair et sombre ; élévation par la luminance des surfaces, coins 14 px.
   ============================================================ */
.thread-state {
  flex: none;
  display: grid; gap: 8px;
  padding: 10px 16px 12px;
  border-bottom: 1px solid var(--border);
  background: var(--panel);
  max-height: 42%;
  overflow-y: auto;
}
.thread-state[hidden] { display: none; }
.ts-rows { display: grid; gap: 6px; }
.ts-row {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 10px;
  padding: 8px 12px;
  border-radius: 14px;
  background: var(--surface);
  font-size: 14px; line-height: 1.45;
  min-width: 0;
}
.ts-row b { font-weight: 600; color: var(--text); white-space: nowrap; }
.ts-row span { color: var(--text2); min-width: 0; overflow-wrap: anywhere; }
.ts-row small, .ts-money small { color: var(--text3); font-size: 12px; margin-left: 2px; }
.ts-row.t-err { background: var(--err-soft); }
.ts-row.t-err b { color: var(--err); }
.ts-row.t-warn { background: var(--warn-soft); }
.ts-row.t-warn b { color: var(--warn); }
.ts-row.t-info { background: var(--info-soft); }
.ts-row.t-info b { color: var(--info); }
.ts-row.t-mute { background: var(--chip-bg); }
.ts-clear { font-size: 14px; color: var(--text2); }
.ts-money { font-size: 12px; line-height: 1.5; color: var(--text2); }
.ts-money > summary {
  display: flex; align-items: baseline; gap: 8px;
  list-style: none; cursor: pointer;
}
.ts-money > summary::-webkit-details-marker { display: none; }
.ts-money > summary > span { min-width: 0; overflow-wrap: anywhere; }
.ts-money > summary::after {
  content: "Details"; margin-left: auto; flex: none;
  color: var(--accent); font-weight: 550; font-size: 12px;
}
.ts-money[open] > summary::after { content: "Hide"; }
.ts-more { display: flex; flex-wrap: wrap; gap: 4px 18px; margin-top: 4px; }
.ts-more > span { min-width: 0; overflow-wrap: anywhere; }
.ts-money em {
  font-style: normal; font-weight: 600; font-size: 12px;
  letter-spacing: 0.07em; text-transform: uppercase;
  color: var(--text3); margin-right: 6px;
}
.ts-money b { color: var(--text); font-weight: 600; }
.ts-money .chip { font-style: normal; padding: 1px 8px; font-size: 12px; }
.ts-money .chip::before { display: none; }

/* Le toast — le seul endroit où une action dit « fait » ou « refusé » — était
   ILLISIBLE en thème clair depuis le 10/09 : fond `--toast-bg` (#17212b,
   sombre) et texte `--text` (#0f1419, sombre aussi). Il prend la couleur de
   texte prévue pour lui (`--toast-text`, blanc dans les deux thèmes). */
.toast { color: var(--toast-text); }

/* Une réponse écrite ici, pas (encore) partie : son état sous la bulle. */
.bubble.ob-pending, .bubble.ob-retrying { opacity: 0.86; }
.bubble.ob-failed { background: var(--surface); box-shadow: inset 0 0 0 1px var(--err-soft); }
.bubble .ob-status { display: inline; }
.bubble .ob-status .badge { margin-right: 4px; }
#reply-msg.reply-block { color: var(--err); font-weight: 550; }
#reply-msg.reply-hold { color: var(--text2); }

/* Today : qui attend de l'argent maintenant. */
.waiting-panel { margin-bottom: 16px; }
.waiting-list { display: flex; flex-direction: column; }
.wait-row {
  display: grid; grid-template-columns: 34px minmax(0, 1fr) auto; gap: 12px; align-items: center;
  padding: 10px 8px; margin: 0 -8px;
  border-top: 1px solid var(--row-border);
  border-radius: 14px;
  color: inherit; text-decoration: none;
}
.waiting-list > .wait-row:first-child { border-top: 0; }
.wait-row:hover { background: var(--hover-fill); }
.wait-row:focus-visible { outline: 2px solid var(--accent-ring); outline-offset: -2px; }
.wait-row .conv-avatar { width: 34px; height: 34px; font-size: 14px; }
.wait-main { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.wait-name { font-weight: 600; font-size: 14px; }
.wait-fact { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 8px; font-size: 12px; color: var(--text2); min-width: 0; }
.wait-fact > span:last-child { min-width: 0; overflow-wrap: anywhere; }
.wait-fact small { color: var(--text3); font-size: 12px; }
.wait-fact .chip { padding: 2px 8px; font-size: 12px; }
.wait-paid { display: flex; flex-direction: column; align-items: flex-end; gap: 1px; text-align: right; white-space: nowrap; }
.wait-paid b { font-family: var(--font-display); font-weight: 600; font-size: 14px; letter-spacing: -0.01em; }
.wait-paid small { color: var(--text3); font-size: 12px; }
.wait-more { margin-top: 6px; border-top: 1px solid var(--row-border); padding-top: 8px; }
.wait-more summary { cursor: pointer; font-size: 12px; color: var(--text2); padding: 4px 0; }
.wait-more .wait-row { opacity: 0.9; }

@media (max-width: 860px) {
  .thread-state { padding: 8px 12px 10px; max-height: 36vh; }
  .ts-row { padding: 7px 10px; font-size: 12px; }
  .ts-money { gap: 3px 12px; font-size: 12px; }
  .waiting-panel .today-h { flex-direction: column; align-items: flex-start; gap: 2px; }
  .wait-row { grid-template-columns: 30px minmax(0, 1fr); gap: 10px; }
  .wait-row .conv-avatar { width: 30px; height: 30px; font-size: 12px; }
  .wait-paid { grid-column: 2; align-items: flex-start; flex-direction: row; gap: 8px; }
}

/* TOUR 99 (12/10) — le nom d'une vague se tape dans sa cellule (page Analytics, « Where fans come from »). */
.an-wave-name { width: 100%; min-width: 170px; font-weight: 600; }

/* 13/10 (tour 11, `argent_telegram`) — la section Money de Today. */
.money-panel { margin-bottom: 16px; }
.money-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 12px; }
.money-cell { display: flex; flex-direction: column; gap: 2px; }
.money-cell > span { font-size: 12px; color: var(--text2); }
.money-cell > b { font-size: 18px; font-variant-numeric: tabular-nums; }
.money-cell > small { font-size: 12px; color: var(--text2); line-height: 1.35; }
.money-h { margin-top: 14px; font-size: 12px; font-weight: 600; }
.money-rows { display: flex; flex-direction: column; }
.money-row { display: grid; grid-template-columns: 170px 120px 1fr auto; gap: 10px; align-items: baseline;
  padding: 7px 0; border-top: 1px solid var(--row-border); color: inherit; text-decoration: none; font-size: 14px; }
.money-row em { font-style: normal; font-variant-numeric: tabular-nums; }
.money-row time { color: var(--text2); }
.money-foot { margin-top: 10px; }
/* Tour 380 (accueil_demarrage) : l'allumage et la première vente, une ligne sous les tuiles. */
.instance-start { margin-top: 8px; font-size: 12px; color: var(--text2); }
.instance-start b { color: var(--accent); font-weight: 600; font-variant-numeric: tabular-nums; }
/* TOUR 504 (16/10, `reglages_vu`) : « Recent changes » sur Today — le journal ouvert, qui défile dans son cadre. */
.audit-panel { margin-bottom: 16px; }
.audit-list { display: flex; flex-direction: column; max-height: 420px; overflow-y: auto; }
.audit-row { padding: 8px 0; border-top: 1px solid var(--row-border); font-size: 14px; }
.audit-list > .audit-row:first-child { border-top: 0; }
.audit-head time, .audit-who, .audit-none { color: var(--text2); }
.audit-head time { font-variant-numeric: tabular-nums; }
.audit-change { margin-top: 2px; color: var(--text2); overflow-wrap: anywhere; }
.audit-change code { color: var(--text); }
.audit-change .btn { margin-left: 6px; color: var(--accent); }
/* TOUR 578 (16/10, `crm_lisible`, audit CRM D1-D3) : en compact, Today garde ses blocs d'action ; le reste ne
   quitte jamais le DOM, il est masqué ici. `crm-full` (« Show everything », la session) rend l'écran d'avant. */
body.crm-compact:not(.crm-full) .is-secondary { display: none; }
.is-compact-only { display: none; }
body.crm-compact:not(.crm-full) .is-compact-only { display: block; }
body.crm-compact:not(.crm-full) .today-cols { grid-template-columns: minmax(0, 1fr); }
.crm-full-btn { display: none; }
body.crm-compact .crm-full-btn { display: inline-flex; }
/* 20/10 (audit UI prod, défaut 1) — la barre du haut : 56 px, titre, lune et « Show everything » centrés sur
   la même ligne, 36 px de haut chacun (mesuré en 390 : barre de 72 px, lune à y=0 coupée en haut, bouton à
   y=14 et 44 px). Sous 400 px le bouton n'est plus que son icône de 36×36 (libellé en aria-label). */
.topbar { gap: 8px; }
.topbar-title { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; font-size: 32px; line-height: 1.2; }
.topbar-actions { gap: 8px; flex: none; }
.topbar-actions .theme-toggle { width: 36px; height: 36px; }
.topbar-actions .month-rev { height: 36px; }
.topbar-actions .crm-full-btn { height: 36px; min-height: 36px; align-self: center; }
.crm-full-ico { display: none; flex: none; }
@media (max-width: 860px) {
  .topbar-title { font-size: 18px; }
  .topbar-actions .crm-full-btn { padding: 0 12px; }
}
@media (max-width: 399px) {
  .topbar-actions .crm-full-btn { width: 36px; padding: 0; }
  .crm-full-ico { display: block; }
  .crm-full-txt { display: none; }
}
#today-behind { margin: 0 0 16px; }
#today-behind[open] > .panel, #today-behind[open] > div { margin-top: 16px; }
/* TOUR 579 (16/10, `crm_lisible`, audit CRM D4-D5) : Conversations et Fans en compact. Le tiroir à onglets,
   les faits et boutons déplacés en fin de tiroir, « More » des filtres, « More details » de la fiche ; les
   ventes retenues au bas de #fanq. Ces nœuds n'existent qu'en compact. */
body.crm-compact:not(.crm-full) .details-tabs { display: flex; border-bottom: 1px solid var(--border); margin-bottom: 14px; }
body.crm-compact:not(.crm-full) .fan-moved { display: flex; flex-direction: column; gap: 10px; }
body.crm-compact:not(.crm-full) .fan-moved .thread-facts { padding: 0 0 10px; }
body.crm-compact:not(.crm-full) .fan-moved .thread-actions { flex-wrap: wrap; }
body.crm-compact:not(.crm-full) .conv-more { margin-top: 6px; }
body.crm-compact:not(.crm-full) .fand-details > .fand-cols { margin-top: 12px; }
body.crm-compact:not(.crm-full) .fanq-held { margin-top: 16px; }

/* TOUR 581 (17/10, `porte_vendable`) — vendable ou ce qui manque, une ligne en tête de Today (créée par loadReady). */
.ready-gate {
  display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap;
  border-radius: 14px; padding: 10px 16px; margin: 0 0 14px;
  border: 1px solid var(--border);
}
.ready-gate.is-ready { background: var(--ok-soft); }
.ready-gate.is-ready b { color: var(--ok); }
.ready-gate.is-missing { background: var(--warn-soft); border-color: var(--warn-border); flex-direction: column; gap: 4px; }
.ready-gate.is-missing b { color: var(--warn); }
.ready-gate ul { margin: 0; padding-left: 18px; }
.ready-gate li { margin: 2px 0; }
/* 20/10 (audit UI prod, défaut 3) — un fan réellement retenu par une marque mineur : une ligne sous le bandeau
   d'état (renderMinorAlert), le tableau vit dans « Behind the scenes ». */
.minor-alert {
  display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap;
  border-radius: 14px; padding: 10px 16px; margin: 0 0 14px;
  background: var(--err-soft); border: 1px solid var(--border);
  color: var(--text); font-size: 14px;
}
.minor-alert a { color: var(--err); font-weight: 600; }
/* 20/10 (audit UI prod, défaut 2) — « Minor flags not lifted » en 390 : la citation était coupée à droite, sans
   indice de défilement, et le bouton « Lift » hors de vue. Sous 600 px chaque ligne devient une carte : le fan
   et la date, la citation entière, l'état et « Lift », puis les deux dates secondaires. Le <table> reste ;
   au-dessus de 600 px rien ne change. */
@media (max-width: 600px) {
  .table.minor-table, .minor-table tbody { display: block; overflow: visible; white-space: normal; }
  .minor-table thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
  .minor-table tr {
    display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 6px 12px; align-items: center;
    padding: 12px 0; border-bottom: 1px solid var(--row-border);
  }
  .minor-table tr:last-child { border-bottom: 0; }
  .minor-table td { display: block; padding: 0; border: 0; white-space: normal; overflow-wrap: anywhere; }
  .minor-table .mf-fan { grid-row: 1; grid-column: 1; font-size: 14px; }
  .minor-table .mf-at { grid-row: 1; grid-column: 2; font-size: 12px; text-align: right; }
  .minor-table .mf-lines { grid-row: 2; grid-column: 1 / -1; font-size: 14px; color: var(--text); }
  .minor-table .mf-now { grid-row: 3; grid-column: 1; }
  .minor-table .mf-lift { grid-row: 3; grid-column: 2; }
  .minor-table .mf-reread { grid-row: 4; grid-column: 1 / -1; font-size: 12px; }
  .minor-table .mf-last { grid-row: 5; grid-column: 1 / -1; font-size: 12px; }
  .minor-table .mf-lines::before,
  .minor-table .mf-reread::before,
  .minor-table .mf-last::before { content: attr(data-label); display: block; font-size: 12px; color: var(--text3); }
}
/* 20/10 (UI prod défaut 15) : l'entonnoir dit en phrase va à la ligne au lieu de sortir de sa tuile. */
.money-tile .money.money-words { white-space: normal; overflow-wrap: anywhere; }
.money-tile .money.money-words > span { white-space: nowrap; }
