/* ═════════════════════════════════════════════════════════════════════
   Numeri gestion — la feuille de style.

   ── Pourquoi tout a changé le 31/08/2026 ──────────────────────────────
   Cet écran était resté sur une charte que Numeri n'a plus. Trois écarts,
   tous invisibles tant qu'on ne posait pas les deux pages côte à côte :

     1. **Le fond.** La charte de Numeri est le NOIR depuis le 30/08/2026
        (« version black de base », Joseph). La gestion était blanche.
     2. **L'accent.** Il valait #0B34E6, un bleu qui n'existe nulle part
        chez Numeri. La marque est violette : #B9AEFF sur le noir.
     3. **La police.** Le fichier demandait « Hanken Grotesk », qui n'était
        chargée nulle part : la page tournait depuis le premier jour sur la
        police système. La marque, c'est Poppins + IBM Plex Mono, et ces
        polices étaient déjà auto-hébergées à deux dossiers d'ici.

   Les jetons sont recopiés de `site/assets/css/numeri.css` et non importés :
   la gestion vit sur un autre nom d'hôte, un @import inter-domaine serait une
   requête tierce — et Numeri n'en fait aucune, c'est ce qui lui évite un
   bandeau cookies.

   ⚠️ Si la charte du site bouge, le bloc de jetons ci-dessous bouge avec.
      C'est le seul endroit à reprendre.

   ⚠️ Un seul thème, assumé. Le site a une bascule clair/sombre ; pas cet
      écran. Un thème secondaire n'est jamais regardé, donc jamais vérifié —
      et le jour où quelqu'un l'ouvre, tout ce qui y était faux se voit d'un
      coup. Une gestion interne se regarde en noir, comme la marque.

   Écrit le 30/08/2026, refait le 31/08/2026.
   ═════════════════════════════════════════════════════════════════════ */

/* ── 01 · LES POLICES — auto-hébergées, jamais Google Fonts en CDN ──────
   La CNIL voit dans un appel à fonts.googleapis.com un transfert de données
   non consenti, et la CSP de la page le bloquerait de toute façon. Douze
   woff2, 112 Ko, découpés par plage Unicode : on ne télécharge que « latin »
   tant qu'aucun caractère d'ailleurs n'apparaît. */

@font-face { font-family:"Poppins"; font-style:normal; font-weight:400; font-display:swap;
  src:url("fonts/poppins-400-latin.woff2") format("woff2");
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD; }
@font-face { font-family:"Poppins"; font-style:normal; font-weight:500; font-display:swap;
  src:url("fonts/poppins-500-latin.woff2") format("woff2");
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD; }
@font-face { font-family:"Poppins"; font-style:normal; font-weight:600; font-display:swap;
  src:url("fonts/poppins-600-latin.woff2") format("woff2");
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD; }
@font-face { font-family:"Poppins"; font-style:normal; font-weight:700; font-display:swap;
  src:url("fonts/poppins-700-latin.woff2") format("woff2");
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD; }
@font-face { font-family:"Poppins"; font-style:normal; font-weight:400; font-display:swap;
  src:url("fonts/poppins-400-latinext.woff2") format("woff2");
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF; }
@font-face { font-family:"Poppins"; font-style:normal; font-weight:500; font-display:swap;
  src:url("fonts/poppins-500-latinext.woff2") format("woff2");
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF; }
@font-face { font-family:"Poppins"; font-style:normal; font-weight:600; font-display:swap;
  src:url("fonts/poppins-600-latinext.woff2") format("woff2");
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF; }
@font-face { font-family:"Poppins"; font-style:normal; font-weight:700; font-display:swap;
  src:url("fonts/poppins-700-latinext.woff2") format("woff2");
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF; }

@font-face { font-family:"IBM Plex Mono"; font-style:normal; font-weight:400; font-display:swap;
  src:url("fonts/plexmono-400-latin.woff2") format("woff2");
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD; }
@font-face { font-family:"IBM Plex Mono"; font-style:normal; font-weight:500; font-display:swap;
  src:url("fonts/plexmono-500-latin.woff2") format("woff2");
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD; }
@font-face { font-family:"IBM Plex Mono"; font-style:normal; font-weight:400; font-display:swap;
  src:url("fonts/plexmono-400-latinext.woff2") format("woff2");
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF; }
@font-face { font-family:"IBM Plex Mono"; font-style:normal; font-weight:500; font-display:swap;
  src:url("fonts/plexmono-500-latinext.woff2") format("woff2");
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF; }


