/* ==========================================================================
   Cockpit Step Dream : systeme visuel commun a toutes les pages.

   L'ADN reprend celui de Vay_AI : fond sombre legerement teinte, panneaux en
   verre depoli, un accent unique, angles genereux, transitions souples avec
   la meme courbe d'attenuation.

   Ce qui donne son identite propre au cockpit, et l'eloigne de la page
   generique : une geometrique batie au compas (Jost, dans la lignee de
   l'Avant Garde Gothic) employee du titre a la legende, un second accent or
   reserve a la marque et a la navigation active, et un grain leger sur tout
   le fond. Le grain est ce qui se voit le moins et change le plus : il casse
   l'aplat parfait qui fait "genere".

   Le titrage en serif editorial (Instrument Serif) a ete depose le
   07/09/2026 a la demande de Rassoul, qui voulait la meme police partout.
   ========================================================================== */

:root {
  /* Les fonds sont poses sur les valeurs relevees : #08090F pour le noir de
     page, #0D0F1B pour la grande surface qui porte l'application, #0A0B14
     pour l'interieur du rail. Les six depouillements sont unanimes sur le
     sens : nos noirs etaient trop clairs et surtout trop NEUTRES, quand ceux
     de la reference sont franchement bleus (le canal bleu vaut environ le
     double du rouge et du vert). L'ecart ne se voit pas sur une pastille de
     40 px, il se voit sur les grandes plages vides, c'est-a-dire partout :
     c'est ce bleu qui donne le froid du modele et qui empeche la lueur
     lavande de virer au rose.
     Le rail reste PLUS SOMBRE que la surface qu'il cotoie : c'est ce rapport,
     et non une ombre, qui fait tenir le conteneur flottant du rail sur la
     page (voir la correction sur le rail). --carte suit le meme cran. */
  --fond: #08090F;
  --surface: #0D0F1B;
  --rail-fond: #0A0B14;
  --carte: #14151B;

  /* Echelle de filets recalee. Trois depouillements sur six pointent le meme
     ecart : chez la reference un separateur horizontal fait 10 a 11 % de
     blanc, et TOUT contour de chrome (conteneur du rail, tuiles d'icone,
     boutons de la barre du haut) se tient entre 13,5 et 15 %. Nos anciennes
     valeurs passaient sous le plancher de cette echelle : aucun de nos blocs
     n'avait de bord visible, et c'est ce qui les faisait flotter au lieu de
     se poser.
     --ligne sert de separateur, --ligne-forte de contour de chrome. */
  --panneau: rgba(255, 255, 255, 0.06);
  --panneau-fort: rgba(255, 255, 255, 0.1);
  --ligne: rgba(255, 255, 255, 0.1);
  --ligne-forte: rgba(255, 255, 255, 0.15);

  /* Encres relevees d'un cran. La reference ecrit en BLANC PUR tout ce qui
     porte (libelles de section, titres de bloc, nom du compte, libelles du
     menu, valeurs) et pose son texte secondaire sur un gris strictement
     NEUTRE, sans une trace de violet dedans. Notre #F5F4F8 grisait les blancs
     et notre #ADACB8 tirait sur le lavande : les deux niveaux se ressemblaient
     trop et la hierarchie ne se lisait plus. Le troisieme niveau remonte du
     meme cran. */
  --encre: #FFFFFF;
  --encre-douce: #B4B5B7;
  --encre-faible: #88898C;

  /* UN SEUL ton lavande, #C0B4FE. C'est le releve sur lequel CINQ des six
     depouillements sont tombes independamment (a un ou deux points de bleu
     pres) : le fragment de titre accentue, l'aplat de la tuile de navigation
     active, la coche, les puces et le trait de courbe partagent tous cette
     valeur. Notre #B4A9F0 etait plus sombre et moins bleu, et l'ecart ne se
     voyait pas sur un filet mais sautait aux yeux partout ou le lavande est
     un APLAT.
     --lavande-clair ne survit que pour les etats de survol : un aplat doit
     s'eclaircir sous le curseur, sinon le bouton principal ne repond plus a
     rien. Il se tient un demi-ton au-dessus, plus a deux tons comme avant.
     --magenta ne bouge PAS : deux depouillements le voulaient plus sombre,
     quatre le laissaient tel quel. A six voix contre deux, on ne touche pas a
     une couleur qui porte, chez nous, un etat d'alerte reel. */
  --lavande: #C0B4FE;
  --lavande-clair: #D5CEFF;
  --lavande-sombre: #6E64B4;
  --magenta: #E255B0;
  /* Echelle de gravite : elle ne sort jamais de la gamme lavande-magenta.
     Du plus pale au plus sature, c'est la saturation qui dit l'urgence, pas
     un changement de teinte. Un vert ou un rouge franc jureraient avec tout
     le reste de l'ecran. --niv2 suit l'accent, c'est la meme couleur : sans
     cela un jeton niv2 et le bouton principal cesseraient d'etre du meme
     lavande. */
  --niv1: #CFC8F6;
  --niv2: #C0B4FE;
  --niv3: #CB84D9;
  --niv4: #E255B0;
  /* Anciens noms, gardes pour les regles de pages qui les emploient encore :
     ils pointent tous sur l'echelle ci-dessus. */
  --vert: var(--niv1);
  --ambre: var(--niv3);
  --rouge: var(--niv4);

  /* Verre : le fond des panneaux. Translucide, il laisse passer la lueur du
     fond, ce qui donne la profondeur sans aucune ombre portee. */
  --verre: rgba(255, 255, 255, 0.035);
  --verre-plein: rgba(19, 19, 27, 0.66);
  --filet: rgba(255, 255, 255, 0.075);

  /* Les grands panneaux de la planche tournent autour de 24 a 30 px de rayon ;
     nous etions a 20. C'est ce qui nous faisait plus durs qu'eux sur chaque
     carte de chaque page, alors que le reste du dessin est deja le bon. 26 px
     est le milieu de la fourchette mesuree, et c'est aussi, par chance, le
     rayon deja ecrit en dur sur .surface : les cartes et la grande surface qui
     les porte tombent donc sur la meme rondeur.
     Le petit rayon ne bouge PAS : le rapport de nos petits carres (13 px pour
     40 px, soit 32,5 %) correspond deja aux 30 a 33 % releves sur les
     pastilles, le sigle, les boutons ronds et les tuiles du rail. C'est
     uniquement sur les grandes cartes que nous etions en dessous. */
  --r: 26px;
  --r-petit: 13px;
  --rail: 68px;
  --rail-ouvert: 244px;
  /* Largeur du tiroir sur telephone. Partagee avec la poignee, qui doit se
     deplacer exactement de cette distance. */
  --largeur-menu: min(84vw, 300px);
  --souple: cubic-bezier(0.23, 1, 0.32, 1);

  /* URBANIST, avec Jost derriere pour le cyrillique.

     La planche typographie du modele nomme sa police en toutes lettres :
     Urbanist. Elle n'a aucune lettre cyrillique (verifie sur l'API Google
     Fonts : elle ne sert que les sous-ensembles latin et latin-ext), et
     l'interface existe en russe pour Beslan.

     D'ou la pile a deux familles. Le navigateur choisit la police LETTRE PAR
     LETTRE : le latin rend en Urbanist, donc en police exacte du modele, et
     le cyrillique bascule tout seul sur Jost, sa cousine geometrique, sans
     jamais tomber sur une police systeme. Rien a declarer de plus, c'est le
     comportement natif du repli de police.

     Mesure de controle : la largeur de "Bonjour Rassoul" avec la pile
     complete tombe au centieme de pixel sur celle du meme texte force en
     Urbanist ; celle de "Здравствуй Беслан" tombe sur Jost. */
  --titre: Urbanist, Jost, "Century Gothic", sans-serif;
  --serif: var(--titre);
  --sans: Urbanist, Jost, "Century Gothic", -apple-system, "Segoe UI", Roboto, sans-serif;

  /* Alias : des regles propres a certaines pages emploient encore ces noms.
     Ils pointent tous sur la lavande, il n'y a plus qu'un accent. */
  --barre: var(--rail);
  --violet: var(--lavande);
  --violet-clair: var(--lavande-clair);
  --or: var(--lavande);
  --or-clair: var(--lavande-clair);
  --fond-relief: var(--carte);
  --mono: "JetBrains Mono", ui-monospace, Menlo, monospace;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  /* Ceinture : plus aucun decalage lateral vers du vide. */
  overflow-x: hidden;
  width: 100%;
  background: var(--fond);
  color: var(--encre);
  font-family: var(--sans);
  font-size: 14px;
  font-weight: 400;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  -webkit-font-smoothing: antialiased;
}

/* Grain : bruit fige, tres faible, applique au-dessus de tout mais
   transparent aux clics. C'est le detail qui enleve l'aspect plastique. */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 9999;
  opacity: 0.045;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ---------------------------------------------------------------- Coquille */

/* La mise en page reprend celle de la reference FINANCIA : un fond quasi noir,
   et par-dessus une grande surface arrondie qui porte toute l'application. Le
   rail d'icones se tient a gauche, en dehors de cette surface.

   `.surface` est FIXE et non dans le flux : elle sert de decor, le contenu
   defile par-dessus. C'est aussi ce qui permet de decouper la lueur lavande
   sur ses coins arrondis sans qu'elle deborde. */
.surface {
  position: fixed;
  top: 10px; right: 10px; bottom: 10px;
  left: calc(var(--rail) + 4px);
  z-index: 0;
  border-radius: 26px;
  background: var(--surface);
  border: 1px solid var(--ligne);
  overflow: hidden;
  transition: left 0.28s var(--souple);
}

/* La lueur lavande en haut de la surface : c'est la signature du modele. Elle
   deborde volontairement par le haut et par la gauche, pour qu'on n'en voie
   que la retombee et jamais le centre. */
.lueur {
  position: absolute;
  top: -210px; left: -90px;
  width: min(1050px, 96%); height: 470px;
  pointer-events: none;
  background: radial-gradient(50% 50% at 40% 50%,
              rgba(203, 196, 248, 0.62) 0%,
              rgba(158, 149, 219, 0.26) 42%,
              rgba(14, 14, 21, 0) 70%);
  filter: blur(26px);
}

/* ------------------------------------------------------------------- Rail */

.rail {
  position: fixed;
  inset: 0 auto 0 0;
  z-index: 30;
  width: var(--rail);
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 16px 12px 14px;
  overflow: hidden;
  white-space: nowrap;
  transition: width 0.28s var(--souple), background 0.28s var(--souple);
}

/* Le rail s'ouvre au survol et se referme tout seul. Au repos il ne montre que
   les icones ; les intitules reviennent des qu'on approche la souris. Comme il
   est en position fixe, cette ouverture ne repousse jamais le contenu : elle
   passe par-dessus, donc rien ne bouge sous le curseur. */
@media (hover: hover) {
  /* Le fond et le filet ne sont plus poses au survol : ils deviennent
     permanents, regle juste en dessous. Il ne reste ici que ce qui appartient
     vraiment a l'ouverture : la largeur, et l'ombre qui detache le panneau du
     contenu par-dessus lequel il passe. */
  .rail:hover {
    width: var(--rail-ouvert);
    box-shadow: 34px 0 70px -34px rgba(0, 0, 0, 0.95);
  }
}

/* Le rail de la reference n'est pas une bande collee au bord de la fenetre :
   c'est un CONTENEUR FLOTTANT, un bloc arrondi pose a la meme distance des
   bords que la grande surface, avec un filet sur ses QUATRE cotes et un fond
   plus sombre que la surface voisine. Deux depouillements sur six l'ont vu
   ainsi, et c'est ce qui donne son caractere a toute la silhouette : sans fond
   ni filet permanents, notre colonne d'icones flottait dans le vide et ne se
   mettait a exister qu'au survol, c'est-a-dire jamais au premier regard.

   Le remplissage a 12 px n'est pas esthetique mais arithmetique : 68 - 2 x 12
   = 44, et 44 est le cote des tuiles carrees de la correction suivante. Le
   rail doit faire exactement la largeur d'une tuile, marges comprises. (Le
   depouillement d'origine proposait 15 px, ce qui ne laissait que 38 px et
   aurait fait rogner les tuiles par overflow: hidden.)

   Le prefixe body sur les trois derniers selecteurs n'est pas cosmetique :
   .entete-haute (ligne 289) et .contenu (ligne 369) sont declarees PLUS BAS
   dans ce fichier avec un raccourci margin, et a specificite egale c'est la
   derniere posee qui gagne. Sans ce prefixe, le contenu ne se decalerait pas
   et passerait sous le rail. Une media query ne change rien a la specificite.

   Tout est borne au grand ecran. Sous 900 px le rail redevient un tiroir
   plein cadre qui coulisse hors de l'ecran par translateX(-100%) : une
   position flottante y laisserait 10 px de panneau visibles en permanence sur
   le bord gauche, menu ferme. */
@media (min-width: 901px) {
  .rail {
    top: 10px; bottom: 10px; left: 10px;
    /* 11 px et non 12, et l'arithmetique du commentaire ci-dessus oubliait un
       terme : avec `box-sizing: border-box`, le filet d'un pixel de chaque
       cote se prend AUSSI sur les 68 px. A 12 px de remplissage il ne restait
       que 68 - 2 - 24 = 42 px pour une tuile qui en fait 44, donc deux pixels
       rognes sur chaque tuile en permanence. A 11 : 68 - 2 - 22 = 44, pile la
       largeur d'une tuile. Mesure faite dans le navigateur, pas deduite. */
    padding: 12px 11px;
    border-radius: var(--r-petit);
    background: var(--rail-fond);
    border: 1px solid var(--ligne-forte);
  }
  /* Le rail commence a 10 px et fait 68 px : son arete droite tombe a 78 px.
     Avec 10 px de gouttiere, tout ce qui suit demarre a 88 px. */
  body .surface { left: calc(var(--rail) + 20px); }
  body .entete-haute { margin-left: calc(var(--rail) + 20px); }
  body .contenu { margin-left: calc(var(--rail) + 20px); }
}