/* ── 02 · LES JETONS — le noir de la charte ────────────────────────── */
:root {
  color-scheme: dark;

  --n-bg:            #0B0B0F;
  --n-bg-soft:       #101017;
  --n-surface-1:     #141420;
  --n-surface-2:     #1A1A28;
  --n-surface-3:     #222232;
  --n-surface-4:     #2C2C40;

  --n-text:          #F2F1F8;
  --n-text-strong:   #FFFFFF;
  --n-text-muted:    #B3B2C2;
  --n-text-faint:    #9A99AA;
  --n-text-dim:      #8E8D9E;
  --n-text-disabled: #5A5A68;
  --n-text-on-accent:#0B0B0F;

  --n-accent:        #B9AEFF;
  --n-accent-hi:     #D2CBFF;
  --n-accent-lo:     #7A6CF0;
  --n-accent-soft:   rgba(185,174,255,0.14);
  --n-accent-veil:   rgba(185,174,255,0.06);
  --n-grad:          linear-gradient(115deg,#FF8A99 0%,#D3A5F7 52%,#9E92FF 100%);

  --n-ok:            #4ED396;   --n-ok-soft:     rgba(78,211,150,0.14);
  --n-warn:          #F0B95C;   --n-warn-soft:   rgba(240,185,92,0.14);
  --n-danger:        #FF8480;   --n-danger-soft: rgba(255,132,128,0.14);
  --n-info:          #8FBEE6;   --n-info-soft:   rgba(143,190,230,0.14);

  --n-line:          rgba(255,255,255,0.09);
  --n-line-2:        rgba(255,255,255,0.14);
  --n-line-3:        rgba(255,255,255,0.20);
  --n-line-strong:   #8E8DA0;
  --n-line-grid:     rgba(255,255,255,0.06);

  --n-r-sm:    9px;
  --n-r-md:   12px;
  --n-r-lg:   16px;
  --n-r-xl:   18px;
  --n-r-pill: 999px;

  --n-shadow-1: 0 1px 2px rgba(0,0,0,0.5);
  --n-shadow-2: 0 6px 18px -12px rgba(0,0,0,0.7);
  --n-shadow-3: 0 20px 50px -34px rgba(0,0,0,0.8);
  --n-glow:     0 12px 30px -16px rgba(185,174,255,0.4);

  --n-dur-1: 120ms; --n-dur-2: 180ms;
  --n-ease: cubic-bezier(0.2, 0.7, 0.2, 1);

  /* ── LES SÉRIES ──────────────────────────────────────────────────────
     Ordre FIXE, jamais recyclé : la couleur suit l'entité, pas son rang.
     Un filtre qui retire une série ne repeint pas les autres.

     ⚠️ Ces quatre-là ne sont PAS celles du thème clair d'avant : sur un fond
     à #141420, un #0B34E6 est un trou noir. Elles sont validées sur CETTE
     surface (bande de clarté OKLCH 0,48–0,67, plancher de chroma, séparation
     daltonienne sur toutes les paires, plancher vision normale, contraste) —
     `data-palette` sur le <body> porte la même liste pour qu'on puisse
     rejouer la vérification sans la retaper.

     Le bénéfice est CYAN et non vert : rose et vert se confondent en vision
     deutane (ΔE 4,3 mesuré), et ces deux séries se touchent dans la légende
     du mois par mois. Le vert reste réservé au statut « ça monte ». */
  --s1: #8272F5;   /* Encaissé            — le violet de la marque */
  --s2: #A8912B;   /* Coût en jetons      — ambre */
  --s3: #E45F86;   /* Commissions Mollie  — le rose de la rampe */
  --s4: #0FA3C0;   /* Bénéfice            — cyan */

  --hausse: #4ED396;
  --baisse: #FF8480;

  --police: "Poppins", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --chiffres: "IBM Plex Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }

/* ⚠️ LA GARDE DE `hidden`. `[hidden] { display: none }` vient de la feuille du
   NAVIGATEUR : elle n'a aucune spécificité, et la moindre classe qui déclare
   `display: flex` la bat. Le bloc reste affiché, sans une erreur en console,
   et le HTML a l'air juste puisque l'attribut y est bien écrit. Payé quatre
   fois sur Numeri — `.n-field__error`, les panneaux de la forge, son dépôt de
   photo, `.n-forge__form`. Ici `.g-rappel`, `.g-bouton--discret` et
   `.g-message` posent tous un display : sans cette ligne, le rappel du
   versement et le message du bas resteraient visibles en permanence. */
[hidden] { display: none !important; }
body {
  margin: 0; background: var(--n-bg); color: var(--n-text);
  font: 400 15px/1.55 var(--police);
  -webkit-font-smoothing: antialiased;
  min-height: 100vh;
}

/* Le halo de la marque : le seul décor de la page, posé derrière tout et
   sous l'en-tête. Deux taches très diluées — il donne la profondeur de la
   charte sans rien coûter à la lecture des chiffres, qui vivent sur des
   cartes opaques par-dessus. */
.g-halo {
  position: fixed; inset: 0; z-index: 0; pointer-events: none;
  background:
    radial-gradient(46rem 26rem at 12% -8%, rgba(122,108,240,.20), transparent 62%),
    radial-gradient(38rem 22rem at 92% 4%, rgba(255,138,153,.11), transparent 60%);
}

/* ── L'EN-TÊTE ──────────────────────────────────────────────────────── */
.g-tete {
  position: sticky; top: 0; z-index: 20;
  display: flex; align-items: center; gap: 22px; flex-wrap: wrap;
  padding: 12px 22px;
  background: rgba(11,11,15,.82);
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--n-line);
}
.g-tete__marque {
  display: inline-flex; align-items: baseline; gap: 8px;
  text-decoration: none; color: var(--n-text);
}
.g-tete__marque img { display: block; height: 18px; width: auto; }
.g-tete__marque span { color: var(--n-text-faint); font-size: 14px; font-weight: 400; }
.g-tete__qui { margin-left: auto; display: flex; align-items: center; gap: 14px;
  color: var(--n-text-muted); font-size: 13px; }

.g-onglets { display: flex; gap: 2px; flex-wrap: wrap; }
.g-onglet {
  border: 1px solid transparent; background: none; cursor: pointer;
  font: 500 14px/1 var(--police); color: var(--n-text-muted);
  padding: 9px 14px; border-radius: var(--n-r-pill);
  transition: background var(--n-dur-2) var(--n-ease), color var(--n-dur-2) var(--n-ease);
}
.g-onglet:hover { background: var(--n-surface-2); color: var(--n-text); }
.g-onglet.is-actif {
  background: var(--n-accent-soft); color: var(--n-accent-hi); font-weight: 600;
  border-color: rgba(185,174,255,.28);
}
.g-onglet:focus-visible, .g-filtre:focus-visible, .g-bouton:focus-visible,
.g-lien:focus-visible, .g-rappel:focus-visible, .g-ligne-action:focus-visible,
input:focus-visible, select:focus-visible, .g-tete__marque:focus-visible {
  outline: 2px solid var(--n-accent); outline-offset: 2px; border-radius: var(--n-r-sm);
}
.g-lien { color: var(--n-accent); text-decoration: none; }
.g-lien:hover { color: var(--n-accent-hi); text-decoration: underline; }

.g-page { position: relative; z-index: 1; max-width: 1240px; margin: 0 auto; padding: 26px 22px 90px; }
.g-vue { display: none; }
.g-vue.is-actif { display: block; }

/* ── LES ALERTES — avant les chiffres, jamais après ──────────────────── */
.g-alertes:not(:empty) { display: grid; gap: 8px; margin-bottom: 22px; }
.g-alerte {
  padding: 12px 15px; border-radius: var(--n-r-md); font-size: 13.5px;
  border: 1px solid var(--n-line-2); background: var(--n-surface-1); margin: 0;
  color: var(--n-text-muted);
}
.g-alerte strong { display: block; margin-bottom: 2px; color: var(--n-text); }
.g-alerte--critique { border-color: rgba(255,132,128,.45); background: var(--n-danger-soft); }
.g-alerte--critique strong { color: var(--n-danger); }
.g-alerte--attention { border-color: rgba(240,185,92,.40); background: var(--n-warn-soft); }
.g-alerte--attention strong { color: var(--n-warn); }

/* ── LES TUILES ─────────────────────────────────────────────────────── */
.g-tuiles { display: grid; gap: 14px; margin-bottom: 18px;
  grid-template-columns: repeat(auto-fit, minmax(196px, 1fr)); }
.g-tuile {
  background: var(--n-surface-1); border: 1px solid var(--n-line);
  border-radius: var(--n-r-lg); padding: 16px 18px; box-shadow: var(--n-shadow-2);
}
.g-tuile h2 { margin: 0 0 8px; font-size: 11.5px; font-weight: 600; letter-spacing: .06em;
  text-transform: uppercase; color: var(--n-text-faint); }
.g-tuile__chiffre { margin: 0; font: 500 28px/1.1 var(--chiffres); letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums; color: var(--n-text-strong); }
.g-tuile__note { margin: 7px 0 0; font-size: 12.5px; line-height: 1.45; color: var(--n-text-faint); }

/* La tuile phare porte la rampe de la marque en filet haut : c'est le seul
   endroit où le dégradé apparaît, et il désigne LE chiffre de l'écran. */
.g-tuile--phare { position: relative; overflow: hidden; background: var(--n-surface-2); }
.g-tuile--phare::before {
  content: ""; position: absolute; inset: 0 0 auto; height: 2px; background: var(--n-grad);
}
.g-tuile--phare .g-tuile__chiffre { font-size: 38px; color: var(--n-accent-hi); }

/* ── LE RAPPEL DU VERSEMENT ──────────────────────────────────────────
   Une seule ligne, cliquable, qui mène à l'onglet du partage. Elle répond à
   « est-ce que je dois virer quelque chose, et quand » — le détail est
   ailleurs, exprès. */
.g-rappel {
  display: flex; align-items: center; gap: 12px; width: 100%; text-align: left;
  font: inherit; cursor: pointer; margin-bottom: 18px;
  padding: 13px 18px; border-radius: var(--n-r-lg);
  border: 1px solid rgba(185,174,255,.30); background: var(--n-accent-veil);
  color: var(--n-text);
  transition: background var(--n-dur-2) var(--n-ease), border-color var(--n-dur-2) var(--n-ease);
}
.g-rappel:hover { background: var(--n-accent-soft); border-color: rgba(185,174,255,.5); }
.g-rappel__chiffre { font: 500 20px/1 var(--chiffres); color: var(--n-accent-hi);
  font-variant-numeric: tabular-nums; }
.g-rappel__quoi { color: var(--n-text-muted); font-size: 13.5px; }
.g-rappel__fleche { margin-left: auto; color: var(--n-accent); font-size: 18px; line-height: 1; }
.g-rappel--fait { border-color: rgba(78,211,150,.32); background: var(--n-ok-soft); }
.g-rappel--fait .g-rappel__chiffre { color: var(--n-ok); }
.g-rappel--fait .g-rappel__fleche { color: var(--n-ok); }

/* ── LES CADRES ─────────────────────────────────────────────────────── */
.g-cadre {
  background: var(--n-surface-1); border: 1px solid var(--n-line);
  border-radius: var(--n-r-xl); padding: 18px 20px; margin-bottom: 18px;
  box-shadow: var(--n-shadow-2);
}
.g-cadre--saisie { border-color: rgba(185,174,255,.24); background: var(--n-surface-2); }
.g-cadre__tete { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-bottom: 14px; }
.g-cadre__tete h2 { margin: 0; font-size: 16px; font-weight: 600; letter-spacing: -0.01em; }
.g-cadre__note { margin: 12px 0 0; font-size: 12.5px; line-height: 1.55;
  color: var(--n-text-faint); max-width: 78ch; }
.g-cadre__note strong { color: var(--n-text-muted); }
.g-cadre__note code { font-family: var(--chiffres); font-size: .92em; color: var(--n-text-muted); }

/* Les filtres, en une seule ligne AU-DESSUS du graphique. */
.g-filtres { margin-left: auto; display: flex; gap: 4px; }
.g-filtre {
  border: 1px solid var(--n-line-2); background: transparent; cursor: pointer;
  font: 500 12.5px/1 var(--police); color: var(--n-text-muted);
  padding: 7px 12px; border-radius: var(--n-r-pill);
  transition: background var(--n-dur-2) var(--n-ease), color var(--n-dur-2) var(--n-ease);
}
.g-filtre:hover { background: var(--n-surface-3); color: var(--n-text); }
.g-filtre.is-actif { background: var(--n-accent-soft); border-color: rgba(185,174,255,.35);
  color: var(--n-accent-hi); font-weight: 600; }

/* ── LES GRAPHIQUES ─────────────────────────────────────────────────── */
.g-graphe { width: 100%; min-height: 230px; }
.g-graphe svg { display: block; width: 100%; height: auto; }
/* Les repères d'axe et la valeur du jour portent la mono de la marque : un
   chiffre à chasse variable danse d'un repère à l'autre. */
.g-graphe text { font-family: var(--chiffres); font-variant-numeric: tabular-nums; }
.g-graphe .g-ax  { font-size: 11px; }
.g-graphe .g-val { font-size: 14px; font-weight: 500; }
.g-vide { padding: 36px 8px; text-align: center; color: var(--n-text-dim); font-size: 13px; }
.g-zone { cursor: crosshair; }

/* Deux escaliers côte à côte sur large écran : le MRR et les abonnés se
   lisent ensemble ou ne se lisent pas. Jamais superposés sur deux axes —
   des euros et un compte d'abonnés ne se comparent pas en hauteur. */
.g-duo { display: grid; gap: 22px; }
@media (min-width: 900px) { .g-duo { grid-template-columns: 1fr 1fr; } }
.g-duo__titre { margin: 0 0 4px; font-size: 12px; font-weight: 600; letter-spacing: .05em;
  text-transform: uppercase; color: var(--n-text-faint); }

/* La légende est TOUJOURS là dès deux séries : l'identité ne tient jamais
   à la seule couleur. */
.g-legende { display: flex; flex-wrap: wrap; gap: 8px 20px; margin-top: 12px;
  font-size: 12.5px; color: var(--n-text-muted); }
.g-legende__item { display: inline-flex; align-items: center; gap: 7px; }
.g-legende__puce { width: 10px; height: 10px; border-radius: 3px; flex: none; }
.g-legende__valeur { font-family: var(--chiffres); font-variant-numeric: tabular-nums;
  color: var(--n-text); }

/* ── LA RÉPARTITION DU MOIS — une barre, quatre segments ─────────────
   2 px de fond entre deux segments : sans ce filet, deux aplats qui se
   touchent se lisent comme un seul. */
.g-repartition { display: flex; gap: 2px; height: 40px; }
.g-repartition__seg { border-radius: 3px; min-width: 3px; position: relative; }
.g-repartition__seg:first-child { border-radius: var(--n-r-sm) 3px 3px var(--n-r-sm); }
.g-repartition__seg:last-child  { border-radius: 3px var(--n-r-sm) var(--n-r-sm) 3px; }

/* ── L'INFOBULLE ────────────────────────────────────────────────────── */
.g-infobulle {
  position: fixed; z-index: 60; pointer-events: none;
  background: var(--n-surface-4); color: var(--n-text);
  border: 1px solid var(--n-line-2);
  padding: 9px 11px; border-radius: var(--n-r-md);
  font-size: 12.5px; line-height: 1.5; box-shadow: 0 14px 40px -14px rgba(0,0,0,.9);
  max-width: 300px;
}
.g-infobulle b { font-family: var(--chiffres); font-variant-numeric: tabular-nums; }
.g-infobulle .g-ib-ligne { display: flex; align-items: center; gap: 7px; white-space: nowrap; }
.g-infobulle .g-legende__puce { width: 8px; height: 8px; }

/* ── LE MESSAGE — ce qui remplace alert() ────────────────────────────
   ⚠️ `alert()` et `confirm()` GÈLENT la page tant qu'on n'a pas cliqué, et
   avec elle tout pilotage par CDP : impossible de contrôler l'écran au
   navigateur après un geste. Piège déjà payé sur la console d'Odratta. */
.g-message {
  position: fixed; z-index: 70; left: 50%; bottom: 24px; transform: translateX(-50%);
  max-width: min(520px, calc(100vw - 32px));
  padding: 12px 18px; border-radius: var(--n-r-md);
  background: var(--n-surface-4); border: 1px solid var(--n-line-2);
  color: var(--n-text); font-size: 13.5px; box-shadow: 0 18px 50px -18px rgba(0,0,0,.9);
}
.g-message--ok   { border-color: rgba(78,211,150,.45); }
.g-message--rate { border-color: rgba(255,132,128,.5); }

/* ── LES TABLEAUX ───────────────────────────────────────────────────── */
.g-tableau-enveloppe { overflow-x: auto; margin: 0 -4px; padding: 0 4px; }
.g-tableau { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.g-tableau th, .g-tableau td { padding: 10px 12px; text-align: left;
  border-bottom: 1px solid var(--n-line); white-space: nowrap; }
/* La ligne secondaire sous une cellule se lit à la ligne : `nowrap` la
   pousserait hors du cadre et rendrait le tableau plus large que l'écran. */
.g-tableau td .g-secondaire { white-space: normal; display: block; max-width: 42ch; }
.g-tableau th { font-size: 11px; text-transform: uppercase; letter-spacing: .05em;
  color: var(--n-text-faint); font-weight: 600; border-bottom-color: var(--n-line-2); }
.g-tableau td.n, .g-tableau th.n { text-align: right; font-family: var(--chiffres);
  font-variant-numeric: tabular-nums; }
.g-tableau tbody tr:hover { background: var(--n-surface-2); }
.g-tableau tbody tr:last-child td { border-bottom: none; }
.g-tableau .g-secondaire { color: var(--n-text-faint); font-size: 12px; }

.g-pastille { display: inline-flex; align-items: center; gap: 6px; }
.g-pastille::before { content: ""; width: 7px; height: 7px; border-radius: 50%;
  background: currentColor; flex: none; }
.g-statut--actif { color: var(--n-ok); }
.g-statut--paid  { color: var(--n-ok); }
.g-statut--en_retard, .g-statut--en_attente, .g-statut--open, .g-statut--pending { color: var(--n-warn); }
.g-statut--suspendu, .g-statut--resilie, .g-statut--annule,
.g-statut--failed, .g-statut--expired, .g-statut--canceled { color: var(--n-text-dim); }
.g-neg { color: var(--n-danger); }
.g-pos { color: var(--n-ok); }

/* Les actions de ligne : discrètes tant qu'on ne survole pas la ligne, mais
   JAMAIS invisibles au clavier ni au doigt — `:focus-within` et les écrans
   sans survol les gardent toujours là. */
.g-actions { display: flex; gap: 6px; justify-content: flex-end; }
.g-ligne-action {
  font: 500 12px/1 var(--police); cursor: pointer;
  border: 1px solid var(--n-line-2); background: transparent; color: var(--n-text-muted);
  padding: 6px 10px; border-radius: var(--n-r-pill);
  opacity: .45; transition: opacity var(--n-dur-2) var(--n-ease),
                            background var(--n-dur-2) var(--n-ease), color var(--n-dur-2) var(--n-ease);
}
tr:hover .g-ligne-action, tr:focus-within .g-ligne-action { opacity: 1; }
.g-ligne-action:hover { background: var(--n-surface-3); color: var(--n-text); }
.g-ligne-action--danger:hover { background: var(--n-danger-soft); color: var(--n-danger);
  border-color: rgba(255,132,128,.5); }
.g-ligne-action--confirme { opacity: 1; background: var(--n-danger-soft); color: var(--n-danger);
  border-color: rgba(255,132,128,.6); font-weight: 600; }
@media (hover: none) { .g-ligne-action { opacity: 1; } }

/* ── LE PARTAGE ───────────────────────────────────────────────────────
   `auto-fit` et non deux colonnes en dur : au premier mois, il n'y a qu'une
   carte, et une carte seule dans une grille figée laisse une demi-page vide
   à côté d'elle. */
.g-partage { display: grid; gap: 18px; margin-bottom: 18px;
  grid-template-columns: repeat(auto-fit, minmax(360px, 1fr)); }

.g-mois {
  background: var(--n-surface-1); border: 1px solid var(--n-line);
  border-radius: var(--n-r-xl); padding: 18px 20px; box-shadow: var(--n-shadow-2);
}
/* Le mois CLOS est celui qu'on vire : il porte l'accent. Le mois en cours
   reste sourd — c'est une estimation, pas une somme à virer. */
.g-mois--clos { border-color: rgba(185,174,255,.30); box-shadow: var(--n-glow); }
.g-mois__tete { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin-bottom: 4px; }
.g-mois__nom { margin: 0; font-size: 17px; font-weight: 600; }
.g-mois__etat {
  font-size: 11px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase;
  padding: 3px 9px; border-radius: var(--n-r-pill);
  background: var(--n-surface-3); color: var(--n-text-faint);
}
.g-mois__etat--clos  { background: var(--n-accent-soft); color: var(--n-accent-hi); }
.g-mois__etat--verse { background: var(--n-ok-soft); color: var(--n-ok); }
.g-mois__benef { margin: 10px 0 2px; font: 500 30px/1.1 var(--chiffres);
  font-variant-numeric: tabular-nums; color: var(--n-text-strong); letter-spacing: -.02em; }
.g-mois__quoi { margin: 0 0 14px; font-size: 12.5px; color: var(--n-text-faint); }

.g-versement {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 12px 0; border-top: 1px solid var(--n-line);
}
.g-versement__qui { flex: 1 1 240px; min-width: 0; }
.g-versement__nom { margin: 0; font-size: 14px; font-weight: 600; }
.g-versement__note { margin: 2px 0 0; font-size: 12px; color: var(--n-text-faint); }
.g-versement__montant { margin-left: auto; font: 500 21px/1 var(--chiffres);
  font-variant-numeric: tabular-nums; white-space: nowrap; }
.g-versement__bouton { flex: none; }
.g-ecart { color: var(--n-warn); }

/* ── LES PARTS (la ligne d'Odratta) ─────────────────────────────────── */
.g-parts__grille { display: grid; gap: 12px; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); }
.g-part {
  border: 1px solid var(--n-line); border-radius: var(--n-r-md);
  padding: 14px 16px; background: var(--n-surface-2);
}
.g-part h3 { margin: 0 0 6px; font-size: 12.5px; font-weight: 600; color: var(--n-text-muted); }
.g-part__chiffre { margin: 0; font: 500 23px/1.15 var(--chiffres);
  font-variant-numeric: tabular-nums; color: var(--n-text-strong); }
.g-part__note { margin: 6px 0 0; font-size: 12px; line-height: 1.5; color: var(--n-text-faint); }
.g-part--total { background: var(--n-surface-1); border-left: 3px solid var(--n-accent-lo); }
.g-part--total .g-part__chiffre { color: var(--n-accent-hi); }

/* ── LES FORMULAIRES ────────────────────────────────────────────────── */
.g-form { display: grid; gap: 14px; margin-top: 4px; }
.g-form--ligne { grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); align-items: end; }
.g-form--frais { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); align-items: end; }
.g-champ { display: grid; gap: 5px; font-size: 12px; color: var(--n-text-muted); }
.g-champ > span { font-weight: 500; }
.g-champ em { font-style: normal; color: var(--n-text-dim); }
.g-champ--large { grid-column: span 2; }
.g-champ input, .g-champ select {
  font: 400 15px/1.3 var(--police); color: var(--n-text); padding: 10px 12px;
  border: 1px solid var(--n-line-2); border-radius: var(--n-r-sm);
  background: var(--n-bg-soft); min-width: 0; min-height: 42px;
  transition: border-color var(--n-dur-2) var(--n-ease);
}
.g-champ input::placeholder { color: var(--n-text-disabled); }
.g-champ input:hover, .g-champ select:hover { border-color: var(--n-line-3); }
/* Le sélecteur de date d'un navigateur sombre rend une icône noire sur noir. */
.g-champ input[type="date"], .g-champ input[type="month"] { color-scheme: dark; }
.g-form__action { display: flex; align-items: flex-end; }

/* Le champ du code et son bouton « Tirer », sur une seule ligne : tirer un
   code au hasard est le geste le plus fréquent, il ne doit pas coûter un
   aller-retour ailleurs dans le formulaire. */
.g-champ__duo { display: flex; gap: 6px; align-items: stretch; }
.g-champ__duo .g-bouton { flex: none; }
.g-champ__code {
  flex: 1 1 auto; min-width: 0;
  /* Un code se relit caractère par caractère : mono et majuscules, pour
     qu'aucune paire ne se confonde à l'œil. */
  font-family: var(--chiffres) !important; text-transform: uppercase;
  letter-spacing: .06em;
}

.g-bouton {
  font: 600 14px/1 var(--police); cursor: pointer; padding: 12px 20px;
  border: 1px solid var(--n-accent); background: var(--n-accent); color: var(--n-text-on-accent);
  border-radius: var(--n-r-pill); min-height: 42px;
  transition: background var(--n-dur-2) var(--n-ease), border-color var(--n-dur-2) var(--n-ease);
}
.g-bouton:hover { background: var(--n-accent-hi); border-color: var(--n-accent-hi); }
.g-bouton--discret { background: transparent; color: var(--n-accent);
  border-color: var(--n-line-2); font-weight: 500; padding: 8px 14px; font-size: 13px;
  min-height: 36px; text-decoration: none; display: inline-flex; align-items: center; }