.rail .marque {
  flex: none;
  display: flex; align-items: center; gap: 12px;
  padding: 4px 4px 10px;
  text-decoration: none; color: inherit;
}
/* Aucune ombre portee sous la pastille : la doctrine du fichier est que la
   profondeur vient de la lueur du fond, et la maquette pose son sigle a plat
   sur le rail. Le halo lavande qui trainait ici etait un reste. */
.rail .sigle {
  width: 40px; height: 40px; flex: none;
  display: grid; place-items: center;
  border-radius: 13px;
  /* Le sigle de la maquette est un carre SOMBRE portant un logo blanc, avec
     exactement l'habillage d'une tuile de navigation inactive. Deux
     depouillements le disent. Le notre etait un aplat lavande plein,
     c'est-a-dire un deuxieme aplat de couleur dans un rail qui n'en admet
     qu'un : celui de l'entree en cours. Avec deux taches lavande l'une au-dessus
     de l'autre, on ne sait plus laquelle dit ou l'on se trouve. En le rendant
     sombre, la tuile de navigation active redevient la seule couleur du rail,
     donc la seule chose qu'on cherche du regard : la marque cede la couleur a
     l'etat.
     var(--encre) plutot que du blanc en dur : c'est le blanc de la palette,
     celui de tous les textes de tete. */
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid var(--ligne);
  color: var(--encre);
}
.rail .sigle svg { width: 22px; height: 19px; display: block; }
.marque .nom { display: block; font-size: 15.5px; font-weight: 500; letter-spacing: -0.01em; }
.marque .sous {
  display: block; font-size: 10.5px; letter-spacing: 0;
  text-transform: none; color: var(--encre-faible); margin-top: 1px;
}

/* Le menu prend la place restante et DEFILE si le contenu ne tient pas.

   Sans `overflow-y`, quand les dix entrees plus les trois intitules de section
   depassaient la hauteur de l'ecran, le navigateur compressait tout : flex
   retrecit ses enfants par defaut. Les entrees, qui ont une hauteur ecrite,
   resistaient ; les intitules de section, qui n'en ont pas, se retrouvaient
   rognes a deux pixels par leur propre `overflow: hidden` ; et le pied, lui
   aussi compresse, venait se superposer aux dernieres entrees. C'est ce qui
   melangeait les sections sur telephone.

   D'ou les trois lignes : le menu defile, et NI ses enfants NI le pied ne se
   compriment. */
.menu {
  display: flex; flex-direction: column; gap: 3px;
  flex: 1; min-height: 0;
  overflow-y: auto; overflow-x: hidden;
  /* Ascenseur INVISIBLE, et c'est arithmetique, pas esthetique.

     Le rail fait 68 px, son remplissage 12 px de chaque cote : il reste
     exactement 44 px, la largeur d'une tuile. Un ascenseur classique prend sa
     place dans la mise en page : il ne restait que 39 px et chaque tuile se
     faisait rogner sur sa droite par l'`overflow: hidden` du rail. C'est ce
     qu'on voyait sur ordinateur des que le menu depassait la hauteur de la
     fenetre — donc depuis l'ajout des pages "A relancer" et "Archive", qui
     ont porte le menu a douze entrees.

     Le menu defile toujours (a la molette, au clavier, au toucher), on ne
     dessine simplement plus la barre. Sur telephone le rail est un tiroir
     pleine largeur : rien n'y etait rogne, et rien n'y change. */
  scrollbar-width: none;
}
.menu::-webkit-scrollbar { width: 0; height: 0; display: none; }
.menu > * { flex: none; }

/* Il reste a dire qu'il y a quelque chose en dessous. L'ascenseur ne se
   dessine plus (il rognait les tuiles), et sans lui rien n'indiquait que
   "Bots", derniere entree, attendait un coup de molette. D'ou ce degrade de
   dissolution sur 18 px : le bas du menu s'efface, ce qui se lit
   immediatement comme "ca continue". Il passe en haut quand on est arrive au
   bout, et disparait quand tout tient a l'ecran. Aucun pixel de largeur pris,
   contrairement a une barre. */