.g-bouton--discret:hover { background: var(--n-accent-soft); border-color: rgba(185,174,255,.4);
  color: var(--n-accent-hi); }
.g-bouton--petit { padding: 8px 14px; font-size: 13px; min-height: 36px; }
.g-bouton[disabled] { opacity: .5; cursor: default; }

.g-controle { display: grid; gap: 12px; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }

/* ── LE MOUVEMENT DU MOIS ────────────────────────────────────────────
   Des compteurs, pas un graphique : à ces ordres de grandeur (« 3 entrées,
   1 sortie »), un camembert ou des barres feraient un dessin pour trois
   chiffres qu'on lit plus vite écrits. */
.g-mouvement { display: grid; gap: 10px; grid-template-columns: repeat(auto-fit, minmax(126px, 1fr)); }
.g-mvt { border: 1px solid var(--n-line); border-radius: var(--n-r-md); padding: 12px 14px;
  background: var(--n-surface-2); }
.g-mvt__n { margin: 0; font: 500 23px/1.15 var(--chiffres); font-variant-numeric: tabular-nums;
  color: var(--n-text-strong); }
.g-mvt__l { margin: 3px 0 0; font-size: 12px; color: var(--n-text-faint); }
.g-mvt--plus  .g-mvt__n { color: var(--n-ok); }
.g-mvt--moins .g-mvt__n { color: var(--n-danger); }
.g-mvt--net { background: var(--n-surface-1); border-left: 3px solid var(--n-accent-lo); }
.g-mvt--net .g-mvt__n { color: var(--n-accent-hi); }
/* Un zéro ne s'écrit ni en vert ni en rouge : « 0 descente de palier » en
   rouge se lit comme une alerte, alors que c'est la bonne nouvelle. */
.g-mvt--zero .g-mvt__n { color: var(--n-text-disabled); }

/* ── L'ÉCRAN DE CONNEXION ───────────────────────────────────────────── */
.g-login-page { display: grid; place-items: center; min-height: 100vh; padding: 24px;
  position: relative; z-index: 1; }
.g-login { width: 100%; max-width: 390px; background: var(--n-surface-1);
  border: 1px solid var(--n-line); border-radius: var(--n-r-xl); padding: 30px;
  box-shadow: var(--n-shadow-3); }
.g-login__marque { margin: 0 0 6px; font-size: 23px; font-weight: 600; letter-spacing: -0.02em; }
.g-login__marque span { color: var(--n-text-faint); font-weight: 400; }
.g-login__sous { margin: 0 0 22px; font-size: 13.5px; color: var(--n-text-faint); }
.g-login .g-form { gap: 14px; }
.g-login .g-bouton { width: 100%; justify-content: center; }

/* ── MOBILE ─────────────────────────────────────────────────────────── */
@media (max-width: 720px) {
  .g-page { padding: 18px 14px 70px; }
  .g-tete { padding: 12px 14px; gap: 12px; }
  .g-onglets { order: 3; width: 100%; overflow-x: auto; flex-wrap: nowrap;
    scrollbar-width: none; }
  .g-onglets::-webkit-scrollbar { display: none; }
  .g-onglet { flex: none; }
  .g-tete__qui { margin-left: auto; }
  .g-tuile--phare .g-tuile__chiffre { font-size: 32px; }
  .g-champ--large { grid-column: auto; }
  .g-versement__montant { margin-left: 0; width: 100%; }
}