.menu.deborde-bas { mask-image: linear-gradient(to bottom, #000 calc(100% - 18px), transparent); }
.menu.deborde-haut { mask-image: linear-gradient(to bottom, transparent, #000 18px); }
.menu.deborde-haut.deborde-bas {
  mask-image: linear-gradient(to bottom, transparent, #000 18px,
                              #000 calc(100% - 18px), transparent);
}
.rail-trait { height: 1px; background: var(--ligne); margin: 7px 6px; }

/* Les intitules et les titres de groupe n'existent que rail ouvert. On les
   fait disparaitre en opacite plutot qu'en `display`, pour que la largeur du
   rail les traverse en fondu au lieu de les faire clignoter. */
.rail .etiq, .rail-groupe, .etat-synchro {
  opacity: 0;
  transition: opacity 0.16s linear;
}
@media (hover: hover) {
  .rail:hover .etiq, .rail:hover .rail-groupe, .rail:hover .etat-synchro { opacity: 1; }
}
.rail.ouverte .etiq, .rail.ouverte .rail-groupe, .rail.ouverte .etat-synchro { opacity: 1; }

/* Meme regle que le sur-titre : plus de capitales espacees nulle part. Les
   trois intitules de groupe restent lisibles, simplement ecrits comme des
   mots, et gagnent un demi-point de taille pour compenser. */
.rail-groupe {
  font-size: 11px; letter-spacing: 0;
  /* 14/6 a l'origine. Resserre a 9/4 avec l'arrivee des douze entrees : le
     menu tient de nouveau sans defiler sur un ecran d'ordinateur portable. */
  color: var(--encre-faible); padding: 9px 10px 4px;
  overflow: hidden;
}

/* Chaque entree du modele est une TUILE CARREE, pas une rangee. Son cote vaut
   la largeur utile du rail (68 - 2 x 12 = 44 px) et son rayon environ 27 pour
   cent de ce cote, soit 12 px. Les inactives ont un fond a peine distinct du
   rail et un filet d'un pixel ; l'active est un APLAT lavande plein, sans
   filet, avec une icone SOMBRE au centre. C'est le seul aplat de couleur de
   tout le rail, donc on la trouve sans chercher.

   Le point qui change tout : l'aplat est pose sur la TUILE et non sur le
   lien. Chez nous il etait sur le lien, donc rail ouvert la pastille lavande
   s'etirait sur 244 px et devenait une barre pleine largeur, ce qui n'existe
   nulle part dans le modele. Ici la tuile reste carree quelle que soit la
   largeur du rail, et l'intitule s'ecrit a cote en encre normale : on garde
   nos etiquettes au survol, qui n'existent pas dans la maquette mais dont on
   a besoin a dix pages, sans casser le dessin.

   Deux depouillements independants ont releve exactement la meme grammaire :
   l'etat n'appartient jamais a la ligne, il appartient a la tuile. */
.menu a {
  position: relative;
  display: flex; align-items: center; gap: 12px;
  height: 44px; padding: 0;
  color: var(--encre-douce);
  text-decoration: none;
  font-size: 13.5px;
  /* Il n'y a plus ni fond ni rayon sur la ligne : plus rien a animer sur
     elle, tout le mouvement se joue desormais dans la tuile. */
  transition: color 0.2s var(--souple);
}
.menu a .ico {
  width: 44px; height: 44px; flex: none;
  display: grid; place-items: center;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.028);
  border: 1px solid var(--ligne);
  transition: background 0.2s var(--souple), border-color 0.2s var(--souple),
              color 0.2s var(--souple);
}
.menu a svg { width: 20px; height: 20px; display: block; }
/* Au survol c'est la tuile qui s'eclaire, jamais la ligne entiere. */
.menu a:hover { color: var(--encre); }
.menu a:hover .ico { background: rgba(255, 255, 255, 0.07); }

/* L'entree en cours : aplat lavande plein, aucun filet, icone sombre. */
.menu a.actif { color: var(--encre); font-weight: 500; }
.menu a.actif .ico {
  background: var(--lavande);
  border-color: transparent;
  color: #14111C;
}
.menu a.actif:hover .ico { background: var(--lavande-clair); }

/* Le pied ne se comprime jamais : c'est lui qui venait recouvrir les
   dernieres entrees du menu. */
.rail-pied { display: flex; flex-direction: column; gap: 3px; flex: none; }
.rail .rail-action {
  display: flex; align-items: center; gap: 14px;
  height: 42px; padding: 0 10px; width: 100%;
  border: 0; border-radius: 14px;
  background: transparent; color: var(--encre-douce);
  font-family: inherit; font-size: 13px; cursor: pointer;
  transition: background 0.2s var(--souple), color 0.2s var(--souple);
}
.rail .rail-action .ico {
  width: 22px; flex: none; display: grid; place-items: center;
  font-size: 11.5px; letter-spacing: 0.04em;
}
.rail .rail-action svg { width: 19px; height: 19px; display: block; }
.rail .rail-action:hover { background: rgba(255, 255, 255, 0.055); color: var(--encre); }
.rail .rail-action.principal { color: var(--lavande-clair); }
.rail .rail-action.principal:hover { background: rgba(180, 169, 240, 0.13); }
/* Pendant la synchronisation l'icone tourne : c'est le seul signe visible
   quand le rail est ferme et que l'intitule est masque. */
.rail .rail-action.tourne svg { animation: tourner 1.1s linear infinite; }
@keyframes tourner { to { transform: rotate(360deg); } }
.etat-synchro {
  font-size: 10px; color: var(--encre-faible);
  padding: 6px 10px 0; line-height: 1.55; overflow: hidden;
}
.point { display: inline-block; width: 6px; height: 6px; border-radius: 50%; background: var(--vert); margin-right: 6px; vertical-align: middle; }
.point.vieux { background: var(--ambre); }
.point.actif { background: var(--lavande); animation: pulse 1.1s ease-in-out infinite; }
@keyframes pulse { 50% { opacity: 0.25; } }

/* ------------------------------------------------------------ Barre du haut */

.entete-haute {
  /* La maquette n'a PAS de barre du haut. Deux depouillements independants le
     disent : la recherche et les actions de compte sont posees a nu au-dessus
     de la surface, sans aplat, sans flou d'arriere-plan et sans coins
     arrondis. Notre bandeau translucide et colle en haut etait le seul element
     de l'ecran a couper la surface en deux, et son flou de 16 px se lisait
     comme une seconde couche de verre par-dessus celle des cartes. C'est aussi
     ce qui trahit le plus vite un tableau de bord generique.

     position: relative et NON static : .surface est en position fixe avec un
     z-index de 0. Un element non positionne passerait dessous, et la recherche
     disparaitrait purement et simplement derriere l'aplat de la surface. Le
     z-index reste donc declare, il ne sert plus qu'a cela.

     Effet de bord assume : la barre n'est plus collante, elle defile avec la
     page. C'est ce que fait la maquette, ou la recherche est le premier
     element du contenu, au-dessus du titre. Et une bande transparente ET
     collante laisserait le contenu defiler visiblement derriere la recherche.
     Verifie : rien dans cockpit.js ne depend de la position sticky. */
  position: relative;
  z-index: 25;
  margin: 10px 10px 0 calc(var(--rail) + 4px);
  height: 62px;
  display: flex; align-items: center; gap: 14px;
  /* Meme retrait lateral que .contenu (26 px) : la pastille de recherche tombe
     alors exactement sur la verticale du titre de page. Avec 18 px elle etait
     decalee de 8 px vers la gauche, ce qui se voit sur un fond desormais nu. */
  padding: 0 26px;
  transition: margin-left 0.28s var(--souple);
}

.recherche {
  display: flex; align-items: center; gap: 9px;
  height: 40px; padding: 0 16px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid var(--ligne);
  width: min(340px, 42vw);
  transition: border-color 0.22s var(--souple), background 0.22s var(--souple);
}
/* Le curseur de saisie sur TOUTE la pilule, pas seulement sur le champ : ce
   qui ressemble a un champ doit se comporter comme un champ sur toute sa
   surface. Le script complete en donnant le focus au champ quand on appuie
   sur la loupe ou sur le vide autour. */
.recherche { cursor: text; }
.recherche:focus-within { border-color: rgba(180, 169, 240, 0.5); background: rgba(255, 255, 255, 0.085); }
.recherche .ico { display: grid; place-items: center; color: var(--encre-faible); }
.recherche svg { width: 16px; height: 16px; display: block; }
.recherche input {
  flex: 1; min-width: 0;
  background: none; border: 0; outline: none; padding: 0;
  font-family: inherit; font-size: 13px; color: var(--encre);
}
.recherche input::-webkit-search-cancel-button { filter: invert(0.6); }

.actions-haut { display: flex; align-items: center; gap: 9px; margin-left: auto; }

.rond {
  position: relative;
  width: 40px; height: 40px;
  display: grid; place-items: center;
  border-radius: 13px;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid var(--ligne);
  color: var(--encre-douce);
  transition: background 0.22s var(--souple), color 0.22s var(--souple);
}
.rond:hover { background: rgba(255, 255, 255, 0.09); color: var(--encre); }
.rond svg { width: 18px; height: 18px; display: block; }

/* La pastille de compte, posee a cheval sur le coin de l'icone. */
.pastille {
  position: absolute; top: -5px; right: -5px;
  min-width: 18px; height: 18px; padding: 0 5px;
  border-radius: 999px;
  background: var(--lavande); color: #17131F;
  font-size: 10px; font-weight: 500; line-height: 18px; text-align: center;
  border: 2px solid var(--surface);
}
.pastille.rouge { background: var(--rouge); color: #23100F; }

.profil {
  display: flex; align-items: center; gap: 10px;
  padding: 4px 12px 4px 4px;
  border-radius: 999px;
  text-decoration: none; color: inherit;
  transition: background 0.22s var(--souple);
}
.profil:hover { background: rgba(255, 255, 255, 0.05); }
/* Dans la reference, TOUT ce qui vit dans la barre du haut est aligne sur une
   seule et meme hauteur : bouton carre, avatar, pilule de recherche, au pixel
   pres. C'est cette ligne d'horizon qui tient la barre. Chez nous il y avait
   trois hauteurs differentes (recherche 40, bouton 40, avatar 34) dans une
   barre de 62 : rien n'etait aligne sur rien, et trois depouillements ont
   releve le meme defaut avec trois tailles differentes. On retient le RAPPORT
   (une seule hauteur pour les quatre objets) et une valeur mediane, 48 px :
   les mesures absolues des planches viennent d'un ecran de telephone et
   donneraient une barre de 80 px qui mangerait le premier ecran de chaque
   page.

   L'avatar : la maquette montre une PHOTO reelle en carre arrondi. Nous n'en
   avons pas, les comptes viennent d'amoCRM et n'en portent pas ; le script y
   ecrit une initiale. On garde donc l'initiale, mais on lui retire son degrade
   lavande-magenta, qui etait le troisieme aplat de couleur de l'ecran et
   entrait en concurrence avec la tuile de navigation active. Il prend
   l'habillage sobre de tout le reste du chrome.

   Ces regles sont posees APRES celles qu'elles corrigent (.entete-haute,
   .recherche et .rond sont declarees plus haut dans le fichier), elles gagnent
   donc sans qu'on touche aux originales. Le bloc mobile, lui, est plus bas
   encore et reprend la main sous 900 px. */
.entete-haute { height: 70px; }
.recherche { height: 48px; }
.rond { width: 48px; height: 48px; }
.rond svg { width: 20px; height: 20px; display: block; }
.avatar {
  width: 44px; height: 44px; flex: none;
  display: grid; place-items: center;
  border-radius: 13px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid var(--ligne-forte);
  color: var(--encre); font-weight: 500; font-size: 15px;
}
.profil .qui { display: flex; flex-direction: column; line-height: 1.25; }
.profil .nom { font-size: 13px; }
.profil .role { font-size: 10.5px; color: var(--encre-faible); }

/* ------------------------------------------------------------------ Contenu */

.contenu {
  position: relative;
  z-index: 1;
  margin: 0 10px 0 calc(var(--rail) + 4px);
  padding: 14px 26px 54px;
  transition: margin-left 0.28s var(--souple);
}

.entete { display: flex; justify-content: space-between; align-items: flex-end; gap: 22px; flex-wrap: wrap; margin-bottom: 22px; }
/* Le sur-titre s'ecrit comme une phrase, pas en capitales espacees. La
   maquette n'emploie de capitales nulle part : ce traitement est la signature
   des vieux tableaux de bord, et c'est la premiere ligne de chacune des dix
   pages. Il reste petit et pale, c'est ce qui le tient a sa place. */
/* La date de l'accueil est ecrite par toLocaleDateString, qui rend "lundi 7
   septembre" et "понедельник, 7 сентября", tous deux en minuscules. Les
   capitales forcees les rattrapaient ; en les retirant, il ne reste qu'a
   relever la premiere lettre. Les neuf autres pages ont un sur-titre deja
   capitalise dans leur objet de traduction, cette regle ne leur fait rien. */
/* La reference ouvre CHAQUE planche par le meme marqueur de section : un petit
   anneau a pastille blanche halonee, le libelle a distance de lui, puis un
   filet qui court jusqu'a la marge droite. Deux depouillements l'ont releve
   independamment. C'est le composant qui annonce le debut d'une section, et nos
   dix pages n'avaient que du texte nu au-dessus du titre.

   Deux precautions de mise en oeuvre :
   - l'anneau est un ::before en position ABSOLUE et .sur-titre reste un bloc.
     C'est la seule facon de conserver la regle ::first-letter juste dessous,
     qui releve la premiere lettre de la date de l'accueil : ::first-letter ne
     s'applique qu'aux conteneurs de bloc et cesserait net si on passait
     .sur-titre en flex pour y loger l'anneau ;
   - le filet est porte par le bas de l'entete complete et non par la ligne du
     libelle : il rejoint ainsi la marge droite de la page sans qu'on ait a
     deviner la largeur d'un libelle traduit en deux langues, et sans toucher au
     flex de .entete, ou vivent aussi les boutons de droite. */
.entete { padding-bottom: 20px; border-bottom: 1px solid var(--ligne); }
.sur-titre {
  position: relative;
  padding-left: 36px;
  min-height: 23px; line-height: 23px;
  font-size: 11.5px; letter-spacing: 0; text-transform: none;
  color: var(--encre-douce);
}
/* L'anneau : filet blanc a 13 %, pastille pleine de 6 px au centre et son halo
   diffus qui s'eteint sur 7 px. Le halo est NEUTRE, jamais lavande : c'est ce
   qui empeche le marqueur de se lire comme un etat de plus. */
.sur-titre::before {
  content: "";
  position: absolute;
  left: 0; top: 50%;
  width: 23px; height: 23px; margin-top: -11.5px;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.13);
  background: radial-gradient(circle at 50% 50%,
              rgba(255, 255, 255, 1) 0 3px,
              rgba(255, 255, 255, 0.16) 3.5px 7px,
              rgba(255, 255, 255, 0) 7.5px);
}
.sur-titre::first-letter { text-transform: uppercase; }
/* Titres en graisse legere : dans le modele, les gros mots ne sont jamais
   gras, c'est leur taille qui porte, pas leur epaisseur. */
/* Le titre de page du modele est UN mot, tres grand, en graisse legere, avec
   du vide au-dessus et au-dessous : c'est le seul texte gros de tout l'ecran,
   et c'est lui qui dit ou l'on est. A 33 px le notre se retrouvait coince entre
   les titres de cartes (15 px) et les grands chiffres (36 px) : plus rien ne
   dominait le haut de page, et l'oeil tombait directement sur les tuiles.
   Trois depouillements ont mesure ce titre a 37, 44 et 46 px : tous les trois
   disent "beaucoup plus grand", aucun ne dit combien exactement. 46 est le haut
   de la fourchette, et c'est la SEULE valeur a baisser si le titre parait trop
   maigre sur un grand ecran. */
h1 { font-family: var(--titre); font-weight: 300; font-size: 46px; line-height: 1.06; margin: 10px 0 0; letter-spacing: -0.02em; }
h1 .accent { color: var(--lavande); }
.chapo { color: var(--encre-douce); font-size: 13px; margin-top: 6px; max-width: 62ch; line-height: 1.6; }

/* -------------------------------------------------------------- Composants */

/* Les blocs du modele sont plats et sombres, poses sur la surface : pas de
   relief marque, juste un aplat legerement plus clair, un filet d'un pixel et
   de grands coins. La profondeur vient de la lueur du fond, pas des ombres. */
.carte, .kpi-carte {
  position: relative;
  /* `isolate` cree un contexte d'empilement local : le halo reste enferme
     dans son bloc et ne peut pas passer devant un bloc voisin. */
  isolation: isolate;
  background: var(--verre);
  backdrop-filter: blur(24px) saturate(115%);
  border: 1px solid var(--ligne);
  border-radius: var(--r);
  transition: border-color 0.3s var(--souple), background 0.3s var(--souple);
}
/* Le retrait interieur vaut EXACTEMENT le rayon. C'est la regle de la
   reference, mesuree sur deux cartes differentes, et c'est de la que vient la
   regularite de ses imbrications : un sous-bloc encastre garde le meme ecart au
   bord que la carte a son contenu, quelle que soit la taille. Nos 22px 24px
   etaient deux valeurs fixes sans rapport avec le rayon. */
.carte { padding: var(--r); }

/* La lueur interne des cartes de la reference : elle ne suit PAS la souris,
   elle monte du BAS. Presque noire en haut, lavande eteinte a quelques pixels
   du bord inferieur, et plus forte dans les deux coins bas qu'au centre : d'ou
   les deux degrades elliptiques ancres aux angles plutot qu'un seul degrade
   vertical. Trois depouillements sur six ont vu cette lumiere montante, chacun
   a un endroit different (la carte du graphique, le bloc de tete, le fond du
   trace) : c'est ce qui donne du volume a leurs cartes, et nous n'avions rien
   d'equivalent. Notre seul effet de carte suit le curseur, donc il ne se voit
   ni au repos ni sur une capture d'ecran.

   Un calque a part (::after) et non un fond, pour deux raisons : ::before est
   deja pris par le halo qui suit le curseur, et un calque epouse les coins
   arrondis tout seul. z-index 0 le laisse sous le contenu, que la regle
   .carte > * remonte deja a 1 plus bas dans ce fichier. */
.carte::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  border-radius: inherit;
  background:
    radial-gradient(120% 60% at 6% 116%, rgba(192, 180, 254, 0.20), rgba(192, 180, 254, 0) 60%),
    radial-gradient(120% 60% at 94% 116%, rgba(192, 180, 254, 0.16), rgba(192, 180, 254, 0) 60%),
    linear-gradient(180deg, rgba(192, 180, 254, 0) 58%, rgba(192, 180, 254, 0.06) 100%);
}

/* Le halo qui suit le curseur.

   Le script pose la position de la souris dans `--souris-x` et `--souris-y`
   au survol ; ce calque en dessine un rond lavande tres faible, centre
   dessus. C'est une couche a part et non un fond, pour deux raisons : elle
   s'allume et s'eteint en fondu sans toucher a l'aplat du bloc, et elle
   epouse les coins arrondis toute seule. */
.carte::before, .kpi-carte::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  border-radius: inherit;
  opacity: 0;
  transition: opacity 0.3s var(--souple);
  /* Toutes les lueurs de la planche sont tres larges et tres faibles : le pic
     de celle posee derriere leur graphique ne depasse le fond que de cinq
     valeurs, sur environ 1200 px de diametre apparent. Notre halo a 0,12 sur
     440 px etait beaucoup plus dur et beaucoup plus local, et il se voyait
     comme un effet plutot que comme une ambiance.
     Il porte aussi le nouvel accent : rgba(192, 180, 254) est le #C0B4FE des
     jetons, la ou l'ancienne valeur restait sur le lavande d'avant.
     Le suivi du curseur est conserve : le script continue de poser --souris-x
     et --souris-y, rien ne change de ce cote. Elargi et affaibli, le halo
     devient une respiration au lieu d'une tache. */
  background: radial-gradient(760px circle at var(--souris-x, 50%) var(--souris-y, 0%),
              rgba(192, 180, 255, 0.05), rgba(192, 180, 255, 0) 66%);
}
/* Le contenu repasse devant le halo. Sans cela le calque, peint apres,
   teinterait le texte. */
.carte > *, .kpi-carte > * { position: relative; z-index: 1; }

/* Un ecran tactile n'a pas de curseur : le halo n'aurait aucun sens et
   resterait fige sur sa derniere position apres un appui. */
@media (hover: hover) {
  .carte:hover::before, .kpi-carte:hover::before { opacity: 1; }
  .carte:hover { border-color: rgba(180, 169, 240, 0.26); }
}

/* Les intitules de blocs restent petits : dans le modele, ce sont les
   chiffres qui parlent, pas les titres au-dessus d'eux. */
.carte h2 {
  font-family: var(--titre); font-weight: 400; font-size: 15px;
  margin: 0 0 2px; letter-spacing: -0.005em; color: var(--encre);
}
.carte .legende { font-size: 11.5px; color: var(--encre-faible); margin-bottom: 16px; }

.grille { display: grid; gap: 12px; }
/* Bretelle, et vraie cause du debordement : par defaut un enfant de grille
   refuse de retrecir sous la largeur de son contenu (`min-width: auto`). Un
   tableau large poussait donc sa colonne au-dela de l'ecran au lieu de
   defiler dans son cadre. */
.grille > *, .carte, .defile { min-width: 0; }
.defile { max-width: 100%; overflow-x: auto; }
/* Les chiffres de tete ne sont plus six boites posees cote a cote mais UN
   seul panneau divise en cases. L'astuce tient en une ligne : le conteneur
   porte la couleur des filets, les cases ont leur propre fond, et l'ecart
   d'un pixel entre elles laisse voir le conteneur. Le resultat est un
   quadrillage net quel que soit le nombre de cases et la facon dont elles se
   replient, ce qu'aucune regle de bordure ne sait faire avec `auto-fit`. */
.grille.kpi {
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 1px;
  background: var(--filet);
  border: 1px solid var(--ligne);
  border-radius: var(--r);
  overflow: hidden;
}
.grille.deux { grid-template-columns: repeat(auto-fit, minmax(420px, 1fr)); align-items: start; }
/* Le panneau de tete : chiffres en haut, puis graphique et cadran, le tout
   sous le meme verre. Dedans, les chiffres perdent leur quadrillage et leur
   fond : ce ne sont plus des cases mais du texte pose sur le panneau, comme
   dans la reference. Un filet unique les separe du graphique. */
.panneau-tete { padding: 24px 26px 22px; }
.panneau-tete > .grille.kpi {
  background: none; border: 0; border-radius: 0; overflow: visible;
  grid-template-columns: repeat(auto-fit, minmax(148px, 1fr));
  gap: 20px 28px;
  padding-bottom: 22px;
  border-bottom: 1px solid var(--ligne);
  margin-bottom: 22px;
}
.panneau-tete > .grille.kpi .kpi-carte {
  background: none; backdrop-filter: none; padding: 0;
}
.panneau-tete > .grille.kpi .kpi-carte::before { display: none; }
.panneau-tete > .grille.kpi .kpi-carte .val { font-size: 31px; margin-top: 7px; }

.duo-tete { display: grid; grid-template-columns: minmax(0, 2.2fr) minmax(0, 1fr); gap: 26px; }
.part-cadran { border-left: 1px solid var(--ligne); padding-left: 26px; display: flex; flex-direction: column; }
.part-cadran #cadran-suivi { flex: 1; display: grid; place-items: center; }
.ligne .quand { color: var(--encre-faible); font-size: 11.5px; min-width: 34px; text-align: right; }
.ligne .montant { color: var(--encre); font-size: 13px; font-variant-numeric: tabular-nums; min-width: 72px; text-align: right; }

/* Le graphique large, le cadran etroit a cote. */
.grille.large-etroit { grid-template-columns: minmax(0, 2.1fr) minmax(0, 1fr); align-items: stretch; }
.grille.large-etroit > .carte { display: flex; flex-direction: column; }
.grille.large-etroit > .carte > #cadran-suivi { flex: 1; display: grid; place-items: center; }

/* La composition de la carte de chiffre cle du modele, relevee de haut en bas :
   l'intitule tout en haut, PUIS UN GRAND VIDE d'environ 40 pour cent de la
   hauteur, puis le montant en tres gros lavande cale EN BAS a gauche, puis la
   ligne de variation sous lui. Chez nous les trois blocs etaient colles les uns
   aux autres en haut de la tuile.

   Le vide ne se fabrique pas avec une marge devinee : six tuiles au meme
   contenu font six tuiles de meme hauteur, et un margin-top: auto n'aurait rien
   contre quoi pousser. Il faut donc une hauteur plancher, puis une colonne flex
   dont le nombre est le dernier element pousse vers le bas. */
.kpi-carte {
  display: flex; flex-direction: column;
  background: var(--verre-plein);
  backdrop-filter: blur(24px) saturate(115%);
  border: 0;
  border-radius: 0;
  padding: 20px 22px 21px;
}
.kpi-carte::before { border-radius: 0; }
/* La hauteur plancher qui cree le vide du haut. */
.grille.kpi > .kpi-carte { min-height: 152px; }
/* Sauf dans les deux endroits ou les tuiles ne sont plus des cartes mais du
   texte pose sur un panneau : le panneau de tete de l'accueil et la colonne des
   discussions. La hauteur plancher y creverait la mise en page, et ces deux
   contextes redeclarent deja margin-top et font-size sur .val avec une
   specificite superieure, donc le calage en bas ne s'y applique pas non plus. */
.panneau-tete > .grille.kpi > .kpi-carte,
.colonne-gauche > .grille.kpi > .kpi-carte { min-height: 0; }
/* Etiquette en casse normale, pas en capitales : le modele n'en emploie
   nulle part, et les capitales font "tableau de bord d'usine". */
.kpi-carte .etiq { font-size: 12px; color: var(--encre-faible); letter-spacing: 0; text-transform: none; }
/* Le grand nombre en graisse legere : c'est sa taille qui doit porter, pas
   son epaisseur. Chiffres tabulaires pour que 1 et 8 aient la meme largeur,
   sinon le nombre saute pendant l'animation du compteur.
   Il est TOUJOURS lavande dans le modele, jamais en encre blanche : c'est lui
   qui porte la couleur de la carte. Le lavande etant aussi --niv2, la valeur
   par defaut et l'echelon 2 tombent naturellement sur le meme ton. */
.kpi-carte .val {
  font-family: var(--titre); font-size: 42px; font-weight: 300;
  line-height: 1.02; margin-top: auto; letter-spacing: -0.02em;
  color: var(--lavande);
  font-variant-numeric: tabular-nums;
}
.kpi-carte .note { font-size: 11.5px; color: var(--encre-faible); margin-top: 7px; }
/* L'echelle de gravite reste : c'est NOTRE langage de donnees, pas celui du
   modele, qui n'a rien a signaler. Elle ne fait que deplacer le nombre dans la
   gamme lavande-magenta, elle ne le sort jamais du lavande. */
.kpi-carte.alerte .val { color: var(--niv4); }
.kpi-carte.attention .val { color: var(--niv3); }
.kpi-carte.bien .val { color: var(--niv1); }
/* Le lien remplit la tuile et devient lui aussi une colonne : sans cela le
   margin-top: auto du nombre n'aurait rien contre quoi pousser, puisque sur
   l'accueil les trois blocs sont a l'interieur du <a>. */
.kpi-carte a {
  color: inherit; text-decoration: none;
  display: flex; flex-direction: column; flex: 1; min-height: 0;
}

table { width: 100%; border-collapse: collapse; font-size: 13px; }
th {
  text-align: left; font-size: 10.5px; letter-spacing: 0.02em;
  color: var(--encre-faible); font-weight: 400;
  padding: 0 12px 11px 0; white-space: nowrap;
}
td { padding: 12px 12px 12px 0; border-top: 1px solid var(--ligne); color: var(--encre-douce); vertical-align: top; }
tbody tr { transition: background 0.18s var(--souple); }
tbody tr:hover { background: rgba(255, 255, 255, 0.025); }
td strong { color: var(--encre); font-weight: 500; }
.num { text-align: right; font-variant-numeric: tabular-nums; }

/* Les jetons du modele sont des pastilles pleines et sombres, pas des
   contours : plus calmes dans un tableau dense. */
.jeton {
  /* Les jetons du modele sont des RECTANGLES arrondis a environ 30 % de leur
     hauteur, hauts, largement remplis a l'horizontale. Les notres etaient des
     pilules de 10,5 px avec 3,5 px de marge haute : plates et menues la ou les
     leurs sont des blocs qui tiennent la colonne. C'est le composant le plus
     repete du site, il se voit sur sept pages.
     Deux depouillements ont mesure ce jeton et s'accordent sur la GEOMETRIE
     (rectangle, rayon moyen, retrait horizontal double du notre). Ils se
     contredisent sur le remplissage : l'un le voit vide a filet fin, l'autre
     plein sans filet. On ne change donc que ce sur quoi ils s'accordent, et on
     laisse les variantes teintees (.violet, .ambre, .rouge, .niv1 a .niv4)
     exactement ou elles sont : elles portent NOTRE echelle de gravite, que la
     maquette n'a pas et ne peut donc pas arbitrer.
     Le filet transparent part : il n'ajoutait que deux pixels de hauteur
     invisible et personne ne le colorait jamais. */
  display: inline-block; font-size: 11px; padding: 6px 13px;
  border-radius: 8px; white-space: nowrap;
  background: rgba(255, 255, 255, 0.06);
  border: 0;
  color: var(--encre-douce);
}
.jeton.violet, .jeton.niv2 { background: rgba(180, 169, 240, 0.16); color: var(--niv2); }
.jeton.or { background: rgba(207, 200, 246, 0.14); color: var(--niv1); }
.jeton.vert, .jeton.niv1 { background: rgba(207, 200, 246, 0.13); color: var(--niv1); }
.jeton.ambre, .jeton.niv3 { background: rgba(203, 132, 217, 0.17); color: var(--niv3); }
.jeton.rouge, .jeton.niv4 { background: rgba(226, 85, 176, 0.18); color: var(--niv4); }
/* Un numero de telephone n'a pas besoin d'une machine a ecrire : la maquette
   n'emploie aucune police a chasse fixe, nulle part. Les chiffres tabulaires
   de Jost suffisent a les aligner en colonne, et le jeton reste dans la
   meme famille que tout le reste de l'ecran. */
.jeton.mono { font-family: inherit; font-size: 10.5px; font-variant-numeric: tabular-nums; letter-spacing: 0.01em; }

button, .bouton {
  font-family: inherit; font-size: 12.5px; color: var(--encre-douce);
  background: rgba(255, 255, 255, 0.055);
  border: 1px solid var(--ligne);
  border-radius: 999px; padding: 9px 16px; cursor: pointer;
  display: inline-flex; align-items: center; gap: 7px; text-decoration: none;
  transition: background 0.22s var(--souple), color 0.22s var(--souple), border-color 0.22s var(--souple);
}
button:hover, .bouton:hover { background: rgba(255, 255, 255, 0.1); color: var(--encre); }
button:disabled { opacity: 0.45; cursor: not-allowed; }
/* Le bouton principal du modele est un aplat lavande a texte sombre. C'est le
   seul endroit ou du texte est ecrit en noir : ca le rend impossible a rater. */
button.principal {
  background: var(--lavande); border-color: transparent; color: #15111D; font-weight: 500;
}
button.principal:hover { background: var(--lavande-clair); color: #15111D; }
button.actif { background: rgba(180, 169, 240, 0.18); border-color: rgba(180, 169, 240, 0.4); color: var(--lavande-clair); }
.bouton-large { width: 100%; justify-content: center; }

/* ------------------------------------------------------- Page Surveillance

   Les regles du systeme sont affichees en haut de la page, dans un encadre
   qui ne se replie pas. Ce n'est pas de la decoration : une surveillance qui
   n'affiche pas ses limites finit par etre utilisee autrement qu'annonce, et
   c'est precisement ce qui la rendrait illegitime. */
.cadre-veille { border-left: 2px solid var(--niv2); }
.regles-veille {
  margin: 12px 0 0; padding-left: 18px;
  display: flex; flex-direction: column; gap: 7px;
  font-size: 12.5px; line-height: 1.6; color: var(--encre-douce);
}
.regles-veille b { color: var(--encre); font-weight: 500; }

/* Un signalement : une ligne pliante, comme les listes du reste du site, mais
   avec des boutons dedans. La difference tient a ca : les autres listes se
   lisent, celle-ci se traite. */
.flag { border-top: 1px solid var(--ligne); }
.flag:first-child { border-top: 0; }
.flag-tete {
  width: 100%; background: none; border: 0; border-radius: 0; padding: 13px 2px;
  display: grid; grid-template-columns: auto 1fr auto; gap: 12px;
  align-items: center; text-align: left; cursor: pointer;
}
.flag-tete:hover { background: rgba(255, 255, 255, 0.02); }
.flag-bloc { min-width: 0; }
.flag-nom { display: block; font-size: 13.5px; color: var(--encre); }
.flag-sous {
  display: block; font-size: 11.5px; color: var(--encre-faible); margin-top: 2px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.flag-fin { display: flex; align-items: center; gap: 9px; white-space: nowrap; }

/* Meme mecanique de repli que les listes pliantes : une grille dont on anime
   la fraction, ce qui evite de mesurer une hauteur en JavaScript. */
.flag-repli {
  display: grid; grid-template-rows: 0fr;
  transition: grid-template-rows 0.28s var(--souple);
}
.flag.ouvert .flag-repli { grid-template-rows: 1fr; }
.flag-repli-in { overflow: hidden; }
.flag-contenu {
  display: flex; flex-direction: column; gap: 11px;
  padding: 4px 2px 16px;
}
.flag-champ { display: flex; flex-direction: column; gap: 4px; }
.flag-champ .quoi {
  font-size: 10.5px; color: var(--encre-faible); text-transform: none;
}
.flag-champ a { color: var(--lavande); text-decoration: none; }

/* Un constat de comportement n'est pas une citation. Le liseré magenta et le
   fond sombre du bloc disent "voici ses mots" : sur une note calculee, ce
   serait un faux temoignage. Il change donc de couleur et de ton. */
.extrait.constat {
  border-left-color: var(--niv2);
  background: rgba(255, 255, 255, 0.035);
  font-style: italic; color: var(--encre-douce);
}
.extrait {
  margin: 0; padding: 10px 13px;
  border-left: 2px solid var(--niv4);
  background: rgba(0, 0, 0, 0.24); border-radius: 0 8px 8px 0;
  font-size: 12.5px; line-height: 1.55; color: var(--encre);
  white-space: pre-wrap; word-break: break-word;
}

/* Le contexte : les messages autour, celui qui est signale mis en avant.
   C'est ce qui separe un signalement d'une accusation. */
.ctx-bloc { display: flex; flex-direction: column; gap: 3px; }
.ctx {
  display: grid; grid-template-columns: 58px 1fr; gap: 10px;
  padding: 6px 9px; border-radius: 7px; font-size: 12px; line-height: 1.5;
}
.ctx.cible { background: rgba(226, 85, 176, 0.09); }
.ctx-qui { color: var(--encre-faible); font-size: 10.5px; padding-top: 2px; }
.ctx-txt { color: var(--encre-douce); word-break: break-word; }

.flag-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 3px; }

.avert {
  border-top: 1px solid var(--ligne); padding: 12px 2px;
}
.avert:first-child { border-top: 0; }
.avert-tete { display: flex; justify-content: space-between; gap: 10px; align-items: baseline; }
.avert-texte { font-size: 12.5px; color: var(--encre-douce); margin-top: 5px; line-height: 1.55; }
.avert-pied { font-size: 10.5px; color: var(--encre-faible); margin-top: 5px; }

@media (max-width: 620px) {
  .flag-tete { grid-template-columns: auto 1fr; }
  .flag-fin { grid-column: 1 / -1; justify-content: flex-start; }
  .ctx { grid-template-columns: 1fr; gap: 2px; }
}

/* ------------------------------------------------------ Onglets d'anciennete

   Les trois ages d'un lead (actif / a relancer / archive) plus "tous". Ce
   sont de vrais liens, pas des boutons : chaque categorie a son adresse, donc
   son titre de page et son lien partageable. Le compte est colle a l'intitule
   pour qu'on sache ce qu'il y a dedans avant de cliquer. */
.onglets {
  display: flex; gap: 8px; flex-wrap: wrap; align-items: center;
  margin-bottom: 14px; padding-bottom: 14px;
  border-bottom: 1px solid var(--ligne);
}
.onglet {
  font-family: inherit; font-size: 12.5px; color: var(--encre-douce);
  background: transparent; border: 1px solid transparent;
  border-radius: 999px; padding: 8px 14px; cursor: pointer;
  display: inline-flex; align-items: center; gap: 8px; text-decoration: none;
  transition: background 0.22s var(--souple), color 0.22s var(--souple), border-color 0.22s var(--souple);
}
.onglet:hover { background: rgba(255, 255, 255, 0.06); color: var(--encre); }
.onglet.actif {
  background: rgba(180, 169, 240, 0.18);
  border-color: rgba(180, 169, 240, 0.4);
  color: var(--lavande-clair);
}
.onglet-compte {
  font-size: 11px; font-variant-numeric: tabular-nums;
  color: var(--encre-faible);
  background: rgba(255, 255, 255, 0.07);
  border-radius: 999px; padding: 2px 8px;
}
.onglet.actif .onglet-compte { color: var(--lavande-clair); background: rgba(180, 169, 240, 0.2); }

input, select {
  font-family: inherit; font-size: 13px; color: var(--encre);
  /* `background-color` et non `background` : la regle `select` ci-dessous pose
     son chevron en image de fond, et une declaration raccourcie l'effacerait. */
  background-color: rgba(255, 255, 255, 0.05);
  border: 1px solid var(--ligne); border-radius: 999px;
  padding: 10px 16px; outline: none;
  transition: border-color 0.22s var(--souple), background-color 0.22s var(--souple);
}

/* Les listes deroulantes de la maquette sont des pastilles avec un petit
   chevron clair (Date, Amount, Filter). Sans `appearance: none`, Windows
   dessine par-dessus sa propre fleche grise en relief : le seul morceau de
   l'ecran qui ne vienne pas du dessin. Le chevron est une image de fond et
   non un element a part, parce qu'une balise `select` n'accepte aucun
   enfant ; la reserve a droite l'empeche de mordre sur le texte. */
select {
  appearance: none; -webkit-appearance: none; -moz-appearance: none;
  padding-right: 34px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none'%3E%3Cpath d='M1 1.5 6 6.5l5-5' stroke='%23ADACB8' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
  cursor: pointer;
}
input:focus, select:focus { border-color: rgba(180, 169, 240, 0.5); background-color: rgba(255, 255, 255, 0.08); }
input::placeholder { color: var(--encre-faible); }
select option { background: #16161F; color: var(--encre); }

/* La croix qui vide un champ de recherche est dessinee en noir par le
   navigateur, donc invisible sur fond sombre. Elle etait deja inversee dans
   la barre du haut ; elle l'est maintenant dans tous les filtres. */
input[type=search]::-webkit-search-cancel-button { filter: invert(0.65); cursor: pointer; }

/* Anneau de mise au point maison. Celui du navigateur est un double liseré
   blanc et bleu qui n'appartient a aucune palette. `:focus-visible` ne le
   montre qu'a qui navigue au clavier, jamais apres un simple clic. */
button:focus-visible, .bouton:focus-visible, a:focus-visible,
input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: 2px solid rgba(180, 169, 240, 0.55);
  outline-offset: 2px;
}
/* La pastille de recherche de la barre du haut signale deja la mise au point
   par sa bordure : un second anneau a l'interieur ferait deux cercles
   imbriques. */
.recherche input:focus-visible { outline: none; }


.filtres { display: flex; gap: 9px; flex-wrap: wrap; align-items: center; margin-bottom: 16px; }
.filtres input[type=search] { flex: 1; min-width: 210px; }

.pagination { display: flex; gap: 9px; align-items: center; justify-content: space-between; margin-top: 16px; font-size: 12px; color: var(--encre-faible); }

.jauge { height: 5px; background: rgba(255, 255, 255, 0.07); border-radius: 999px; overflow: hidden; margin-top: 7px; }
.jauge div { height: 100%; border-radius: 999px; background: var(--lavande); transition: width 0.5s var(--souple); }

/* ------------------------------------------------- Barre de parts et legende

   Le bloc "Overview" du modele : une seule barre coupee en segments de
   couleur, puis la liste des postes avec leur pastille, leur montant et leur
   part. La barre et la liste partagent le meme jeu de couleurs, c'est ce qui
   permet de lire l'une par l'autre sans legende explicite. */
.barre-parts {
  display: flex; gap: 3px; height: 6px; margin: 14px 0 18px;
}
.barre-parts span {
  height: 100%; border-radius: 999px; min-width: 4px;
  transition: flex-grow 0.6s var(--souple);
}
.parts-liste { display: flex; flex-direction: column; gap: 2px; }
.part-ligne {
  display: grid; grid-template-columns: 16px 1fr auto auto;
  align-items: center; gap: 12px;
  padding: 11px 2px; border-top: 1px solid var(--ligne);
}
.part-ligne:first-child { border-top: 0; }
.part-ligne .puce { width: 14px; height: 14px; border-radius: 5px; }
.part-ligne .nom { font-size: 13px; color: var(--encre); }
.part-ligne .sous { font-size: 10.5px; color: var(--encre-faible); margin-top: 1px; }
.part-ligne .valeur { font-size: 13.5px; font-variant-numeric: tabular-nums; }
.part-ligne .pourcent { font-size: 11px; color: var(--encre-faible); font-variant-numeric: tabular-nums; min-width: 44px; text-align: right; }

/* ------------------------------------------------------------------- Cadran

   Le demi-cercle du modele. Deux arcs superposes : la piste sombre, puis
   l'arc colore decoupe au bon angle par `stroke-dasharray`. La valeur est
   posee au-dessus en HTML plutot que dans le SVG, pour rester nette a toute
   taille et prendre la police du site. */
.cadran { position: relative; display: grid; place-items: center; padding: 6px 0 0; }
.cadran svg { width: 100%; max-width: 280px; display: block; }
.cadran .centre {
  position: absolute; left: 50%; bottom: 4px;
  transform: translateX(-50%); text-align: center;
}
.cadran .val {
  font-family: var(--titre); font-size: 34px; font-weight: 300;
  letter-spacing: -0.02em; color: var(--lavande-clair);
  font-variant-numeric: tabular-nums;
}
.cadran .quoi { font-size: 11.5px; color: var(--encre-faible); margin-top: 2px; }

/* Ascenseur lateral reduit a un filet. On ne peut pas toujours l'eviter sur
   les grands tableaux, mais il n'a aucune raison d'etre une barre grise de
   navigateur au milieu du dessin. */
.defile { scrollbar-width: thin; scrollbar-color: rgba(255, 255, 255, 0.16) transparent; }
.defile::-webkit-scrollbar { height: 6px; width: 6px; }
.defile::-webkit-scrollbar-track { background: transparent; }
.defile::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.16); border-radius: 999px; }
.defile.defile::-webkit-scrollbar-thumb { border: 0; background-clip: border-box; }
::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, 0.28); }