/* ── MOUVEMENT ──────────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  * { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}

/* ── LES MODÈLES VIDÉO ───────────────────────────────────────────────
   Ajoutés le 02/09/2026 avec l'onglet « Les modèles ». Rien de neuf en
   dehors de la vignette : l'écran réutilise `.g-cadre`, `.g-form`,
   `.g-champ`, `.g-tableau` et `.g-ligne-action` — un onglet qui invente
   sa propre grammaire est un onglet qu'on relit plus lentement.

   ⚠️ La vignette a une TAILLE FIXE et un `object-fit: cover`. Sans elle,
      la hauteur des lignes du tableau suivrait la proportion de chaque
      vidéo : une colonne qui saute d'une ligne à l'autre, et une liste
      qu'on ne peut plus balayer de l'œil.
   ────────────────────────────────────────────────────────────────── */

.g-modele__vignette {
  inline-size: 64px; block-size: 80px;
  object-fit: cover; display: block;
  border-radius: 6px;
  background: var(--n-surface-2, rgba(255,255,255,.06));
}
.g-modele__sans {
  display: inline-flex; align-items: center; justify-content: center;
  inline-size: 64px; block-size: 80px;
  border-radius: 6px;
  border: 1px dashed var(--n-line, rgba(255,255,255,.18));
  color: var(--n-text-dim, #8E8D9E);
  font-size: .68rem; text-align: center; line-height: 1.2;
  padding: 4px;
}

.g-modele__sous { color: var(--n-text-dim, #8E8D9E); font-size: .78rem; }
/* La note est INTERNE : elle se distingue de ce que le client lit. */
.g-modele__note {
  color: var(--n-baisse, #FF8480); font-size: .74rem; font-style: italic;
}

.g-modele__familles { border: 0; padding: 0; margin: 0; min-inline-size: 0; }
.g-modele__familles legend { font-size: .8rem; color: var(--n-text-dim, #8E8D9E); }
.g-modele__familles > div {
  display: flex; flex-wrap: wrap; gap: .25rem 1rem; margin-block: .35rem;
}

.g-modele__coche {
  display: flex; align-items: center; gap: .4rem;
  min-block-size: 32px; cursor: pointer;
  font-size: .85rem;
}
.g-modele__coche em { color: var(--n-text-dim, #8E8D9E); }

.g-modele__vars code {
  background: var(--n-surface-2, rgba(255,255,255,.07));
  border-radius: 4px; padding: 1px 5px;
}

.g-modele__apercu { display: flex; flex-direction: column; gap: .5rem; }
.g-modele__aide { font-size: .78rem; color: var(--n-text-dim, #8E8D9E); margin: .25rem 0 0; }
.g-modele__vu { display: flex; gap: .75rem; align-items: flex-start; flex-wrap: wrap; }
.g-modele__vu video {
  inline-size: 220px; max-inline-size: 100%;
  border-radius: 8px; background: #000;
}

/* Un prompt de 9 000 caractères se relit mal en 3 lignes. */
#gFormModele textarea {
  font-family: var(--n-font-mono, ui-monospace, monospace);
  font-size: .82rem; line-height: 1.5;
  resize: vertical; min-block-size: 9rem;
}

/* ── LA GRILLE DU FORMULAIRE DES MODÈLES ─────────────────────────────
   `g-form--frais` est fait pour des champs COURTS et nombreux : douze
   colonnes de 150 px qui se replient toutes seules. Posée sur ce
   formulaire-ci, elle mettait deux zones de texte de 9 000 caractères
   dans deux colonnes de 300 px, et `align-items: end` décalait chaque
   champ d'une hauteur différente — vu au contrôle visuel du 02/09/2026.

   Douze colonnes, des portées explicites, et `align-items: start` : les
   étiquettes s'alignent, et les deux prompts occupent chacun la moitié
   de la largeur, côte à côte, parce qu'on les écrit en se relisant l'un
   l'autre.
   ────────────────────────────────────────────────────────────────── */

.g-form--modele {
  grid-template-columns: repeat(12, 1fr);
  align-items: start;
  column-gap: 18px;
}
/* Par défaut, TOUT prend la ligne entière : sur téléphone, deux champs
   côte à côte dans 380 px ne se remplissent pas. */
.g-form--modele > * { grid-column: 1 / -1; }

@media (min-width: 900px) {
  .g-form--modele .g-mod--3  { grid-column: span 3; }
  .g-form--modele .g-mod--6  { grid-column: span 6; }
  .g-form--modele .g-mod--12 { grid-column: 1 / -1; }
}

.g-form--modele textarea {
  font: 400 13px/1.5 var(--chiffres, ui-monospace, monospace);
  color: var(--n-text); padding: 10px 12px;
  border: 1px solid var(--n-line-2); border-radius: var(--n-r-sm);
  background: var(--n-bg-soft);
  inline-size: 100%; min-inline-size: 0;
  resize: vertical; min-block-size: 12rem;
}
.g-form--modele textarea:hover { border-color: var(--n-line-3); }
.g-form--modele textarea::placeholder { color: var(--n-text-disabled); }

/* L'état : deux cases l'une sous l'autre, alignées sur le haut du champ
   voisin plutôt que sur son bas. */
.g-form--modele .g-champ > .g-modele__coche { margin-block-start: 2px; }