/* Le meme traitement pour TOUS les ascenseurs, a commencer par celui de la
   page elle-meme. Sans cette regle, une barre gris clair descend le long du
   bord droit de chaque ecran : sur un fond presque noir c'est la seule chose
   de l'interface qui ne vienne pas du dessin, et elle se voit de loin.

   La bordure transparente avec `background-clip: padding-box` donne au
   curseur sa marge : sans elle il colle au bord et parait deux fois plus
   epais. Les navigateurs recents preferent `scrollbar-width` et
   `scrollbar-color` aux pseudo-elements webkit, les deux ecritures sont donc
   posees et donnent le meme filet. */
html { scrollbar-width: thin; scrollbar-color: rgba(255, 255, 255, 0.16) transparent; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, 0.14);
  border: 3px solid transparent;
  background-clip: padding-box;
  border-radius: 999px;
}
.defile::-webkit-scrollbar-thumb { border: 0; background-clip: border-box; }
::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, 0.26); background-clip: padding-box; }
::-webkit-scrollbar-corner { background: transparent; }

/* ------------------------------------------------------------ Listes pliantes

   Ce qui remplace les tableaux a six colonnes : la ligne montre le nom, un
   sous-titre et une valeur, et le reste s'ouvre au clic sous la ligne. Rien
   ne deborde donc jamais en largeur, ni sur telephone ni ailleurs.

   Le dessin est celui de la liste du modele : une vraie grille. Les memes
   quatre colonnes pour toutes les lignes, une hauteur constante, un filet
   horizontal entre les lignes et un filet vertical apres la pastille. Ce
   dernier est ce qui change tout : sans lui, la place laissee libre entre le
   nom et la valeur se lit comme un trou au milieu de la ligne ; avec lui,
   elle se lit comme une colonne.

   Le depliage passe par `grid-template-rows: 0fr -> 1fr` plutot que par une
   hauteur maximale devinee : la transition est exacte quelle que soit la
   quantite de detail, sans jamais couper le contenu. */
.liste { display: flex; flex-direction: column; }
.ligne-groupe { border-top: 1px solid var(--ligne); }
.ligne-groupe:first-child { border-top: 0; }

/* Les cases ne sont plus centrees mais etirees sur toute la hauteur de la
   ligne (`align-items` reste a sa valeur par defaut) : c'est ce qui permet au
   filet vertical du bloc de texte d'aller d'un bord a l'autre. Le centrage se
   fait alors case par case, plus bas. */
.ligne {
  display: grid;
  grid-template-columns: 30px minmax(0, 1fr) auto 14px;
  column-gap: 11px;
  /* Ecrit noir sur blanc, et non laisse a la valeur par defaut : `.ligne` est
     un <button>, et la regle generale des boutons pose `align-items: center`.
     Sans cette declaration, les cases resteraient centrees et le filet
     vertical du bloc de texte ne ferait pas la hauteur de la ligne, ce qui
     est pourtant tout l'interet du dessin. */
  align-items: stretch;
  /* Hauteur imposee. Sans elle, une ligne sans sous-titre est plus courte que
     ses voisines et la liste ondule : c'est exactement ce qui se voit sur la
     premiere ligne des "Derniers arrives", qui n'a pas de telephone. */
  min-height: 58px;
  width: 100%; padding: 0 2px;
  border: 0; border-radius: var(--r-petit);
  background-color: transparent;
  color: inherit; font-family: inherit; font-size: 13.5px; text-align: left;
  cursor: pointer;
  /* `color` est dans la transition parce que la regle generale des boutons
     change la couleur du texte au survol : sans elle, le texte sauterait
     d'une teinte a l'autre alors que le fond, lui, fondrait. */
  transition: background-color 0.18s var(--souple), color 0.18s var(--souple);
}
/* Au survol on ne touche qu'a la couleur de fond : la regle generale des
   boutons emploie le raccourci `background`, qui remettrait le reste a zero. */
.ligne:hover { background-color: rgba(255, 255, 255, 0.028); }
/* Une ligne sans detail a ouvrir n'est pas une ligne a moitie effacee : elle
   n'a simplement pas de chevron. La regle generale `button:disabled` la
   passait a 45 % d'opacite, d'ou des lignes plus pales que leurs voisines
   sans raison visible. */
.ligne:disabled { cursor: default; opacity: 1; }

/* La pastille du modele est sobre : un carre arrondi en verre, un filet fin,
   les initiales en gris. L'aplat lavande d'avant tirait l'oeil vers la gauche
   alors que ce qui compte dans la ligne est a droite. */
.rond-nom {
  align-self: center;
  /* 36 px et non 30. Sur les planches, la hauteur d'une ligne vaut environ 1,65
     fois le cote de sa pastille ; a 30 px pour une ligne de 58 px nous etions a
     1,93, et la pastille flottait, trop petite, au bord d'une ligne trop haute
     pour elle. On monte la pastille plutot que de baisser la ligne : la
     maquette a des lignes hautes et aerees, ce sont ses pastilles qui sont
     grosses.
     Rayon 12 px pour 36 px de cote, soit 33 % : la meme proportion que .rond et
     que le sigle, celle mesuree sur toutes les planches. */
  width: 36px; height: 36px; display: grid; place-items: center;
  border-radius: 12px;
  font-size: 11.5px; font-weight: 500; letter-spacing: 0.02em;
  background: rgba(255, 255, 255, 0.045);
  border: 1px solid var(--ligne);
  color: var(--encre-douce);
}

/* PLUS AUCUN filet vertical dans la ligne. TROIS depouillements sur six l'ont
   releve, c'est le consensus le plus net du lot : meme une ligne a six colonnes
   ne separe ses colonnes que par du vide, c'est l'espace seul qui fait la
   grille. Le trait que nous posions ici etait la derniere trace du tableau
   d'avant, et il coupait la ligne en deux juste apres la pastille, exactement
   la ou la maquette ne coupe rien. */
.ligne .bloc {
  display: flex; flex-direction: column; justify-content: center;
  min-width: 0;
  padding-left: 13px;
}
/* La premiere colonne suit la nouvelle pastille. La regle est repetee ici,
   apres la definition d'origine de .ligne : a specificite egale c'est la
   derniere posee qui gagne, et la definition d'origine reste lisible a sa
   place, avec le commentaire qui l'explique. */
.ligne { grid-template-columns: 36px minmax(0, 1fr) auto 14px; }
/* Le detail replie doit toujours commencer exactement sous le nom :
   2 (retrait de la ligne) + 36 (pastille) + 11 (ecart de colonne) + 13 (retrait
   du bloc) = 62. Deux classes et non une, pour passer devant la regle
   raccourcie de .repli-contenu qui vient plus bas dans le fichier et qui, a
   specificite egale, gagnerait. Bornee au grand ecran : le bloc telephone
   ramene deja ce retrait a 2 px, et il ne doit pas etre touche. */
@media (min-width: 901px) {
  .liste .repli-contenu { padding-left: 62px; }
}
.ligne .nom {
  font-size: 13.5px; color: var(--encre);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Le sous-titre est coupe lui aussi : un numero long ne doit pas pouvoir
   pousser la colonne du milieu. */
.ligne .sous {
  font-size: 11px; color: var(--encre-faible); margin-top: 3px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* La colonne de droite. Tout y est cale a droite, donc la derniere valeur de
   chaque ligne tombe sur la meme verticale d'un bout a l'autre de la liste. */
.ligne .fin {
  display: flex; align-items: center; justify-content: flex-end;
  gap: 10px; font-size: 12.5px; color: var(--encre-douce);
}
/* Largeur plancher et plafond du jeton : les jetons se suivent alors sur une
   colonne nette au lieu de danser au gre de la longueur du mot, et un nom de
   responsable a rallonge ne peut plus decaler toute la ligne. */
.ligne .fin > .jeton {
  min-width: 62px; max-width: 140px;
  text-align: center; overflow: hidden; text-overflow: ellipsis;
}
/* Chiffres tabulaires : sans eux "1 j" et "391 j" ne s'empilent pas droit. */
.ligne .quand {
  color: var(--encre-faible); font-size: 11.5px;
  min-width: 36px; text-align: right; font-variant-numeric: tabular-nums;
}
.ligne .montant {
  color: var(--encre); font-size: 13px;
  min-width: 74px; text-align: right; font-variant-numeric: tabular-nums;
}

.ligne .chevron {
  align-self: center;
  width: 14px; height: 14px; color: var(--encre-faible);
  transition: transform 0.28s var(--souple), color 0.2s var(--souple);
}
.ligne:hover .chevron { color: var(--encre-douce); }
.ligne .chevron svg { width: 14px; height: 14px; display: block; }
.ligne-groupe.ouverte .chevron { transform: rotate(180deg); }

.repli { display: grid; grid-template-rows: 0fr; transition: grid-template-rows 0.3s var(--souple); }
.ligne-groupe.ouverte .repli { grid-template-rows: 1fr; }
.repli-in { overflow: hidden; }
/* Le detail commence exactement sous le nom (2 + 30 + 11 + 12) : il se lit
   comme la suite de la ligne, pas comme un bloc rapporte. Sous 900 px une
   regle du bloc mobile le ramene au bord : a 390 px de large, 55 px de retrait
   ne laisseraient presque plus rien au detail. */
.repli-contenu {
  display: flex; flex-wrap: wrap; gap: 10px 24px;
  padding: 0 2px 15px 55px;
}
.repli-champ { display: flex; flex-direction: column; gap: 3px; }
.repli-champ .quoi { font-size: 10px; color: var(--encre-faible); }
.repli-champ .quoi-val { font-size: 12.5px; color: var(--encre-douce); }

.vide { color: var(--encre-faible); font-size: 13px; padding: 26px 0; text-align: center; }

/* --------------------------------------------------------------- Connexion */

.page-connexion { display: grid; place-items: center; min-height: 100vh; padding: 24px; position: relative; z-index: 1; }
/* La lueur lavande occupe tout le haut de l'ecran, comme sur la page de
   creation de compte du modele. */
.page-connexion::before {
  content: "";
  position: fixed; top: -42vh; left: 50%;
  width: min(900px, 130vw); height: 92vh;
  transform: translateX(-50%);
  pointer-events: none; z-index: -1;
  background: radial-gradient(50% 50% at 50% 50%,
              rgba(197, 189, 244, 0.42) 0%,
              rgba(150, 141, 214, 0.13) 48%,
              rgba(7, 7, 11, 0) 72%);
  filter: blur(26px);
}
/* La boite disparait. Sur les deux images de reference qui montrent cet
   ecran, la creation de compte n'est pas une fenetre posee sur la page :
   c'est la page. Le contenu se tient directement sur la lueur, cale a
   gauche, le sigle seul tout en haut, et le bouton principal est le seul
   aplat de couleur. Un cadre de plus ici faisait "formulaire
   d'administration". */
.boite-connexion { width: 100%; max-width: 372px; background: none; border: 0; padding: 0; }
.boite-connexion .marque { justify-content: flex-start; padding-bottom: 68px; display: flex; align-items: center; gap: 12px; }
.boite-connexion .sigle { width: 46px; height: 46px; display: grid; place-items: center; border-radius: 15px; background: var(--lavande); color: #12101A; }
.boite-connexion .sigle svg { width: 25px; height: 22px; display: block; }
.boite-connexion h1 { font-size: 34px; font-weight: 300; line-height: 1.16; text-align: left; margin: 0 0 6px; letter-spacing: -0.02em; }
.boite-connexion p { text-align: left; color: var(--encre-faible); font-size: 12.5px; margin: 0 0 24px; }
/* Champs alignes a gauche et sans interlettrage : un identifiant ecarte
   lettre par lettre au milieu du champ etait un reste de l'ancien style, la
   maquette n'espace aucun texte. */
.boite-connexion input { width: 100%; margin-bottom: 10px; text-align: left; letter-spacing: 0; }
.boite-connexion button.principal { margin-top: 6px; }
.erreur { color: var(--niv4); font-size: 12px; text-align: left; min-height: 17px; margin-top: 11px; }

/* ------------------------------------------------------------------ Mobile */

.bouton-menu { display: none; }

/* Voile sous le menu ouvert. Sans lui, sur telephone, on ouvre le menu et
   il n'y a aucun endroit evident ou appuyer pour le refermer : c'est
   exactement ce qui bloquait. */
.voile {
  position: fixed; inset: 0; z-index: 29;
  background: rgba(5, 5, 9, 0.7);
  backdrop-filter: blur(2px);
  opacity: 0; pointer-events: none;
  transition: opacity 0.3s var(--souple);
}
.voile.visible { opacity: 1; pointer-events: auto; }

/* Poignee de glissement, sur le bord droit du menu. Visible en permanence sur
   telephone : on l'attrape au pouce et on tire vers la droite pour sortir le
   menu, vers la gauche pour le ranger. Un simple appui bascule aussi, comme
   un bouton. */
.poignee { display: none; }

@media (max-width: 900px) {
  /* Sur telephone le rail redevient un tiroir a intitules, qui coulisse hors
     de l'ecran.

     NE JAMAIS poser d'animation CSS portant sur `transform` sur cet element.
     Une valeur animee passe AVANT une declaration normale dans la cascade :
     une animation d'entree qui finit sur `transform: none` avec un
     remplissage `both` figerait cette valeur pour toujours et ecraserait le
     `translateX(-100%)` ci-dessous. C'etait la cause du menu qui restait
     ouvert en permanence, sans qu'aucune fermeture n'ait le moindre effet. */
  .rail {
    animation: none;
    transform: translateX(-100%);
    transition: transform 0.32s var(--souple);
    width: var(--largeur-menu);
    background: var(--rail-fond);
    border-right: 1px solid var(--ligne);
    padding: 18px 14px 16px;
  }
  .rail.ouverte { transform: none; box-shadow: 0 0 60px rgba(0, 0, 0, 0.8); }
  /* Pendant le glissement au doigt, la position vient du script en style en
     ligne : toute transition doit disparaitre, sinon le panneau traine
     derriere le doigt. */
  .rail.glisse, .voile.glisse, .poignee.glisse, .bouton-menu.glisse { transition: none; }

  .surface { left: 8px; right: 8px; top: 8px; bottom: 8px; border-radius: 22px; }
  .entete-haute { margin: 8px 8px 0; padding: 0 12px 0 60px; height: 56px; gap: 8px; }
  .contenu { margin: 0 8px; padding: 10px 12px 46px; }

  /* Le bouton du menu passe AU-DESSUS du tiroir ouvert (z-index 40 contre 30),
     sinon il devient inatteignable des que le panneau est deploye et on ne
     peut plus refermer. */
  .bouton-menu {
    display: inline-flex; position: fixed; top: 16px; left: 16px; z-index: 40;
    width: 40px; height: 40px; padding: 0; justify-content: center;
    font-size: 16px; line-height: 1; border-radius: 13px;
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid var(--ligne);
    transition: transform 0.32s var(--souple);
  }
  /* Menu ouvert : la croix part se ranger dans le coin haut-droit du tiroir.
     A sa place d'origine elle tombait pile sur le logo Step Dream. Le calcul
     place son bord droit a 12 px du bord du tiroir : largeur du tiroir, moins
     12 px de marge, moins ses 40 px, moins les 16 px dont elle est deja
     decalee a gauche. */
  .bouton-menu.ouvert { transform: translateX(calc(var(--largeur-menu) - 68px)); }

  .poignee {
    display: block;
    position: fixed;
    left: 0; top: 50%; margin-top: -42px;
    z-index: 31;
    width: 24px; height: 84px;
    padding: 0;
    border: 1px solid var(--ligne-forte); border-left: 0;
    border-radius: 0 11px 11px 0;
    background: rgba(22, 22, 30, 0.9);
    backdrop-filter: blur(12px);
    box-shadow: 6px 0 22px -10px rgba(0, 0, 0, 0.9);
    transform: translateX(0);
    transition: transform 0.32s var(--souple);
    /* Sans cela, iOS prend le glissement pour un defilement de page et la
       poignee ne recoit jamais les mouvements. */
    touch-action: none;
    -webkit-tap-highlight-color: transparent;
    cursor: grab;
  }
  /* Le petit trait blanc : c'est la seule chose qu'on voit vraiment, le reste
     n'est qu'un support assez large pour le pouce. */
  .poignee::before {
    content: "";
    position: absolute;
    left: 50%; top: 50%;
    width: 3px; height: 36px; margin: -18px 0 0 -1.5px;
    border-radius: 2px;
    background: rgba(255, 255, 255, 0.85);
  }
  .poignee.ouverte { transform: translateX(var(--largeur-menu)); }
  .poignee.glisse { cursor: grabbing; }

  /* La recherche du haut prend toute la place restante ; les deux icones et
     l'avatar tiennent a cote. Le nom et le role passent a la trappe : ils ne
     rentrent pas et n'apprennent rien a qui tient le telephone. */
  .recherche { width: auto; flex: 1; min-width: 0; padding: 0 12px; }
  .profil .qui { display: none; }
  .profil { padding: 4px; }
  .rond { width: 36px; height: 36px; border-radius: 11px; }
  .recherche { height: 40px; }
  .avatar { width: 36px; height: 36px; border-radius: 11px; font-size: 13px; }

  h1 { font-size: 25px; }
  .chapo { font-size: 12.5px; }
  .entete { margin-bottom: 16px; gap: 12px; }

  /* Deux tuiles par ligne : une seule gaspille l'ecran, trois sont illisibles. */
  .grille.kpi { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1px; }
  /* La hauteur plancher de 152 px vient d'une mesure faite sur la maquette de
     BUREAU, ou une tuile occupe le sixieme d'une largeur de panneau. En deux
     colonnes sur un telephone, elle laisse un grand vide sous chaque nombre.
     On la redescend a la hauteur reelle du contenu, tout en gardant un
     plancher : sans lui, une tuile sans note serait plus courte que sa voisine
     et la grille ondulerait. */
  .grille.kpi > .kpi-carte { min-height: 104px; }
  /* Un nombre IMPAIR de tuiles laisse une case vide en bas a droite : c'est le
     cas de l'ecran Analytique et de ses cinq chiffres. La derniere prend alors
     les deux colonnes. La regle se calcule toute seule quel que soit le nombre
     de tuiles, contrairement a une exception ecrite pour cinq. */
  .grille.kpi > .kpi-carte:last-child:nth-child(odd) { grid-column: 1 / -1; }
  .kpi-carte { padding: 16px 16px 17px; }
  .repli-contenu { padding-left: 2px; }
  .kpi-carte .val { font-size: 29px; margin-top: 7px; }
  .kpi-carte .etiq { font-size: 11px; }
  .kpi-carte .note { font-size: 11px; }

  .grille.deux, .grille.large-etroit { grid-template-columns: minmax(0, 1fr); }
  .panneau-tete { padding: 16px 15px 14px; }
  .panneau-tete > .grille.kpi { gap: 16px 14px; grid-template-columns: repeat(2, minmax(0, 1fr)); padding-bottom: 16px; margin-bottom: 16px; }
  .panneau-tete > .grille.kpi .kpi-carte .val { font-size: 27px; }
  .duo-tete { grid-template-columns: minmax(0, 1fr); gap: 18px; }
  .part-cadran { border-left: 0; border-top: 1px solid var(--ligne); padding-left: 0; padding-top: 18px; }
  .carte { padding: 18px 16px; }
  .carte h2 { font-size: 16px; }

  /* Les filtres passent en colonne : cote a cote ils depassaient. */
  .filtres { flex-direction: column; align-items: stretch; }
  .filtres input[type=search], .filtres select, .filtres button { width: 100%; }

  table { font-size: 12.5px; }
  th, td { padding-right: 10px; }

  .pagination { flex-direction: column; align-items: stretch; gap: 10px; }
  .pagination span { justify-content: center; }

  .barre-h { grid-template-columns: 92px 1fr 50px; font-size: 11.5px; }
  .bulle { max-width: 88%; }
  .info-courbe { display: none; }
}

@media (max-width: 420px) {
  h1 { font-size: 22px; }
  .grille.kpi > .kpi-carte { min-height: 96px; }
  .kpi-carte { padding: 14px 13px 15px; }
  .kpi-carte .val { font-size: 25px; }
  .kpi-carte .etiq { font-size: 10px; }
  .kpi-carte .note { font-size: 10px; }
  .contenu { padding: 8px 9px 40px; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}

/* ====================================================================== */
/* Transitions de page                                                     */
/*                                                                         */
/* Le site fait plusieurs pages, chacune rechargee par le navigateur. Sans  */
/* rien, le passage est un clignotement sec. On enchaine donc deux temps :  */
/* le contenu monte doucement a l'arrivee, et disparait avant de partir     */
/* (classe posee par le script sur le lien clique).                        */
/* ====================================================================== */

@keyframes entree-page {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: none; }
}
@keyframes entree-bloc {
  from { opacity: 0; transform: translateY(14px) scale(0.995); }
  to   { opacity: 1; transform: none; }
}

.contenu { animation: entree-page 0.42s var(--souple) both; }

/* Les blocs arrivent en cascade, un decalage par rang. Le retard reste
   court : au-dela de quelques dixiemes de seconde, ce n'est plus une
   animation, c'est une attente. */
.grille.kpi > *, .grille.deux > *, .contenu > .carte {
  animation: entree-bloc 0.44s var(--souple) both;
}
.grille.kpi > *:nth-child(1) { animation-delay: 0.05s; }
.grille.kpi > *:nth-child(2) { animation-delay: 0.10s; }
.grille.kpi > *:nth-child(3) { animation-delay: 0.15s; }
.grille.kpi > *:nth-child(4) { animation-delay: 0.20s; }
.grille.kpi > *:nth-child(5) { animation-delay: 0.25s; }
.grille.kpi > *:nth-child(6) { animation-delay: 0.30s; }
.grille.deux > *:nth-child(2) { animation-delay: 0.10s; }

body.sortie .contenu { opacity: 0; transform: translateY(-8px);
  transition: opacity 0.16s ease, transform 0.16s ease; }

/* ====================================================================== */
/* Infobulle du graphique                                                  */
/* ====================================================================== */

.info-courbe {
  position: fixed;
  z-index: 60;
  pointer-events: none;
  opacity: 0;
  transform: translate(-50%, -118%);
  transition: opacity 0.14s var(--souple);
  background: rgba(24, 24, 33, 0.98);
  border: 1px solid var(--ligne-forte);
  border-radius: 12px;
  padding: 8px 11px;
  box-shadow: 0 12px 28px -10px rgba(0, 0, 0, 0.9);
  white-space: nowrap;
}
.info-courbe.visible { opacity: 1; }
/* L'infobulle de la planche est minuscule : deux lignes seulement, la date en
   encre pleine et l'heure en gris plus petit dessous, AUCUN grand chiffre. La
   notre affichait un nombre de 18 px, c'est-a-dire plus gros que tout ce qu'il
   y a dans le panneau : elle attirait l'oeil davantage que la courbe qu'elle
   est censee commenter.

   On ne copie pas leur contenu a l'identique : chez eux la seconde ligne est une
   heure, chez nous c'est la valeur du jour, et c'est precisement l'information
   qu'on vient chercher en survolant. On garde donc les trois lignes, mais on
   inverse la hierarchie : la date prend l'encre pleine, la valeur redescend au
   rang de detail lisible. */
.info-courbe .jour { font-size: 12px; color: var(--encre); }
.info-courbe .valeur { font-size: 12.5px; font-weight: 400; margin-top: 2px; color: var(--encre-douce); font-variant-numeric: tabular-nums; }
.info-courbe .detail { font-size: 10.5px; color: var(--encre-faible); margin-top: 1px; }

/* Le degrade sous la courbe s'allume legerement au survol : le graphique
   repond au curseur avant meme qu'on ait vise un point. */
.aire-courbe { opacity: 0.85; transition: opacity 0.3s var(--souple); }
svg:hover .aire-courbe { opacity: 1; }

.zone-survol { fill: transparent; cursor: crosshair; }
/* Le trait de survol passe du lavande clair au lavande de la marque : c'est la
   teinte que la maquette emploie pour ce reperage. */
.trait-survol { stroke: rgba(180, 169, 240, 0.55); stroke-width: 1; opacity: 0; }
.trait-survol.visible { opacity: 1; }
/* Le marqueur du modele est un ANNEAU : un cercle evide a filet lavande dont
   l'interieur reprend le fond, releve par deux depouillements. Un disque plein
   se confond avec les pastilles de pic deja posees sur la courbe, et on ne sait
   plus lequel des deux suit le curseur.
   Le remplissage garde var(--carte) : le depouillement d'origine proposait
   var(--surface), mais c'etait dans l'hypothese ou la carte perdait son aplat
   de verre, correction qui n'a PAS ete retenue. Nos cartes gardent leur verre,
   donc --carte reste la valeur la plus proche de ce qu'on voit au travers de
   l'anneau. */
.pastille-survol { fill: var(--carte); stroke: var(--lavande); stroke-width: 2.2; opacity: 0; }
.pastille-survol.visible { opacity: 1; }

/* ====================================================================== */
/* Barres horizontales (analytique)                                        */
/* ====================================================================== */

.barres-h { display: flex; flex-direction: column; }
.barre-h {
  display: grid; grid-template-columns: 138px 1fr 62px;
  gap: 14px; align-items: center; font-size: 12.5px;
  padding: 11px 0; border-top: 1px solid var(--ligne);
}
.barre-h:first-child { border-top: 0; }
.barre-h .nom { color: var(--encre-douce); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.barre-h .piste { height: 6px; background: rgba(255, 255, 255, 0.06); border-radius: 999px; overflow: hidden; }
.barre-h .piste div {
  height: 100%; border-radius: 999px;
  background: var(--lavande);
  transition: width 0.6s var(--souple);
}
/* La plus haute valeur passe au magenta : c'est le seul repere dont on a
   besoin pour trouver le maximum d'un coup d'oeil. */
.barre-h.pic .piste div { background: var(--magenta); }
.barre-h.pic .valeur { color: var(--magenta); }
.barre-h .valeur { text-align: right; color: var(--encre); font-variant-numeric: tabular-nums; }

.colonnes-heures { display: flex; align-items: flex-end; gap: 4px; height: 128px; }
.colonnes-heures .h {
  flex: 1; border-radius: 999px; min-height: 3px;
  background: linear-gradient(180deg, var(--lavande), rgba(180, 169, 240, 0.22));
  position: relative;
  transition: background 0.25s var(--souple), opacity 0.25s var(--souple);
}
.colonnes-heures:hover .h { opacity: 0.45; }
.colonnes-heures .h:hover { opacity: 1; }
/* L'heure de pointe en magenta : meme repere que sur les barres couchees. */
.colonnes-heures .h.pic { background: linear-gradient(180deg, var(--magenta), rgba(226, 85, 176, 0.22)); }
.etiquettes-heures { display: flex; gap: 4px; margin-top: 9px; }
/* 10,5 px et non 9 : les heures ne sont ecrites qu'une fois sur trois, il y a
   donc largement la place, et 9 px etait le seul texte du site sous le seuil
   de lisibilite confortable sur un telephone. */
.etiquettes-heures div { flex: 1; text-align: center; font-size: 10.5px; color: var(--encre-faible); font-variant-numeric: tabular-nums; }

/* ====================================================================== */
/* Formulaires de saisie                                                   */
/* ====================================================================== */

.champ { margin-bottom: 15px; }
.champ label { display: block; font-size: 11.5px; color: var(--encre-faible); margin-bottom: 7px; }
.champ input, .champ select, .champ textarea { width: 100%; }
.champ textarea {
  font-family: inherit; font-size: 13px; color: var(--encre); min-height: 84px;
  /* On garde le redimensionnement mais on cache la poignee en escalier du
     navigateur (regle ::-webkit-resizer plus bas) : ce petit tas de traits
     gris dans le coin bas-droit n'existe sur aucune image de reference. Le
     supprimer pour de bon condamnerait a ecrire une reponse WhatsApp dans
     quatre lignes sans pouvoir agrandir. */
  resize: vertical;
  scrollbar-width: thin; scrollbar-color: rgba(255, 255, 255, 0.16) transparent;
  /* Meme fond que les autres champs : le 0.035 laissait la zone de texte
     plus sombre que les entrees juste au-dessus d'elle. */
  background: rgba(255, 255, 255, 0.05); border: 1px solid var(--ligne);
  border-radius: var(--r-petit); padding: 11px 14px; outline: none;
  transition: border-color 0.22s var(--souple), background 0.22s var(--souple);
}
.champ textarea::placeholder { color: var(--encre-faible); }
.champ textarea:focus { border-color: rgba(180, 169, 240, 0.5); background: rgba(255, 255, 255, 0.08); }
/* La poignee en escalier du navigateur, en bas a droite des zones de texte,
   n'existe sur aucune image de reference. On la rend invisible sans retirer
   le redimensionnement lui-meme. */
.champ textarea::-webkit-resizer { background-color: transparent; }

.champ .aide { font-size: 11.5px; color: var(--encre-faible); margin-top: 5px; line-height: 1.5; }
.choix-sources { display: flex; flex-wrap: wrap; gap: 7px; }
.message { border-radius: var(--r-petit); padding: 11px 14px; font-size: 13px; margin-top: 14px; }
.message.ok { background: rgba(180, 169, 240, 0.12); border: 1px solid rgba(180, 169, 240, 0.34); color: var(--lavande-clair); }
.message.ko { background: rgba(226, 85, 176, 0.12); border: 1px solid rgba(226, 85, 176, 0.36); color: #F3A8DA; }

/* ====================================================================== */
/* Fil de conversation                                                     */
/*                                                                         */
/* Codes visuels de la messagerie : le client a gauche, nous a droite,     */
/* pour que le sens de l'echange se lise sans rien decrypter.              */
/* ====================================================================== */

.fil {
  display: flex; flex-direction: column; gap: 9px;
  max-height: 460px; overflow-y: auto;
  padding: 4px 6px 4px 2px;
}
.bulle {
  max-width: 74%;
  padding: 9px 13px;
  border-radius: 14px;
  font-size: 13px;
  line-height: 1.55;
  position: relative;
  word-break: break-word;
  animation: entree-bloc 0.3s var(--souple) both;
}
.bulle .qui { font-size: 10.5px; color: var(--encre-faible); margin-bottom: 3px; }
.bulle .heure { font-size: 10px; color: var(--encre-faible); margin-top: 4px; text-align: right; }
/* Le client : a gauche, teinte neutre. */
.bulle.entrant {
  align-self: flex-start;
  background: rgba(255, 255, 255, 0.055);
  border: 1px solid var(--ligne);
  border-bottom-left-radius: 4px;
}
/* Nous : a droite, dans la lavande de la marque. */
.bulle.sortant {
  align-self: flex-end;
  background: rgba(180, 169, 240, 0.16);
  border: 1px solid rgba(180, 169, 240, 0.34);
  border-bottom-right-radius: 4px;
}
.bulle.media { font-style: italic; color: var(--encre-faible); }

.fil-entete {
  display: flex; justify-content: space-between; align-items: flex-start;
  gap: 14px; margin-bottom: 14px;
}
/* La ligne choisie reprend la lavande du site. Le rgba(127, 119, 221) etait
   un bleu-violet d'une palette anterieure, qui ne correspond a aucun jeton. */
tbody tr.choisie { background: rgba(180, 169, 240, 0.12); }
tbody tr.cliquable { cursor: pointer; }

/* ======================================================================= */
/* Page Discussions : les chiffres a gauche, le chat a droite               */
/*                                                                         */
/* Le fil ne s'ouvre plus SOUS les tuiles pour disparaitre a la fermeture.  */
/* C'est un panneau permanent, a droite, d'une hauteur arretee. Cette       */
/* hauteur fixe n'est pas un caprice de mise en page : c'est elle qui       */
/* permet au fil de defiler chez lui et a la zone de reponse de rester      */
/* collee en bas. Avec une hauteur qui suit le contenu, le panneau          */
/* grandirait a chaque message recu et le champ de reponse finirait hors    */
/* de l'ecran.                                                             */
/* ======================================================================= */

.zone-discussion {
  /* Hauteur du bandeau haut, declaree une seule fois : la colonne de gauche
     et le panneau de chat s'y accrochent tous les deux, c'est ce qui les
     fait finir exactement sur le meme trait, comme sur le croquis. */
  --h-chat: 588px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.18fr);
  /* Une ligne de hauteur arretee, et non `auto` : sans cela un fil charge de
     cent messages ferait grandir la ligne et le defilement interne ne
     s'enclencherait jamais. */
  /* Plancher, pas plafond. La requete du resume ne limite pas le nombre de
     responsables : le jour ou il y en a six au lieu de quatre, la ligne
     grandit avec les tuiles au lieu d'ecraser le bloc du dessous. */
  grid-template-rows: minmax(var(--h-chat), auto);
  /* Et jamais plus que ce que l'ecran montre d'un coup : sur un portable de
     768 px de haut, une hauteur fixe mettait le bouton Envoyer sous la ligne
     de flottaison. */
  max-height: calc(100vh - 210px);
  gap: 12px;
  margin-bottom: 12px;
}

.colonne-gauche {
  display: flex; flex-direction: column; gap: 12px;
  height: 100%; min-width: 0;
}
/* Les quatre chiffres en carre, comme sur le croquis. Deux colonnes
   imposees : `auto-fit` en ferait une seule bande de quatre dans une colonne
   de cette largeur. `flex: none` empeche la grille de se faire ecraser par
   le bloc d'appoint, qui prend ce qui reste. */
.colonne-gauche > .grille.kpi {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  flex: none;
}

/* ------------------------------------------------- Bloc d'appoint gauche */

/* Il prend tout ce qui reste sous les chiffres et ne deborde jamais : ses
   deux parties longues (la repartition, la note sur l'historique manquant)
   defilent chacune chez elle. */
.bloc-attente {
  flex: 1; min-height: 0;
  display: flex; flex-direction: column;
  padding: 18px 20px;
}
.bloc-attente .legende { margin-bottom: 0; }
.bloc-attente .barre-parts { margin: 13px 0 12px; }
.bloc-attente .parts-liste { flex: 1 1 auto; min-height: 44px; overflow-y: auto; }
.bloc-attente .part-ligne { padding: 8px 2px; }
/* Un nom de responsable trop long doit se couper, pas pousser la colonne des
   chiffres hors du bloc. */
.bloc-attente .part-ligne .nom {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* La note cede la place quand il y a beaucoup de responsables : c'est une
   precaution a lire une fois, alors que la repartition, elle, est
   l'information du jour. */
.note-webhook {
  flex: 0 1 auto; max-height: 122px; overflow-y: auto;
  margin-top: 12px; padding-top: 12px;
  border-top: 1px solid var(--ligne);
  font-size: 11.5px; line-height: 1.55; color: var(--encre-faible);
}
.note-webhook strong { color: var(--encre-douce); font-weight: 500; }

/* ------------------------------------------------------ Panneau de chat */

.panneau-chat {
  height: 100%; min-width: 0;
  display: flex; flex-direction: column;
  padding: 18px 20px;
}
/* Trois zones, une seule qui bouge : l'entete tient en haut, le fil defile,
   la reponse reste en bas. */
.panneau-chat .fil-entete { flex: none; margin-bottom: 12px; }
.panneau-chat .fil-entete .legende { margin-bottom: 0; }
.panneau-chat .fil-entete h2 {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* La legende se coupe comme le titre. Sur une colonne etroite, le texte du
   fil vide y tenait sur cinq lignes, et ces cinq lignes etaient prises au fil
   de messages, pas a l'entete. */
.panneau-chat .fil-entete .legende {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.panneau-chat .fil {
  flex: 1 1 0; min-height: 80px;
  /* La hauteur vient desormais du panneau : le plafond du bloc autonome
     couperait le fil bien avant le bas de la carte. */
  max-height: none;
  overflow-y: auto;
  padding-right: 6px;
}
/* Le mot d'explication quand la conversation n'a aucun message enregistre.
   Il prend la place du fil, sinon la zone de reponse remonterait au milieu
   du panneau au lieu de rester en bas. */
.chat-explique {
  flex: 1 1 0; min-height: 60px; overflow-y: auto;
  display: flex; align-items: center;
  font-size: 13px; line-height: 1.7; color: var(--encre-douce);
  padding: 4px 6px 4px 2px;
}
.chat-explique p { margin: 0; }

/* Etat vide. Le panneau ne se vide jamais de sens : sans conversation
   choisie il dit quoi faire. Un panneau qui disparaitrait ferait sauter
   toute la page a chaque ouverture et a chaque fermeture, et le regard
   perdrait sa place dans la liste. */
.chat-vide {
  flex: 1; min-height: 0;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 11px;
  text-align: center; color: var(--encre-faible); padding: 18px;
}
.chat-vide .rond-vide {
  width: 52px; height: 52px; border-radius: var(--r-petit);
  display: grid; place-items: center;
  background: rgba(180, 169, 240, 0.1);
  border: 1px solid rgba(180, 169, 240, 0.22);
  color: var(--lavande);
}
.chat-vide .rond-vide svg { width: 24px; height: 24px; display: block; }
.chat-vide strong {
  font-family: var(--titre); font-weight: 400; font-size: 15.5px;
  letter-spacing: -0.005em; color: var(--encre-douce);
}
.chat-vide p { margin: 0; font-size: 12.5px; line-height: 1.6; max-width: 32ch; }

/* Zone de reponse, collee en bas du panneau. */
.chat-pied {
  flex: none;
  margin-top: 12px; padding-top: 12px;
  border-top: 1px solid var(--ligne);
}
.chat-pied .champ { margin-bottom: 9px; }
.chat-pied textarea { min-height: 60px;   /* Hauteur arretee du panneau : agrandir le champ prendrait sur le fil,
     puis deborderait de la carte. */
  resize: none;
}
/* Le bouton et l'avertissement d'envoi sur la meme ligne : empiles, ils
   prenaient trois hauteurs de ligne, toutes prises sur le fil. */
.chat-pied .ligne-envoi { display: flex; align-items: center; gap: 12px; }
.chat-pied .ligne-envoi button { flex: none; }
.chat-pied .ligne-envoi .aide {
  flex: 1; min-width: 0;
  font-size: 11px; line-height: 1.45; color: var(--encre-faible);
}
.chat-pied .message { margin-top: 9px; padding: 8px 12px; font-size: 12px; }

/* Ascenseurs internes reduits a un filet, comme ceux des tableaux. */
.panneau-chat .fil, .chat-explique, .bloc-attente .parts-liste, .note-webhook {
  scrollbar-width: thin; scrollbar-color: rgba(255, 255, 255, 0.16) transparent;
}
.panneau-chat .fil::-webkit-scrollbar,
.chat-explique::-webkit-scrollbar,
.bloc-attente .parts-liste::-webkit-scrollbar,
.note-webhook::-webkit-scrollbar { width: 6px; }
.panneau-chat .fil::-webkit-scrollbar-track,
.chat-explique::-webkit-scrollbar-track,
.bloc-attente .parts-liste::-webkit-scrollbar-track,
.note-webhook::-webkit-scrollbar-track { background: transparent; }
.panneau-chat .fil::-webkit-scrollbar-thumb,
.chat-explique::-webkit-scrollbar-thumb,
.bloc-attente .parts-liste::-webkit-scrollbar-thumb,
.note-webhook::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, 0.16); border-radius: 999px;
}

/* Les deux blocs du bandeau arrivent en fondu comme les autres cartes : la
   regle d'origine ne vise que les enfants directs de `.contenu`, et ils ne
   le sont plus. */
.zone-discussion > .carte, .colonne-gauche > .carte {
  animation: entree-bloc 0.44s var(--souple) both;
}
.colonne-gauche > .carte { animation-delay: 0.08s; }

/* Les tuiles se resserrent dans la demi-largeur : a taille pleine elles
   poussaient le bloc d'appoint hors du panneau. Regle bornee au grand ecran,
   pour ne pas ecraser les tailles deja prevues plus bas pour le telephone. */
@media (min-width: 901px) {
  .colonne-gauche .kpi-carte { padding: 14px 15px 15px; }
  .colonne-gauche .kpi-carte .val { font-size: 28px; margin-top: 6px; }
  .colonne-gauche .kpi-carte .etiq { font-size: 11.5px; }
  .colonne-gauche .kpi-carte .note { font-size: 11px; margin-top: 5px; }
}

@media (max-width: 900px) {
  /* Une seule colonne. `display: contents` fait remonter les deux blocs de
     gauche au rang de cases de la grille : c'est ce qui permet de glisser le
     chat ENTRE les chiffres et le bloc d'appoint, alors que le HTML les garde
     ensemble pour la mise en page du croquis sur grand ecran. */
  .zone-discussion {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: none;
    /* Le plafond de hauteur ne vaut QUE sur grand ecran, ou le bandeau tient
       sur une seule rangee et ou il empeche le bouton Envoyer de passer sous
       la ligne de flottaison. En une colonne les trois blocs s'empilent :
       leur somme depassait le plafond, et le surplus retombait par-dessus la
       carte de la liste, en dessous. C'est ce qui melangeait les sections. */
    max-height: none;
    --h-chat: 452px;
  }
  .colonne-gauche { display: contents; }
  .colonne-gauche > .grille.kpi { order: 1; }
  .panneau-chat { order: 2; height: var(--h-chat); }
  .bloc-attente { order: 3; height: auto; }

  .panneau-chat, .bloc-attente { padding: 16px 15px; }
  /* Sur telephone il y a de la place en hauteur : la note se lit d'un trait
     plutot que dans une fenetre de huit lignes. */
  .note-webhook { max-height: none; overflow-y: visible; }
  /* L'entete du fil doit tenir sur 356 px : boutons plus courts. */
  .panneau-chat .fil-entete { gap: 8px; }
  .panneau-chat .fil-entete .bouton,
  .panneau-chat .fil-entete button { font-size: 11.5px; padding: 7px 12px; }
  /* L'avertissement d'envoi passe sous le bouton : cote a cote il ne reste
     que quatre mots par ligne. */
  .chat-pied .ligne-envoi { flex-direction: column; align-items: stretch; gap: 8px; }
  .chat-pied .ligne-envoi button { justify-content: center; }
}

@media (max-width: 420px) {
  .zone-discussion { --h-chat: 404px; }
}

/* Deux mots n'ont pas besoin de 26 px de marge haute et basse : ici le message
   vide tient dans une liste qui defile deja, pas dans un tableau. */
.bloc-attente .parts-liste .vide { padding: 14px 0; }

/* ====================================================================== */
/* Menus deroulants maison                                                 */
/* ====================================================================== */

/* Pourquoi : un <select> natif ouvre la liste du systeme, blanche sur iOS
   comme sur Windows. Elle perce le fond sombre a chaque ouverture, c'est le
   seul endroit de l'interface qui ne suit pas la maquette.

   Le select n'est PAS remplace : il reste dans le DOM, invisible, et garde
   le role de source de verite. Les quatre pages qui s'en servent (courtiers, discussions, leads, nouveau) continuent de
   lire .value et d'ecouter "change" sans une ligne a changer. */

.menu-maison {
  position: relative;
  display: inline-flex;
  max-width: 100%;
  min-width: 0;
  vertical-align: middle;
}

/* Le select garde sa place et sa valeur, il ne garde que ca. Il est sorti du
   parcours au clavier : c'est le bouton qui le remplace pour la navigation. */
.menu-maison > select.menu-source {
  position: absolute;
  top: 0; left: 0;
  width: 1px; height: 1px;
  margin: 0; padding: 0; border: 0;
  opacity: 0;
  pointer-events: none;
  overflow: hidden;
  clip-path: inset(50%);
}

/* Le declencheur reprend exactement la pilule des champs de saisie : meme
   fond, meme filet, meme rayon. De face, rien ne distingue un menu d'un
   champ, ce qui est le but. */
.menu-maison .menu-declencheur {
  flex: 1 1 auto;
  min-width: 0;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: inherit;
  font-size: 13px;
  font-weight: 400;
  color: var(--encre);
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid var(--ligne);
  border-radius: 999px;
  padding: 10px 15px 10px 16px;
  text-align: left;
  cursor: pointer;
  transition: border-color 0.22s var(--souple), background 0.22s var(--souple),
              color 0.22s var(--souple);
}
.menu-maison .menu-declencheur:hover {
  background: rgba(255, 255, 255, 0.08);
  color: var(--encre);
}
.menu-maison .menu-declencheur:focus-visible {
  outline: none;
  border-color: rgba(180, 169, 240, 0.5);
  background: rgba(255, 255, 255, 0.08);
}
.menu-maison.ouvert .menu-declencheur {
  border-color: rgba(180, 169, 240, 0.5);
  background: rgba(255, 255, 255, 0.08);
}
.menu-maison .menu-declencheur:disabled { opacity: 0.45; cursor: not-allowed; }

.menu-maison .menu-etiquette {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Valeur vide (« Choisir… », « Tous les responsables ») : l'intitule se lit
   comme un indice et non comme un choix deja fait. */
.menu-maison.vide-valeur .menu-etiquette { color: var(--encre-faible); }

.menu-maison .menu-chevron {
  width: 13px; height: 13px; flex: none;
  color: var(--encre-faible);
  transition: transform 0.28s var(--souple), color 0.22s var(--souple);
}
.menu-maison .menu-chevron svg { width: 100%; height: 100%; display: block; }
.menu-maison.ouvert .menu-chevron { transform: rotate(180deg); color: var(--lavande-clair); }

/* Dans un formulaire, le menu prend toute la largeur du champ, comme les
   input poses juste au-dessus de lui. */
.champ > .menu-maison { display: flex; width: 100%; }

/* Dans le tableau des discussions, la liste de transfert partage sa cellule
   avec le lien vers amoCRM : elle reste courte et discrete. */
.menu-maison[data-classe~="select-transfert"] { max-width: 148px; }
.menu-maison[data-classe~="select-transfert"] .menu-declencheur {
  font-size: 11.5px;
  padding: 6px 10px 6px 12px;
  gap: 7px;
}

/* Le panneau vit dans <body> et se place en coordonnees d'ecran.

   Il le faut : .carte porte un backdrop-filter, ce qui fait d'elle le repere
   de tout position:fixed pose a l'interieur. Un panneau ouvert depuis une
   carte se collerait au coin de la carte au lieu de suivre l'ecran. Le sortir
   de la carte regle aussi le decoupage par .defile, qui a un overflow.

   Il est unique et partage : un seul menu est deploye a la fois. */
.menu-panneau {
  position: fixed;
  z-index: 70;
  display: none;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 5px;
  background: var(--verre-plein);
  backdrop-filter: blur(24px) saturate(115%);
  border: 1px solid var(--ligne-forte);
  border-radius: var(--r-petit);
  box-shadow: 0 20px 46px -16px rgba(0, 0, 0, 0.9);
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, 0.16) transparent;
}
.menu-panneau::-webkit-scrollbar { width: 6px; }
.menu-panneau::-webkit-scrollbar-track { background: transparent; }
.menu-panneau::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.16); border-radius: 999px; }

.menu-panneau.ouvert { display: block; animation: menu-entree 0.17s var(--souple) both; }
/* Quand le panneau s'ouvre vers le haut, il doit arriver du bas : sinon le
   mouvement contredit la direction dans laquelle il se deploie. */
.menu-panneau[data-sens="haut"].ouvert { animation-name: menu-entree-haut; }

@keyframes menu-entree {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: none; }
}
@keyframes menu-entree-haut {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}

.menu-option {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border-radius: 9px;
  font-size: 13px;
  line-height: 1.35;
  color: var(--encre-douce);
  cursor: pointer;
  transition: background 0.14s var(--souple), color 0.14s var(--souple);
}
.menu-option .texte {
  flex: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* La coche occupe sa place meme invisible : les intitules restent alignes
   entre l'entree choisie et les autres. */
.menu-option .coche { width: 14px; height: 14px; flex: none; opacity: 0; color: var(--lavande); }
.menu-option .coche svg { width: 100%; height: 100%; display: block; }

.menu-option:hover, .menu-option.vise {
  background: rgba(180, 169, 240, 0.16);
  color: var(--lavande-clair);
}
.menu-option.choisie { color: var(--lavande-clair); }
.menu-option.choisie .coche { opacity: 1; }
.menu-option.inactif { opacity: 0.4; cursor: not-allowed; }
.menu-option.inactif:hover { background: none; color: var(--encre-douce); }

.menu-panneau .menu-vide {
  padding: 12px;
  font-size: 12.5px;
  color: var(--encre-faible);
  text-align: center;
}

@media (max-width: 900px) {
  /* Les filtres passent en colonne : le menu suit, comme le champ de
     recherche et les boutons a cote de lui. */
  .filtres > .menu-maison { width: 100%; }
  /* Au doigt, une entree doit rester assez haute pour etre visee sans
     precision. */
  .menu-option { padding: 12px 13px; font-size: 13.5px; }
}
