/* =====================================================================
   WIN STORE - systeme de design
   Palette : celle recommandee par la base UI/UX Pro Max pour le domaine
   « Fintech/Crypto » (refonte 27/09) — « Gold trust + purple tech » :
   bleu #262223 (marque), bleu clair #8D8D8F (accents), fond sombre #1A1617,
   texte #E6E1E2. Le violet sert aux ACTIONS (boutons, liens, onglets actifs),
   l'or aux accents et aux mises en avant. Typographie recommandee pour le
   domaine finance : IBM Plex Sans.
   Les nuances sont ajustees pour tenir le contraste 4.5:1 demande par la base :
   bleu 600 #262223 sous du texte blanc ; l'ambre ne sert plus qu'aux etats
   ===================================================================== */
:root {
  --brand-50: #E6E1E2;  --brand-100: #D9D4D5; --brand-200: #B9B3B4; --brand-300: #8D8D8F;
  --brand-400: #8D8D8F; --brand-500: #3A3536; --brand-600: #262223; --brand-700: #1A1617;
  --brand-800: #0A0809; --brand-900: #0A0809;

  --slate-50: #E6E1E2; --slate-100: #D9D4D5; --slate-200: #C9C4C5; --slate-300: #B9B3B4;
  --slate-400: #5C5657; --slate-500: #6E6869; --slate-600: #433E3F; --slate-700: #3A3536;
  --slate-800: #1A1617; --slate-900: #1A1617; --slate-950: #0A0809;

  --amber-50: #FBF0DA; --amber-100: #F5E4BE; --amber-200: #EFD79E; --amber-500: #C9942B;
  --amber-600: #8A6212; --amber-700: #6E4E0E; --amber-800: #5E4A1C;
  --violet-50: #E6E1E2; --violet-200: #C9C4C5; --violet-500: #8D8D8F; --violet-700: #3A3536;
  --sky-50: #E6E1E2; --sky-500: #8D8D8F; --sky-600: #5C5657; --sky-700: #3A3536;
  --emerald-50: #E3F3E8; --emerald-200: #B7DFC4; --emerald-500: #22A052; --emerald-600: #15803D;
  --emerald-700: #15803D; --emerald-800: #15803D;
  --rose-50: #FBE9EE; --rose-200: #EFC3CF; --rose-500: #C23A5C; --rose-600: #A32B4A; --rose-700: #A32B4A;

  /* Couleurs des DEUX CARTES D'ACTION de l'accueil. Trois demandes du client le
     30/09/2026 : « couleur vert pour le bouton depot et couleur rouge pour le bouton
     retrait », puis « couleur bleu clair pour le depot et vert clair pour le bouton
     retrait », puis « un peu plus clair et transparent », enfin « maintenant rend le
     transparent comme du verre ». Etat retenu : BLEU CLAIR au depot (famille de la
     marque) et VERT CLAIR au retrait (famille emerald), poses EN VERRE a 45 % : la
     teinte est translucide (le fond de page compose la couleur) et le flou est pose
     sur la carte plus bas (regle `body.client-app .cx-act`). Les jetons sont FIGES
     (declares ici, nulle part dans le bloc de nuit) : la TEINTE ne bascule pas, c'est
     l'ENCRE qui bascule (voir la regle de la carte). Le contraste se mesure sur la
     COULEUR COMPOSEE sur le fond de page (--brand-50 le jour, le fond de nuit la
     nuit) et non sur le jeton ecrit a la main : 10,8:1 et 7,7:1 pour le depot,
     6,5:1 et 4,9:1 pour le retrait le jour, 7,8:1 a 12,5:1 la nuit. ui_check
     9quinquies mesure ces rapports sur les deux themes. */
  --act-dep-1: rgba(141, 141, 143, .45); --act-dep-2: rgba(58, 53, 54, .45);
  --act-wd-1: rgba(34, 160, 82, .45); --act-wd-2: rgba(21, 128, 61, .45);
  /* Encre de la vitre « retrait » le jour : le vert de la palette qui tient 4,5:1 sur
     une vitre claire (--emerald-800 #15803D ne donne que 4,1:1). Le bleu, lui, prend
     --brand-900. La nuit, les deux vitres prennent --on-brand. */
  --act-encre-vert: #0B3D20;

  --radius: 16px; --radius-lg: 24px; --radius-sm: 12px;
  /* surfaces (le mode sombre les redefinit : voir :root[data-theme="dark"]) */
  --surface: #F0ECED; --surface-2: #ECE8E9;
  /* fond des barres collees (barre du bas de l'admin) : blanc a 97 % en clair,
     bleu nuit a 97 % la nuit (voir :root[data-theme="dark"]) */
  --surface-glass: rgba(240, 236, 237, .97);
  /* geste « tirer pour actualiser » (core.js) : le rond qui suit le doigt. Le JS
     ne pose que des var(), donc le rond suit le theme ; en clair il prend la
     surface (blanc) et le bleu de marque pour l'aiguille, et la NUIT il bascule
     tout seul (--surface devient sombre, l'aiguille passe au bleu 400 : voir le
     bloc du theme sombre). Le cerne donne un bord au rond quand les deux fonds
     se ressemblent. */
  --ptr-fond: var(--surface); --ptr-bord: var(--slate-200);
  --ptr-trait: var(--brand-600); --ptr-pret: var(--brand-600);
  --ptr-pret-trait: var(--on-brand);
  /* ombres : teintees de la marque (bleu de la plateforme de reference) */
  --shadow: 0 1px 2px rgba(26, 22, 23, .05), 0 8px 24px -12px rgba(38, 34, 35, .22);
  --shadow-lg: 0 24px 60px -24px rgba(26, 22, 23, .35);
  --shadow-hover: 0 4px 20px rgba(38, 34, 35, .12);
  --shadow-cta: 0 8px 24px rgba(38, 34, 35, .32);
  --ring: 0 0 0 1px var(--slate-200);
  /* typographie recommandee pour le domaine finance : IBM Plex Sans, titres et
     texte. Auto-hebergee (voir static/css/fonts.css) : le CSP interdit un
     domaine de polices externe. */
  --font: 'IBM Plex Sans', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --font-titre: 'IBM Plex Sans', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  /* degrades : or -> violet pour le titre (la signature de la palette),
     violet pour les boutons. Le violet 600 tient le contraste sous du blanc. */
  --grad: linear-gradient(90deg, #262223, #8D8D8F);                 /* titre du hero : bleu -> bleu clair */
  --grad-cta: linear-gradient(135deg, #3A3536, #0A0809);
  /* texte pose SUR la marque (bouton plein, onglet actif) : blanc dans les
     deux themes, puisque le fond est toujours fonce. Nomme une fois pour
     toutes plutot que d'ecrire #fff dans les regles (la zone d'animations de
     la feuille interdit toute couleur litterale, cf. tests/ui_check.py). */
  --on-brand: #F0ECED;
  /* Verre (glassmorphism) : style recommande pour le domaine fintech par la
     base UI/UX Pro Max, et signature visuelle de la plateforme de reference
     (son .glass-card : flou 20 px, fond translucide, cerne 1 px, ombre teintee
     au survol). Valeurs transcrites de sa feuille de style. */
  --glass-bg: rgba(255, 255, 255, .86);      /* clair : blanc a 86 % */
  --glass-bg-2: rgba(255, 255, 255, .96);    /* au survol */
  --glass-border: rgba(201, 196, 197, .8);
  --glass-blur: blur(20px);
  /* barres qui restent sombres dans les deux themes (barre laterale du
     panneau, bandeau de l'accueil) : indigo nuit */
  --night: #1A1617;   /* fond sombre recommande (Dark Mode OLED) */

  /* theme clair de la page publique */
  --dark-bg: #1A1617; --dark-1: #262223; --dark-2: #1C1819; --dark-3: #433E3F;
  --dark-text: #F0ECED; --dark-muted: #B9B3B4;
  --landing-red: #262223; --landing-red-dark: #1A1617; --landing-red-light: #3A3536;
}

/* =====================================================================
   MODE SOMBRE — active par data-theme="dark" sur <html> et <body>
   (bascule presente dans l'en-tete de chaque espace, choix garde dans
   localStorage sous la cle 'cd_theme'). On inverse l'echelle de gris et
   on eclaircit les accents de marque pour garder un contraste lisible.
   ===================================================================== */
:root[data-theme="dark"] {
  color-scheme: dark;

  /* echelle de gris inversee : tout composant qui utilise var(--slate-*)
     pour un fond passe en sombre, et pour un texte passe en clair.
     C'est le style « Dark Mode OLED » recommande par la base : fond #1A1617,
     cartes #1A1617, bordures #3A3536, texte #E6E1E2, secondaire #5C5657. */
  --slate-50: #262223;  --slate-100: #1C1819; --slate-200: #433E3F; --slate-300: #5C5657;
  --slate-400: #B9B3B4; --slate-500: #D9D4D5; --slate-600: #C9C4C5; --slate-700: #D9D4D5;
  --slate-800: #FFFFFF; --slate-900: #FFFFFF; --slate-950: #FFFFFF;

  /* surfaces */
  --surface: #1C1819; --surface-2: #332E2F;
  --surface-glass: rgba(28, 24, 25, .97);

  /* geste « tirer pour actualiser » : le rond prend la surface (sombre, par la
     chaine de var() du theme clair) mais l'aiguille en bleu 600 (#E6E1E2) ne
     donnait que 2,9:1 sur ce rond — le client ne voyait presque rien au moment
     de tirer. On monte au bleu 400 : 5,2:1. */
  --ptr-trait: var(--brand-400);
  /* encre posee sur la marque : sombre la nuit, la marque etant claire */
  --on-brand: #1A1617;

  /* marque : le violet 600 reste le fond des boutons (texte blanc : 5.7:1) et
     le violet 400 porte les traits et les icones sur fond nuit */
  --brand-50: #3A3536; --brand-100: #332E2F; --brand-200: #433E3F; --brand-300: #5C5657;
  --brand-400: #F0ECED; --brand-500: #F0ECED; --brand-600: #E6E1E2; --brand-700: #E6E1E2;
  --brand-800: #E6E1E2; --brand-900: #3A3536;

  /* teintes semantiques : fonds sombres, accents eclaircis */
  --amber-50: #5E4A1C;   --amber-100: #5E4A1C; --amber-200: #6E5820; --amber-500: #FFD27A;
  --amber-600: #FFD27A;  --amber-700: #FFD27A; --amber-800: #FFD27A;
  --violet-50: #3A3536;  --violet-200: #433E3F; --violet-500: #F0ECED; --violet-700: #F0ECED;
  --sky-50: #3A3536;     --sky-500: #F0ECED;    --sky-600: #F0ECED; --sky-700: #E6E1E2;
  --emerald-50: #0B3D20; --emerald-200: #0B3D20; --emerald-500: #22A052; --emerald-600: #86EFAC;
  --emerald-700: #86EFAC; --emerald-800: #86EFAC;
  --rose-50: #6E2B42;    --rose-200: #6E2B42;   --rose-500: #FF9E9E; --rose-600: #FF9E9E;
  --rose-700: #FF9E9E;

  /* page publique : style sombre de la palette fintech */
  --dark-bg: #262223; --dark-1: #1C1819; --dark-2: #1C1819; --dark-3: #433E3F;
  --dark-text: #E6E1E2; --dark-muted: #B9B3B4;
  --landing-red: #E6E1E2; --landing-red-dark: #E6E1E2; --landing-red-light: #F0ECED;

  --ring: 0 0 0 1px var(--slate-200);
  --shadow: 0 1px 2px rgba(0, 0, 0, .5), 0 10px 30px -14px rgba(0, 0, 0, .7);
  --shadow-lg: 0 30px 70px -30px rgba(0, 0, 0, .85);
  /* refonte 27/09 : ombres et degrades revus pour la nuit. Un degrade de
     marque fonce disparaitrait sur fond nuit, on part donc des tons clairs. */
  --shadow-hover: 0 4px 20px rgba(0, 0, 0, .48);
  --shadow-cta: 0 8px 24px rgba(0, 0, 0, .55);
  --grad: linear-gradient(90deg, #C9C4C5, #F0ECED);                 /* nuit : bleu clair -> bleu pale */
  --grad-cta: linear-gradient(135deg, #F0ECED, #C9C4C5);
  /* teinte des barres toujours sombres (barre laterale du panneau, bandeau
     de l'accueil) : indigo nuit, aligne sur la marque */
  --night: #0A0809;   /* fond sombre recommande (Dark Mode OLED) */
  /* verre, version nuit : un voile blanc tres leger sur le fond profond */
  --glass-bg: rgba(255, 255, 255, .06);
  --glass-bg-2: rgba(255, 255, 255, .12);
  --glass-border: rgba(255, 255, 255, .10);
}

:root[data-theme="dark"] body { background: var(--slate-50); color: var(--slate-900); }
/* barres et panneaux translucides : version sombre */
:root[data-theme="dark"] .bottomnav { background: rgba(26, 22, 23, .96); }
:root[data-theme="dark"] .landing-nav { background: rgba(26, 22, 23, .94); }
:root[data-theme="dark"] .modal,
:root[data-theme="dark"] .sheet { background: rgba(10, 8, 24, .78); }
/* la barre laterale de l'admin est sombre dans les deux themes (bleu nuit
   var(--night)) : le mode sombre du PANNEAU suit le
   mode sombre general, section « admin » plus bas. */
/* les separateurs internes (historiques, listes) etaient invisibles sur fond nuit */
:root[data-theme="dark"] .divide > * + * { border-top-color: var(--slate-200); }
:root[data-theme="dark"] .phone-mock { background: linear-gradient(160deg, var(--surface), var(--night)); }
/* icones sur pastille : trop sombres sinon */
:root[data-theme="dark"] .tile .t-ico,
:root[data-theme="dark"] .feat .fi { color: var(--brand-400); }
/* champs de saisie : garder le texte clair et le placeholder lisible */
:root[data-theme="dark"] .input::placeholder,
:root[data-theme="dark"] .textarea::placeholder { color: var(--slate-400); }
:root[data-theme="dark"] .select option { background: var(--surface); color: var(--slate-900); }

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  font-family: var(--font);
  background: var(--slate-50);
  color: var(--slate-900);
  /* Rendu du texte sur iOS/iPadOS. « antialiased » rend les lettres plus
     FINES et plus delavees sur iPad (constate le 25/09/2026 : l'en-tete de
     l'appli semblait flou a cote de la carte sombre). On laisse le reglage
     par defaut du systeme, qui donne des lettres plus franches. Sur Android
     cette propriete n'a aucun effet : rien ne change pour les telephones. */
  -webkit-font-smoothing: auto;
  font-size: 15px;
  line-height: 1.5;
}
a { color: inherit; text-decoration: none; }
button { font-family: inherit; font-size: inherit; }
img { max-width: 100%; display: block; }

/* ---------- utilitaires de mise en page ---------- */
.container { width: 100%; max-width: 1120px; margin: 0 auto; padding: 0 16px; }
.narrow { max-width: 640px; }
.flex { display: flex; } .iflex { display: inline-flex; }
.col { display: flex; flex-direction: column; }
.grid { display: grid; }
.wrap { flex-wrap: wrap; }
.items-center { align-items: center; } .items-start { align-items: flex-start; } .items-end { align-items: flex-end; }
.justify-between { justify-content: space-between; } .justify-center { justify-content: center; }
.justify-end { justify-content: flex-end; }
.grow { flex: 1 1 auto; } .shrink-0 { flex: 0 0 auto; } .min0 { min-width: 0; }
.gap1 { gap: 4px; } .gap2 { gap: 8px; } .gap3 { gap: 12px; } .gap4 { gap: 16px; } .gap6 { gap: 24px; }
.mt1 { margin-top: 4px; } .mt2 { margin-top: 8px; } .mt3 { margin-top: 12px; }
.mt4 { margin-top: 16px; } .mt6 { margin-top: 24px; } .mt8 { margin-top: 32px; }
.mb1 { margin-bottom: 4px; } .mb2 { margin-bottom: 8px; } .mb3 { margin-bottom: 12px; }
.mb4 { margin-bottom: 16px; } .mb6 { margin-bottom: 24px; } .mb0 { margin-bottom: 0; }
.ml-auto { margin-left: auto; } .mr-auto { margin-right: auto; }
.p2 { padding: 8px; } .p3 { padding: 12px; } .p4 { padding: 16px; } .p5 { padding: 20px; } .p6 { padding: 24px; }
.px4 { padding-left: 16px; padding-right: 16px; } .py2 { padding-top: 8px; padding-bottom: 8px; }
.py3 { padding-top: 12px; padding-bottom: 12px; } .py6 { padding-top: 24px; padding-bottom: 24px; }
.w-full { width: 100%; } .h-full { height: 100%; }
.relative { position: relative; } .absolute { position: absolute; } .fixed { position: fixed; }
.hidden { display: none !important; }
.text-center { text-align: center; } .text-right { text-align: right; } .text-left { text-align: left; }
.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nowrap { white-space: nowrap; }
.mono { font-family: var(--mono); }
.caps { text-transform: uppercase; letter-spacing: .06em; }
.muted { color: var(--slate-500); }
.small { font-size: 13px; } .xs { font-size: 12px; } .lg { font-size: 17px; }
.strong { font-weight: 600; } .bold { font-weight: 700; }
.mw-md { max-width: 480px; } .mw-lg { max-width: 720px; }
.text-brand { color: var(--brand-600); } .text-emerald { color: var(--emerald-700); }
.text-rose { color: var(--rose-700); } .text-amber { color: var(--amber-700); }
.text-sky { color: var(--sky-600); } .text-slate4 { color: var(--slate-400); }
.pt2 { padding-top: 8px; } .pt3 { padding-top: 12px; } .pt4 { padding-top: 16px; }
.pb2 { padding-bottom: 8px; } .pb4 { padding-bottom: 16px; }
.logo { display: flex; align-items: center; justify-content: center; border-radius: 10px;
  color: #fff; font-weight: 800; font-size: 15px; overflow: hidden; }
/* logo en IMAGE (bookmakers, 01/10/2026) : le fichier livre est carre et porte
   son propre fond, il remplit donc la vignette ; « contain » evite de rogner un
   logo plus large venu du panneau (`logo_url`). */
.logo-img { object-fit: contain; }
.scroll-x { overflow-x: auto; -webkit-overflow-scrolling: touch; }

h1, h2, h3, h4 { margin: 0; line-height: 1.2; font-weight: 700; }
.h1 { font-size: 26px; } .h2 { font-size: 21px; } .h3 { font-size: 17px; } .h4 { font-size: 15px; }

/* ---------- cartes / surfaces ---------- */
.card {
  background: var(--surface); border-radius: var(--radius); box-shadow: var(--ring);
  overflow: hidden;
}
.card.p4 { padding: 16px; }
.card-hd { padding: 14px 16px; border-bottom: 1px solid var(--slate-100); display: flex;
  align-items: center; justify-content: space-between; gap: 8px; }
.card-bd { padding: 16px; }
.card-ft { padding: 12px 16px; border-top: 1px solid var(--slate-100); background: var(--slate-50); }
.elevated { box-shadow: var(--shadow); }
.soft { background: var(--slate-50); border-radius: var(--radius-sm); padding: 12px; }
.hairline { border: 1px solid var(--slate-200); }
.divide > * + * { border-top: 1px solid var(--slate-100); }
.grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

/* ---------- boutons ---------- */
/* PASTILLE (30/09/2026, demande du client : « arrondit bien les boutons de
   l'interface ») : tous les boutons de la maison sont des pastilles — le rayon
   suit la hauteur, donc aucune taille de bouton ne peut redevenir rectangulaire.
   Les rayons par taille (.btn-sm / .btn-xs) ont ete retires le meme jour : ils
   cassaient cette regle. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 11px 16px; border-radius: 999px; border: 1px solid transparent;
  background: var(--slate-100); color: var(--slate-800); font-weight: 600; cursor: pointer;
  transition: filter .15s ease, background .15s ease; line-height: 1.1;
}
.btn:active { transform: scale(.96); }   /* reference : active:scale-95 */
.btn:disabled { opacity: .55; cursor: not-allowed; }
.btn-primary { background: var(--brand-600); color: #fff; }
.btn-primary:hover { filter: brightness(1.06); }
.btn-dark { background: var(--brand-700); color: #fff; }
.btn-ok { background: var(--emerald-600); color: #fff; }
.btn-warn { background: var(--amber-500); color: #5E4A1C; }
.btn-danger { background: var(--rose-600); color: #fff; }
.btn-ghost { background: transparent; border-color: var(--slate-200); color: var(--slate-700); }
.btn-ghost.white { border-color: rgba(255,255,255,.3); color: #fff; }
/* ---------- bascule clair / sombre ---------- */
.btn-theme {
  display: inline-flex; align-items: center; gap: 8px; padding: 8px 12px; border-radius: 999px;
  border: 1px solid var(--slate-200); background: var(--surface); color: var(--slate-700);
  font-size: 13px; font-weight: 600; cursor: pointer; line-height: 1;
}
.btn-theme:hover { border-color: var(--brand-300); color: var(--brand-700); }
.btn-theme [data-theme-icon] { display: inline-flex; }
.btn-theme.white { background: rgba(255,255,255,.10); border-color: rgba(255,255,255,.3); color: #fff; }
.btn-theme.white:hover { background: rgba(255,255,255,.2); border-color: rgba(255,255,255,.5); color: #fff; }
@media (max-width: 700px) { .btn-theme .btn-theme-label { display: none; } }
.btn-sm { padding: 7px 11px; font-size: 13px; }
.btn-xs { padding: 4px 9px; font-size: 12px; }
.btn-block { width: 100%; }
.btn-row { display: flex; gap: 8px; flex-wrap: wrap; }

/* ---------- formulaires ---------- */
.label { display: block; font-size: 12px; font-weight: 600; color: var(--slate-600);
  text-transform: uppercase; letter-spacing: .05em; margin-bottom: 6px; }
.input, .select, .textarea {
  width: 100%; padding: 11px 13px; border: 1px solid var(--slate-200); border-radius: 12px;
  background: var(--surface); color: var(--slate-900); font-size: 15px; outline: none;
}
.input:focus, .select:focus, .textarea:focus { border-color: var(--brand-500);
  box-shadow: 0 0 0 3px var(--brand-100); }
.input.mono { font-family: var(--mono); letter-spacing: .14em; }
/* Champ du bookmaker du depot (01/10/2026, dessin de la reference) : FERME comme
   un select, il s'ouvre au toucher. Tant que rien n'est choisi : tuile grise,
   icone de boutique et texte gris ; une fois choisi, la vignette du bookmaker et
   son nom en encre normale. Le chevron reste a droite. */
.bm-champ { display: flex; align-items: center; gap: 10px; text-align: left; cursor: pointer; }
.bm-champ .bm-tuile { flex: none; width: 34px; height: 34px; border-radius: 10px;
  background: var(--slate-100); color: var(--slate-500); display: flex; align-items: center;
  justify-content: center; }
.bm-champ .bm-nom { color: var(--slate-400); }
.bm-champ.choisi .bm-nom { color: var(--slate-900); }
.bm-champ .bm-chev { flex: none; margin-left: auto; color: var(--slate-400); }
.textarea { min-height: 90px; resize: vertical; }
.field { margin-bottom: 14px; }
.hint { font-size: 12px; color: var(--slate-500); margin-top: 6px; }
.err-text { font-size: 13px; color: var(--rose-600); margin-top: 6px; }
.switch { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; }

/* ---------- badges / pastilles ---------- */
.badge { display: inline-flex; align-items: center; gap: 6px; padding: 3px 9px; border-radius: 999px;
  font-size: 12px; font-weight: 600; background: var(--slate-100); color: var(--slate-700); white-space: nowrap; }
.badge-pending { background: var(--amber-100); color: var(--amber-800); }
.badge-awaiting_admin { background: var(--violet-50); color: var(--violet-700); }
.badge-paid, .badge-success { background: var(--emerald-50); color: var(--emerald-700); }
.badge-rejected { background: var(--rose-50); color: var(--rose-700); }
.badge-cancelled { background: var(--slate-100); color: var(--slate-600); }
.badge-expired { background: var(--slate-200); color: var(--slate-700); }
.badge-review { background: var(--amber-100); color: var(--amber-800); }
.badge-info { background: var(--sky-50); color: var(--sky-700); }
.badge-deposit { background: var(--brand-50); color: var(--brand-700); }
.badge-payout { background: var(--sky-50); color: var(--sky-700); }
.badge-admin { background: var(--brand-700); color: #fff; }
.badge-super { background: var(--brand-600); color: #fff; }
/* Credit manuel sur preuve (ajout a nous) : un depot credite SANS SMS marchand.
   Deux marques distinctes pour l'audit : « credit manuel » (qui l'a fait) et
   « sans SMS » (comment on l'a prouve). */
.badge-manual { background: var(--violet-50); color: var(--violet-700); }
.badge-nosms { background: var(--amber-100); color: var(--amber-800); }
.dot { width: 8px; height: 8px; border-radius: 50%; background: var(--slate-400); display: inline-block; }
.dot.ok { background: var(--emerald-500); } .dot.warn { background: var(--amber-500); }
.dot.err { background: var(--rose-500); } .dot.brand { background: var(--brand-600); }
.dot.sky { background: var(--sky-500); }   /* seconde serie de la tendance (retraits) */

/* ---------- tableau ---------- */
.table { width: 100%; border-collapse: collapse; font-size: 14px; }
.table th { text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--slate-500); padding: 10px 12px; background: var(--slate-50); border-bottom: 1px solid var(--slate-200); }
.table td { padding: 11px 12px; border-bottom: 1px solid var(--slate-100); vertical-align: middle; }
.table tr:hover td { background: var(--slate-50); }
.table .num { text-align: right; font-variant-numeric: tabular-nums; }

/* ---------- tableaux en cartes sur telephone (classe mob-cards) ----------
   Sur un ecran etroit, une ligne de tableau se lit de haut en bas : chaque
   cellule devient une ligne « NOM DE COLONNE -> valeur ». L'en-tete disparait
   (le nom est repris cellule par cellule par le noyau : data-label), donc plus
   aucun defilement horizontal et les colonnes de droite (statut, actions) ne
   sont plus hors de vue. Les cellules d'etat vide (colspan) restent telles quelles. */
@media (max-width: 700px) {
  .mob-cards { min-width: 0 !important; border-collapse: separate; border-spacing: 0; }
  .mob-cards thead { display: none; }
  .mob-cards tbody, .mob-cards tr, .mob-cards td { display: block; width: auto; }
  .mob-cards tr { border: 1px solid var(--slate-200); border-radius: var(--radius-sm);
    background: var(--surface); padding: 10px 12px; margin-bottom: 10px; }
  .mob-cards tr:hover td { background: transparent; }
  .mob-cards td { border: 0; padding: 3px 0; text-align: left; }
  .mob-cards td[data-label]:not([data-label=""]) { display: flex; flex-wrap: wrap;
    align-items: baseline; gap: 2px 12px; }
  .mob-cards td[data-label]:not([data-label=""])::before { content: attr(data-label);
    flex: 0 0 40%; font-size: 11px; text-transform: uppercase; letter-spacing: .06em;
    color: var(--slate-500); }
  .mob-cards td[data-label]:not([data-label=""]) > * { flex: 1 1 calc(60% - 12px); min-width: 0; }
  .mob-cards td[colspan] { padding: 0; }
  .mob-cards .num { text-align: left; }
  /* boutons d'action : toute la largeur de la carte, alignes a droite */
  .mob-cards td .tx-actions { flex: 1 1 100%; justify-content: flex-end; }
  .mob-cards td .btn { white-space: nowrap; }
  /* ---- listes de transactions : les champs separes, le cadre arrondi -------
     « separe-les et arrondis les bornes » (04/10/2026) : un trait entre deux
     champs et un rayon plus large. Pose sur la classe du tableau (liste-champs)
     pour ne pas modifier les autres listes, qui n'ont pas ete demandees. */
  .mob-cards.liste-champs tr { border-radius: 14px; padding: 12px 14px; }
  .mob-cards.liste-champs td { padding: 8px 0; }
  .mob-cards.liste-champs tbody tr > td + td { border-top: 1px solid var(--slate-100); }
}

/* ---------- LISTE DES TRANSACTIONS SUR TELEPHONE (04/10/2026) --------------
   « affiche les details comme avant, separe-les et arrondis les bornes », puis
   « comme ca c'est mieux ». Sur le telephone, la ligne de tableau retrouve donc
   ses champs — reference, date, client, type, montant, statut, ceux de la liste
   de l'accueil (voir .mob-cards.liste-champs) — un par ligne, libelle a gauche
   et valeur dans la colonne suivante, separes par un trait et reunis dans un
   cadre arrondi : `.dt-liste` / `.dt-row` / `.dt-l` / `.dt-v` (poses dans
   admin.html, remplis par `dtRow` dans admin.js). Tout le reste — bookmaker et
   ID joueur, moyen et numero de paiement, frais, chaque horodatage, journal,
   note — vit dans « Details », qui lit la MEME ligne : rien n'est perdu.

   Rien n'est masque par une classe de tableau ici : le telephone recoit des
   cartes (.tx-mob, rendu par txCardMob dans admin.js) et le grand ecran garde
   le tableau complet (.tx-desk). Un seul des deux est affiche a la fois, donc
   aucun contenu n'est rendu deux fois a l'ecran. Couleurs prises aux variables
   du theme : les deux themes suivent tout seuls. */
.tx-mob { display: none; }
.tx-card { padding: 10px; }
.tx-card + .tx-card { margin-top: 8px; }
.tx-card .tx-actions { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
@media (max-width: 700px) {
  .tx-desk { display: none; }
  .tx-mob { display: block; }
}

/* ---------- KPI ---------- */
.kpi { background: var(--surface); border-radius: var(--radius); box-shadow: var(--ring); padding: 14px; }
.kpi .k-label { font-size: 11px; text-transform: uppercase; letter-spacing: .06em; color: var(--slate-500); }
.kpi .k-value { font-size: 22px; font-weight: 700; margin-top: 4px; font-variant-numeric: tabular-nums; }
.kpi .k-sub { font-size: 12px; color: var(--slate-500); margin-top: 2px; }
.kpi.highlight { box-shadow: 0 0 0 2px var(--brand-500); }
/* ---- Tableau de bord : variation, courbe miniature, echelle -----------------
   Trois ajouts seulement, tous en jetons du projet (aucune couleur nouvelle) :
   la pastille de variation, la courbe de 7 points des tuiles, et l'echelle
   graduee de la tendance. La fleche de la pastille est un triangle CSS : pas de
   police d'icones, pas d'image, rien a charger. */
.delta { display: inline-flex; align-items: center; gap: 4px; padding: 1px 7px;
  border-radius: 999px; font-size: 11.5px; font-weight: 700;
  font-variant-numeric: tabular-nums; }
.delta-up { background: var(--emerald-50); color: var(--emerald-700); }
.delta-down { background: var(--rose-50); color: var(--rose-700); }
.delta-new { background: var(--slate-100); color: var(--slate-600); font-weight: 600; }
.tri-haut, .tri-bas { width: 0; height: 0; border-left: 4px solid transparent;
  border-right: 4px solid transparent; }
.tri-haut { border-bottom: 5px solid currentColor; }
.tri-bas { border-top: 5px solid currentColor; }
.kpi .spark { display: block; width: 100%; height: 28px; margin-top: 8px; color: var(--brand-500); }
.kpi .spark polyline { fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linejoin: round; stroke-linecap: round; vector-effect: non-scaling-stroke; }
/* File d'attente : tuiles compactes, deux colonnes des que la place le permet
   (sur telephone, six tuiles pleine largeur feraient deux ecrans de defilement). */
.qa-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(148px, 1fr)); gap: 10px; }
.qa-card-live { box-shadow: 0 0 0 1px var(--brand-300), var(--shadow); }
/* Tendance : grille horizontale graduee, echelle ecrite a gauche. */
.chart-wrap { display: flex; align-items: stretch; gap: 10px; }
.chart-y { display: flex; flex-direction: column; justify-content: space-between;
  font-size: 10.5px; color: var(--slate-500); text-align: right; min-width: 52px;
  font-variant-numeric: tabular-nums; }
.chart-plot { flex: 1 1 auto; min-width: 0; position: relative; }
.chart-grid { position: absolute; inset: 0; border-bottom: 1px solid var(--slate-200);
  border-radius: 6px 6px 0 0;
  background-image: repeating-linear-gradient(to top, var(--slate-100) 0 1px, transparent 1px 50%); }
.chart-x { display: flex; justify-content: space-between; gap: 8px; margin-top: 6px;
  font-size: 10.5px; color: var(--slate-500); }
/* Pied de la carte « Tendance » : quatre reperes separes par un simple espace. */
.dash-strip { display: flex; flex-wrap: wrap; gap: 4px 22px; }
.dash-stat { display: flex; flex-direction: column; min-width: 92px; }
.dash-stat .strong { font-variant-numeric: tabular-nums; }
@media (max-width: 700px) {
  .chart-y { min-width: 38px; font-size: 9.5px; }
  .chart-x { font-size: 9.5px; }
  .qa-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
  .dash-strip { gap: 4px 16px; }
  .dash-stat { min-width: 78px; }
}

/* ---------- application cliente ---------- */
/* En-tete repris de la capture de reference : fond blanc bleute (pas de
   degrade sombre), logo dans une vignette carree arrondie, nom de marque,
   puis les actions (menu, theme, cloche + pastille, initiale du pseudo). */
/* 112 px : la barre du bas (barre + rond du support) PLUS la silhouette
   « vallees et montagnes » qui monte de ~20 px au-dessus d'elle depuis le
   28/09/2026 — sinon la derniere carte passait sous les collines.
   LA ZONE DE GESTES DU TELEPHONE S'AJOUTE (03/10/2026) : la barre flotte a
   `10 px + env(safe-area-inset-bottom)` du bord bas, donc la reserve doit
   grandir avec elle — sinon la derniere ligne d'une page longue passe sous la
   barre sur un telephone en navigation a trois boutons (zone de gestes ~48 px). */
.app-shell { max-width: 720px; margin: 0 auto; padding-bottom: calc(112px + env(safe-area-inset-bottom)); }
.topbar {
  position: sticky; top: 0; z-index: 20; background: var(--brand-50); color: var(--slate-900);
  padding: 10px 16px;
}
.topbar .brand { font-weight: 800; letter-spacing: -.02em; }
.topbar .who { font-size: 12px; opacity: .85; }
:root[data-theme="dark"] .topbar { background: var(--surface-2); }
.balance-hero {
  background: linear-gradient(140deg, var(--brand-600), var(--brand-800));
  color: #fff; border-radius: var(--radius-lg); padding: 20px;
}
.balance-hero .amt { font-size: 30px; font-weight: 800; font-variant-numeric: tabular-nums; }
.bottomnav {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 30; background: rgba(255,255,255,.98);
  /* BORD HAUT ARRONDI (30/09/2026, demande du client : « arrondit bien les boutons de
     l'interface et la barre de navigation »). La silhouette « vagues et montagnes »
     (navWave) qui dessinait le bord haut est partie le meme jour : elle est posee
     AU-DESSUS de la barre, donc elle depasserait dans les coins arrondis — les deux
     ne peuvent pas cohabiter. La barre du telephone suit desormais la barre BORNEE
     de l'ordinateur : meme rayon (--radius-lg) et meme trait fin de 1 px, qui remplace
     ce que dessinait la silhouette. */
  display: flex; justify-content: flex-start; align-items: center; gap: 6px;
  padding: 6px 10px calc(6px + env(safe-area-inset-bottom));
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  border-top: 1px solid var(--slate-200);
  backdrop-filter: blur(8px);
}
:root[data-theme="dark"] .bottomnav { border-top-color: rgba(255, 255, 255, .10); }
/* Les entrees de la barre. Depuis le 30/09/2026 (2e demande du client : « colle
   exactement a leur barre : Accueil a GAUCHE en pilule, puis les autres entrees en
   icones a droite ») : l'ACCUEIL vient en PREMIER, a GAUCHE, et c'est LUI qui porte
   son libelle DANS une pilule quand on est dessus ; « Coupon » est AU MILIEU (hors
   du flux, `.nav-milieu`) et « Historique » reste a DROITE, en icone seule. Le
   support n'est plus un rond flottant (retire le 30/09/2026) : seule l'entree ACTIVE
   montre son libelle. Depuis le 08/10/2026 la barre porte les QUATRE entrees du
   modele (Accueil, Discussion, Historique, Profil) : elles se partagent la largeur
   en parts egales (`flex: 1 1 0`), donc plus de `nav-vide` ni de `nav-milieu`. */
.bottomnav .item {
  position: relative; flex: 1 1 0; display: flex; flex-direction: row; align-items: center;
  justify-content: center; gap: 8px; padding: 9px 12px; border-radius: 999px;
  color: var(--slate-500);
  font-size: 13.5px; font-weight: 600; background: none; border: 0; cursor: pointer;
}
/* L'ENTREE ACTIVE : la pilule (icone + libelle), la signature de leur barre. Ses
   marges sont un peu plus larges pour que le libelle respire. */
/* 01/10/2026 (habillage retenu par l'agent, le client ayant laisse la main :
   « c'est pas joli, tu peux faire a ta guise ») : la pilule active est PLEINE, a la
   couleur de la maison, icone et libelle en blanc — elle se detache nettement du
   fond clair de la barre, comme la pastille d'une barre de navigation moderne. */
.bottomnav .item.active { background: var(--brand-600); color: var(--on-brand); padding: 9px 16px; }
/* Les libelles des entrees NON actives restent dans le document — le nom lisible
   vient de l'`aria-label` pose par navItem — mais ne s'affichent pas. */
.bottomnav .item span { display: none; }
.bottomnav .item.active span { display: inline; }
.bottomnav .item svg { width: 22px; height: 22px; }
/* La place laissee entre les deux entrees : c'est elle qui ecarte « Historique »
   du bord gauche et le pose au bord droit. */
.nav-vide { flex: 1 1 0; }
/* L'ENTREE DU MILIEU (30/09/2026, demande du client : « met le au milieu »). Elle
   est prise HORS du flux et posee a 50 % de la barre : elle tombe donc au CENTRE
   de l'ecran quelle que soit la largeur de l'accueil (qui est une PILULE quand on
   est dessus) et de l'historique (icone seule). Dans le flux, elle serait collee a
   l'accueil : c'est justement ce que le client a fait corriger. Sans `top`, le
   navigateur la place comme si elle etait seule dans la barre (align-items center),
   donc exactement a la hauteur des deux autres entrees — ne pas ajouter de `top`,
   la barre a un rembourrage bas qui inclut la zone de gestes du telephone. */
.nav-milieu { position: absolute; left: 50%; transform: translateX(-50%); }
/* Depuis le 30/09/2026 l'entree active est une PILULE (fond teinte + libelle) :
   plus de pastille derriere l'icone, donc plus besoin de reserver 5 px autour de
   chaque icone. Les entrees gardent la meme hauteur, la pilule seule marque
   l'entree active (voir `.bottomnav .item.active` plus haut). */
.sheet {
  position: fixed; inset: 0; z-index: 40; background: rgba(10, 8, 24, .55);
  display: flex; align-items: flex-end; justify-content: center;
}
.sheet-card { background: var(--surface); width: 100%; max-width: 720px; border-radius: 22px 22px 0 0;
  max-height: 92vh; overflow: auto; padding: 18px; }
.modal { position: fixed; inset: 0; z-index: 50; background: rgba(10, 8, 24, .55);
  display: flex; align-items: flex-start; justify-content: center; padding: 16px;
  overflow-y: auto; overscroll-behavior: contain; }
/* margin:auto centre la fenetre quand elle tient a l'ecran ET laisse le
   defilement partir du HAUT quand elle est plus grande (avec align-items:center,
   le haut devenait inatteignable : la fenetre « se figeait »). */
.modal-card { background: var(--surface); width: 100%; max-width: 440px; border-radius: var(--radius-lg);
  padding: 20px; box-shadow: var(--shadow-lg); margin: auto; position: relative; }
.modal-card h3 { margin-bottom: 8px; padding-right: 40px; }
/* Fermeture toujours a portee de pouce, meme sur une fenetre tres longue. */
.modal-x { position: absolute; top: 10px; right: 10px; width: 34px; height: 34px; border: 0;
  border-radius: 999px; background: var(--slate-100); color: var(--slate-600); cursor: pointer;
  display: flex; align-items: center; justify-content: center; }
.modal-x:hover { background: var(--slate-200); color: var(--slate-800); }
/* La barre d'actions de la fenetre reste visible pendant le defilement. */
.modal-card > .btn-row:last-child { position: sticky; bottom: 0; background: var(--surface);
  padding-top: 10px; }
.stepper { display: flex; align-items: center; gap: 6px; margin: 4px 2px 0; }
.stepper .bar { height: 4px; border-radius: 999px; background: var(--slate-200); flex: 1; }
.stepper .bar.on { background: var(--brand-600); }
.choice {
  display: flex; align-items: center; gap: 12px; padding: 12px; border: 1px solid var(--slate-200);
  border-radius: 14px; background: var(--surface); cursor: pointer; width: 100%; text-align: left;
}
.choice.active { border-color: var(--brand-500); box-shadow: 0 0 0 3px var(--brand-50); }
.choice .logo { width: 40px; height: 40px; border-radius: 10px; display: flex; align-items: center;
  justify-content: center; color: #fff; font-weight: 800; font-size: 15px; }
/* Logos des reseaux Mobile Money (Flooz = Moov Money, Mixx by Yas = Togocom).
   Les deux fichiers ont leur PROPRE fond opaque : la vignette est un CARRE de
   40 px, rempli de la couleur de fond du logo lui-meme, et l'image y tient en
   entier (contain) — un carre plein, sans liseré, identique pour les deux. */
/* =====================================================================
   ECRAN DE CONNEXION / INSCRIPTION, calque sur la reference : pleine page
   sombre, logo, nom de marque (deuxieme mot en couleur), formulaire, « ou »,
   bouton Google, lien vers l'autre ecran. Aucun en-tete ni barre du bas.
   ===================================================================== */
/* Le fond de la page de connexion doit GAGNER sur celui de l'espace client
   (`body.client-app`, plus bas dans la feuille, meme specificite (0,1,1)) : sinon
   c'est le bleu clair #E6E1E2 qui peint le fond de page, et il se voyait AUTOUR
   de l'ecran sombre — une bande d'environ 14 px a gauche, a droite et en haut
   (mesure sur la capture du 28/09/2026, 15:40 : #EDF2F9 au bord, l'ecran sombre
   ne commencant qu'au 48e pixel d'image). Une classe de plus (0,2,1) : l'ordre
   des feuilles ne compte plus. Le mode sombre n'echappait pas au defaut — mais
   comme son fond d'espace client est deja sombre, la bande ne s'y voyait pas. */
body.auth-page,
body.auth-page.client-app,
body.auth-page.admin-app { background: #0A0809; }
/* Habillage 2 (30/09/2026) : l'ecriture de la reference (Inter) est abandonnee.
   Les deux ecrans de connexion prennent la police de la maison, IBM Plex Sans
   (--font), comme tout le reste du site : c'etait le dernier morceau de la
   reference qui restait visible chez nous. La fonte Inter reste sur le disque et
   son @font-face a ete retire de css/fonts.css (et de la liste du service
   worker) : pour revenir en arriere, le redeclarer et remettre la famille ici. */
body.auth-page, body.auth-page h1, body.auth-page h2, body.auth-page h3,
body.auth-page .auth-brand, body.auth-page .btn, body.auth-page input,
body.auth-page select, body.auth-page textarea {
  font-family: var(--font); }
/* Sur les deux ecrans de connexion, la coquille disparait ENTIEREMENT : en-tete et
   barre du bas. Le rond du support n'est plus a cacher ici : depuis le 30/09/2026
   il est flottant et n'apparait que sur l'accueil (syncShell pose `hidden`). */
body.auth-page .topbar, body.auth-page .bottomnav { display: none; }
body.auth-page .app-shell { padding-bottom: 0; }
/* Fond sombre constelle, comme la maquette : halo de la couleur de marque en
   haut, puis un reseau de points relies. */
/* L'IMAGE NE DOIT PAS BOUGER (02/10/2026). Le client : « l'image bouge quand on
   appuie sur Se connecter ». Le bloc etait CENTRE verticalement : plus la carte
   est haute (l'inscription a six champs), plus l'en-tete remonte — le logo sautait
   de 110 px entre les deux ecrans (mesure : 102 px en inscription, 211 en
   connexion). Il est desormais ancre a une distance FIXE du haut, et seule la
   carte s'allonge vers le bas. `overflow-x: hidden` (et non `overflow: hidden`)
   laisse defiler quand l'ecran est trop court : avant, le bas de l'inscription
   etait rogne. */
.auth-shell { position: relative; min-height: 100svh; display: flex; align-items: flex-start;
  justify-content: center; padding: 76px 16px 24px; overflow-x: hidden;
  background: radial-gradient(125% 58% at 50% -6%, rgba(58, 53, 54, .62), transparent 68%), #1A1617; }
.auth-shell::before { content: ''; position: absolute; inset: 0; pointer-events: none; opacity: .62;
  background-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='220'%20height='220'%3E%3Cg%20stroke='rgba(255,255,255,0.16)'%20stroke-width='1'%3E%3Cpath%20d='M18 34L74 62L126 24L176 74L204 44'/%3E%3Cpath%20d='M28 122L82 154L142 112L196 164'/%3E%3Cpath%20d='M62 62L82 154M126 24L142 112M176 74L196 164M18 34L28 122'/%3E%3C/g%3E%3Cg%20fill='rgba(255,255,255,0.34)'%3E%3Ccircle%20cx='18'%20cy='34'%20r='3'/%3E%3Ccircle%20cx='74'%20cy='62'%20r='3'/%3E%3Ccircle%20cx='126'%20cy='24'%20r='3'/%3E%3Ccircle%20cx='176'%20cy='74'%20r='3'/%3E%3Ccircle%20cx='204'%20cy='44'%20r='3'/%3E%3Ccircle%20cx='28'%20cy='122'%20r='3'/%3E%3Ccircle%20cx='82'%20cy='154'%20r='3'/%3E%3Ccircle%20cx='142'%20cy='112'%20r='3'/%3E%3Ccircle%20cx='196'%20cy='164'%20r='3'/%3E%3C/g%3E%3C/svg%3E"); background-size: 220px 220px; }
.auth-wrap { position: relative; z-index: 1; width: 100%; max-width: 384px; }
/* Habillage 2 (30/09/2026) : rayon 16 au lieu des 24 px de la reference, et la
   coche de marque posee en haut de la carte (voir l'habillage, plus bas). */
.auth-card { position: relative; overflow: hidden; width: 100%; background: #fff;
  border-radius: 16px; padding: 20px; margin-top: 14px;
  box-shadow: 0 18px 40px -24px rgba(0, 0, 0, .8); }
/* LE BLANC DE LA CARTE EST OPAQUE PLEIN, ET SANS CERNE. La regle « VERRE » plus
   bas l'englobait : son fond translucide (blanc a 86 %) l'emportait sur le blanc
   pose ci-dessus — la carte s'affichait donc GRISE (mesure 220, 222, 223 sur la
   capture du 28/09) avec un lisere clair tout autour. `.auth-card` a ete retiree
   de la liste du verre (voir la section VERRE) ; ce bloc-ci remet la carte a
   plat, au cas ou une regle voisine la reprendrait : fond blanc, aucun flou,
   aucun bord. Sur une page sombre, une carte blanche n'a pas besoin de cerne.
   Les champs gardent leur propre bord gris (--slate-300) pour rester lisibles
   dessus. Ce bloc est ecrit AVANT la section des mouvements de la feuille :
   tout ce qui suit n'accepte plus aucune couleur en dur (controle « aucune
   couleur nouvelle »). */
.auth-card {
  background: #fff;
  -webkit-backdrop-filter: none; backdrop-filter: none;
  border: 0;
}
.auth-card-t { text-align: center; font-size: 20px; font-weight: 600; letter-spacing: -.025em;
  /* L'ENCRE DE CE TITRE EST FIGEE (03/10/2026, meme defaut que la banniere de
     telechargement, releve sur la meme capture du client) : la carte est blanche
     DANS LES DEUX THEMES (voir `.auth-card`), alors que `--slate-900` devient
     #E6E1E2 la nuit — « Connexion », « Creer un compte » et « Connexion Google »
     s'ecrivaient donc en blanc sur leur propre carte blanche. Valeur du theme
     clair ecrite EN DUR, comme pour les champs (`.fx-in`) : 17,9:1 sur le blanc.
     La section 12-5 de tests/ui_check.py mesure ce rapport dans les deux themes. */
  color: #1A1617; margin: 0 0 16px; }
.auth-head { display: flex; flex-direction: column; align-items: center; text-align: center; }
/* vignette du logo, comme la maquette (elle avait ete retiree le 27/09 au matin) */
.auth-logo { width: 46px; height: 46px; border-radius: 13px; overflow: hidden; margin-bottom: 10px;
  box-shadow: 0 14px 32px -12px rgba(0, 0, 0, .85); }
.auth-logo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.auth-title { font-size: 20px; font-weight: 600; color: #fff; letter-spacing: -.025em; margin: 0; }
.auth-title .auth-brand { color: var(--brand-300); }
.auth-sub { color: rgba(255, 255, 255, .62); font-size: 14px; margin-top: 4px; }
/* ---------- champs a libelle dans la bordure (maquette du 27/09/2026) ----------
   « L'instruction » (le libelle) est posee SUR le fond blanc du champ et bascule
   vers le haut, dans la bordure, des qu'on saisit — ou quand le champ contient
   deja du texte. Le fond blanc derriere le libelle « coupe » la bordure, comme
   sur la capture. */
.fx { position: relative; margin-bottom: 10px; }
.fx-in { width: 100%; height: 44px; border: 1px solid var(--slate-300); border-radius: 20px;
  padding: 0 16px; background: #fff; font: inherit; font-size: 14px; color: #1A1617;
  caret-color: #262223; color-scheme: light;
  -webkit-appearance: none; appearance: none; }
.fx.has-ico .fx-in { padding-left: 48px; }
.fx-in:focus { outline: none; border-color: var(--brand-600);
  box-shadow: 0 0 0 3px rgba(38, 34, 35, .12); }
.fx-ico { position: absolute; left: 14px; top: 50%; transform: translateY(-50%);
  color: var(--slate-400); display: flex; pointer-events: none; }
.fx-lb { position: absolute; left: 11px; top: 50%; transform: translateY(-50%);
  padding: 0 5px; background: #fff; color: var(--slate-500); font-size: 14px; font-weight: 500;
  pointer-events: none; white-space: nowrap;
  transition: top .15s ease, left .15s ease, font-size .15s ease, color .15s ease; }
.fx.has-ico .fx-lb { left: 43px; }
/* CHAMP DONT LE LIBELLE RESTE DANS LA BORDURE : l'indice gris (« +228 … ») occupe
   le fond du champ — la facon de faire d'EMB Money, releve du 27/09/2026 : leur
   champ telephone porte `placeholder={"+228 …"}` et son libelle est deja pose en
   haut. Sans cette classe, le libelle « Telephone » resterait au milieu du champ
   et se superposerait a l'indice. */
.fx.fx-haut .fx-lb { top: 0; left: 11px; font-size: 10px; color: #6E6869; }
.fx.has-ico.fx-haut .fx-lb { top: 0; left: 11px; font-size: 10px; color: #6E6869; }
/* le libelle monte : champ rempli (au repos) puis champ actif (couleur de marque) */
.fx-in:not(:placeholder-shown) + .fx-lb { top: 0; left: 11px; font-size: 10px; color: var(--slate-500); }
.fx-in:focus + .fx-lb { top: 0; left: 11px; font-size: 10px; color: var(--brand-600); }
/* select : un select a toujours une valeur, son libelle reste en haut */
.fx-fixe .fx-lb { top: 0; left: 11px; font-size: 10px; color: var(--slate-500); }
.fx-fixe select.fx-in { padding-right: 40px; }
.fx-fixe::after { content: ''; position: absolute; right: 18px; top: 50%; width: 8px; height: 8px;
  border-right: 2px solid var(--slate-400); border-bottom: 2px solid var(--slate-400);
  transform: translateY(-70%) rotate(45deg); pointer-events: none; }
/* ---------- champ a libelle dans la bordure, DANS L'APPLI (maquette du 28/09/2026) --
   Capture de la reference : le champ « Numero mobile money » du depot porte son
   libelle DANS le champ — il monte dans la bordure des qu'on saisit —, une icone de
   telephone a gauche, et l'exemple du numero (« 90123456 ou 22890123456 ») qui ne se
   montre QU'UNE FOIS le champ actif. Memes mesures que les champs de l'appli
   (`.input` : bord 1 px `--slate-200`, rayon 12, 44 px, texte 15 px, fond
   `--surface`) : c'est exactement le gabarit de la capture, et l'ecran reste
   d'aplomb avec les autres champs — nuit comprise, ou `--surface` et les gris
   s'inversent. C'est ce qui la distingue des champs de connexion (`.fx`, rayon 20,
   fond blanc dans les deux themes puisque la carte de connexion est blanche). */
.fxn { position: relative; margin-bottom: 14px; }
.fxn-in { width: 100%; height: 44px; border: 1px solid var(--slate-200); border-radius: 12px;
  padding: 0 13px; background: var(--surface); color: var(--slate-900);
  caret-color: var(--brand-600);
  font: inherit; font-size: 15px; outline: none;
  -webkit-appearance: none; appearance: none; }
.fxn.has-ico .fxn-in { padding-left: 42px; }
.fxn-in:focus { border-color: var(--brand-500); box-shadow: 0 0 0 3px var(--brand-100); }
.fxn-ico { position: absolute; left: 13px; top: 50%; transform: translateY(-50%);
  color: var(--slate-400); display: flex; pointer-events: none; }
.fxn-lb { position: absolute; left: 9px; top: 50%; transform: translateY(-50%);
  padding: 0 4px; background: var(--surface); color: var(--slate-500); font-size: 15px;
  pointer-events: none; white-space: nowrap;
  transition: top .15s ease, left .15s ease, font-size .15s ease, color .15s ease; }
.fxn.has-ico .fxn-lb { left: 38px; }
/* le libelle monte : champ rempli (au repos), puis champ actif (couleur de marque) —
   l'ordre compte, le focus est ecrit apres */
.fxn-in:not(:placeholder-shown) + .fxn-lb { top: 0; left: 9px; font-size: 12px; color: var(--slate-500); }
.fxn-in:focus + .fxn-lb { top: 0; left: 9px; font-size: 12px; color: var(--brand-600); }
/* L'EXEMPLE NE SE MONTRE QUE SUR LE CHAMP ACTIF (capture de la reference) : au
   repos, le champ ne porte que son libelle, comme une phrase d'instruction. */
.fxn-in::placeholder { color: transparent; }
.fxn-in:focus::placeholder { color: var(--slate-400); }
/* ---------- LE TEXTE DES CHAMPS DE CONNEXION RESTE SOMBRE LA NUIT ---------------
   Les champs de connexion sont BLANCS dans les deux themes (`.fx-in` porte
   `background: #fff`). Or leur texte, leurs libelles et leurs icones suivaient
   les variables `--slate-*`, qui s'INVERSENT en mode sombre : on tapait donc du
   BLANC sur du BLANC — champ Email illisible (capture iOS du 27/09/2026 au soir).
   Les valeurs du theme clair sont donc ecrites EN DUR ici : des variables
   suivraient la nuit. `color-scheme: light` (pose sur `.fx` et rappele sur les
   champs) empeche en plus iOS d'appliquer son rendu sombre aux champs, qui
   forcait le texte en blanc par `-webkit-text-fill-color`.
   Contrastes sur le fond blanc du champ : texte #1A1617 17,9:1 ; libelle
   #6E6869 4,8:1 ; icone #5C5657 2,8:1 (decorative) ; libelle actif #262223
   10,9:1. */
.fx { color-scheme: light; }
.fx-in, .auth-form .input, .auth-form .select {
  -webkit-text-fill-color: #1A1617; }
.fx-in::placeholder, .auth-form .input::placeholder {
  color: #5C5657; -webkit-text-fill-color: #5C5657; }
.fx-ico { color: #5C5657; }
.fx-lb { color: #6E6869; }
.fx-in:not(:placeholder-shown) + .fx-lb { color: #6E6869; }
.fx-in:focus + .fx-lb { color: #262223; }
.fx-fixe .fx-lb { color: #6E6869; }
.fx-fixe::after { border-right-color: #5C5657; border-bottom-color: #5C5657; }
.pw-eye { color: #6E6869; }
.pw-eye:hover { color: #1A1617; }
.auth-form .label { color: #433E3F; }
.auth-form .input, .auth-form .select {
  background: #fff; border-color: #B9B3B4; color: #1A1617; color-scheme: light; }
.auth-shell .gsi-off { border-color: #B9B3B4; background: #E6E1E2; color: #433E3F; }
/* (Le bouton Google maison a ete SUPPRIME le 02/10/2026, sur la demande du client :
   la connexion se fait maintenant avec le bouton de Google lui-meme, dessine dans
   l'application. Ses deux regles « .auth-shell .gsi-app » sont parties avec lui.) */
.auth-shell .gsi-ghost { border-color: #B9B3B4; background: #fff; color: #1A1617; }
/* LE BOUTON DE LA FENETRE GOOGLE DU TELEPHONE (02/10/2026) : le dessin de celui
   de Google (logo a quatre couleurs) — c'est la meme action pour le client, mais
   elle ouvre la liste de SES comptes du telephone.
   02/10/2026 (soir) : BLANC, sur sa demande (« change le bouton de connexion de
   google en blanc »). C'est le dessin du bouton BLANC de Google : fond blanc,
   trait fin gris, encre grise — et plus de pastille blanche derriere le logo
   (invisible sur fond blanc, elle ne faisait que rapetisser le G). */
.auth-shell .gsi-natif { width: 100%; font-family: inherit; font-size: 14px;
  font-weight: 600; cursor: pointer; display: flex; align-items: center;
  justify-content: center; gap: 10px; height: 46px; padding: 0 14px;
  border: 1px solid #DADCE0; border-radius: 23px; background: #fff; color: #3C4043; }
.auth-shell .gsi-natif svg { width: 18px; height: 18px; flex: 0 0 18px; }
.auth-shell .gsi-natif:active { background: #F1F3F4; }
/* LE BOUTON DES COMPTES DU TELEPHONE (03/10/2026) : quand l'application porte la
   fenetre des comptes d'Android, elle dessine CE bouton-la (meme dessin que celui de
   Google, pleine largeur) — un seul bouton Google a l'ecran, jamais deux. */
.gsi-comptes .gsi-natif { width: 100%; }

/* ---------------------- LA FENETRE FLOTTANTE DES COMPTES (03/10/2026, la nuit)
   Deux demandes du client, chacune avec sa capture :
   1. « c'est le rendu de emb money je veux c'est plus moderne l'affichage des email »
      -> la liste grise du systeme ne se redessine pas : la liste est la NOTRE.
   2. « ca doit etre une fentre flottant et s'afficher comme tel » (capture de la page
      Google : comptes separes par un FILET, sans cadre) -> plus une feuille collee en
      bas, mais une CARTE CENTREE : marges tout autour, fond assombri, coins arrondis,
      ombre, croix de fermeture, et une ligne par adresse separee par un filet.
   L'ENCRE SUIT LE THEME (--slate-*), elle n'est PAS figee : la carte porte la surface
   du theme (--surface), qui s'inverse la nuit. La regle du bandeau de telechargement
   (« figer l'ENCRE ») vaut pour une surface BLANCHE dans les deux themes ;
   l'appliquer ici donnerait de l'encre sombre sur fond sombre. */
.ctb-fenetre { position: fixed; inset: 0; z-index: 60; display: flex;
  align-items: center; justify-content: center; padding: 18px;
  background: rgba(10, 8, 24, .58); animation: ctb-fade .16s ease both; }
/* Le fond cliquable couvre TOUTE la surface (l'appui a cote de la carte la ferme) ;
   il sort du flux pour ne pas deplacer la carte. */
.ctb-fond { position: absolute; inset: 0; }
.ctb-card { position: relative; z-index: 1; width: 100%; max-width: 360px;
  max-height: 82vh; overflow: auto; background: var(--surface); border-radius: 22px;
  padding: 20px 16px 16px; box-shadow: var(--shadow-lg); animation: ctb-pop .2s ease both; }
@keyframes ctb-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes ctb-pop { from { opacity: 0; transform: translateY(10px) scale(.97); }
  to { opacity: 1; transform: none; } }
.ctb-x { position: absolute; top: 10px; right: 10px; width: 32px; height: 32px;
  border: 0; border-radius: 999px; background: var(--slate-100); color: var(--slate-600);
  cursor: pointer; display: flex; align-items: center; justify-content: center; }
.ctb-titre { font-size: 1.15rem; font-weight: 800; color: var(--slate-900);
  text-align: center; margin: 0 0 4px; padding: 0 30px; }
.ctb-sous { text-align: center; color: var(--slate-500); font-size: .84rem;
  margin: 0 0 12px; }
.ctb-sous b { color: var(--slate-700); font-weight: 700; }
.ctb-liste { display: flex; flex-direction: column; }
/* Les lignes sont SEPAREES PAR UN FILET, pas encadrees : c'est le dessin de la page
   de Google que le client a montree (« s'afficher comme tel »). */
.ctb-ligne { display: flex; align-items: center; gap: 12px; width: 100%;
  padding: 11px 4px; border: 0; border-bottom: 1px solid var(--slate-200);
  border-radius: 0; background: transparent; text-align: left; cursor: pointer;
  font-family: inherit; transition: background .15s ease; }
.ctb-ligne:active { background: var(--slate-100); }
.ctb-avatar { position: relative; overflow: hidden;
  width: 40px; height: 40px; flex: 0 0 40px; border-radius: 999px;
  display: flex; align-items: center; justify-content: center; color: #fff;
  font-weight: 800; font-size: 1rem;
  background: linear-gradient(135deg, #262223 0%, #5C5657 55%, #8A6212 140%); }
/* LA VRAIE PHOTO SE POSE PAR-DESSUS L'INITIALE (03/10/2026, la nuit) : « la photo du
   profil de l'email doit se faire voir ». Elle couvre la pastille ronde ; si le lien
   ne se charge pas, elle se retire toute seule et l'initiale reste — jamais de case
   vide, jamais d'image cassee dans la liste des comptes. */
.ctb-photo { position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; border-radius: 999px; }
.ctb-plus { background: var(--slate-100); color: #262223; font-size: 1.35rem;
  font-weight: 700; }
.ctb-texte { display: flex; flex-direction: column; min-width: 0; flex: 1 1 auto; }
.ctb-nom { color: var(--slate-900); font-weight: 700; font-size: .97rem;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ctb-mail { color: var(--slate-500); font-size: .84rem; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
.ctb-chev { color: var(--slate-400); flex: 0 0 auto; display: flex; align-items: center; }
/* « Ajouter un compte » ferme la liste : le filet du haut le separe des adresses. */
.ctb-ajout { border-top: 1px solid var(--slate-200); border-bottom: 0; }
.ctb-note { color: var(--slate-500); font-size: .76rem; line-height: 1.45;
  margin: 12px 2px 0; }
/* l'anneau de focus : la seule regle de cette famille qui garde un role ici (le
   fond, la bordure et l'encre sont poses plus haut, en valeurs fixes). */
.auth-form .input:focus { border-color: #8D8D8F; box-shadow: 0 0 0 3px rgba(141, 141, 143, .25); }
/* Bouton d'envoi : mesures relevees sur la reference (42 px de haut, rayon 16,
   libelle 12 px, 14 px au-dessus — l'ecart qui separe le dernier champ). */
.auth-form .btn { height: 42px; padding: 0 16px; border-radius: 20px; font-size: 14px;
  margin-top: 14px; }
.auth-pw { position: relative; }
.auth-pw .input { padding-right: 46px; }
.pw-eye { position: absolute; right: 0; top: 0; height: 100%; padding: 0 12px; background: none;
  border: 0; color: #6E6869; cursor: pointer; display: flex; align-items: center; }
.pw-eye:hover { color: #1A1617; }
.auth-row { display: flex; align-items: center; gap: 12px; }
.auth-link { background: none; border: 0; padding: 0; color: var(--brand-700); font-size: 14px; font-weight: 500;
  text-decoration: underline; cursor: pointer; }
.auth-sep { display: flex; align-items: center; gap: 12px; }
.auth-sep span { height: 1px; flex: 1; background: var(--slate-200); }
.auth-sep b { color: var(--slate-400); font-size: 11px; font-weight: 500; text-transform: uppercase; letter-spacing: .1em; }
.auth-foot { text-align: center; color: rgba(255, 255, 255, .66); font-size: 14px; margin-top: 16px; }
.auth-foot a { color: #E6E1E2; font-weight: 700; }
/* reseaux sociaux, sous la carte (maquette) : des ronds cercles sur le fond sombre */
.auth-soc { margin-top: 18px; text-align: center; }
.auth-soc-t { color: rgba(255, 255, 255, .6); font-size: 13.5px; }
.auth-soc-row { display: flex; justify-content: center; gap: 18px; margin-top: 12px; }
.auth-soc-row a { width: 52px; height: 52px; border-radius: 50%; display: flex; align-items: center;
  justify-content: center; color: #fff; background: rgba(255, 255, 255, .08);
  border: 1px solid rgba(255, 255, 255, .18); }
.auth-soc-row a:active { transform: scale(.94); }
.auth-foot.xs { font-size: 11px; margin-top: 10px; color: var(--slate-400); }

/* ---------- BANNIERE DE TELECHARGEMENT DE L'APPLICATION (page de connexion) --
   Demande du client (02/10/2026, capture de sa page de connexion de reference) :
   « afficher le bouton de telechargement de l'application sur la page de
   connexion exactement comme ca ». La banniere de la reference, reprise ici
   telle quelle dans sa FORME — pastille de la marque a gauche, deux lignes de
   texte, bouton rond de telechargement, croix de fermeture — avec NOS couleurs
   et NOS phrases. Elle FLOTTE en bas de l'ecran (hors du flux) : la page de
   connexion est sombre, la banniere est donc BLANCHE, comme la carte du
   formulaire juste au-dessus (meme famille, meme raison : une page sombre).
   Elle n'est posee que si le telechargement est ouvert (voir app.js) : sans
   fichier, rien ne s'affiche, et l'URL ne sort jamais du serveur. */
.dl-banner { position: fixed; left: 10px; right: 10px; z-index: 5;
  bottom: calc(10px + env(safe-area-inset-bottom));
  /* 03/10/2026, client : « rendre l'affichage moins long un peu rectangle » (capture
     du bandeau a l'appui), puis « reduis encore » dans la meme minute. Mesures du
     rendu REEL avant de toucher (424 px de page, echelle 3) : la reference faisait
     404 x 64 px, rayon 26 (= presque une barre), titre de 172 px dans 235 px de place.
     Etat retenu maintenant : max-width 404 -> 312, rayon 26 -> 16 (il avait demande
     « arrondit les bornes » le 02/10 : CETTE DEMANDE-LA EST PERIMEE), rembourrage
     10 -> 9 px, ecarts 11 -> 9, pastille 44 -> 36, bouton 42 -> 34, croix 26 -> 22,
     titre 14 -> 13 px, phrase 12 -> 11,5 px. La police descend parce que le titre est
     en nowrap + ellipse : retrecir sans baisser la police le COUPE (c'est la plainte
     du 02/10). Plancher a ne pas franchir : 22 (rembourrage) + pastille + TITRE
     NATUREL + bouton + croix + 3 ecarts. Mesure apres coup, titre non coupe :
     312 x 54 px, soit 74 % de la largeur.
     PUIS « augmente la taille vers le haut » (toujours le 03/10/2026) : la LARGEUR ne
     bouge pas (312 px, c'est la demande precedente), c'est la HAUTEUR qui monte — le
     bandeau est ancre en bas, il grandit donc vers le haut. Rembourrage vertical
     9 -> 15 px : 54 -> 66 px de haut, soit un vrai bloc (proportion 4,7:1 au lieu de
     6,3:1 au depart), et le contenu reste centre (align-items: center). La largeur est
     INCHANGEE : agrandir la pastille ou le bouton mangerait le creneau du titre. */
  max-width: 312px; margin: 0 auto; padding: 15px 11px;
  display: flex; align-items: center; gap: 9px;
  background: #fff; border-radius: 16px;
  box-shadow: 0 18px 40px -22px rgba(0, 0, 0, .9); }
.dl-banner[hidden] { display: none; }
/* ---------- LE TEXTE DE LA BANNIERE RESTE SOMBRE LA NUIT (03/10/2026) ----------
   Plainte du client : « le bouton de telechargement de l'application n'affiche pas
   les ecritures en mode sombre » (capture de sa page de connexion, les deux lignes
   blanches dans la banniere blanche). La banniere est BLANCHE dans les DEUX themes
   (voir le bloc du dessus : la page de connexion est sombre), or son titre et sa
   phrase suivaient les variables --slate-*, qui S'INVERSENT la nuit : --slate-900
   passe a #E6E1E2 et --slate-500 a #5C5657 — du presque-blanc sur du blanc, les
   deux lignes disparaissaient. Meme correctif que les champs de connexion
   (`.fx-in` et `.auth-form .input`, plus haut) : sur une surface blanche DANS LES
   DEUX THEMES, l'ENCRE est ecrite EN DUR sur les valeurs du theme clair — une
   variable suivrait la nuit. Contrastes sur le blanc de la banniere : titre
   #1A1617 17,9:1 ; phrase #6E6869 4,8:1. La section 12-5 de tests/ui_check.py
   mesure ces deux rapports dans les deux themes : remettre var(--slate-*) ici
   fait rougir le controle. */
.dl-ico { flex: 0 0 auto; width: 36px; height: 36px; border-radius: 50%;
  background: var(--brand-600); color: #fff;
  display: flex; align-items: center; justify-content: center; }
.dl-txt { flex: 1 1 auto; min-width: 0; }
.dl-t { font-size: 13px; font-weight: 600; color: #1A1617;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dl-s { margin-top: 1px; font-size: 11.5px; line-height: 1.25; color: #6E6869;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.dl-go { flex: 0 0 auto; width: 34px; height: 34px; border: 0; border-radius: 50%;
  background: var(--brand-600); color: #fff; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 10px 22px -12px rgba(38, 34, 35, .95); }
.dl-go:active { transform: scale(.94); }
.dl-x { flex: 0 0 auto; width: 22px; height: 22px; padding: 0; border: 0;
  background: none; color: var(--slate-400); cursor: pointer;
  display: flex; align-items: center; justify-content: center; }
/* ---------- LA PLACE DE LA BANNIERE EST RESERVEE DANS LE FLUX (03/10/2026) ------
   Client : « impossible de defiler l'interface de connexion vers le haut et le
   bas », capture de l'ecran d'inscription a l'appui. La banniere est `position:
   fixed` : elle ne pousse rien, et le document faisait EXACTEMENT la hauteur de
   l'ecran (`min-height: 100svh` sur `.auth-shell`). Sur un ecran court, le bas du
   formulaire passait donc SOUS elle sans qu'on puisse le ramener — mesure a
   840 px de haut : « Deja un compte ? Se connecter » 32 px sous le haut de la
   banniere, et `scrollHeight == clientHeight`, molette sans effet. Ce bloc, pose
   par `banniereApp` juste apres la banniere, rend au document la hauteur que la
   banniere occupe : 66 px + ses 10 px de marge basse. Il disparait avec elle
   (croix). Verifie par ui_check (12-5) et par le parcours de front_smoke. */
.dl-reserve { height: calc(76px + env(safe-area-inset-bottom)); }
.dl-reserve[hidden] { display: none; }

/* =====================================================================
   PANNEAU LATERAL DU BURGER (modele de la reference) : panneau blanc, liste
   verticale, entree active en pastille de la couleur de marque, carte du bas
   (bienvenue pour un visiteur, compte + deconnexion pour un client).
   ===================================================================== */
body.no-scroll { overflow: hidden; }
.sidedrawer { position: fixed; inset: 0; z-index: 70; }
.sd-back { position: absolute; inset: 0; background: rgba(10, 8, 24, .5); }
.sd-panel { position: absolute; top: 0; left: 0; bottom: 0; width: min(87%, 340px);
  display: flex; flex-direction: column; background: var(--surface); color: var(--slate-900);
  box-shadow: 22px 0 60px -30px rgba(0, 0, 0, .45); animation: sd-in .22s ease-out;
  /* La barre d'etat du systeme est dessinee PAR-DESSUS la page (iPad en mode
     application) : sans cette reserve, la marque du panneau et la croix de
     fermeture passaient dessous et paraissaient lavees/floues. Vu sur capture
     le 25/09/2026. L'inset vaut 0 sur Android dans un onglet : rien ne change. */
  padding-top: env(safe-area-inset-top); padding-bottom: env(safe-area-inset-bottom); }
@keyframes sd-in { from { transform: translateX(-16px); opacity: .6; } to { transform: none; opacity: 1; } }
.sd-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px;
  padding: 18px 18px 14px; }
.sd-brand { line-height: 1.15; }
.sd-brand .sd-b1 { font-size: 20px; font-weight: 800; letter-spacing: -.01em; color: var(--slate-900); }
.sd-brand .sd-b2 { font-size: 20px; font-weight: 800; letter-spacing: -.01em; color: var(--brand-600); }
.sd-brand small { display: block; margin-top: 2px; font-size: 12px; letter-spacing: .16em;
  text-transform: uppercase; color: var(--slate-500); }
.sd-x { background: none; border: 0; color: var(--slate-600); padding: 6px; cursor: pointer; }
.sd-list { flex: 1; overflow-y: auto; padding: 4px 12px 12px; }
.sd-item { display: flex; align-items: center; gap: 14px; padding: 13px 14px; margin-bottom: 2px;
  border-radius: 14px; color: var(--slate-700); font-size: 16px; font-weight: 600; text-decoration: none; }
.sd-item:hover { background: var(--slate-50); }
.sd-item .sd-ico { flex: 0 0 auto; opacity: .95; }
.sd-item.on { background: var(--brand-600); color: #fff; }
.sd-foot { padding: 14px; border-top: 1px solid var(--slate-200); }
.sd-user { margin-bottom: 10px; }
.sd-user b { display: block; font-size: 15px; color: var(--slate-900); }
.sd-user small { color: var(--slate-500); font-size: 12px; }
.sd-welcome { background: var(--slate-50); border: 1px solid var(--slate-200);
  border-radius: 18px; padding: 14px; }
.sd-welcome b { display: block; font-size: 15px; color: var(--slate-900); margin-bottom: 4px; }
.sd-welcome small { display: block; color: var(--slate-500); font-size: 12px; margin-bottom: 12px; line-height: 1.35; }
.sd-welcome .btn { margin-bottom: 8px; }
.sd-welcome .btn:last-child { margin-bottom: 0; }
.sd-white { background: #fff; color: var(--brand-700); border: 1px solid var(--slate-300); font-weight: 700; }
.sd-foot .btn-block { width: 100%; justify-content: center; }

/* Bandeau « Nouvelle version disponible » : fixe en bas, au-dessus de la barre. */
.maj-banner { position: fixed; left: 50%; transform: translateX(-50%); bottom: 84px; z-index: 60;
  display: flex; align-items: center; gap: 10px; padding: 10px 10px 10px 13px; border-radius: 18px;
  background: var(--slate-900); color: #fff; font-size: 13px; font-weight: 600;
  box-shadow: 0 12px 30px -12px rgba(26, 22, 23, .5); max-width: calc(100% - 24px); }
.maj-banner .btn { border-radius: 999px; }
/* Demande du client (28/09/2026) : « le bouton de mise a jour en mode sombre ».
   Le bandeau est un fond SOMBRE en clair (--slate-900), mais la nuit cette
   variable devient PRESQUE BLANCHE (#E6E1E2) alors que l'encre reste #fff figee :
   du blanc sur du blanc, libelle invisible, et un bloc qui eclatait la nuit.
   Version nuit explicite : surface du theme + encre claire (13,9:1). */
:root[data-theme="dark"] .maj-banner {
  background: var(--surface); color: var(--slate-900);
  border: 1px solid var(--slate-200);
  box-shadow: 0 12px 30px -12px rgba(0, 0, 0, .7);
}

/* Tournois : banniere de l'ecran (format 2:1 comme la reference, fond degrade
   avec le trophee quand aucune image n'est fournie) et carte de l'accueil. */
.banner { position: relative; aspect-ratio: 2 / 1; width: 100%; overflow: hidden; border-radius: 16px;
  display: flex; align-items: center; gap: 14px; padding: 18px; color: #fff;
  background: linear-gradient(135deg, var(--brand-800), var(--brand-600) 60%, var(--brand-400)); }
.banner img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.banner .bn-ico { flex: 0 0 auto; opacity: .95; }
.banner .bn-txt { position: relative; min-width: 0; }
.banner .bn-txt .strong { font-size: 18px; }
.banner .bn-txt .xs { opacity: .85; }
/* Carte promotionnelle (tournoi), sur le modele de la reference : grande image
   en haut, puis un bandeau blanc avec le titre, le texte et le bouton d'action. */
.cx-tournoi { display: block; margin-top: 16px; border: 1px solid var(--slate-200);
  border-radius: 20px; overflow: hidden; background: var(--surface); text-decoration: none;
  color: inherit; box-shadow: var(--shadow); }
.cx-tournoi .ct-img { display: block; width: 100%; aspect-ratio: 2 / 1; overflow: hidden; }
.cx-tournoi .ct-img img { width: 100%; height: 100%; object-fit: cover; display: block; }
.cx-tournoi .ct-ico { display: flex; align-items: center; justify-content: center; width: 100%;
  aspect-ratio: 2 / 1; color: #fff;
  background: linear-gradient(135deg, var(--brand-800), var(--brand-500)); }
.cx-tournoi .ct-row { display: flex; align-items: center; gap: 12px; padding: 12px 14px; }
.cx-tournoi .ct-txt { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 2px; }
.cx-tournoi .ct-txt b { font-size: 15px; }
.cx-tournoi .ct-txt small { color: var(--slate-500); font-size: 12px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cx-tournoi .ct-go { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 4px;
  background: var(--brand-600); color: #fff; font-size: 13px; font-weight: 700;
  padding: 10px 14px; border-radius: 999px; }

/* ---------------------------------------------------- bloc « Code promo »
   Reference du 06/10/2026 : la VIGNETTE de la marque, son nom, le libelle
   « Code promo » et le CODE dans une puce a pointilles qui se COPIE d'un appui.
   Le bloc vit sous les deux cartes Depot / Retrait, sur les DEUX accueils
   (client et visiteur) — c'est une publicite, la reference la montre a un
   visiteur. Le contenu vient des REGLAGES (voir `codePromoCard` dans app.js) :
   un code vide et le bloc n'existe pas.
   Couleurs de la maison : bleu de la marque pour la vignette, OR (--amber-*)
   pour la puce. Ces jetons S'INVERSENT la nuit, donc aucune regle de nuit a
   doubler ici. Fenetre OPAQUE (socle de l'espace client) : ni flou ni verre. */
.cx-promo { margin-top: 14px; padding: 12px 13px; border: 1px solid var(--slate-200);
  border-radius: 18px; background: var(--surface); box-shadow: var(--shadow); }
.cx-promo-row { display: flex; align-items: center; gap: 12px; }
.cx-promo-logo { flex: 0 0 auto; width: 46px; height: 46px; border-radius: 14px;
  display: flex; align-items: center; justify-content: center; color: #fff;
  background: linear-gradient(135deg, var(--brand-700), var(--brand-500));
  animation: cxPromoFlotte 3.6s ease-in-out infinite; }
@keyframes cxPromoFlotte { 0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-3px); } }
.cx-promo-txt { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.cx-promo-t { font-size: 15px; font-weight: 700; color: var(--slate-900);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cx-promo-s { font-size: 12px; color: var(--slate-500); }
.cx-promo-chip { position: relative; overflow: hidden; flex: 0 0 auto;
  display: inline-flex; align-items: center; gap: 7px; padding: 9px 12px;
  border: 1px dashed var(--amber-600); border-radius: 12px;
  background: var(--amber-50); color: var(--amber-800); font: inherit;
  font-weight: 700; cursor: pointer; animation: cxPromoRespire 2.6s ease-in-out infinite; }
@keyframes cxPromoRespire { 0%, 100% { transform: scale(1); }
  50% { transform: scale(1.03); } }
.cx-promo-code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 15px; font-weight: 700; letter-spacing: 2px; }
.cx-promo-ico { display: inline-flex; opacity: .75; }
/* Le BALAYAGE : une bande claire traverse la puce toutes les 3,4 s et ramene
   l'oeil sur le code. Purement decoratif (aucun evenement, aucun clic). */
.cx-promo-brille { position: absolute; top: 0; bottom: 0; width: 38%; left: -60%;
  pointer-events: none; background: linear-gradient(90deg, transparent,
  rgba(255, 255, 255, .65), transparent);
  animation: cxPromoBrille 3.4s ease-in-out infinite; }
@keyframes cxPromoBrille { 0% { left: -60%; } 45%, 100% { left: 125%; } }
/* Le code vient de partir : la puce se remplit et se coche 1,4 s (classe posee
   par le gestionnaire `promo-copy` d'app.js). L'encre est FIGEE : elle vit sur
   l'or, qui ne bascule pas. */
.cx-promo-copie { background: var(--amber-500); border-style: solid;
  border-color: var(--amber-500); color: #5E4A1C; animation: cxPromoPop .5s ease; }
.cx-promo-copie .cx-promo-brille { display: none; }
.cx-promo-copie .cx-promo-ico svg { display: none; }
.cx-promo-copie .cx-promo-ico::after { content: '\2713'; font-size: 15px; font-weight: 700; }
@keyframes cxPromoPop { 0% { transform: scale(1); } 35% { transform: scale(1.12); }
  100% { transform: scale(1); } }
/* Le bouton d'inscription, quand le reglage `promo_url` est rempli : pleine
   largeur sous la ligne (vide = aucun bouton, le bloc reste celui de la
   reference). */
.cx-promo-cta { display: flex; align-items: center; justify-content: center; gap: 6px;
  margin-top: 11px; padding: 12px; border-radius: 14px; background: var(--brand-600);
  color: #fff; font-size: 14px; font-weight: 700; text-decoration: none; }
@media (prefers-reduced-motion: reduce) {
  .cx-promo-logo, .cx-promo-chip, .cx-promo-copie { animation: none; }
  .cx-promo-brille { display: none; }
}

/* Carte de bienvenue d'un visiteur : meme carte sombre que le client connecte,
   avec la pastille CASHDESK et les deux boutons. */
.cx-hero-guest .cx-pill { display: inline-flex; align-items: center; gap: 6px; }
.cx-hero-guest .cx-spark { display: inline-flex; }
.cx-hero-guest .cx-hello { margin-top: 12px; font-size: 22px; font-weight: 700; line-height: 1.25; }
/* Le mot de marque du titre porte le bleu clair de la maquette du client, sur la
   carte visiteuse COMME sur la carte d'un connecte (02/10/2026). */
.cx-hero .cx-hello b, .cx-hero-guest .auth-brand { color: #E6E1E2; font-weight: 800; }
.cx-hero .btn-white { background: #fff; color: var(--brand-800); border: 0; font-weight: 700; }
.cx-hero .btn-white:hover { background: #D9D4D5; }

/* Bouton « Continuer avec Google » (rendu par Google Identity Services) et ses
   etats d'attente. Le bouton officiel est en theme sombre, forme pilule, comme
   dans la reference. */
/* Le cadre du bouton de Google. EN COLONNE depuis le 02/10/2026 : quand notre
   bouton de secours se montre (Google trop lent a venir), il doit se placer SOUS
   celui de Google. En ligne, les deux se serraient cote a cote et le texte du
   second etait coupe — vu sur la capture du client. */
.gsi-wrap { position: relative; display: flex; flex-direction: column; width: 100%;
  justify-content: center; align-items: stretch; min-height: 40px; }
.gsi-wrap > div { width: 100%; display: flex; justify-content: center; }
/* Le secours ne colle pas au bouton de Google quand les deux sont a l'ecran. */
.gsi-wrap > #gsi-repli { margin-top: 10px; }
/* ECRAN INTERMEDIAIRE SUPPRIME (02/10/2026) : sur la page de connexion Google, le
   bouton est appuye par la page elle-meme, donc il n'a pas a se voir — mais il doit
   rester DANS la page (une case de taille nulle ne se dessine pas, et un element en
   display:none ne se laisse pas appuyer). On le rend donc invisible sans le retirer :
   la transparence ne change pas la mise en page, et « pointer-events: none » empeche
   seulement le doigt du client de le toucher. */
.gsi-wrap.gsi-auto { opacity: 0; pointer-events: none; }
.gsi-ghost { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--slate-200); border-radius: 999px; background: var(--slate-50);
  color: var(--slate-500); font-size: 12px; font-weight: 600; }
/* Etat « Google pas encore configure » : SURTOUT pas en position absolue — la
   classe de chargement ci-dessus s'etale sinon sur toute la page et recouvre le
   formulaire d'inscription. */
.gsi-off { display: block; padding: 12px 14px; text-align: center; border: 1px dashed var(--slate-300);
  border-radius: 999px; background: var(--slate-50); color: var(--slate-500);
  font-size: 12px; font-weight: 600; }
.gsi-sep { display: flex; align-items: center; gap: 10px; color: var(--slate-400); font-size: 12px; }
.gsi-sep::before, .gsi-sep::after { content: ''; height: 1px; flex: 1; background: var(--slate-200); }

/* Illustration de l'attente du SMS dans la modale de paiement (comme la reference). */
.pay-wait { display: flex; align-items: center; justify-content: center; color: var(--brand-600); }
.pay-wait svg { opacity: .85; }
/* Page de suivi du depot (reference : panneau du depot, pastille d'etat en haut).
   Meme forme pour les trois etats finaux, seule la couleur change. */
.dep-suivi .suivi-pastille { width: 64px; height: 64px; margin: 0 auto 16px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center; }
.dep-suivi .suivi-pastille.confirme { background: var(--emerald-50); color: var(--emerald-600); }
.dep-suivi .suivi-pastille.non-trouve { background: var(--amber-100); color: var(--amber-600); }
.dep-suivi .suivi-pastille.clos { background: var(--slate-100); color: var(--slate-500); }
.paylogo { width: 40px; height: 40px; flex: 0 0 auto; border-radius: 10px; overflow: hidden;
  display: flex; align-items: center; justify-content: center; }
.paylogo img { display: block; width: 100%; height: 100%; object-fit: contain; }
.paylogo.flooz { background: #ffffff; }  /* fond du fichier flooz.png */
.paylogo.mixx { background: #003170; }   /* bleu exact de mixxbyyas.png */

/* Cartes de reseau Mobile Money, disposees comme dans la reference : logo
   au-dessus, nom du reseau et operateur en dessous, sur toute la largeur.
   Le reseau choisi prend la teinte de sa marque (jaune Flooz, bleu ciel Mixx)
   et porte une pastille verte, exactement comme la reference. */
.choice.net { flex-direction: column; align-items: center; text-align: center; gap: 8px;
  padding: 14px 10px; position: relative; }
.choice.net .paylogo { width: 48px; height: 48px; }
.choice.net .pick { position: absolute; right: 8px; top: 8px; width: 20px; height: 20px;
  border-radius: 999px; background: var(--emerald-500); color: #fff; display: flex;
  align-items: center; justify-content: center; }
.choice.net.on-flooz { border-color: transparent; background: var(--amber-50);
  box-shadow: 0 0 0 2px var(--amber-500); }
.choice.net.on-mixx { border-color: transparent; background: var(--sky-50);
  box-shadow: 0 0 0 2px var(--sky-500); }
.choice.net.off { opacity: .55; border-style: dashed; }
.choice.net.off .paylogo { filter: grayscale(.55); }
:root[data-theme="dark"] .choice.net.on-flooz { background: rgba(255, 210, 122, .16); }
:root[data-theme="dark"] .choice.net.on-mixx { background: rgba(141, 141, 143, .16); }
.list-item { display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 12px 14px; background: var(--surface); border-bottom: 1px solid var(--slate-100); }
.list-item:last-child { border-bottom: 0; }

/* ---------- historique : une carte PAR operation (01/10/2026) ----------
   Demande du client : « separrer comme tel », capture de la reference a
   l'appui — chaque operation dans SA carte, au lieu d'une seule carte a
   hachures. Squelette de la reference (badges en haut, titre en gras, montant
   a droite, message en rouge), mais nos variables : aucune teinte en dur, donc
   les deux themes suivent tout seuls. */
.hist-list { display: flex; flex-direction: column; gap: 10px; }
.hist-card { display: flex; align-items: center; gap: 10px; padding: 12px 14px; }
.hist-card[data-act] { cursor: pointer; }
.hist-tete { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }
.hist-titre { margin-top: 4px; font-size: 15px; font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hist-ligne { margin-top: 2px; }
.hist-msg { margin-top: 2px; color: var(--rose-600); }
.hist-date { margin-top: 4px; display: flex; align-items: center; gap: 5px; }
.hist-amt { font-variant-numeric: tabular-nums; }
.tile { display: flex; flex-direction: column; gap: 6px; align-items: flex-start; padding: 14px;
  border-radius: 14px; background: var(--surface); box-shadow: var(--ring); cursor: pointer; border: 0; text-align: left; }
.tile .t-ico { width: 34px; height: 34px; border-radius: 10px; display: flex; align-items: center;
  justify-content: center; background: var(--brand-50); color: var(--brand-600); }
.progress { height: 8px; border-radius: 999px; background: var(--slate-200); overflow: hidden; }
.progress > i { display: block; height: 100%; background: var(--brand-600); border-radius: 999px; }
.empty { text-align: center; padding: 34px 16px; color: var(--slate-500); }
.empty svg { width: 34px; height: 34px; margin-bottom: 8px; color: var(--slate-300); }
.tabs { display: flex; gap: 6px; overflow-x: auto; padding-bottom: 2px; }
.tab { padding: 7px 12px; border-radius: 999px; background: var(--slate-100); color: var(--slate-600);
  font-size: 13px; font-weight: 600; border: 0; cursor: pointer; white-space: nowrap; }
.tab.active { background: var(--brand-600); color: #fff; }
.notice { border-radius: 14px; padding: 12px 14px; display: flex; gap: 10px; align-items: flex-start;
  border: 1px solid var(--slate-200); background: var(--surface); }
.notice.success { background: var(--emerald-50); border-color: var(--emerald-200); }
.notice.warning { background: var(--amber-50); border-color: var(--amber-200); }
.notice.error { background: var(--rose-50); border-color: var(--rose-200); }
.notice.info { background: var(--sky-50); border-color: #E6E1E2; }

/* Bandeau de signalement des credits manuels repetes (AJOUT A NOUS) : alerte
   INTERNE de l'equipe (un meme administrateur credite plusieurs depots sans
   SMS). Rouge, en haut du tableau de bord et en petit dans Depot manuel. Couleurs
   prises aux variables du theme (clair et sombre), jamais en dur. Le bouton
   « Vu » reutilise .btn/.btn-danger. */
.alert-manual { display: flex; gap: 12px; align-items: flex-start; flex-wrap: wrap;
  border: 1px solid var(--rose-200); background: var(--rose-50); color: var(--rose-700);
  border-radius: 14px; padding: 14px 16px; margin-bottom: 16px; }
.alert-manual .alert-manual-txt { flex: 1 1 260px; min-width: 0; }
.alert-manual .alert-manual-title { font-weight: 800; letter-spacing: .01em; }
.alert-manual .alert-manual-sub { color: var(--rose-600); font-size: 14px; margin-top: 2px; }
.alert-manual-sm { padding: 10px 12px; margin-bottom: 12px; gap: 10px; }
.alert-manual-sm .alert-manual-title { font-size: 13px; }
.alert-manual-sm .alert-manual-sub { font-size: 13px; }

/* Verification d'identite du joueur : encadre vert avec le nom du compte, comme
   la reference (icone + nom en capitales + ID du joueur, puis la mention). */
.idcheck { display: flex; gap: 12px; align-items: center; border: 1px solid var(--emerald-200);
  background: var(--emerald-50); border-radius: 16px; padding: 14px 16px; }
.idcheck .idc-ico { flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; border-radius: 50%; background: rgba(34, 160, 82, .16);
  color: var(--emerald-700); }
.idcheck .idc-name { font-weight: 700; letter-spacing: .02em; color: var(--emerald-800); }
.idcheck .idc-id { color: var(--emerald-700); opacity: .85; }
.ussd { font-family: var(--mono); font-size: 18px; letter-spacing: .08em; background: var(--brand-800);
  color: #fff; padding: 12px 14px; border-radius: 12px; word-break: break-all; }
.code-box { font-family: var(--mono); font-size: 22px; letter-spacing: .3em; text-align: center;
  padding: 14px; border: 2px dashed var(--slate-300); border-radius: 14px; }
.spinner { width: 22px; height: 22px; border-radius: 50%; border: 3px solid var(--slate-200);
  border-top-color: var(--brand-600); animation: spin .8s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
.center-screen { min-height: 70vh; display: flex; align-items: center; justify-content: center; flex-direction: column; gap: 12px; }

/* ---------- toasts ---------- */
#toasts { position: fixed; z-index: 90; left: 0; right: 0; bottom: 96px; display: flex;
  flex-direction: column; align-items: center; gap: 8px; pointer-events: none; padding: 0 12px; }
.toast { background: var(--brand-800); color: #fff; padding: 11px 15px; border-radius: 12px;
  font-size: 14px; font-weight: 500; box-shadow: var(--shadow-lg); max-width: 520px; animation: pop .18s ease; }
.toast.success { background: var(--emerald-700); } .toast.error { background: var(--rose-700); }
.toast.warning { background: var(--amber-600); }
@keyframes pop { from { transform: translateY(8px); opacity: 0; } }

/* ---------- veille de l'administration : pop-up en HAUT de l'ecran ---------- */
/* Un message client ou une demande de depot/retrait qui arrive s'annonce ici,
   au-dessus de tout, et reste visible une quinzaine de secondes. Le fond suit le
   theme (var(--surface-glass)) : la nuit le pop-up est bleu nuit, pas blanc. */
#alertes { position: fixed; z-index: 96; left: 0; right: 0; display: flex;
  flex-direction: column; align-items: center; gap: 8px; pointer-events: none;
  padding: 0 12px; top: 10px; }
.alerte { pointer-events: auto; width: 100%; max-width: 460px; display: flex; gap: 11px;
  align-items: flex-start; padding: 11px 13px; border-radius: 14px;
  background: var(--surface-glass); backdrop-filter: blur(14px) saturate(1.3);
  border: 1px solid var(--slate-200); border-left: 4px solid var(--brand-600);
  box-shadow: 0 18px 40px -18px rgba(26, 22, 23, .45); animation: fx-alerte .3s var(--fx-ease) both; }
.alerte.sms { border-left-color: var(--sky-500); }
.alerte.dep { border-left-color: var(--emerald-700); }
.alerte.ret { border-left-color: var(--amber-500); }
.alerte .a-ico { flex: 0 0 auto; width: 34px; height: 34px; border-radius: 10px;
  display: flex; align-items: center; justify-content: center;
  background: var(--brand-50); color: var(--brand-600); }
.alerte.sms .a-ico { background: var(--sky-50); color: var(--sky-700); }
.alerte.dep .a-ico { background: var(--emerald-50); color: var(--emerald-700); }
.alerte.ret .a-ico { background: var(--amber-50); color: var(--amber-700); }
.alerte .a-titre { font-size: 13.5px; font-weight: 650; line-height: 1.25; color: var(--slate-900); }
.alerte .a-texte { font-size: 12.5px; color: var(--slate-600); margin-top: 2px;
  overflow: hidden; text-overflow: ellipsis; display: -webkit-box;
  -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.alerte .a-quand { font-size: 11px; color: var(--slate-400); margin-top: 3px; }
@keyframes fx-alerte { from { opacity: 0; transform: translateY(-14px) scale(.98); } to { opacity: 1; transform: none; } }

/* ---------- admin ---------- */
/* Coquille reprise de la reference (embmoney) : barre laterale de 256 px a
   gauche (marque en haut, menu au milieu, carte de compte + bascule
   clair/sombre en bas), zone de contenu ou vit l'en-tete de page (titre 24 px
   + sous-titre gris 14 px, poses par mountPageHead), et barre du haut reservee
   au TELEPHONE (hamburger, marque, cloche, rond d'initiale).
   L'entree active prend le plein de --brand-600, comme la reference.

   =====================================================================
   COULEURS DU PANNEAU : CELLES DE LA MAISON, ET DEPENDANTES DU THEME
   =====================================================================
   La coquille est celle de la reference, la PALETTE est celle de la maison.
   La coquille SUIT LE THEME, comme le reste du panneau (25/09/2026 : le
   patron travaillait en clair et voyait une barre laterale noire) :
     - MODE CLAIR (defaut, pas de data-theme="dark" sur <html>) : barre
       laterale BLANCHE (var(--surface)) detachee du contenu par une bordure
       droite var(--slate-200) — le contenu est blanc lui aussi ; libelles du
       menu var(--slate-700), icones de la meme couleur, survol
       var(--slate-100), entree ACTIVE = plein de --brand-600, texte blanc,
       avec son ombre propre (0 8px 18px -10px rgba(0,0,0,.9)) ; sous-titre de
       la marque var(--slate-500) ; carte de compte var(--slate-50) bordee
       var(--slate-200), pseudo var(--slate-900), role var(--slate-500) ;
       bouton Deconnexion var(--surface) borde var(--slate-200), texte
       var(--slate-700) ; liens du pied var(--slate-600) sur un filet
       var(--slate-200) ; barre du haut mobile var(--surface), filet bas
       var(--slate-200), icones var(--slate-700) ; barre du bas
       var(--surface-glass) (blanc a 97 %), filet haut var(--slate-200),
       libelles var(--slate-600), trait et icone active var(--brand-600) ;
     - MODE SOMBRE : rendu INCHANGE (barre laterale indigo nuit, textes
       blancs translucides, barre du haut indigo nuit, barre du bas indigo nuit a
       97 %). Tout est regroupe dans le bloc « coquille de l'admin : mode
       sombre » plus bas : il ne reste donc AUCUNE couleur sombre en dur dans
       les regles claires, et la bascule de theme suffit a tout changer.
     - accent : celui de :root, rien a redefinir ici — clair --brand-500
       #3A3536 / --brand-600 #262223, nuit --brand-400 #8D8D8F.
   Aucune variable de palette n'est posee sur body.admin-app : le panneau suit
   donc exactement l'accent de l'espace client et de la page d'accueil, en
   clair comme en sombre (mode sombre du panneau = celui de
   :root[data-theme="dark"], nos bleus nocturnes).
   Le FOND DU CONTENU en mode clair est BLANC pur (#fff) et non gris : les
   cartes s'y detachent par leur bordure (--ring, 1 px de --slate-200) et leur
   ombre, qui restent en place ; la nuit, le fond general reprend la main. */
body.admin-app { background: #fff; }
:root[data-theme="dark"] body.admin-app { background: var(--slate-50); }
/* Une fenetre du panneau doit passer AU-DESSUS du tiroir mobile : sur
   telephone la barre laterale est en z-index 60 et son voile en 55, alors que
   les fenetres du projet sont en 50. La confirmation « Fermer la session
   administrateur ? » s'affichait donc DERRIERE le menu ouvert (capture du
   27/09/2026) : on appuyait sur Deconnexion et le menu restait la, ouvert,
   sans qu'aucune fenetre ne se voie. Les toasts (90) et les alertes (96)
   restent au-dessus. */
body.admin-app .modal { z-index: 80; }
.admin-shell { display: flex; min-height: 100vh; }
.admin-side { width: 256px; flex: 0 0 256px; background: var(--surface); color: var(--slate-900);
  border-right: 1px solid var(--slate-200); padding: 16px; position: sticky; top: 0;
  height: 100vh; overflow-y: auto; display: flex; flex-direction: column; }
/* a. marque : logo + nom + « Administration » en petites majuscules espacees */
.admin-side-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px;
  margin-bottom: 32px; }
.admin-side .cx-name { font-size: 17px; color: var(--slate-900); }
.admin-side-sub { font-size: 10.5px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .12em; color: var(--slate-500); }
/* b. le menu occupe le milieu (le pied, pousse par margin-top:auto, reste en bas) */
.admin-nav { display: flex; flex-direction: column; gap: 4px; }
.admin-side a { display: flex; align-items: center; gap: 10px; padding: 10px 12px; border-radius: 12px;
  color: var(--slate-700); font-size: 14px; font-weight: 500; }
.admin-side a:hover { background: var(--slate-100); color: var(--slate-900); }
.admin-side a.active { background: var(--brand-600); color: #fff; font-weight: 600;
  box-shadow: 0 8px 18px -10px rgba(0,0,0,.9); }
/* la marque n'est pas une entree de menu : pas de rembourrage ni de survol */
.admin-side a.cx-brand { padding: 0; border-radius: 0; color: var(--slate-900); }
.admin-side a.cx-brand:hover { background: none; }
/* pastille de compteur a droite d'une entree (rond, fond marque, texte blanc) */
.admin-nav-count[hidden] { display: none; }
.admin-nav-count { margin-left: auto; min-width: 18px; height: 18px; padding: 0 5px; border-radius: 999px;
  background: var(--brand-500); color: #fff; font-size: 11px; font-weight: 700;
  display: inline-flex; align-items: center; justify-content: center; }
/* demarcation entre les FAMILLES du menu (5 familles, voir `group` dans
   static/js/admin.js) : un trait fin de 1 px, encadre d'un espace de 13 px
   (9 px de marge + les 4 px d'ecart normal des entrees), la ou deux entrees
   voisines ne sont separees que par 4 px. Le trait suit la couleur des
   bordures du projet : --slate-200 en clair, --slate-300 la nuit (la barre
   laterale passe alors sur --night). */
.admin-nav-sep { display: block; height: 1px; flex: 0 0 auto;
  background: var(--slate-200); margin: 9px 6px; }
:root[data-theme="dark"] .admin-nav-sep { background: var(--slate-300); }
/* c. pied de la barre : carte de compte, puis bascule et retour au site */
.admin-foot { margin-top: auto; padding-top: 16px; display: flex; flex-direction: column; gap: 12px; }
.admin-acc { background: var(--slate-50); border: 1px solid var(--slate-200);
  border-radius: 12px; padding: 12px; }
.admin-acc-top { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; min-width: 0; }
.admin-acc-avatar { width: 32px; height: 32px; border-radius: 50%; flex: 0 0 auto; background: var(--brand-600);
  color: #fff; font-weight: 800; font-size: 14px; display: inline-flex; align-items: center;
  justify-content: center; }
.admin-acc-name { font-size: 14px; font-weight: 700; color: var(--slate-900); }
.admin-acc-role { font-size: 11px; color: var(--slate-500); text-transform: uppercase;
  letter-spacing: .06em; }
.admin-acc-out { width: 100%; justify-content: center; background: var(--surface);
  color: var(--slate-700); border: 1px solid var(--slate-200); }
.admin-foot-links { display: flex; flex-direction: column; gap: 2px;
  border-top: 1px solid var(--slate-200); padding-top: 10px; }
/* liens du pied (Mode sombre / Notifications / Retour au site) : plus discrets
   que les entrees du menu ; leur version nuit est dans le bloc sombre plus bas */
.admin-foot-links a { color: var(--slate-600); }
/* PLUS DE BARRE DE NAVIGATION EN BAS (retiree le 28/09/2026, demande du client).
   Sur telephone, la navigation passe par le hamburger de la barre du haut, qui
   ouvre la barre laterale complete : une seule liste d'entrees a tenir a jour,
   et plus de 84 px reserves en bas de chaque ecran. */
/* voile de la barre laterale : mobile uniquement. Fond noir translucide a
   70 % + flou de 4 px (corrige un vrai bug : la regle de base pose
   « display: none » et la media query ne le relevait pas, le contenu restait
   donc eclatant derriere le tiroir ouvert) ; un appui dessus le referme. */
.admin-back { display: none; }
.admin-back[hidden] { display: none; }
.admin-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
/* l'en-tete de page vit DANS le contenu (titre 24 px, sous-titre gris 14 px) */
.page-head { margin-bottom: 24px; }
.page-head-title { font-size: 24px; font-weight: 600; letter-spacing: -.02em; color: var(--slate-900);
  margin: 0 0 4px; }
.page-head-sub { font-size: 14px; color: var(--slate-500); margin: 0; }
.admin-body { padding: 32px; }
/* barre du haut : TELEPHONE uniquement (voir la media query plus bas) */
.admin-topbar { display: none; }
.admin-topbar-name { font-size: 17px; font-weight: 800; color: var(--slate-900); }
.admin-topbar .cx-logo { width: 34px; height: 34px; border-radius: 10px; }
.admin-topbar .cx-ico { color: var(--slate-700); }
.admin-topbar .cx-ico:hover { background: var(--slate-100); color: var(--slate-900); }
/* =====================================================================
   COQUILLE DE L'ADMIN : MODE SOMBRE (rendu INCHANGE)
   Tout ce qui etait pose en dur (barre laterale indigo nuit, textes
   blancs translucides, barre du haut indigo nuit, barre du bas indigo nuit a
   97 %) est regroupe ICI. Les regles claires ci-dessus n'en gardent aucune
   trace : il suffit de poser data-theme="dark" sur <html> pour repasser
   toute la coquille en bleu nuit. La disposition (256 px, media queries)
   n'est pas touchee.
   ===================================================================== */
:root[data-theme="dark"] .admin-side { background: var(--night); color: #fff;
  border-right-color: rgba(255,255,255,.08); }
:root[data-theme="dark"] .admin-side .cx-name,
:root[data-theme="dark"] .admin-side a.cx-brand { color: #fff; }
:root[data-theme="dark"] .admin-side-sub { color: rgba(255,255,255,.55); }
:root[data-theme="dark"] .admin-side a { color: rgba(255,255,255,.72); }
:root[data-theme="dark"] .admin-side a:hover { background: rgba(255,255,255,.08); color: #fff; }
/* l'entree active garde son texte BLANC plein (plus clair que le repos) */
:root[data-theme="dark"] .admin-side a.active { color: #fff; }
/* la marque n'a jamais de pave de survol, en clair comme la nuit */
:root[data-theme="dark"] .admin-side a.cx-brand:hover { background: none; }
:root[data-theme="dark"] .admin-acc { background: rgba(255,255,255,.06);
  border-color: rgba(255,255,255,.10); }
:root[data-theme="dark"] .admin-acc-name { color: #fff; }
:root[data-theme="dark"] .admin-acc-role { color: rgba(255,255,255,.55); }
:root[data-theme="dark"] .admin-acc-out { background: rgba(255,255,255,.10); color: #fff; border: 0; }
:root[data-theme="dark"] .admin-foot-links { border-top-color: rgba(255,255,255,.10); }
:root[data-theme="dark"] .admin-foot-links a { color: rgba(255,255,255,.72); }
:root[data-theme="dark"] .admin-topbar { background: var(--night); color: #fff;
  border-bottom-color: rgba(255,255,255,.08); }
:root[data-theme="dark"] .admin-topbar-name { color: #fff; }
:root[data-theme="dark"] .admin-topbar .cx-ico { color: rgba(255,255,255,.82); }
:root[data-theme="dark"] .admin-topbar .cx-ico:hover { background: rgba(255,255,255,.10); color: #fff; }
.mobile-only { display: none; }
.bars { display: flex; align-items: flex-end; gap: 3px; height: 120px; }
.bars .b { flex: 1 1 0; background: var(--brand-500); border-radius: 4px 4px 0 0; min-height: 2px; opacity: .9; }
.chart-legend { display: flex; gap: 14px; font-size: 12px; color: var(--slate-600); }

/* ---------- landing (theme clair, accents bleu fonce) ---------- */
body.landing { background: var(--dark-bg); color: var(--dark-text); }
.landing-nav { position: sticky; top: 0; z-index: 30; background: rgba(255, 255, 255, .94);
  backdrop-filter: blur(10px); border-bottom: 1px solid var(--dark-3); }
.landing-nav .container { display: flex; align-items: center; justify-content: space-between;
  height: 64px; gap: 16px; }
.landing-nav a { color: var(--dark-muted); font-size: 14px; font-weight: 500; }
.landing-nav a:hover { color: var(--brand-700); }
.landing-links { display: flex; gap: 22px; }
.badge-pill { display: inline-flex; align-items: center; gap: 8px; padding: 6px 12px; border-radius: 999px;
  background: var(--brand-50); border: 1px solid var(--brand-200); color: var(--brand-700);
  font-size: 12px; font-weight: 600; }
.hero { padding: 56px 0 48px;
  background: radial-gradient(1000px 420px at 78% -10%, rgba(38, 34, 35, .10), transparent 70%); }
.hero h1 { font-size: clamp(30px, 6vw, 52px); font-weight: 800; letter-spacing: -.03em; color: var(--dark-text); }
.hero h1 em { font-style: normal; color: var(--brand-600); }
.hero p.lead { color: var(--dark-muted); font-size: 17px; max-width: 560px; margin: 18px 0 24px; }
.btn-landing { display: inline-flex; align-items: center; gap: 10px; padding: 14px 22px; border-radius: 12px;
  background: linear-gradient(135deg, var(--brand-600), var(--brand-700)); color: #fff;
  font-weight: 700; box-shadow: 0 16px 40px -18px rgba(38, 34, 35, .75); border: 0; cursor: pointer; }
.stats-row { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px;
  margin-top: 40px; max-width: 560px; }
.stats-row .s { border-left: 2px solid var(--brand-600); padding-left: 12px; }
.stats-row .s b { display: block; font-size: 24px; font-weight: 800; color: var(--brand-700); }
.stats-row .s span { color: var(--dark-muted); font-size: 12px; }
.phone-mock { width: 100%; max-width: 320px; margin-left: auto; background: linear-gradient(160deg, var(--brand-700), var(--brand-900));
  border: 1px solid var(--brand-700); border-radius: 30px; padding: 14px; box-shadow: var(--shadow-lg); }
.phone-mock .screen { background: var(--surface); border-radius: 22px; padding: 14px; color: var(--slate-900); }
.phone-mock .bal { font-size: 26px; font-weight: 800; color: var(--brand-700); }
.pm-row { display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 10px 12px; border-radius: 12px; background: var(--slate-50); border: 1px solid var(--slate-200);
  margin-top: 8px; font-size: 13px; }
.pm-actions { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 12px; }
.pm-actions .b { text-align: center; padding: 12px; border-radius: 12px; font-weight: 700; }
.pm-actions .b.r { background: linear-gradient(135deg, var(--brand-600), var(--brand-700)); color: #fff; }
.pm-actions .b.g { border: 1px solid var(--slate-300); color: var(--brand-700); }
.section { padding: 64px 0; border-top: 1px solid var(--dark-3); }
.section-head { text-align: center; max-width: 640px; margin: 0 auto 40px; }
.section-head .eyebrow { color: var(--brand-600); font-size: 12px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .12em; }
.section-head h2 { font-size: clamp(24px, 4vw, 34px); margin: 12px 0 10px; letter-spacing: -.02em; color: var(--dark-text); }
.section-head p { color: var(--dark-muted); }
.feat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 18px; }
.feat { background: var(--surface); border: 1px solid var(--dark-3); border-radius: var(--radius);
  padding: 22px; transition: border-color .2s ease, transform .2s ease, box-shadow .2s ease; }
.feat:hover { border-color: var(--brand-300); transform: translateY(-2px); box-shadow: var(--shadow); }
.feat .fi { width: 42px; height: 42px; border-radius: 12px; background: var(--brand-50);
  color: var(--brand-600); display: flex; align-items: center; justify-content: center; margin-bottom: 14px; }
.feat h3 { font-size: 17px; margin-bottom: 8px; color: var(--dark-text); }
.feat p { color: var(--dark-muted); font-size: 14px; margin: 0; }
.steps { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 18px; }
.step { background: var(--dark-1); border: 1px solid var(--dark-3); border-radius: var(--radius); padding: 20px; }
.step .n { width: 34px; height: 34px; border-radius: 50%; background: linear-gradient(135deg, var(--brand-600),
  var(--brand-700)); color: #fff; display: flex; align-items: center; justify-content: center; font-weight: 800; margin-bottom: 12px; }
.step h3 { color: var(--dark-text); }
.step p { color: var(--dark-muted); font-size: 14px; }
.quote { background: var(--surface); border: 1px solid var(--dark-3); border-radius: var(--radius); padding: 22px; }
.quote .stars { color: #8A6212; letter-spacing: 2px; margin-bottom: 10px; }
.quote p { font-style: italic; color: var(--slate-700); }
.quote .who { margin-top: 14px; font-size: 13px; color: var(--dark-muted); }
.faq-item { border: 1px solid var(--dark-3); border-radius: 14px; background: var(--surface);
  margin-bottom: 12px; overflow: hidden; }
.faq-q { width: 100%; text-align: left; background: none; border: 0; color: var(--dark-text); padding: 18px;
  font-weight: 600; font-size: 15px; display: flex; justify-content: space-between; gap: 12px; cursor: pointer; }
.faq-a { padding: 0 18px; max-height: 0; overflow: hidden; color: var(--dark-muted);
  transition: max-height .25s ease, padding .25s ease; font-size: 14px; }
.faq-item.open .faq-a { max-height: 420px; padding: 0 18px 18px; }
.dl-band { background: linear-gradient(135deg, var(--brand-50), var(--surface));
  border: 1px solid var(--brand-200); border-radius: var(--radius-lg); padding: 34px; text-align: center; }
.dl-band h2 { color: var(--dark-text); }
.landing-footer { border-top: 1px solid var(--dark-3); padding: 34px 0; color: var(--dark-muted); font-size: 13px; }
.landing-footer a { color: var(--dark-muted); } .landing-footer a:hover { color: var(--brand-700); }

/* ---------- responsive ---------- */
@media (max-width: 900px) {
  .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .admin-side { position: fixed; left: 0; top: 0; z-index: 60; transform: translateX(-104%);
    transition: transform .22s ease; box-shadow: var(--shadow-lg); }
  .admin-side.open { transform: none; }
  /* voile : fond noir translucide a 70 % + flou de 4 px ; un appui en dehors
     de la barre la referme. Il n'etait jamais affiche : la regle de base pose
     « display: none » et la media query ne le relevait pas, donc le contenu
     restait eclatant derriere le tiroir ouvert. */
  .admin-back { display: block; position: fixed; inset: 0; z-index: 55;
    background: rgba(4, 4, 5, .7);
    backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px); }
  .admin-back[hidden] { display: none; }
  /* sur telephone, la barre du haut reprend son role : fond du theme
     (blanc en clair, indigo nuit la nuit — voir le bloc sombre plus
     haut) ; hamburger + marque + cloche + rond d'initiale */
  .admin-topbar { display: flex; align-items: center; justify-content: space-between; gap: 10px;
    position: sticky; top: 0; z-index: 40; background: var(--surface); color: var(--slate-900);
    border-bottom: 1px solid var(--slate-200);
    padding: calc(10px + env(safe-area-inset-top)) 14px 10px; }
  /* La barre du bas n'existe plus : le contenu descend jusqu'au bord, avec
     seulement de quoi ne pas passer SOUS la barre de gestes du telephone. */
  .admin-body { padding: 16px; padding-bottom: calc(16px + env(safe-area-inset-bottom)); }
  .page-head { margin-bottom: 20px; }
  .mobile-only { display: inline-flex; }
  .desk-only { display: none; }
}
@media (max-width: 640px) {
  .grid-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .hide-sm { display: none; }
  .hero { padding: 34px 0; }
  .section { padding: 44px 0; }
}

/* ---------- iPad et grands ecrans : aligner la coquille cliente -------------
   Sur un iPad, la barre du bas etait fixe de bord a bord : les six entrees
   partaient dans les coins, tres loin du contenu qui, lui, reste dans une
   colonne de 720 px. L'en-tete passait sous la barre d'etat (heure et batterie
   affichees par-dessus la page) et debordait de 16 px de chaque cote par rapport
   aux cartes (colonne de 720 px, padding a l'exterieur).
   Trois corrections, et rien qui change sur telephone (<= 720 px) :
     1. barre du bas, en-tete et cartes partagent EXACTEMENT les memes bords
        (688 px = 720 - 2 x 16) ;
     2. panneau du compte ancre sur le bord droit des cartes, pas du telephone ;
     3. en-tete et colonne reservent la barre d'etat (env(safe-area-inset-*)).
   Sur telephone, aucun changement : la barre reste pleine largeur. */
@media (min-width: 721px) {
  /* .colonne : 720 px moins 16 px de chaque cote = les cartes de .app-shell */
  /* +40 px : sur iPad, la bande translucide du systeme descend plus bas que la
     barre d'etat (mesure du 25/09/2026 : un texte a 27 px du haut sort a
     191/255 de gris — lave — alors qu'un bord net a 74 px est intact ; l'inset
     ne vaut que ~36 px). On place donc le contenu a ~76 px du haut. */
  .topbar {
    padding-left: 0; padding-right: 0;
    padding-top: calc(40px + env(safe-area-inset-top));
  }
  .cx-top {
    padding-left: calc(16px + env(safe-area-inset-left));
    padding-right: calc(16px + env(safe-area-inset-right));
  }
  .app-shell {
    padding-left: calc(16px + env(safe-area-inset-left));
    padding-right: calc(16px + env(safe-area-inset-right));
  }
  .bottomnav {
    left: 50%; right: auto; margin-left: -344px; width: 688px;
    max-width: calc(100% - 32px); border-radius: var(--radius-lg) var(--radius-lg) 0 0;
    /* sur ordinateur la barre est bornee : elle garde son bord haut arrondi et son
       trait fin — le telephone fait desormais pareil (30/09/2026). */
    border-top: 1px solid var(--slate-200);
    padding-left: env(safe-area-inset-left); padding-right: env(safe-area-inset-right);
  }
  /* panneau du compte : bord droit aligne sur celui des cartes (420 px de large,
     donc bord gauche a 420 - 344 = 76 px a gauche du centre). Le haut suit
     l'en-tete : inset + 40 px de marge + 60 px de haut d'en-tete + 2 px. */
  .cx-acc { top: calc(102px + env(safe-area-inset-top)); left: 50%; right: auto;
    width: 420px; max-width: 100%; margin-left: -76px; }
  /* panneau lateral : sa marque descend au meme niveau que celle de l'en-tete
     de l'appli (40 px sous la barre d'etat), au lieu de coller au bord. */
  .sd-head { padding-top: 40px; }
}

/* ---------- tableau de bord sur telephone : des cartes separees --------------
   Chaque chiffre devient une petite carte ARRONDIE, bordee, avec un petit espace
   entre elles : les champs sont separes et se lisent un par un (la version bureau
   garde ses gros paves). Rien ne change sur ordinateur. */
@media (max-width: 700px) {
  .kpi-grid { display: block; }
  /* Chaque champ : carte arrondie, fond legerement teinte (pour la detacher du
     fond de page), bordure franche et un peu plus d'air entre elles. */
  .kpi-grid .kpi { background: var(--brand-50); box-shadow: 0 0 0 1px var(--slate-300);
    border-radius: 14px; padding: 12px 14px; margin-bottom: 13px; display: grid;
    grid-template-columns: minmax(0, 1fr) auto; align-items: baseline; column-gap: 12px; }
  .kpi-grid .kpi:last-child { margin-bottom: 0; }
  .kpi-grid .kpi .k-label { grid-column: 1; font-size: 10.5px; line-height: 1.3; }
  .kpi-grid .kpi .k-value { grid-column: 2; text-align: right; font-size: 19px; margin-top: 0;
    white-space: nowrap; }
  .kpi-grid .kpi .k-sub { grid-column: 1 / -1; font-size: 11.5px; margin-top: 4px; }
  /* la carte mise en avant : meme forme, bordure de marque */
  .kpi-grid .kpi.highlight { box-shadow: 0 0 0 2px var(--brand-500); }
  .tabs.dash-tabs { overflow-x: auto; -webkit-overflow-scrolling: touch; flex-wrap: nowrap; }
  /* En-tete du tableau de bord : les filtres et le bouton sur UNE ligne (le
     bouton passait a la ligne, la periode en dessous : trois lignes avant le
     premier chiffre). Les filtres defilent, le bouton reste au bout. */
  .dash-head { flex-wrap: nowrap; gap: 8px; }
  .dash-head .dash-tabs { flex: 1 1 auto; min-width: 0; }
  .dash-head .btn { flex: 0 0 auto; padding: 8px 10px; }
  .dash-head .tab { padding: 7px 11px; font-size: 12.5px; white-space: nowrap; }
  /* En-tete de l'admin sur telephone : la barre sombre reste compacte (icones
     plus serrees) et le titre de page, dans le contenu, redescend un peu, pour
     que les titres longs ne poussent rien hors de l'ecran. */
  .admin-topbar { padding: calc(8px + env(safe-area-inset-top)) 12px 8px; }
  .admin-topbar .cx-actions { gap: 2px; }
  .admin-topbar .cx-ico { width: 34px; height: 34px; border-radius: 10px; }
  .admin-topbar .cx-avatar { width: 34px; height: 34px; font-size: 15px; }
  .admin-topbar-name { font-size: 16px; }
  .page-head-title { font-size: 21px; }
}

/* =====================================================================
   ESPACE CLIENT — alignement sur la reference (ref-client-emb.md) :
   carte sombre (fond bleu nuit) de l'accueil et du portefeuille, et
   badges de statut colores (bleu, indigo, ambre, gris, orange, violet,
   rose, emeraude, marque) utilises par l'historique.
   ===================================================================== */
.hero-dark { background: linear-gradient(150deg, var(--brand-900), var(--night) 62%); }
.badge-sky { background: var(--sky-50); color: var(--sky-700); }
.badge-indigo { background: var(--violet-50); color: var(--violet-700); }
.badge-amber { background: var(--amber-100); color: var(--amber-800); }
.badge-slate { background: var(--slate-100); color: var(--slate-600); }
.badge-orange { background: var(--amber-50); color: var(--amber-700); }
.badge-violet { background: var(--violet-50); color: var(--violet-700); }
.badge-rose { background: var(--rose-50); color: var(--rose-700); }
.badge-emerald { background: var(--emerald-50); color: var(--emerald-700); }
.badge-brand { background: var(--brand-50); color: var(--brand-700); }

/* =====================================================================
   CIRCUITS DEPOT / RETRAIT — barre d'etapes et blocs repliables
   (reference : « Pays & bookmaker … Confirmation », « Comment faire ? »).
   ===================================================================== */
/* Adresse du point de vente (etape « Bookmaker » du retrait) : c'est ce que le
   joueur recopie dans SON application bookmaker pour generer son code. Bloc de
   la reference — titre en petites majuscules precedees d'une punaise, puis les
   lignes Rue / Ville — dans nos couleurs (le fond et la bordure viennent de
   .soft et .hairline, deja utilises par le panneau). */
.pdv { display: grid; gap: 6px; }
.pdv-t { display: flex; align-items: center; gap: 6px; font-size: 11px; font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase; color: var(--slate-600); }
.pdv-t svg { flex: 0 0 auto; }
.pdv-l { font-size: 13px; color: var(--slate-900); }
.pdv-k { color: var(--slate-600); }
.pdv-v { font-weight: 700; }
/* Barre des etapes, presentee EXACTEMENT comme la reference : cercles relies par
   un trait, libelle SOUS chaque cercle. L'etape faite est une pastille pleine
   avec une coche blanche ; l'etape en cours est un cercle blanc avec un anneau
   de la couleur de la marque et un halo doux, son libelle en gras. Reparties
   equitablement, les cinq tiennent sur un ecran etroit. */
.stepbar { display: flex; align-items: flex-start; padding: 6px 0 14px; }
.stepbar .s { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; align-items: center;
  gap: 6px; position: relative; color: var(--slate-400); font-size: 10px; font-weight: 600; }
.stepbar .s::before { content: ''; position: absolute; top: 13px; left: -50%; width: 100%;
  height: 3px; border-radius: 2px; background: var(--slate-200); }
.stepbar .s:first-child::before { display: none; }
.stepbar .s .n { width: 28px; height: 28px; border-radius: 50%; background: var(--surface);
  color: var(--slate-400); border: 2px solid var(--slate-200); display: inline-flex;
  align-items: center; justify-content: center; font-size: 12px; font-weight: 700;
  position: relative; z-index: 1; }
.stepbar .s .lb { font-size: 10px; line-height: 1.15; text-align: center; }
.stepbar .s.done .n { background: var(--brand-600); border-color: var(--brand-600); color: #fff; }
.stepbar .s.done::before { background: var(--brand-600); }
.stepbar .s.on .n { border-color: var(--brand-600); color: var(--brand-700);
  box-shadow: 0 0 0 4px var(--brand-50); }
.stepbar .s.on .lb { color: var(--slate-900); font-weight: 700; }
.stepbar .s.on { color: var(--brand-700); }
.stepbar .s.on .n { background: var(--brand-600); color: #fff; }
.stepbar .s.done { color: var(--emerald-700); }
.stepbar .s.done .n { background: var(--emerald-600); color: #fff; }
.fold { border: 1px solid var(--slate-200); border-radius: 14px; background: var(--surface); }
.fold > summary { cursor: pointer; padding: 12px 14px; font-weight: 600; font-size: 14px; display: flex;
  align-items: center; justify-content: space-between; gap: 10px; list-style: none; }
.fold > summary::-webkit-details-marker { display: none; }
.fold[open] > summary { border-bottom: 1px solid var(--slate-100); }
.fold-bd { padding: 12px 14px; }
/* pastille cliquable (IDs joueurs enregistres) */
.pill { border: 0; cursor: pointer; font: inherit; }

/* =====================================================================
   ACCUEIL CLIENT — reproduction de la capture de reference (EMB Money)
   avec nos couleurs : l'indigo de la marque remplace leur rouge.
   Fond blanc bleute, en-tete clair, carte hero sombre, deux gros ronds
   Depot / Retrait, bloc reseaux sociaux, barre du bas a 6 entrees avec un
   bouton WhatsApp rond flottant au centre.
   ===================================================================== */
:root { --hero-id: #8D8D8F; }              /* pseudo affiche sur la carte sombre */
:root[data-theme="dark"] { --hero-id: #F0ECED; }

/* fond de page de l'espace client : blanc bleute tres clair (pas de blanc pur) */
body.client-app { background: var(--brand-50); }
:root[data-theme="dark"] body.client-app { background: var(--slate-50); }

/* ---------- en-tete : logo, marque, cloche + pastille, initiale ---------- */
.cx-top { max-width: 720px; margin: 0 auto; display: flex; align-items: center;
  justify-content: space-between; gap: 10px; }
.cx-brand { display: flex; align-items: center; gap: 10px; min-width: 0; }
.cx-logo { width: 40px; height: 40px; border-radius: 12px; flex: 0 0 auto; overflow: hidden;
  background: var(--brand-800); display: flex; align-items: center; justify-content: center; }
.cx-logo img { width: 100%; height: 100%; object-fit: cover; }
.cx-name { font-size: 19px; font-weight: 800; letter-spacing: -.02em; color: var(--slate-900);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cx-actions { display: flex; align-items: center; gap: 4px; flex: 0 0 auto; }
.cx-ico { position: relative; width: 36px; height: 36px; border-radius: 999px; border: 0; cursor: pointer;
  background: transparent; color: var(--slate-700); display: inline-flex; align-items: center;
  justify-content: center; }
.cx-ico:hover { background: var(--brand-100); }
/* pastille rouge du nombre de notifications non lues (masquee si vide) */
.cx-count { position: absolute; top: -1px; right: -1px; min-width: 19px; height: 19px; padding: 0 5px;
  border-radius: 999px; background: var(--rose-600); color: #fff; font-size: 10px; font-weight: 700;
  line-height: 1; display: inline-flex; align-items: center; justify-content: center; }
.cx-count:empty { display: none; }
/* rond plein avec l'initiale du pseudo, cliquable vers « Mon compte » */
.cx-avatar { width: 38px; height: 38px; border-radius: 50%; background: var(--brand-600); color: #fff;
  font-weight: 800; font-size: 17px; display: inline-flex; align-items: center; justify-content: center;
  flex: 0 0 auto; }

/* ---------- carte hero sombre ---------- */
.cx-hero { position: relative; overflow: hidden; border-radius: var(--radius-lg); padding: 18px;
  color: #fff; background: linear-gradient(150deg, var(--brand-900), var(--night) 62%);
  box-shadow: 0 22px 50px -26px rgba(26, 22, 23, .8); }
/* halo de lumiere colore derriere la carte (comme la reference) */
.cx-hero::after { content: ''; position: absolute; top: -45%; right: -18%; width: 250px; height: 250px;
  border-radius: 50%; pointer-events: none;
  background: radial-gradient(circle, rgba(141, 141, 143, .5), transparent 68%); }
:root[data-theme="dark"] .cx-hero { background: linear-gradient(150deg, #332E2F, #262223 66%);
  box-shadow: 0 22px 50px -30px #000, 0 0 0 1px var(--slate-200); }
:root[data-theme="dark"] .cx-hero::after {
  background: radial-gradient(circle, rgba(240, 236, 237, .38), transparent 68%); }
/* pastille arrondie bordee : nom de la marque */
.cx-pill { position: relative; z-index: 1; display: inline-flex; align-items: center; padding: 5px 14px;
  border-radius: 999px; border: 1px solid rgba(255, 255, 255, .3); background: rgba(255, 255, 255, .07);
  font-size: 13px; font-weight: 600; }
.cx-hello-row { position: relative; z-index: 1; display: flex; align-items: center;
  justify-content: space-between; gap: 12px; margin-top: 14px; }
.cx-hello { font-size: 22px; font-weight: 800; letter-spacing: -.02em; min-width: 0; overflow-wrap: anywhere; }
.cx-hello b { color: var(--hero-id); }
/* bouton carre blanc arrondi : copier le nom d'utilisateur */
.cx-copy { flex: 0 0 auto; width: 46px; height: 46px; border-radius: 14px; border: 0; cursor: pointer;
  background: #fff; color: var(--slate-900); display: inline-flex; align-items: center;
  justify-content: center; }
.cx-copy:hover { filter: brightness(.95); }
/* La nuit, ce carre blanc devenait la source la plus lumineuse de l'ecran, et son
   icone disparaissait : `--slate-900` passe au blanc casse en mode sombre, donc le
   dessin se noyait dans le fond blanc. Meme forme, meme taille, meme place — on le
   pose en verre translucide, comme la pastille de la marque juste au-dessus. */
:root[data-theme="dark"] .cx-copy { background: rgba(255, 255, 255, .12); color: #F0ECED;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .28); }
:root[data-theme="dark"] .cx-copy:hover { background: rgba(255, 255, 255, .2);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .4); filter: none; }
/* grand bouton vert WhatsApp (couleur officielle #25D366) */

/* ---------- (les deux ANCIENNES tuiles Depot / Retrait ont disparu le
   30/09/2026 : elles sont devenues les deux cartes `.cx-acts` / `.cx-act` plus
   bas. Les regles `.cx-rounds` / `.cx-round` / `.cx-round-cir` / `.cx-round-lb`
   ont ete retirees le meme jour, pour ne pas laisser deux dispositions
   concurrentes dans la feuille.) ---------- */

/* ---------- accueil : la question et les deux cartes d'action (30/09/2026) ----
   Squelette repris de l'interface envoyee par le client ce jour-la : la carte du
   haut pose la question (« Que voulez-vous faire ? »), puis Depot et Retrait sont
   deux CARTES cote a cote, entierement teintees, avec leur pastille d'icone
   ronde, leur libelle et leur sous-titre ; la ligne « Messages » vient juste
   dessous. Les COULEURS sont celles de la maison, mais BLEU CLAIR / VERT CLAIR
   depuis le 30/09/2026 (demande du client : « couleur bleu clair pour le depot et
   vert clair pour le bouton retrait », apres un premier passage VERT / ROUGE) : le
   depot prend la famille de la marque (bleu clair 400 -> 500), le retrait la
   famille emerald (600 -> 700). Les jetons --act-dep-* / --act-wd-* sont declares dans :root
   et FIGES (jamais redefinis la nuit) : en clair les deux cartes portent leur
   teinte pleine et une encre blanche, mesures par ui_check 9quinquies. */
.cx-ask { position: relative; z-index: 1; margin-top: 14px; font-size: 26px; font-weight: 800;
  letter-spacing: -.03em; line-height: 1.12; }
.cx-ask-sub { position: relative; z-index: 1; margin-top: 8px; font-size: 13.5px; opacity: .8; }

.cx-acts { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 20px; }
.cx-act { position: relative; display: flex; flex-direction: column; gap: 4px;
  padding: 14px 14px 16px; border-radius: var(--radius-lg); overflow: hidden;
  color: #fff; text-decoration: none; box-shadow: var(--shadow);
  transition: transform .18s var(--fx-ease, ease), box-shadow .18s var(--fx-ease, ease); }
.cx-act-ico { width: 42px; height: 42px; border-radius: 999px; margin-bottom: 10px;
  display: inline-flex; align-items: center; justify-content: center;
  background: rgba(255, 255, 255, .18); }
.cx-act-t { font-size: 19px; font-weight: 800; letter-spacing: -.02em; }
.cx-act-s { font-size: 12.5px; opacity: .88; }
.cx-act-dep { background: linear-gradient(160deg, var(--act-dep-1), var(--act-dep-2)); }
.cx-act-wd { background: linear-gradient(160deg, var(--act-wd-1), var(--act-wd-2)); }
.cx-act-dep .cx-act-s, .cx-act-wd .cx-act-s { opacity: .9; }
.cx-act:hover { box-shadow: var(--shadow-lg); }
.cx-act:active { transform: scale(.98); }

/* la ligne « Messages » : pastille sombre, titre, sous-titre, chevron */
.cx-msg { display: flex; align-items: center; gap: 13px; margin-top: 12px; padding: 12px 14px;
  background: var(--surface); border: 1px solid var(--slate-200); border-radius: var(--radius);
  box-shadow: var(--shadow); color: inherit; text-decoration: none; }
/* La pastille de la ligne « Messages » de l'accueil : ICONE DE LA MARQUE (bleu),
   et non plus l'or des etats (demande du client, 30/09/2026 : « changer l icone de
   la messagerie de depot en bleu »). Teinte claire + encre bleue en clair (9,8:1),
   teinte nuit + bleu clair la nuit (5,1:1) : les deux sont mesurees par ui_check
   9quinquies, donc remettre l'or fait rougir. */
.cx-msg-ico { flex: 0 0 auto; width: 42px; height: 42px; border-radius: 999px;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--brand-50); color: var(--brand-600); }
.cx-msg-txt { display: flex; flex-direction: column; min-width: 0; }
.cx-msg-t { font-size: 15.5px; font-weight: 700; }
.cx-msg-s { font-size: 12.5px; color: var(--slate-500); }
.cx-msg-go { margin-left: auto; display: inline-flex; color: var(--slate-400); }
:root[data-theme="dark"] .cx-msg { border-color: var(--slate-200); }
:root[data-theme="dark"] .cx-msg-ico { background: var(--brand-900); color: var(--brand-400); }

/* ---------- accueil : le suivi en direct (30/09/2026) ------------------------
   Repris du bloc « suivi en direct » de la reference : le type et le montant de
   l'operation, sa reference, son badge d'etat, les trois temps Envoyee / Prise en
   charge / Terminee et le mot du moment (recherche d'un caissier, nom du caissier
   qui traite, ou resultat). Palette de la maison uniquement. */
.cx-suivi { position: relative; margin-top: 14px; padding: 14px; background: var(--surface);
  border: 1px solid var(--slate-200); border-radius: var(--radius-lg); box-shadow: var(--shadow); }
.cx-suivi-hd { display: flex; align-items: center; gap: 11px; }
.cx-suivi-ico { flex: 0 0 auto; width: 38px; height: 38px; border-radius: 12px; display: inline-flex;
  align-items: center; justify-content: center; background: var(--brand-50); color: var(--brand-600); }
.cx-suivi-t { display: block; font-size: 15.5px; font-weight: 700; }
.cx-suivi-ref { display: block; font-size: 11.5px; color: var(--slate-500); }
.cx-steps { display: flex; align-items: flex-start; margin-top: 14px; }
.cx-step { display: flex; flex-direction: column; align-items: center; gap: 6px; min-width: 0; }
.cx-step-rond { width: 26px; height: 26px; border-radius: 999px; display: inline-flex; align-items: center;
  justify-content: center; font-size: 12px; font-weight: 700; background: var(--slate-100);
  color: var(--slate-500); box-shadow: inset 0 0 0 1px var(--slate-200); }
.cx-step.fait .cx-step-rond { background: var(--brand-600); color: #fff; box-shadow: none; }
.cx-step.encours .cx-step-rond { background: var(--surface); color: var(--brand-600);
  box-shadow: inset 0 0 0 2px var(--brand-500); }
.cx-step.ko .cx-step-rond { background: var(--rose-50); color: var(--rose-600);
  box-shadow: inset 0 0 0 1px var(--rose-200); }
.cx-step-lb { font-size: 10.5px; color: var(--slate-500); text-align: center; }
.cx-step.fait .cx-step-lb, .cx-step.encours .cx-step-lb { color: var(--slate-900); font-weight: 600; }
/* le trait entre deux pastilles : pose a hauteur du CENTRE de la pastille (13 px
   moins la demi-epaisseur du trait) */
.cx-step-lien { flex: 1 1 auto; height: 2px; margin: 12px 6px 0; background: var(--slate-200); }
.cx-step-lien.fait { background: var(--brand-500); }
.cx-suivi-msg { display: flex; align-items: center; gap: 8px; margin-top: 12px;
  font-size: 12.5px; color: var(--slate-600); }
.cx-suivi.ok .cx-suivi-msg { color: var(--emerald-700); }
.cx-suivi.ko .cx-suivi-msg { color: var(--rose-700); }
.cx-suivi-go { display: inline-flex; align-items: center; gap: 6px; margin-top: 12px; padding: 9px 14px;
  border-radius: 999px; font-size: 13px; font-weight: 600; text-decoration: none;
  color: var(--brand-600); background: var(--brand-50); }
:root[data-theme="dark"] .cx-suivi-go { color: var(--brand-300); }
/* Le bouton qui FERME la demande de suivi (30/09/2026, demande du client) : meme
   famille visuelle que le bouton de copie de la carte du haut (gris clair en clair,
   voile blanc la nuit), en plus petit. */
.cx-suivi-x { flex: 0 0 auto; width: 30px; height: 30px; padding: 0; border: 0; cursor: pointer;
  border-radius: 999px; background: var(--slate-100); color: var(--slate-500);
  display: inline-flex; align-items: center; justify-content: center; }
.cx-suivi-x:hover { background: var(--slate-200); color: var(--slate-900); }
.cx-suivi-x:active { transform: scale(.94); }
:root[data-theme="dark"] .cx-suivi-x { background: rgba(255, 255, 255, .12); color: #F0ECED; }
:root[data-theme="dark"] .cx-suivi-x:hover { background: rgba(255, 255, 255, .2); }
body.client-app .cx-suivi-x { border-radius: var(--cx-r-sm); }

/* ---------- raccourcis de l'accueil (28/09/2026) -----------------------------
   « Mes IDs » et « Historique » ENCADRENT la paire de tuiles Depot/Retrait :
   une pilule au-dessus, une pilule en dessous, chacune centree. Elles sont
   posees sur les memes fondations que les cartes (verre : fond translucide,
   flou, cerne 1 px, ombre teintee de la marque) pour ne pas jurer avec elles.
   Le lien pointe sur la MEME route que la barre du bas (#/players, #/history) :
   deux chemins vers le meme ecran, pas deux ecrans. */
.cx-racc { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; }
.cx-racc-haut { margin-top: 20px; }
.cx-racc-bas { margin-top: 22px; }
.cx-racc-a { display: inline-flex; align-items: center; gap: 8px; padding: 9px 16px;
  border-radius: 999px; font: inherit; font-size: 13.5px; font-weight: 600;
  color: var(--slate-700); background-color: var(--glass-bg);
  -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-border); box-shadow: var(--shadow); }
.cx-racc-a svg { color: var(--brand-600); }
.cx-racc-a:active { transform: scale(.96); }

/* ---------- reseaux sociaux ---------- */
.cx-social { margin-top: 28px; text-align: center; }
.cx-social-t { font-size: 14px; color: var(--slate-500); }
.cx-social-row { display: flex; justify-content: center; gap: 20px; margin-top: 14px; }
.cx-soc { width: 54px; height: 54px; border-radius: 50%; background: var(--surface);
  border: 1px solid var(--slate-200); display: flex; align-items: center; justify-content: center;
  color: var(--slate-900); box-shadow: var(--shadow); }

/* Le libelle de la PILULE (30/09/2026) : une seule ligne, jamais coupee. Sa
   taille suit celle de l'entree (13,5 px, posee plus haut). Le petit trait de la
   marque au-dessus de l'entree active a disparu : la pilule teintee suffit. */
.bottomnav .item span { letter-spacing: -.02em; max-width: 100%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* --------------------------------------------- panneau du compte (avatar)
   Feuille ancree en haut a droite, ouverte par le rond d'initiale : infos du
   compte, entrees secondaires, puis « Deconnexion » — comme la reference. */
.cx-acc-back { position: fixed; inset: 0; background: rgba(26, 22, 23, .34); z-index: 70; }
.cx-acc-back[hidden] { display: none; }
/* Panneau du compte, REDUIT et ancre au cote droit (maquette du 27/09/2026) : il
   ne couvre plus toute la largeur, l'ecran reste visible derriere a gauche.
   `left: auto` + une largeur en pourcentage le collent au bord droit. */
.cx-acc { position: fixed; z-index: 71; top: 68px; right: 10px; left: auto;
  width: min(58%, 330px);
  background: var(--surface); color: inherit; border-radius: var(--radius-lg);
  box-shadow: 0 22px 55px -18px rgba(26, 22, 23, .55); overflow: hidden;
  animation: cxAccIn .16s ease-out; }
.cx-acc[hidden] { display: none; }
@keyframes cxAccIn { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: none; } }
.cx-acc-head { padding: 12px 15px 11px; border-bottom: 1px solid var(--slate-100); }
.cx-acc-row { display: flex; align-items: center; gap: 10px; width: 100%; padding: 13px 15px;
  background: none; border: 0; text-align: left; cursor: pointer;
  font: inherit; font-size: 14px; color: inherit; }
/* un libelle long (« Conditions d'utilisation ») ne doit pas deborder du panneau
   etroit : il se coupe proprement. */
.cx-acc-row span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cx-acc-row svg { flex: none; }
.cx-acc-row + .cx-acc-row { border-top: 1px solid var(--slate-100); }
.cx-acc-row:active { background: var(--brand-50); }
.cx-acc-row.danger { color: var(--rose-600); }
.cx-acc-sep { height: 8px; background: var(--slate-50); border-top: 1px solid var(--slate-100); }

/* ==========================================================================
   Tchat (modele Telegram, 26/09/2026)
   La carte sombre du haut de l'accueil est l'entree du chat (nom du service,
   « En ligne » + point vert, apercu du dernier message, compteur de non lus).
   L'ecran de discussion suit Telegram : en-tete en pastille (fleche retour,
   avatar, nom, statut), pastille de jour, messages recus en blanc a gauche,
   messages envoyes en vert pale a droite avec l'heure et les deux coches,
   barre du bas en pastille (smiley, « Message », trombone) et rond bleu qui
   enregistre un message vocal. Les couleurs vivent dans des variables pour que
   le mode sombre les reprenne (fond sombre, bulles sombres).
   ========================================================================== */
.cx-chat { display: block; color: #fff; }
.cx-chat-top { position: relative; z-index: 1; display: flex; align-items: center; gap: 10px; }
.cx-chat-nom { font-size: 17px; font-weight: 800; letter-spacing: -.01em; }
.cx-chat-nb { margin-left: auto; min-width: 22px; height: 22px; padding: 0 7px; border-radius: 999px;
  background: #fff; color: var(--brand-900); font-size: 12px; font-weight: 800;
  display: inline-flex; align-items: center; justify-content: center; }
.cx-chat-statut { position: relative; z-index: 1; display: flex; align-items: center; gap: 6px;
  margin-top: 5px; font-size: 12.5px; color: #B9B3B4; }
.cx-chat-bas { position: relative; z-index: 1; display: flex; align-items: center; gap: 10px; margin-top: 12px; }
.cx-chat-apercu { flex: 1; min-width: 0; font-size: 13.5px; color: #D9D4D5;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cx-chat-heure { flex: none; font-size: 11.5px; color: #8D8D8F; }

/* pastille verte « En ligne » : carte de l'accueil et en-tete du tchat */
.tg-point { flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--emerald-500);
  box-shadow: 0 0 0 3px rgba(34, 160, 82, .18); }

.tg { position: fixed; inset: 0; z-index: 60; display: flex; flex-direction: column;
  color: var(--tg-encre); background: var(--tg-fond);
  /* palette Telegram : vert clair (le theme de Serge) et, en mode sombre, la
     palette Telegram sombre. Les motifs du papier peint sont dessines ici
     (le dessin d'origine de Telegram n'est pas copie). */
  /* Fond BLANC du chat du support (demande du 27/09/2026). Le degrade vert du
     papier peint Telegram est retire ; les teintes ci-dessous sont recalees pour
     se detacher sur blanc (une bulle blanche sur fond blanc disparaitrait). */
  --tg-fond: #F0ECED;
  --tg-pastille: rgba(26, 22, 23, .05);
  --tg-encre: #1A1617;
  --tg-recu: #E6E1E2;
  --tg-envoi: #DFF3E3;
  --tg-meta: #5C5657;   /* assombri : sur fond blanc, le gris precedent ne tenait pas 4.5:1 */
  /* L'accent du tchat est celui de la MARQUE : l'ancien bleu de la messagerie
     jurait avec le reste du site. `--tg-accent-bg` est son aplat pale. */
  --tg-accent: var(--brand-600);
  --tg-accent-bg: rgba(38, 34, 35, .12);
  --tg-saisie: #E6E1E2;
  --tg-clavier: #F0ECED;
  --tg-valide: #15803D; }
:root[data-theme="dark"] .tg {
  --tg-fond: linear-gradient(168deg, #1C1819, #1C1819 55%, #1C1819);
  --tg-pastille: rgba(255,255,255,.09);
  --tg-encre: #FFFFFF;
  --tg-recu: #332E2F;
  --tg-envoi: #22A052;
  --tg-meta: #B9B3B4;
  --tg-accent: var(--brand-400);
  --tg-accent-bg: rgba(240, 236, 237, .16);
  --tg-saisie: rgba(255,255,255,.07);
  --tg-clavier: #1C1819; }
/* Le fond de la discussion est UNI, comme la maquette du 27/09/2026 : le papier
   peint a motifs de Telegram (data-URL ci-dessous, conserve juste apres) est
   simplement desactive en supprimant la regle qui suit. */
.tg::before { display: none; }

/* ---- en-tete : bande de la marque, rond du retour, titre en blanc, menu ---- */
/* Demande du 27/09/2026 : la barre du haut passe en BLEU et « Support » s'ecrit
   en BLANC. La bande est pleine largeur. La barre d'etat du telephone, elle, est
   portee par la reserve claire decrite ci-dessus (correction du 27/09/2026) : la
   couleur de l'en-tete ne monte donc plus jusqu'en haut de l'ecran. */
/* ---- bande de la barre d'etat, AU-DESSUS de l'en-tete ---------------------
   La bande du haut (heure, batterie) est peinte avec le FOND DU TCHAT (blanc en
   clair), et non avec le bleu de l'en-tete. Raison (capture de Serge du
   27/09/2026, « le haut du tchat est flou et blanc ») : sur iPad en mode
   application, la barre d'etat du systeme est une bande translucide qui FLoute
   et eclaircit ce qu'elle recouvre ; peinte sur le bleu, elle le lavait et le
   haut du tchat paraissait blanchi, avec une transition floue. Sous un fond
   clair, une bande claire ne se voit plus : le bleu commence donc SOUS la bande.
   La reserve de 40 px sur grand ecran reprend la mesure du 25/09/2026 (la bande
   du systeme descend jusqu'a ~76 px du haut de l'ecran alors que l'inset ne vaut
   que ~36 px). Sur telephone (<= 720 px, inset a 0 dans un onglet) : rien ne
   change, la barre bleue reste collee en haut. */
.tg { padding-top: env(safe-area-inset-top); }
@media (min-width: 721px) { .tg { padding-top: calc(env(safe-area-inset-top) + 40px); } }

.tg-head { flex: none; display: flex; align-items: center; gap: 8px;
  padding: 8px 10px 10px;
  background: var(--brand-600); color: #fff; }
/* Ronds de l'en-tete : BLANC FRANC et bords nets (demande du 27/09/2026 : ils
   paraissaient flous et laiteux). Le verre depoli (backdrop-filter) et l'ombre
   large sont retires : un rond opaque sur le bleu, avec une ombre courte, se
   detache nettement. Le blanc vient de --on-brand (le blanc pose sur la marque),
   donc aucune couleur en dur. */
.tg-back, .tg-rond-blanc { flex: none; width: 46px; height: 46px; border: 0; border-radius: 50%;
  cursor: pointer; display: grid; place-items: center; background: var(--tg-pastille);
  color: var(--tg-encre); box-shadow: 0 1px 3px rgba(10,8,9,.3); }
.tg-back { background: var(--on-brand); color: #1A1617; }
.tg-back svg { transform: rotate(180deg); }
:root[data-theme="dark"] .tg-back { background: rgba(255,255,255,.14); color: var(--tg-encre); }
.tg-back:active, .tg-rond-blanc:active { transform: scale(.94); }
.tg-pill { flex: 1; min-width: 0; display: flex; align-items: center; gap: 10px; height: 46px;
  padding: 0 14px 0 4px; border-radius: 999px; background: var(--tg-pastille);
  backdrop-filter: blur(12px); box-shadow: 0 6px 20px rgba(28,24,25,.16); }
.tg-avatar { flex: none; width: 38px; height: 38px; border-radius: 50%; overflow: hidden;
  background: var(--brand-600); display: grid; place-items: center; }
.tg-avatar img { width: 100%; height: 100%; object-fit: cover; }
.tg-qui { min-width: 0; display: flex; flex-direction: column; }
.tg-nom { font-size: 16px; font-weight: 700; line-height: 1.15;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tg-statut { display: flex; align-items: center; gap: 5px; font-size: 12.5px; color: var(--tg-encre);
  opacity: .7; }

/* ---- ecran de support : en-tete fleche + titre + menu ---------------------
   Maquette du 27/09/2026 : l'en-tete ne porte plus la pastille Telegram mais le
   seul titre de l'ecran. La bande bleue de marque (« Support / L'equipe repond
   ici des que possible. ») a ete supprimee le 27/09/2026 : son bouton de menu
   est remonte dans l'en-tete, a droite du titre, sur la meme pastille ronde que
   la fleche de retour. */
.tg-titre { flex: 1; min-width: 0; font-size: 19px; font-weight: 800; color: #fff;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Meme traitement que la fleche de retour : blanc franc, ombre courte, sans
   verre depoli — les deux ronds doivent avoir exactement le meme aspect. */
.tg-head-plus { flex: none; width: 46px; height: 46px; border: 0; border-radius: 50%;
  cursor: pointer; display: grid; place-items: center;
  background: var(--on-brand); color: #1A1617;
  box-shadow: 0 1px 3px rgba(10,8,9,.3); }
:root[data-theme="dark"] .tg-head-plus { background: rgba(255,255,255,.14); color: var(--tg-encre); }
.tg-head-plus:active { transform: scale(.94); }

/* min-height: 0 est INDISPENSABLE : sans lui, un enfant de colonne flex refuse de
   se reduire sous la taille de son contenu. Quand le clavier monte, le fil poussait
   alors la barre hors de l'ecran au lieu de se reduire et de rester sur le dernier
   message (bug constate le 26/09). */
.tg-fil { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
  display: flex; flex-direction: column; gap: 6px; padding: 2px 10px 10px; }
.tg-jour { display: flex; justify-content: center; margin: 6px 0 2px; }
.tg-jour span { background: var(--slate-100); color: var(--slate-600); font-size: 12px;
  font-weight: 600; padding: 4px 11px; border-radius: 999px; }
:root[data-theme="dark"] .tg-jour span { background: rgba(255,255,255,.1); color: var(--tg-encre); }

.tg-ligne { display: flex; }
.tg-ligne.them { justify-content: flex-start; }
.tg-ligne.me { justify-content: flex-end; }
.tg-ligne.tg-suite { margin-top: -3px; }
.tg-bulle { position: relative; max-width: 82%; padding: 6px 10px 5px; border-radius: 14px;
  background: var(--tg-recu); color: var(--tg-encre); box-shadow: 0 1px 2px rgba(28,24,25,.14); }
.tg-ligne.me .tg-bulle { background: var(--tg-envoi); }
.tg-ligne.them .tg-bulle { border-top-left-radius: 6px; }
.tg-ligne.me .tg-bulle { border-top-right-radius: 6px; }
.tg-texte { font-size: 14.5px; line-height: 1.35; overflow-wrap: anywhere; white-space: pre-wrap; }
.tg-meta { float: right; display: inline-flex; align-items: center; gap: 2px;
  margin: 6px 0 0 10px; font-size: 11px; color: var(--tg-meta); }
.tg-meta svg { width: 14px; height: 14px; }
.tg-meta svg { color: var(--tg-meta); }
.tg-meta.tg-lu svg { color: var(--tg-valide); }
.tg-modif { font-style: italic; opacity: .8; margin-right: 3px; }

/* emoji seul : en grand, sans bulle, l'heure en dessous a droite (Telegram) */
.tg-emoji-seul { display: flex; flex-direction: column; align-items: flex-end;
  max-width: 78%; font-size: 42px; line-height: 1.08; overflow-wrap: anywhere; }
.tg-emoji-seul .tg-meta { float: none; margin: 2px 0 0; }
.tg-emoji-seul .tg-meta svg { color: var(--tg-valide); }

/* citation (« Repondre ») : barre coloree + nom + texte, comme Telegram.
   Demande du 27/09/2026 : la BANDE LATERALE (le trait a gauche du message cite)
   etait verte dans les messages envoyes — elle passe au bleu de la marque, comme
   celle des messages recus : l'identite du site est bleue. */
.tg-cite { display: flex; flex-direction: column; gap: 1px; margin-bottom: 5px; padding: 4px 9px;
  border-left: 3px solid var(--tg-accent); border-radius: 5px; background: var(--tg-accent-bg); }
.tg-cite b { font-size: 12.5px; font-weight: 700; }
.tg-cite span { font-size: 13px; opacity: .86; max-width: 230px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tg-ligne.them .tg-cite { border-left-color: var(--brand-500); background: rgba(58,53,54,.12); }
.tg-ligne.them .tg-cite b { color: var(--brand-600); }
.tg-ligne.me .tg-cite { border-left-color: var(--brand-500); background: rgba(58,53,54,.12); }
.tg-ligne.me .tg-cite b { color: var(--brand-600); }
:root[data-theme="dark"] .tg-ligne.them .tg-cite b { color: #D9D4D5; }
:root[data-theme="dark"] .tg-ligne.me .tg-cite b { color: #D9D4D5; }
:root[data-theme="dark"] .tg-ligne.them .tg-cite,
:root[data-theme="dark"] .tg-ligne.me .tg-cite { border-left-color: var(--brand-400);
  background: rgba(240,236,237,.16); }

.tg-copier { margin-top: 6px; display: inline-flex; align-items: center; gap: 6px; cursor: pointer;
  border: 0; border-radius: 8px; padding: 5px 9px; font: inherit; font-size: 12.5px; font-weight: 600;
  background: var(--tg-accent-bg); color: #3A3536; }
:root[data-theme="dark"] .tg-copier { color: #D9D4D5; }
.tg-valeur { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-weight: 700; }

/* message vocal : bouton d'ecoute, avancement, duree */
.tg-audio { display: flex; align-items: center; gap: 9px; min-width: 186px; }
.tg-play { flex: none; width: 40px; height: 40px; border: 0; border-radius: 50%; cursor: pointer;
  background: var(--tg-saisie); color: var(--tg-accent); display: grid; place-items: center; }
.tg-ligne.me .tg-play { background: rgba(255,255,255,.55); }
.tg-ligne.them .tg-play { background: var(--tg-accent-bg); }
/* forme d'onde : des barres plutot qu'un trait (comme Telegram) */
.tg-piste { flex: 1; display: flex; align-items: center; gap: 2px; height: 22px; }
.tg-barre { width: 2px; border-radius: 2px; background: currentColor; opacity: .28; }
.tg-barre.on { opacity: .85; }
.tg-duree { flex: none; font-size: 12px; color: var(--tg-meta); font-variant-numeric: tabular-nums; }
.tg-bulle-audio { padding-top: 8px; padding-bottom: 8px; }

.tg-vide { flex: 1; display: flex; align-items: center; justify-content: center;
  padding: 24px 26px; text-align: center; font-size: 15px; color: var(--slate-500); }

/* pastille « aller au dernier message », au-dessus de la barre (Telegram) */
.tg-descendre { position: absolute; right: 12px; bottom: calc(78px + env(safe-area-inset-bottom));
  z-index: 2; width: 44px; height: 44px; border: 0; border-radius: 50%; cursor: pointer;
  background: var(--tg-saisie); color: var(--tg-encre); display: grid; place-items: center;
  box-shadow: 0 4px 16px rgba(28,24,25,.22); }

/* panneau d'emojis : onglets en icones, recherche, pave, onglets du bas et
   touche effacer (modele : le panneau de Telegram montre par Serge) */
/* Le panneau d'emojis se deploie a la place du clavier : colle au bas de
   l'ecran, toute la largeur, coins arrondis en haut (comme sur la capture de
   Telegram montree par Serge). Il est place APRES la barre dans le gabarit. */
.tg-emoji { position: relative; z-index: 4; flex: none; margin: 0;
  padding: 6px 10px calc(6px + env(safe-area-inset-bottom));
  border-radius: 16px 16px 0 0; background: var(--tg-clavier);
  box-shadow: 0 -6px 22px rgba(28,24,25,.22); }
/* panneau ouvert : la barre se recolle dessus et perd ses ombres */
.tg-panneau .tg-bar { padding-bottom: 6px; }
.tg-panneau .tg-saisie, .tg-panneau .tg-rond { box-shadow: none; }
.tg-cats { display: flex; gap: 2px; overflow-x: auto; padding: 2px 0 6px;
  border-bottom: 1px solid rgba(127,127,127,.18); }
.tg-cat { flex: none; width: 38px; height: 30px; border: 0; border-radius: 9px; cursor: pointer;
  background: transparent; color: var(--tg-meta); display: grid; place-items: center; }
.tg-cat.on { color: var(--tg-accent); background: var(--tg-accent-bg); }
.tg-cherche { display: flex; align-items: center; gap: 8px; margin: 8px 0 6px; padding: 0 12px;
  height: 38px; border-radius: 999px; background: rgba(127,127,127,.12); color: var(--tg-meta); }
.tg-cherche input { flex: 1; min-width: 0; border: 0; background: transparent; color: var(--tg-encre);
  font: inherit; font-size: 14.5px; outline: none; }
.tg-emos { display: flex; flex-wrap: wrap; gap: 1px; max-height: 212px; overflow-y: auto; padding: 2px 0; }
.tg-emo { border: 0; background: transparent; font-size: 25px; line-height: 1.15; padding: 3px 6px;
  cursor: pointer; border-radius: 10px; }
.tg-emo:active { background: rgba(127,127,127,.18); }
.tg-emo-grand { font-size: 34px; padding: 2px 5px; }
.tg-emo-vide { padding: 14px 8px; font-size: 13.5px; color: var(--tg-meta); text-align: center; }
.tg-onglets { display: flex; align-items: center; gap: 4px; padding: 4px 0 2px;
  border-top: 1px solid rgba(127,127,127,.18); }
.tg-onglet { flex: 1; height: 34px; border: 0; border-radius: 10px; cursor: pointer;
  background: transparent; color: var(--tg-meta); font: inherit; font-size: 13.5px; font-weight: 600; }
.tg-onglet.on { color: var(--tg-accent); background: var(--tg-accent-bg); }
.tg-effacer { flex: none; width: 42px; height: 34px; border: 0; border-radius: 10px; cursor: pointer;
  background: transparent; color: var(--tg-meta); display: grid; place-items: center; }

/* citation en cours de redaction, au-dessus du champ */
.tg-citation { display: flex; align-items: center; gap: 8px; margin: 0 10px 6px;
  padding: 6px 8px 6px 10px; border-radius: 12px; background: var(--tg-saisie); }
.tg-citation .tg-cite { flex: 1; min-width: 0; margin: 0; }

.tg-bar { flex: none; display: flex; align-items: center;
  padding: 7px 10px calc(9px + env(safe-area-inset-bottom)); }
/* Un element marque hidden doit RESTER cache : une regle comme
   « .tg-rec { display: flex } » ecrase le [hidden] du navigateur (bug vu le
   26/09 : la barre d'enregistrement s'affichait en permanence). */
.tg [hidden] { display: none !important; }
.tg-saisie { flex: 1; min-width: 0; height: 54px; border-radius: 999px; display: flex;
  align-items: center; gap: 4px; padding: 0 6px 0 18px; background: var(--tg-saisie);
  box-shadow: 0 3px 14px rgba(28,24,25,.18); }
/* barre d'enregistrement : une ligne d'aide, puis corbeille, forme d'onde en
   direct, chrono et Pause — la disposition de WhatsApp, montree par Serge */
.tg-rec { position: relative; flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px;
  padding: 5px 10px 6px; border-radius: 20px; background: var(--tg-saisie);
  box-shadow: 0 3px 14px rgba(28,24,25,.18); }
/* repere du glissement : la fleche et le cadenas montent avec le doigt */
/* Il flotte AU-DESSUS de la barre : place a l'interieur, il passait sous le
   bouton Pause et ne se voyait pas (constate le 26/09). */
.tg-rec-glisse { position: absolute; right: 18px; bottom: calc(100% + 5px); display: flex;
  flex-direction: column; align-items: center; gap: 0; padding: 4px 7px 5px; border-radius: 14px;
  background: var(--tg-clavier); box-shadow: 0 4px 14px rgba(28,24,25,.26);
  color: var(--tg-accent); opacity: 0; pointer-events: none; transition: opacity .12s linear; }
/* barre en message d'explication (micro refuse par exemple) */
.tg-rec-blocage { background: rgba(163,43,74,.16); }
.tg-rec-blocage .tg-rec-aide { color: var(--tg-encre); white-space: normal; }
.tg-rec-glisse svg { display: block; }
.tg-rec-glisse .tg-glisse-chev svg { transform: rotate(180deg); }
.tg-rec-poubelle { transition: transform .1s ease-out, color .1s linear; }
.tg-rec-ligne { display: flex; align-items: center; gap: 10px; height: 34px; }
.tg-ico { flex: none; width: 38px; height: 38px; border: 0; border-radius: 50%; cursor: pointer;
  background: transparent; color: #8D8D8F; display: grid; place-items: center; }
:root[data-theme="dark"] .tg-ico { color: #B9B3B4; }
.tg-champ { flex: 1; min-width: 0; border: 0; background: transparent; color: var(--tg-encre);
  font: inherit; font-size: 15.5px; outline: none; }
.tg-champ::placeholder { color: var(--tg-meta); }
/* le rond bleu est PLUS GROS que la barre et chevauche la pastille (capture) */
.tg-rond { flex: none; width: 56px; height: 56px; margin-left: 8px; border: 0; border-radius: 50%;
  cursor: pointer; background: var(--brand-600); color: #fff; display: grid; place-items: center;
  box-shadow: 0 10px 22px -8px rgba(38, 34, 35, .65); }
.tg-rond:active { transform: scale(.95); }
.tg-rec-onde { flex: 1; min-width: 0; display: flex; align-items: center; gap: 2px; height: 28px;
  overflow: hidden; color: var(--rose-600); }
.tg-rec-onde i { flex: none; width: 3px; height: 3px; border-radius: 2px; background: currentColor;
  opacity: .8; transition: height .09s linear; }
.tg-rec-pause { flex: none; display: flex; align-items: center; gap: 5px; height: 30px; padding: 0 10px;
  border: 0; border-radius: 999px; cursor: pointer; background: rgba(127,127,127,.16);
  color: var(--tg-encre); font: inherit; font-size: 12.5px; font-weight: 600; }
.tg-rec-pause-on { background: var(--tg-accent-bg); color: var(--tg-accent); }
/* appui long : le rond passe au rouge, et l'aide annonce l'annulation */
.tg-rond-rec { background: var(--rose-600); box-shadow: 0 5px 16px rgba(163,43,74,.45); }
.tg-rec-aide { display: flex; align-items: center; gap: 6px; font-size: 11.5px; color: var(--tg-meta);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tg-rec.tg-annule { background: rgba(163,43,74,.16); }
.tg-rec.tg-annule .tg-rec-poubelle { color: var(--rose-600); transform: scale(1.45); }
.tg-rec.tg-annule .tg-rec-time { opacity: .45; }
.tg-rec-poubelle { transition: transform .12s ease-out, color .12s linear; }
.tg-rec.tg-verrou { background: var(--tg-accent-bg); }
.tg-rec-cadenas { flex: none; color: var(--tg-accent); display: grid; place-items: center;
  animation: tgCadenas .26s ease-out; }

/* ---- appareil photo integre (apercu en direct, comme WhatsApp) ------------ */
.tg-appareil { position: absolute; inset: 0; z-index: 6; display: flex; flex-direction: column;
  background: #0A0809; }
.tg-appareil[hidden] { display: none; }
.tg-ap-haut { position: absolute; top: calc(10px + env(safe-area-inset-top)); left: 12px; right: 12px;
  display: flex; justify-content: space-between; z-index: 2; }
.tg-ap-rond { width: 44px; height: 44px; border: 0; border-radius: 50%; cursor: pointer;
  background: rgba(20,26,34,.62); color: #fff; display: grid; place-items: center; }
.tg-ap-rond.on { background: #FFD27A; color: #1A1A1A; }
/* L'apercu REMPLIT l'ecran (26/09 : Serge ne veut pas des bandes noires). Le
   recadrage reste modere parce que le flux est demande en vraie resolution. */
.tg-ap-video { flex: 1; min-height: 0; width: 100%; object-fit: cover; background: #000; }
.tg-ap-prises { flex: none; display: flex; align-items: center; justify-content: space-between;
  padding: 14px 22px 6px; background: #0A0809; }
.tg-ap-mini { width: 48px; height: 48px; border: 0; border-radius: 14px; cursor: pointer;
  background: rgba(255,255,255,.12); color: #fff; display: grid; place-items: center; }
.tg-ap-prise { width: 74px; height: 74px; border: 4px solid #fff; border-radius: 50%; cursor: pointer;
  background: transparent; display: grid; place-items: center; }
.tg-ap-prise span { display: block; width: 56px; height: 56px; border-radius: 50%; background: #fff; }
.tg-ap-prise-rec span { border-radius: 12px; background: var(--rose-600); }
.tg-ap-onglets { flex: none; display: flex; justify-content: center; gap: 10px;
  padding: 6px 0 calc(12px + env(safe-area-inset-bottom)); background: #0A0809; }
.tg-ap-onglet { border: 0; border-radius: 999px; cursor: pointer; background: transparent;
  color: #D9D4D5; font: inherit; font-size: 14px; font-weight: 600; padding: 7px 16px; }
.tg-ap-onglet.on { background: rgba(255,255,255,.16); color: #fff; }
.tg-ap-chrono { position: absolute; top: calc(16px + env(safe-area-inset-top)); left: 50%;
  transform: translateX(-50%); color: #fff; font-size: 14px; font-variant-numeric: tabular-nums;
  background: rgba(20,26,34,.62); padding: 4px 12px; border-radius: 999px; z-index: 2; }
.tg-ap-chrono[hidden] { display: none; }
/* bulle d'une note video dans le fil */
.tg-video { display: flex; align-items: center; gap: 10px; border: 0; cursor: pointer;
  background: var(--tg-accent-bg); color: var(--tg-accent); border-radius: 12px; padding: 12px 18px; }
.tg-video span { font-size: 13px; font-variant-numeric: tabular-nums; color: var(--tg-encre); }
.tg-vue video { max-width: 96%; max-height: 84%; border-radius: 10px; background: #000; }

/* ---- gestes de l'appui long : mouvements (places avant la section dediee) ---- */
@keyframes tgPulse { 0% { transform: scale(1); } 45% { transform: scale(1.13); } 100% { transform: scale(1); } }
@keyframes tgOnde { 0% { box-shadow: 0 0 0 0 rgba(163,43,74,.5); }
  100% { box-shadow: 0 0 0 15px rgba(163,43,74,0); } }
@keyframes tgPoint { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: .3; transform: scale(.75); } }
@keyframes tgCadenas { 0% { transform: translateY(9px) scale(.7); opacity: 0; }
  100% { transform: translateY(0) scale(1); opacity: 1; } }
@keyframes tgCran { 0% { transform: scale(1); } 45% { transform: scale(1.3); } 100% { transform: scale(1); } }
/* au franchissement du seuil, le cadenas marque le coup */
.tg-rec.tg-verrou .tg-rec-cadenas svg { animation: tgCran .34s ease-out; }
/* l'appui fait pulser le rond et rayonner une onde rouge, le point clignote */
.tg-rond-rec { background: var(--rose-600); animation: tgPulse .42s ease-out, tgOnde 1.5s ease-out infinite; }
.tg-rond-envoi { background: var(--tg-accent); animation: tgPulse .35s ease-out; }
.tg-rond-rec .tg-rec-dot, .tg-rec-dot { animation: tgPoint 1.1s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) {
  .tg-rond-rec, .tg-rond-envoi, .tg-rec-dot, .tg-rec-cadenas { animation: none; }
}
.tg-rec-time { font-size: 14.5px; font-variant-numeric: tabular-nums; color: var(--tg-encre); }

/* feuille « Repondre / Copier », ouverte par un appui long sur un message */
.tg-sheet { position: absolute; inset: 0; z-index: 4; display: flex; align-items: flex-end; }
.tg-sheet[hidden] { display: none; }
.tg-sheet-fond { position: absolute; inset: 0; background: rgba(8,20,16,.38); }
.tg-sheet-card { position: relative; width: 100%; display: flex; flex-direction: column; gap: 4px;
  padding: 12px 12px calc(14px + env(safe-area-inset-bottom)); border-radius: 18px 18px 0 0;
  background: var(--tg-recu); color: var(--tg-encre); box-shadow: 0 -8px 30px rgba(0,0,0,.28); }
.tg-sheet-row { display: flex; align-items: center; gap: 10px; border: 0; border-radius: 12px;
  background: transparent; color: inherit; font: inherit; font-size: 15px; font-weight: 600;
  padding: 13px 10px; text-align: left; cursor: pointer; }
.tg-sheet-row:active { background: rgba(127,127,127,.14); }

/* photo jointe : vignette dans la bulle, ouverte en grand sur un appui */
.tg-bulle-media { padding: 4px 6px 5px; }
.tg-bulle-media .tg-meta { margin-right: 6px; }
.tg-photo { display: block; border: 0; padding: 0; background: transparent; cursor: pointer;
  border-radius: 12px; overflow: hidden; max-width: 260px; }
.tg-photo img { display: block; width: 100%; height: auto; max-height: 320px; object-fit: cover;
  border-radius: 12px; background: rgba(127,127,127,.18); min-height: 90px; }
.tg-vue { position: absolute; inset: 0; z-index: 5; display: flex; align-items: center;
  justify-content: center; background: rgba(6,12,20,.92); }
.tg-vue[hidden] { display: none; }
.tg-vue img { max-width: 96%; max-height: 84%; border-radius: 10px; }
.tg-vue-x { position: absolute; top: calc(10px + env(safe-area-inset-top)); right: 12px;
  width: 44px; height: 44px; border: 0; border-radius: 50%; cursor: pointer;
  background: rgba(255,255,255,.16); color: #fff; display: grid; place-items: center; }
.tg-sheet-row.danger { color: #A32B4A; }
:root[data-theme="dark"] .tg-sheet-row.danger { color: #FF9E9E; }

/* =====================================================================
   SELECTEUR DE LANGUE (01/10/2026) - la pastille « FR / EN » de la reference
   (site.ldmservice.com), posee dans l'en-tete de l'espace client, dans celui
   du visiteur et en haut a droite des ecrans de connexion. Aucune teinte
   figee : jetons et rgba seulement, donc la pastille suit le theme comme le
   reste de la coquille. L'entree ACTIVE se marque par la classe `on` ET par
   `aria-pressed` (l'etat se lit sans la couleur).
   ===================================================================== */
.cx-lang { display: inline-flex; align-items: center; gap: 2px; height: 30px; padding: 0 2px 0 7px;
  border-radius: 999px; border: 1px solid var(--cx-cerne); background: var(--surface);
  color: var(--slate-500); flex: 0 0 auto; }
.cx-lang-b { border: 0; background: transparent; color: inherit; font: inherit; font-size: 11.5px;
  font-weight: 700; letter-spacing: .02em; padding: 0 7px; height: 24px; display: inline-flex;
  align-items: center; justify-content: center; border-radius: 999px;
  cursor: pointer; line-height: 1; }
.cx-lang-b.on { background: var(--brand-600); color: var(--on-brand); }
/* Page GOOGLE ouverte dans le NAVIGATEUR du telephone (elle porte encore la
   pastille de langue) : la page est SOMBRE, la pastille prend donc le meme verre
   translucide que le bouton de recopie de l'accueil. Les ecrans de connexion et
   d'inscription de l'application, eux, ne portent plus QUE le bouton de retour
   (la pastille y a ete retiree le 01/10/2026, le retour ajoute le 03/10/2026 —
   voir `.auth-back` juste apres). */
.auth-lang { position: fixed; top: calc(10px + env(safe-area-inset-top)); right: 12px; z-index: 30; }
.auth-lang .cx-lang { background: rgba(255, 255, 255, .12); border-color: rgba(255, 255, 255, .30);
  color: rgba(255, 255, 255, .82); }
.auth-lang .cx-lang-b.on { background: var(--on-brand); color: var(--brand-700); }
/* BOUTON DE RETOUR des ecrans d'entree (03/10/2026, demande du client :
   « ajoute un bouton de retour en arriere sur l'interface de connexion et
   d'inscription »). Meme habillage que la pastille ci-dessus — la page est sombre
   par choix, donc un verre blanc translucide sans aucune teinte figee — mais pose
   en HAUT A GAUCHE, la ou l'oeil cherche un retour, et AVANT le logo dans le flux
   (il est fixe : il ne pousse donc rien). La fleche est le chevron de la maison
   tourne d'un demi-tour, comme celle du tchat (`.tg-back svg`). */
.auth-back { position: fixed; top: calc(10px + env(safe-area-inset-top)); left: 12px; z-index: 30;
  width: 38px; height: 38px; padding: 0; display: inline-flex; align-items: center;
  justify-content: center; border-radius: 50%; cursor: pointer;
  border: 1px solid rgba(255, 255, 255, .30); background: rgba(255, 255, 255, .12);
  color: #fff; -webkit-appearance: none; appearance: none; }
.auth-back svg { transform: rotate(180deg); }
.auth-back:active { transform: scale(.94); }

/* ---------------------------------------------------------------------------
   ICONE FLOTTANTE DE LANGUE (02/10/2026 — demande du client : « change le bouton
   de langue en icone flottante sur l'ecran, touche le bouton pour changer la
   langue et vice-versa »). Un SEUL bouton rond remplace la pastille FR / EN de
   l'en-tete ; il FLOTTE au-dessus du contenu, a l'endroit exact qu'occupait le
   rond de messagerie (retire le 30/09/2026), donc juste au-dessus de la barre du
   bas et sur le bord droit. Il est pose DANS l'en-tete (comme la pastille qu'il
   remplace) : la ou l'en-tete disparait — les deux ecrans de connexion, la
   discussion en pleine page — l'icone disparait donc aussi.
   Le fond est plein a la couleur de la maison (l'appui EST une action), et la
   nuit elle suit la meme regle que la pilule active de la barre.
   Aucune teinte figee : jetons seulement. --------------------------------- */
.cx-lang-fab {
  position: fixed; right: 12px; bottom: calc(74px + env(safe-area-inset-bottom));
  z-index: 25; width: 52px; height: 52px; padding: 0; border: 0; border-radius: 50%;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  background: var(--brand-600); color: var(--on-brand); cursor: pointer;
  box-shadow: 0 14px 26px -16px rgba(38, 34, 35, .95);
  transition: transform .12s ease;
  /* Le bouton SE DEPLACE au doigt (02/10/2026) : sans cela le navigateur prend le
     geste pour un defilement et le bouton reste cloue a sa place. */
  touch-action: none;
}
.cx-lang-fab:active { transform: scale(.95); }
.cx-lang-fab svg { display: block; }
/* Le code de la langue CIBLE, sous le globe (l'appui y bascule). */
.cx-lang-fab-t { font-size: 10.5px; font-weight: 800; letter-spacing: .04em; line-height: 1;
  margin-top: 1px; }
:root[data-theme="dark"] .cx-lang-fab { background: var(--brand-500); }
/* Pendant une saisie, la barre du bas s'efface (`data-clavier`) : l'icone suit le
   meme sort, sinon elle flotterait par-dessus le clavier. */
body.client-app[data-clavier="1"] .cx-lang-fab { display: none; }

/* =====================================================================
   « MON COMPTE » ET REGLAGES — habillage modernise (30/09/2026)
   Demande du client : « moderniser la partie mon compte et les boutons de
   mise a jour et theme ». Meme palette que le reste du site : bleu de la
   marque, or pour les etats, un seul rouge (deconnexion). Aucune couleur
   nouvelle : uniquement les variables existantes, donc les deux themes
   suivent tout seuls. Les lignes font au moins 56 px de haut (cible
   tactile), et l'interrupteur du theme se peint sur aria-pressed, pose
   par le noyau (voir paintThemeIcons) : rien a cabler ici.
   ===================================================================== */

/* ---- bandeau d'identite : degrade de la marque, texte blanc ---- */
.pf-hero { position: relative; overflow: hidden; border-radius: var(--radius-lg);
  padding: 20px; color: #fff;
  background: linear-gradient(140deg, var(--brand-600) 0%, var(--brand-700) 60%, var(--brand-800) 100%);
  box-shadow: 0 18px 34px -22px rgba(10, 8, 9, .9); }
.pf-hero::after { content: ""; position: absolute; right: -46px; top: -58px; width: 168px; height: 168px;
  border-radius: 50%; background: rgba(255, 255, 255, .10); pointer-events: none; }
.pf-hero-top { position: relative; display: flex; align-items: center; gap: 14px; }
.pf-ava { flex: 0 0 auto; width: 58px; height: 58px; border-radius: 19px; display: grid; place-items: center;
  background: rgba(255, 255, 255, .18); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .30);
  font-weight: 800; font-size: 21px; letter-spacing: .02em; }
.pf-nom { font-size: 19px; font-weight: 700; line-height: 1.2; }
.pf-meta { font-size: 12.5px; color: rgba(255, 255, 255, .84); margin-top: 3px; }
.pf-chip { position: relative; display: inline-flex; align-items: center; gap: 6px; margin-top: 16px;
  padding: 6px 11px; border-radius: 999px; background: rgba(255, 255, 255, .14);
  font-size: 11.5px; color: rgba(255, 255, 255, .94); }

/* ---- trois compteurs : cagnotte, depots, retraits ----
   Budget mesure (viewport 363 px du client, police Inter du site) : 331 px
   utiles pour trois tuiles, soit 79 px de texte par tuile en 3 colonnes. Or
   « 1 234 567 F » en gras 700 mesure 83 px a 15 px et 88 px a 16 px : en trois
   colonnes, un solde a sept chiffres serait coupe. Donc SUR TELEPHONE, les
   trois compteurs passent en PLEINE LARGEUR (libelle a gauche, montant a
   droite, 259 px disponibles) — c'est la forme deja retenue pour le tableau de
   bord sur telephone, et le montant reste en 16 px. */
.pf-stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; margin-top: 12px; }
.pf-stat { background: var(--surface); border-radius: var(--radius); box-shadow: var(--ring); padding: 12px; }
.pf-stat .k-label { font-size: 10.5px; text-transform: uppercase; letter-spacing: .05em; color: var(--slate-500); }
.pf-stat .k-value { font-size: 15px; font-weight: 700; margin-top: 3px; font-variant-numeric: tabular-nums; }
.pf-stat.lead { box-shadow: 0 0 0 2px var(--brand-500); }
.pf-stat.lead .k-value { color: var(--brand-600); }
@media (max-width: 480px) {
  .pf-stats { grid-template-columns: 1fr; gap: 8px; }
  .pf-stat { display: grid; grid-template-columns: 36px minmax(0, 1fr) auto;
    align-items: center; gap: 11px; padding: 12px 14px; }
  .pf-stat .pf-ico { margin-bottom: 0; }
  .pf-stat .k-label { font-size: 11px; }
  .pf-stat .k-value { font-size: 16px; margin-top: 0; text-align: right; white-space: nowrap; }
}

/* ---- tuile d'icone : titres de section et lignes ---- */
.pf-ico { flex: 0 0 auto; width: 36px; height: 36px; border-radius: 11px; display: grid; place-items: center;
  background: var(--brand-50); color: var(--brand-600); }
.pf-ico.sm { width: 32px; height: 32px; border-radius: 10px; }
.pf-stat .pf-ico { margin-bottom: 8px; }
:root[data-theme="dark"] .pf-ico { background: rgba(240, 236, 237, .16); color: var(--brand-400); }

/* ---- titre de section : tuile + libelle + sous-titre ---- */
.pf-hd { display: flex; align-items: center; gap: 11px; min-width: 0; }
.pf-hd .pf-txt { display: grid; gap: 1px; min-width: 0; }
.pf-hd .pf-t { display: block; font-weight: 700; font-size: 14.5px; }
.pf-hd .pf-s { display: block; font-size: 11.5px; color: var(--slate-500); margin-top: 1px; }

/* ---- ligne de navigation / de reglage ---- */
.pf-row { display: flex; align-items: center; gap: 12px; width: 100%; min-height: 56px;
  padding: 11px 14px; background: var(--surface); border: 0; border-bottom: 1px solid var(--slate-100);
  color: inherit; font: inherit; text-align: left; text-decoration: none; cursor: pointer;
  transition: background .15s ease; }
.pf-row:last-child { border-bottom: 0; }
.pf-row:hover, .pf-row:active { background: var(--slate-50); }
.pf-row:focus-visible { outline: 2px solid var(--brand-500); outline-offset: -2px; }
.pf-row .pf-lib { flex: 1 1 auto; min-width: 0; }
.pf-row .pf-lib .pf-t { display: block; font-weight: 600; font-size: 13.5px; }
.pf-row .pf-lib .pf-s { display: block; font-size: 11.5px; color: var(--slate-500); margin-top: 2px; }
.pf-row .pf-end { flex: 0 0 auto; display: flex; align-items: center; gap: 8px; color: var(--slate-400); }

/* ---- interrupteur du theme ----
   Le bouton est BLANC FIGE (comme .sd-white et .zg-bulle deja whitelistes) : il
   doit rester le plus CLAIR, toujours. La piste, elle, prend --slate-300, qui
   bascule tout seul : gris clair (#B9B3B4) sur la carte blanche, gris moyen
   (#433E3F) sur la carte sombre. Une seule regle, donc — et le bouton ne doit
   JAMAIS suivre la piste (un bouton var(--surface) passerait SOUS la piste la
   nuit : interrupteur invisible, meme piege que la section 9novo). */
.pf-sw { flex: 0 0 auto; width: 48px; height: 28px; border-radius: 999px; background: var(--slate-300);
  position: relative; transition: background .2s ease; }
.pf-sw::after { content: ""; position: absolute; top: 3px; left: 3px; width: 22px; height: 22px;
  border-radius: 50%; background: #fff; box-shadow: 0 1px 4px rgba(26, 22, 23, .32);
  transition: transform .2s ease; }
[data-theme-toggle][aria-pressed="true"] .pf-sw { background: var(--brand-500); }
[data-theme-toggle][aria-pressed="true"] .pf-sw::after { transform: translateX(20px); }

/* ---- bandeau « nouvelle version disponible » : tuile + texte + action ---- */
.maj-banner .mb-ico { flex: 0 0 auto; width: 30px; height: 30px; border-radius: 10px; display: grid;
  place-items: center; background: rgba(255, 255, 255, .16); }
:root[data-theme="dark"] .maj-banner .mb-ico { background: rgba(38, 34, 35, .14); color: var(--brand-500); }
.maj-banner .mb-txt { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.maj-banner .mb-t { font-size: 12.5px; font-weight: 700; line-height: 1.25; }
.maj-banner .mb-s { font-size: 11px; font-weight: 500; opacity: .74; line-height: 1.25; }

/* ==========================================================================
   LE MARCHE (30/09/2026) : rayons, cartes d'articles, panier, commande.
   Meme palette que le reste : bleu maison #262223, or #8A6212, plus le vert et
   le rouge deja utilises par les cartes de l'accueil. Aucune teinte etrangere.
   ========================================================================== */
.sh-tete { display: flex; align-items: center; gap: 12px; margin-top: 4px; }
.sh-caddie { position: relative; flex: 0 0 auto; display: inline-flex; align-items: center;
  justify-content: center; width: 46px; height: 46px; border-radius: 999px; cursor: pointer;
  background: var(--brand-50); color: var(--brand-600); border: 0; }
.sh-nb { position: absolute; top: -4px; right: -4px; min-width: 20px; height: 20px; padding: 0 5px;
  border-radius: 999px; background: var(--amber-500); color: var(--slate-900);
  font-size: 11.5px; font-weight: 800; line-height: 20px; text-align: center; }
.sh-nb.vide { display: none; }
.sh-rech { display: flex; align-items: center; gap: 8px; margin-top: 14px; padding: 4px 4px 4px 12px;
  background: var(--surface); border: 1px solid var(--slate-200); border-radius: 999px;
  color: var(--slate-500); }
.sh-rech input { flex: 1 1 auto; min-width: 0; border: 0; background: none; font: inherit;
  font-size: 14px; color: var(--slate-900); padding: 8px 0; }
.sh-rech input:focus { outline: none; }
.sh-rech-b { flex: 0 0 auto; border: 0; cursor: pointer; border-radius: 999px; padding: 8px 14px;
  background: var(--brand-600); color: #fff; font: inherit; font-size: 13px; font-weight: 600; }
.sh-rayons { display: flex; gap: 8px; overflow-x: auto; margin-top: 12px; padding-bottom: 4px;
  scrollbar-width: none; }
.sh-rayons::-webkit-scrollbar { display: none; }
.sh-rayon { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 6px; cursor: pointer;
  padding: 8px 14px; border-radius: 999px; border: 1px solid var(--slate-200);
  background: var(--surface); color: var(--slate-600); font: inherit; font-size: 13px; font-weight: 600; }
.sh-rayon.on { background: var(--brand-600); border-color: var(--brand-600); color: #fff; }
.sh-rayon-n { font-size: 11px; opacity: .75; }
.sh-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 14px; }
.sh-card { display: flex; flex-direction: column; gap: 6px; padding: 10px; cursor: pointer;
  background: var(--surface); border: 1px solid var(--slate-200); border-radius: 16px; }
.sh-photo { display: flex; align-items: center; justify-content: center; height: 104px;
  border-radius: 12px; background: var(--brand-50); color: var(--brand-500); overflow: hidden; }
.sh-photo img { width: 100%; height: 100%; object-fit: cover; }
.sh-nom { font-size: 13.5px; font-weight: 700; color: var(--slate-900); line-height: 1.25;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.sh-prix { display: flex; align-items: baseline; gap: 6px; font-size: 15px; font-weight: 800;
  color: var(--brand-700); }
.sh-prix.big { font-size: 20px; }
.sh-old { font-size: 12px; font-weight: 600; color: var(--slate-400); text-decoration: line-through; }
.sh-tags { display: flex; flex-wrap: wrap; gap: 4px; }
.sh-tag { display: inline-flex; align-items: center; gap: 3px; padding: 2px 8px; border-radius: 999px;
  background: var(--slate-100); color: var(--slate-600); font-size: 10.5px; font-weight: 700; }
.sh-tag-num { background: var(--brand-50); color: var(--brand-600); }
.sh-tag-18 { background: var(--rose-50); color: var(--rose-700); }
.sh-tag-vide { background: var(--slate-200); color: var(--slate-600); }
.sh-tag-peu { background: var(--amber-100); color: var(--amber-700); }
.sh-fiche { display: flex; gap: 12px; padding: 12px; }
.sh-fiche .sh-photo { flex: 0 0 96px; height: 96px; }
.sh-vide { padding: 12px; border-radius: 12px; background: var(--slate-50);
  color: var(--slate-600); font-size: 13px; }
.sh-qte { display: flex; align-items: center; gap: 10px; }
.sh-pm { display: inline-flex; align-items: center; justify-content: center; cursor: pointer;
  width: 34px; height: 34px; border-radius: 10px; border: 1px solid var(--slate-200);
  background: var(--surface); color: var(--brand-600); }
.sh-pm:active { transform: scale(.94); }
.sh-q { min-width: 28px; text-align: center; font-weight: 800; font-size: 15px; }
.sh-ligne { display: flex; align-items: center; gap: 10px; padding: 10px 0; }
.sh-ligne + .sh-ligne { border-top: 1px solid var(--slate-100); }
.sh-vign { position: relative; flex: 0 0 auto; display: inline-flex; align-items: center;
  justify-content: center; width: 44px; height: 44px; border-radius: 12px; overflow: hidden;
  background: var(--brand-50); color: var(--brand-500); }
.sh-vign img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.sh-x { flex: 0 0 auto; width: 32px; height: 32px; border-radius: 999px; border: 0; cursor: pointer;
  background: var(--rose-50); color: var(--rose-600); display: inline-flex;
  align-items: center; justify-content: center; }
.sh-tot { display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  padding: 7px 0; font-size: 13.5px; color: var(--slate-700); }
.sh-tot.big { font-size: 16px; color: var(--slate-900); }
.sh-tot.muted { color: var(--slate-500); font-size: 12.5px; }
.sh-cmd { display: flex; align-items: center; gap: 10px; padding: 12px 0; cursor: pointer; }
.sh-cmd + .sh-cmd { border-top: 1px solid var(--slate-100); }
.sh-cmd-t { font-size: 14px; font-weight: 800; color: var(--slate-900); }
.sh-note { padding: 11px 13px; border-radius: 12px; background: var(--brand-50);
  color: var(--brand-800); font-size: 13px; line-height: 1.45; }
.sh-ev { display: flex; gap: 10px; padding: 6px 0; }
.sh-ev .xs { flex: 0 0 128px; }
:root[data-theme="dark"] .sh-photo, :root[data-theme="dark"] .sh-vign { background: var(--brand-900); }
:root[data-theme="dark"] .sh-note { background: rgba(38, 34, 35, .28); color: var(--brand-100); }
/* dans l'habillage de l'espace client : meme cerne, memes angles que le reste */
body.client-app .sh-card, body.client-app .sh-rech { border-color: var(--cx-cerne); box-shadow: var(--cx-flat); }
body.client-app .sh-card, body.client-app .sh-photo, body.client-app .sh-vign { border-radius: var(--cx-r); }

/* ==========================================================================
   AVIS DE L'ESPACE CLIENT (03/10/2026) — « le support t'a repondu », un
   depot valide, un retrait paye ou refuse.
   Le BANDEAU D'INTERFACE (la pastille sombre posee au-dessus de la barre du bas)
   a ete RETIRE le meme jour, le soir : « ne pas afficher le message du support en
   bas de l'ecran avec le bouton Ouvrir ; faire afficher les messages dans la barre
   de notification du telephone ». Seule la NOTIFICATION DU TELEPHONE annonce
   desormais (pont FSNotif / service worker) : ne rien remettre ici sans demande.
   Reste la pastille des messages non lus, en --rose-600, comme le compteur de
   la cloche (.cx-count).
   ========================================================================== */
/* La pastille des messages du support non lus : sur la ligne « Messages » de
   l'accueil (a cote du titre) et sur l'entree « Support » du panneau du compte
   (repoussee a droite). Elle disparait quand il n'y a rien a lire. */
.cx-nb { flex: 0 0 auto; margin-left: 6px; min-width: 19px; height: 19px; padding: 0 6px;
  border-radius: 999px; background: var(--rose-600); color: #fff; font-size: 10.5px;
  font-weight: 700; line-height: 1; display: inline-flex; align-items: center;
  justify-content: center; vertical-align: middle; }
.cx-nb[hidden] { display: none; }
.cx-acc-row .cx-nb { margin-left: auto; }

/* =====================================================================
   ANIMATIONS — mouvement discret, au service de la lecture.
   Trois principes : AUCUNE couleur nouvelle (on ne rejoue que la palette
   et des alphas), des durees courtes (0,26 a 0,5 s), et l'arret TOTAL
   quand le systeme demande moins de mouvement (prefers-reduced-motion).
   Le conteneur #view recoit la classe « no-anim » quand le meme ecran se
   redessine TOUT SEUL (suivi d un depot toutes les 6 s) : sans ce garde-fou
   la page clignoterait a chaque rafraichissement.
   ===================================================================== */
:root {
  --fx-ease: cubic-bezier(.22, .61, .36, 1);
  --fx-step: 32ms;                       /* ecart entre deux blocs d un ecran */
  --fx-glow: rgba(38, 34, 35, .45);     /* halo = bleu de la marque, en alpha */
}
:root[data-theme="dark"] { --fx-glow: rgba(240, 236, 237, .45); }

@keyframes fx-rise { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
@keyframes fx-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes fx-pop { from { opacity: 0; transform: scale(.96); } to { opacity: 1; transform: none; } }
@keyframes fx-sheet { from { opacity: 0; transform: translateY(26px) scale(.99); } to { opacity: 1; transform: none; } }
@keyframes fx-toast { from { opacity: 0; transform: translateY(14px) scale(.98); } to { opacity: 1; transform: none; } }
@keyframes fx-ping { 0% { opacity: 0; transform: scale(.55); } 60% { opacity: 1; transform: scale(1.14); } 100% { opacity: 1; transform: none; } }
@keyframes fx-draw { from { opacity: 0; transform: scaleX(.1); } to { opacity: 1; transform: none; } }
@keyframes fx-breathe { 0%, 100% { box-shadow: 0 0 0 0 var(--fx-glow); } 55% { box-shadow: 0 0 0 7px rgba(38, 34, 35, 0); } }
@keyframes fx-dot { 0%, 100% { opacity: 1; } 50% { opacity: .3; } }
@keyframes fx-ballon { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
@keyframes fx-bar { from { transform: scaleY(.04); } to { transform: none; } }
@keyframes fx-draw-c { from { opacity: 0; transform: translateX(-50%) scaleX(.1); }
  to { opacity: 1; transform: translateX(-50%); } }
@keyframes fx-toast-c { from { opacity: 0; transform: translateX(-50%) translateY(14px); }
  to { opacity: 1; transform: translateX(-50%); } }

/* ---- 1. entree d un ecran : chaque bloc monte et apparait, en cascade ---- */
#view > * { animation: fx-rise .34s var(--fx-ease) backwards; }
#view > *:nth-child(1) { animation-delay: 0ms; }
#view > *:nth-child(2) { animation-delay: 32ms; }
#view > *:nth-child(3) { animation-delay: 64ms; }
#view > *:nth-child(4) { animation-delay: 96ms; }
#view > *:nth-child(5) { animation-delay: 128ms; }
#view > *:nth-child(6) { animation-delay: 160ms; }
#view > *:nth-child(7) { animation-delay: 192ms; }
#view > *:nth-child(8) { animation-delay: 224ms; }
#view > *:nth-child(9) { animation-delay: 256ms; }
#view > *:nth-child(n+10) { animation-delay: 288ms; }
/* grilles (raccourcis, cartes, formulaires) et listes : meme cascade, plus fine */
#view .grid-2 > *, #view .grid-3 > *, #view .grid-4 > * {
  animation: fx-rise .30s var(--fx-ease) backwards; }
#view .grid-2 > *:nth-child(2), #view .grid-3 > *:nth-child(2), #view .grid-4 > *:nth-child(2) { animation-delay: 40ms; }
#view .grid-2 > *:nth-child(3), #view .grid-3 > *:nth-child(3), #view .grid-4 > *:nth-child(3) { animation-delay: 80ms; }
#view .grid-2 > *:nth-child(4), #view .grid-3 > *:nth-child(4), #view .grid-4 > *:nth-child(4) { animation-delay: 120ms; }
#view .grid-2 > *:nth-child(5), #view .grid-3 > *:nth-child(5), #view .grid-4 > *:nth-child(5) { animation-delay: 160ms; }
#view .grid-2 > *:nth-child(n+6), #view .grid-3 > *:nth-child(n+6), #view .grid-4 > *:nth-child(n+6) { animation-delay: 200ms; }
#view .cx-acts > * { animation: fx-pop .34s var(--fx-ease) backwards; }
#view .cx-acts > *:nth-child(2) { animation-delay: 70ms; }
#view .cx-racc > * { animation: fx-pop .34s var(--fx-ease) backwards; }
#view .cx-social-row > * { animation: fx-pop .34s var(--fx-ease) backwards; }
#view .cx-social-row > *:nth-child(2) { animation-delay: 60ms; }
#view .table tbody tr { animation: fx-fade .26s var(--fx-ease) backwards; }
#view .table tbody tr:nth-child(2) { animation-delay: 30ms; }
#view .table tbody tr:nth-child(3) { animation-delay: 60ms; }
#view .table tbody tr:nth-child(4) { animation-delay: 90ms; }
#view .table tbody tr:nth-child(n+5) { animation-delay: 120ms; }
/* Verification d identite du joueur : elle apparait pendant la frappe, sa
   petite apparition annonce que la reponse du bookmaker est arrivee. */
#view:not(.no-anim) .idcheck { animation: fx-pop .30s var(--fx-ease) backwards; }

/* ---- 2. redessin automatique du MEME ecran : aucune animation d entree ---- */
#view.no-anim > *, #view.no-anim .grid-2 > *, #view.no-anim .grid-3 > *,
#view.no-anim .grid-4 > *, #view.no-anim .cx-acts > *, #view.no-anim .cx-racc > *,
#view.no-anim .cx-social-row > *,
#view.no-anim .table tbody tr, #view.no-anim .idcheck { animation: none; }

/* ---- 3. le geste : boutons, cartes, champs, onglets du bas ---- */
.btn { transition: filter .15s ease, background .15s ease, transform .12s var(--fx-ease); }
.btn:active { transform: translateY(1px) scale(.97); }
.tile, .choice { transition: transform .16s var(--fx-ease), box-shadow .16s var(--fx-ease), border-color .16s ease; }
.tile:active, .choice:active { transform: scale(.985); }
.cx-act-ico { transition: transform .18s var(--fx-ease), box-shadow .18s var(--fx-ease); }
.cx-act:active .cx-act-ico { transform: scale(.94); }
.cx-soc { transition: transform .18s var(--fx-ease); }
.cx-soc:active { transform: scale(.92); }
.cx-copy { transition: transform .16s var(--fx-ease), filter .16s ease; }
.cx-copy:active { transform: scale(.94); }
.cx-ico, .sd-item, .cx-acc-row, .tab { transition: background .15s ease, color .15s ease; }
.input, .select, .textarea { transition: border-color .15s ease, box-shadow .18s var(--fx-ease); }
.bottomnav .item svg { transition: transform .18s var(--fx-ease); }
.bottomnav .item.active svg { transform: translateY(-1px) scale(1.08); }
.bottomnav .item:active svg { transform: scale(.88); }
.list-item { transition: background .15s ease; }

/* ---- 4. panneaux, modales, feuilles et messages ---- */
.modal { animation: fx-fade .16s ease both; }
.modal-card { animation: fx-sheet .26s var(--fx-ease) both; }
.sheet { animation: fx-fade .16s ease both; }
.sheet-card { animation: fx-sheet .30s var(--fx-ease) both; }
.sd-back { animation: fx-fade .20s ease both; }
.toast { animation: fx-toast .22s var(--fx-ease) both; }
.maj-banner { animation: fx-toast-c .30s var(--fx-ease) both; }

/* ---- 5. signaux « ca travaille » et « ca attend » ---- */
.stepbar .s.on .n { animation: fx-breathe 1.9s ease-in-out infinite; }
.stepbar .s.done .n { animation: fx-ping .30s var(--fx-ease) both; }
/* Le ballon de football qui tourne sur lui-meme — illustration de l'attente du
   SMS depuis le 27/09/2026 (remplace la silhouette qui marchait, fx-walk).
   `transform-box: view-box` + origine au CENTRE sont indispensables : sans elles
   la rotation d'un SVG part du coin haut-gauche du viewBox et le ballon decrit
   une ORBITE au lieu de tourner sur place. */
.pay-wait svg { animation: fx-ballon 2.6s linear infinite;
  transform-box: view-box; transform-origin: center; }
.cx-count { animation: fx-ping .26s var(--fx-ease) both; }
.dot.warn, .dot.brand { animation: fx-dot 1.7s ease-in-out infinite; }
.bars .b { transform-origin: bottom; animation: fx-bar .50s var(--fx-ease) backwards; }
.bars .b:nth-child(2n) { animation-delay: 60ms; }
.bars .b:nth-child(3n) { animation-delay: 110ms; }
.progress > i { transition: width .50s var(--fx-ease); }

/* ---- 6. respect du reglage systeme « moins de mouvement » ---- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
}

/* =====================================================================
   CONCOURS (promotion) — contenu de la page publique /concours
   Repris de l'ecran /admin/promotion de la reference. On ne cree aucune
   couleur : uniquement les variables de la palette existante.
   ===================================================================== */
.flex-col { flex-direction: column; }
.w-sm { width: 84px; }

/* une section du formulaire de contenu (En-tête, Lots, Classement...) */
.promo-sec { margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--slate-200); }
.promo-sec:first-child { margin-top: 0; padding-top: 0; border-top: 0; }

/* un lot / une étape dans la liste editable */
.promo-item { padding: 12px; border: 1px solid var(--slate-200); border-radius: var(--radius-sm);
  background: var(--surface-2); }

/* aperçu du logo du concours */
.promo-logo { display: flex; align-items: center; justify-content: center; width: 76px; height: 76px;
  overflow: hidden; border: 1px solid var(--slate-200); border-radius: var(--radius-sm);
  background: var(--surface-2); color: var(--slate-400); }
.promo-logo img { width: 100%; height: 100%; object-fit: contain; }

/* valeur deja cumulee d'une action (non saisissable) */
.promo-cumul { width: 84px; padding: 6px 8px; text-align: right; font-weight: 600;
  border-radius: var(--radius-sm); background: var(--slate-100); color: var(--slate-700); }

/* saisie des points d'un participant */
.promo-pt { width: 84px; text-align: right; }

/* capture de partage affichee dans la fenetre */
.promo-shot { display: block; width: 100%; max-height: 60vh; margin-top: 12px; object-fit: contain;
  border: 1px solid var(--slate-200); border-radius: var(--radius-sm); }

/* PIECE JOINTE D'UN CLIENT (photo ou video) affichee en grand dans le panneau
   (03/10/2026, client : « impossible d'ouvrir le fichier photo recu dans
   l'interface admin conversation »). Meme cadre que la capture de partage
   ci-dessus : la piece jointe occupe la fenetre, entiere et sans deformation. */
.chat-vue { display: block; width: 100%; max-height: 60vh; margin-top: 12px; object-fit: contain;
  border: 1px solid var(--slate-200); border-radius: var(--radius-sm);
  /* le fond derriere la piece jointe : un aplat sombre FIXE (rgba, donc insensible
     a la bascule de theme) — la ou l'image ne remplit pas le cadre, un fond blanc
     ferait croire a une image vide. */
  background: rgba(26, 22, 23, .92); }

/* --------- page publique du concours (espace client) --------- */
.promo-hero { padding: 18px; text-align: center; border: 1px solid var(--slate-200);
  border-radius: var(--radius); background: var(--surface-2); }
.promo-hero .promo-logo { margin: 0 auto 10px; }
.promo-pastille { display: inline-flex; align-items: center; padding: 3px 10px; border-radius: 999px;
  font-size: 12px; font-weight: 700; background: var(--brand-50); color: var(--brand-700); }
.promo-sous-titre { margin-top: 8px; font-size: 13px; font-weight: 600; color: var(--brand-600); }

/* compte a rebours : quatre cases (jours, heures, minutes, secondes) */
.promo-compteur { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin-top: 10px;
  text-align: center; }
.promo-compteur > div { display: flex; flex-direction: column; gap: 2px; padding: 8px 4px;
  border-radius: var(--radius-sm); background: var(--slate-100); }
.promo-num { font-size: 20px; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--slate-900); }

/* podium, lots et etapes */
.promo-podium { display: grid; gap: 8px; }
.promo-podium-item, .promo-lot, .promo-etape { display: flex; align-items: center; gap: 10px;
  padding: 10px 12px; border: 1px solid var(--slate-200); border-radius: var(--radius-sm);
  background: var(--surface-2); }
.promo-lot-emoji, .promo-etape-emoji { font-size: 24px; line-height: 1; }

/* =====================================================================
   EFFETS D'ANIMATION DE LA REFERENCE (embmoney) sur nos composants.
   Memes effets : survol qui souleve, appui qui retrecit, filet de lumiere
   qui balaie, changement de fond en douceur. Nos apparitions (fx-*) et nos
   signaux (fx-breathe / fx-dot) couvrent deja fade-up / pulse / pulse-glow.
   ===================================================================== */

/* 1. ronds de l'accueil client : souleves au survol, ecrases a l'appui
      (reference : transition-transform duration-200 + hover:-translate-y-1
      + hover:scale-110 + active:scale-95) */
.cx-round-c { transition: transform .20s var(--fx-ease), box-shadow .20s var(--fx-ease); }
.cx-round:hover .cx-round-c { transform: translateY(-4px) scale(1.08);
  box-shadow: 0 14px 26px -14px var(--brand-600); }
.cx-round:active .cx-round-c { transform: translateY(0) scale(.95); }

/* 2. cartes de l'espace client : elles se soulevent au survol (l'admin reste
      fixe, comme la reference) */
body:not(.admin-app) #view .card { transition: transform .25s var(--fx-ease), box-shadow .25s var(--fx-ease); }
body:not(.admin-app) #view .card:hover { transform: translateY(-3px); box-shadow: var(--shadow-lg); }

/* 3. lignes et entrees de menu : changement de fond en douceur
      (reference : transition-colors partout) */
tbody tr, .admin-nav a, .bottomnav .item, .list-row, .cx-link {
  transition: background .18s ease, color .18s ease, border-color .18s ease; }

/* 4. boutons : appui qui retrecit (reference : active:scale-95) et lumiere */
.btn { transition: transform .15s var(--fx-ease), filter .15s var(--fx-ease),
  box-shadow .15s var(--fx-ease), background .15s ease; }
.btn:active { transform: scale(.96); }
body:not(.admin-app) .btn-primary { position: relative; overflow: hidden; }
body:not(.admin-app) .btn-primary:hover { box-shadow: 0 10px 24px -12px var(--brand-600); }
body:not(.admin-app) .btn-primary::after { content: ''; position: absolute; top: 0; bottom: 0; width: 42%;
  background: linear-gradient(100deg, transparent, rgba(255,255,255,.32), transparent);
  opacity: 0; pointer-events: none; transform: translateX(-160%) skewX(-12deg); }
body:not(.admin-app) .btn-primary:hover::after { opacity: 1; animation: fx-shine 1.1s ease-in-out; }

/* 5. filet lumineux en haut des cartes survolees (reference : ::after scaleX) */
@keyframes fx-shine { 0% { transform: translateX(-160%) skewX(-12deg); }
                      55%, 100% { transform: translateX(160%) skewX(-12deg); } }
@keyframes fx-lift-line { from { transform: scaleX(0); } to { transform: none; } }
body:not(.admin-app) #view .card { position: relative; }
body:not(.admin-app) #view .card::after { content: ''; position: absolute; top: 0; left: 0; right: 0;
  height: 2px; background: linear-gradient(90deg, transparent, var(--brand-400), transparent);
  transform: scaleX(0); transition: transform .35s var(--fx-ease); pointer-events: none; border-radius: var(--radius-lg) var(--radius-lg) 0 0; }
body:not(.admin-app) #view .card:hover::after { transform: scaleX(1); }

/* =====================================================================
   REFONTE DU 27/09 — habillage repris de la maquette de reference
   (uupm.cc/demo/ai-chatbot-platform), transpose sur NOTRE palette bleue.
   Seul l'habillage est touche : aucune classe, aucun ecran, aucune logique
   ne change. Ce qui suit vient apres tout le reste : a specificite egale,
   ces regles gagnent.
   ===================================================================== */

/* 1. typographie : les titres passent en Space Grotesk (texte deja en
      DM Sans via --font). On ne touche NI aux montants NI aux tableaux,
      qui gardent des chiffres tabulaires en DM Sans. */
h1, h2, h3, h4, .h1, .h2, .h3,
.cx-name, .admin-topbar-name, .auth-brand, .logo, .user-name,
.hero h1, .section-head h2, .stats-row .s b, .sd-welcome h2 {
  font-family: var(--font-titre);
}
h1, h2, .h1, .hero h1, .section-head h2 { letter-spacing: -.028em; }
h3, h4, .h3 { letter-spacing: -.012em; }

/* 2. boutons pleins : degrade de la marque au lieu de l'aplat, et leger
      soulevement au survol (reference : .btn-primary / hover translateY).
      ATTENTION : les boutons semantiques gardent LEUR couleur — « ok » reste
      vert et « danger » reste rouge, sinon le sens du bouton disparait. */
.btn-primary, .btn-dark, .btn-landing { background-image: var(--grad-cta); }
.btn-primary:hover, .btn-dark:hover, .btn-landing:hover {
  transform: translateY(-2px); filter: none; box-shadow: var(--shadow-cta); }
.btn-ok:hover, .btn-danger:hover, .btn-warn:hover { transform: translateY(-2px); filter: brightness(1.06); }
.btn-ghost:hover { border-color: var(--brand-300); color: var(--brand-700); }

/* 3. cartes : au survol, cerne de la marque + ombre teintee (reference :
      .card-hover { border-color: primary; box-shadow 0 4px 20px primary/10 }),
      a la place de la grande ombre noire qui ecrasait la page */
body:not(.admin-app) #view .card:hover {
  transform: translateY(-2px);
  box-shadow: 0 0 0 1px var(--brand-300), var(--shadow-hover); }
#view .kpi, .card, .promo-hero, .auth-card, .sd-panel { transition: box-shadow .2s var(--fx-ease), transform .2s var(--fx-ease); }
#view .kpi:hover { box-shadow: 0 0 0 1px var(--brand-300), var(--shadow-hover); }

/* 4. titres : un mot en degrade, comme le titre du hero de la reference.
      @supports evite d'effacer le texte si background-clip n'existe pas. */
.hero h1 em { color: var(--brand-600); }
@supports (-webkit-background-clip: text) or (background-clip: text) {
  .hero h1 em {
    background-image: var(--grad);
    -webkit-background-clip: text; background-clip: text;
    -webkit-text-fill-color: transparent; color: transparent;
  }
}

/* 5. elements actifs (onglets, pastilles de statut, chiffres cles) : meme
      traitement en degrade, en gardant la lisibilite sur les deux themes */
.tab.active, .dash-tabs .tab.active { background-image: var(--grad-cta); color: var(--on-brand); border-color: transparent; }
.stats-row .s { border-left-color: var(--brand-600); }
/* ATTENTION : ne PAS reposer ici la couleur du libelle de l'entree active du
   menu lateral. La regle « .admin-nav a.active { color: var(--brand-600) } »
   avait la MEME specificite que « .admin-side a.active » (ci-dessus) mais
   venait plus bas dans le fichier : en mode clair elle ecrasait donc le blanc
   et le libelle comme l'icone (currentColor) se peignaient du bleu de la
   pastille SUR la pastille bleue -> bande bleue vide dans le menu, sur
   telephone comme sur ordinateur. Les couleurs de l'entree active sont posees
   une seule fois, avec sa pastille (.admin-side a.active : texte blanc). */
.cx-round:hover .cx-round-c { box-shadow: 0 14px 26px -14px var(--brand-500); }

/* 6. champs de saisie : cerne de focus un peu plus large, dans l'esprit de
      la reference (ring teinte) */
.input:focus, .select:focus, .textarea:focus {
  border-color: var(--brand-500); box-shadow: 0 0 0 3px rgba(38, 34, 35, .16); }
:root[data-theme="dark"] .input:focus,
:root[data-theme="dark"] .select:focus,
:root[data-theme="dark"] .textarea:focus { box-shadow: 0 0 0 3px rgba(240, 236, 237, .22); }

/* 7. page publique : les sections respirent comme dans la reference */
.hero { padding: 48px 0 40px; }
.section-head h2 { font-weight: 700; }
.btn-landing { font-weight: 600; border-radius: var(--radius-sm); }

/* 8. focus clavier : la plateforme impose un anneau de focus VISIBLE. Le halo
      par defaut du navigateur jure avec la palette, on le remplace par le bleu
      de la marque, en gardant un decalage pour qu'il ne colle pas au bord. */
a:focus-visible, button:focus-visible, .btn:focus-visible, .tab:focus-visible,
.bottomnav .item:focus-visible, .admin-nav a:focus-visible,
.list-row:focus-visible,
.cx-round:focus-visible, .card-hd [role="button"]:focus-visible,
input:focus-visible, select:focus-visible, textarea:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--brand-600); outline-offset: 2px;
}
:root[data-theme="dark"] a:focus-visible, :root[data-theme="dark"] button:focus-visible,
:root[data-theme="dark"] .btn:focus-visible, :root[data-theme="dark"] .tab:focus-visible,
:root[data-theme="dark"] .bottomnav .item:focus-visible,
:root[data-theme="dark"] .admin-nav a:focus-visible,
:root[data-theme="dark"] .list-row:focus-visible, :root[data-theme="dark"] .cx-round:focus-visible,
:root[data-theme="dark"] input:focus-visible, :root[data-theme="dark"] select:focus-visible,
:root[data-theme="dark"] textarea:focus-visible, :root[data-theme="dark"] [tabindex]:focus-visible {
  outline-color: var(--brand-400);
}

/* 9. cibles tactiles : la plateforme demande 44 px minimum. On ne l'impose
      que sur les ecrans TACTILES (pointer: coarse) : a la souris, la densite
      des tableaux du panneau reste celle d'avant. */
@media (pointer: coarse) {
  .btn-xs, .btn-sm, .tab { min-height: 44px; }
  .bottomnav .item { min-height: 52px; }
}

/* =====================================================================
   VERRE (glassmorphism) — style recommande pour le domaine fintech
   (« Glassmorphism + Dark Mode (OLED) ») et signature de la plateforme de
   reference. Fond translucide + flou de 20 px + cerne de 1 px : l'effet se
   voit parce que les halos de la page passent dessous.
   Valeurs transcrites de sa feuille de style (.glass-card) ; l'ombre du
   survol prend notre violet au lieu de son bleu.
   Performance : la base classe le verre en « bon » et non « excellent » — il
   reste donc limite aux cartes, jamais sur les tableaux ni les listes.
   ===================================================================== */
/* `.auth-card` (l'ecran de connexion) a ete RETIREE de cette liste le 28/09 :
   sa charte est « page sombre, carte blanche », et le fond translucide la
   rendait grise avec un lisere clair. Elle reprend son blanc opaque juste
   en dessous. */
.card, .kpi, .net-card, .feat,
.tile, .promo-hero, .sd-panel, .stats-row .s {
  background-color: var(--glass-bg);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-border);
}
/* Les FENETRES (modale, feuille) sont OPAQUES : posees sur un voile sombre, un
   fond translucide laissait passer ce voile et la fenetre paraissait grise au
   milieu d'un site clair. C'etait le cas du suivi de depot. */
.modal-card, .sheet-card {
  background: var(--surface);
  -webkit-backdrop-filter: none; backdrop-filter: none;
  border: 1px solid var(--glass-border);
}
.card:hover, .net-card:hover, .kpi:hover { background-color: var(--glass-bg-2); }
body:not(.admin-app) #view .card:hover {
  border-color: var(--brand-300);
  background-color: var(--glass-bg-2);
}
/* ombre du survol : valeur de la maquette (0 20px 25px -5px primary/15) */
.net-card:hover, .card:hover {
  box-shadow: 0 20px 25px -5px rgba(38, 34, 35, .15), 0 8px 10px -6px rgba(38, 34, 35, .10);
}
:root[data-theme="dark"] .net-card:hover, :root[data-theme="dark"] .card:hover {
  box-shadow: 0 20px 25px -5px rgba(0, 0, 0, .45);
}
/* le contenu du panneau garde son fond : pas de flou sur la coquille */
body.admin-app .admin-body { backdrop-filter: none; }

/* =====================================================================
   GALERIE DE STYLES (/galerie) — page de consultation du catalogue de design
   repris de la plateforme de reference. Le rendu est fait par
   static/js/galerie.js ; ces regles vivent ici, avec le reste du systeme de
   design, pour qu'il n'y ait qu'une seule feuille.
   ===================================================================== */
/* =====================================================================
     GALERIE DE STYLES — la base de donnees de design de la plateforme de
     reference, reproduite telle quelle. Page de consultation : elle ne fait
     aucun appel a l'API et reste hors de l'application.
     ===================================================================== */
  body.galerie { background: var(--slate-50); color: var(--slate-900); }
  body.galerie::before {
    content: ''; position: fixed; inset: -20% -10% auto -10%; height: 70vh; pointer-events: none;
    background:
      radial-gradient(520px 320px at 18% 12%, rgba(58, 53, 54, .28), transparent 70%),
      radial-gradient(460px 300px at 82% 4%, rgba(38, 34, 35, .22), transparent 70%);
    filter: blur(60px); z-index: 0;
  }
  .g-head {
    position: sticky; top: 0; z-index: 20;
    background: var(--glass-bg); -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
    border-bottom: 1px solid var(--glass-border);
  }
  .g-head .container { display: flex; align-items: center; justify-content: space-between; gap: 12px;
    min-height: 60px; padding-top: 8px; padding-bottom: 8px; flex-wrap: wrap; }
  .g-head .brand { display: inline-flex; align-items: center; gap: 10px; color: var(--slate-900); }
  .g-head .brand .brand-mark { width: 30px; height: 30px; border-radius: 9px; }
  .g-head .brand b { font-family: var(--font-titre); font-size: 16px; }
  .g-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
  main.container { position: relative; z-index: 1; padding-top: 28px; padding-bottom: 40px; }
  .g-bar { display: flex; flex-direction: column; gap: 12px; margin: 18px 0 22px; }
  .g-onglets { flex-wrap: wrap; }
  .g-onglets .tab { display: inline-flex; align-items: center; gap: 6px; }
  .g-n { font-size: 11px; opacity: .8; }
  .g-grille { display: grid; grid-template-columns: repeat(auto-fill, minmax(290px, 1fr)); gap: 16px; }
  .g-card { padding: 16px; display: flex; flex-direction: column; gap: 8px; }
  .g-top { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
  .g-top .h3 { margin: 0; }
  .g-tags { display: flex; flex-wrap: wrap; gap: 6px; }
  .g-card { align-items: stretch; }
  .g-card > .g-tags, .g-card > .g-swatches, .g-card > .g-meta { align-self: flex-start; max-width: 100%; }
  .g-card .badge { margin: 2px 4px 2px 0; }
  .g-col { font-size: 13px; color: var(--slate-600); }
  .g-swatches { display: flex; gap: 5px; flex-wrap: wrap; }
  .g-sw { width: 20px; height: 20px; border-radius: 6px; box-shadow: var(--ring); display: inline-block; }
  .g-champ { display: flex; gap: 8px; font-size: 12.5px; }
  .g-lb { color: var(--slate-500); text-transform: uppercase; font-size: 10.5px; letter-spacing: .06em;
    font-weight: 700; flex: 0 0 74px; padding-top: 2px; }
  .g-vl { color: var(--slate-700); flex: 1 1 auto; }
  .g-meta { display: flex; flex-wrap: wrap; gap: 6px; }
  .g-chip { font-size: 11.5px; background: var(--slate-100); color: var(--slate-600);
    border-radius: 999px; padding: 3px 9px; }
  .g-chip b { color: var(--slate-800); }
  .g-det { font-size: 12.5px; }
  .g-det summary { cursor: pointer; color: var(--brand-700); font-weight: 600; }
  .g-det p { margin: 6px 0 0; color: var(--slate-600); }
  .g-rows { display: flex; flex-direction: column; gap: 5px; margin: 4px 0; }
  .g-row { display: flex; align-items: center; gap: 8px; font-size: 12.5px; }
  .g-row .g-lb { flex: 0 0 76px; }
  .g-prev { display: flex; align-items: center; justify-content: space-between; gap: 10px;
    border: 1px solid var(--slate-200); border-radius: 12px; padding: 12px 14px; font-size: 13px; }
  .g-btn { padding: 6px 12px; border-radius: 10px; color: var(--on-brand); font-weight: 600; font-size: 12.5px;
    font-family: var(--font-titre); }
  .g-duo { display: flex; gap: 14px; flex-wrap: wrap; }
  .g-duo .g-lb { display: block; flex: none; }
  .g-do { font-size: 12.5px; color: var(--emerald-700); }
  .g-dont { font-size: 12.5px; color: var(--rose-700); }
  .g-do b, .g-dont b { font-size: 10.5px; text-transform: uppercase; letter-spacing: .06em; }
  /* Bandeau de l'apercu live : on essaie une palette de la galerie sans rien
     enregistrer. Il reste colle en haut pour qu'on puisse toujours revenir. */
  .g-apercu { position: sticky; top: 60px; z-index: 19; display: flex; align-items: center;
    justify-content: center; gap: 12px; flex-wrap: wrap; padding: 10px 16px;
    background: var(--brand-600); color: var(--on-brand); font-size: 13px; }
  .g-apercu[hidden] { display: none; }
  .g-apercu b { font-family: var(--font-titre); }
  .g-ap-note { opacity: .85; }
  .g-apercu .btn-ghost { border-color: currentColor; color: var(--on-brand); }
  .g-apercu .btn-ghost:hover { background: rgba(255, 255, 255, .16); color: var(--on-brand); }
  .g-essai { margin-top: 6px; align-self: flex-start; }
  .g-essai.actif { background: var(--brand-600); color: var(--on-brand); border-color: transparent; }
  /* Deux axes de l'apercu de style qui ne passent pas par une variable CSS :
     la respiration (styles « spacious ») et la lueur (styles neon / glow). */
  html[data-espace="1"] .g-grille { gap: 24px; }
  html[data-espace="1"] .g-card { padding: 26px; }
  html[data-espace="1"] .g-bar { margin: 26px 0 30px; }
  html[data-lueur="1"] .g-card .h3,
  html[data-lueur="1"] .g-head .brand b { text-shadow: 0 0 10px currentColor; }
  .g-foot { padding: 22px 16px 34px; }
  .g-foot p { max-width: 720px; margin: 0 auto; text-align: center; }
  .g-foot .tab.active { border: 0; }
  @media (max-width: 620px) {
    .g-grille { grid-template-columns: 1fr; }
    .g-head .container { justify-content: center; }
  }

/* ==========================================================================
   HABILLAGE 2 — 30/09/2026
   L'interface cliente reprenait le SQUELETTE de la plateforme de reference
   (EMB Money) : carte hero sombre avec son halo de lumiere, deux gros carres
   Depot / Retrait, pilules arrondies, silhouette « vallees et montagnes » sur
   la barre du bas, rond du support a halo. Une autre application tourne
   aujourd'hui avec exactement cette interface : on garde NOS ecrans et NOS
   couleurs, on change la FORME.
     - angles francs (12 / 16 px) la ou la reference etait toute en rondeurs ;
     - surfaces OPAQUES a cerne de 1 px, sans verre, sans flou, sans halo ;
       l'ombre est reservee a ce qui FLOTTE (barre du bas, bouton du support) ;
     - le bandeau d'identite remplace la carte hero : clair, sobre, avec une
       coche de marque sur son bord gauche ;
     - les deux tuiles Depot / Retrait deviennent deux LIGNES pleine largeur,
       icone carree et chevron : un tableau de bord, pas deux gros carres ;
     - la barre du bas perd sa silhouette : barre droite a cerne, bouton
       d'accueil CARRE arrondi, plus aucun rond a halo.
   Tout est porte par `body.client-app` : le PANNEAU D'ADMINISTRATION et les
   ecrans de connexion gardent leur habillage (regles plus haut dans la
   feuille). Les noms de classes ne changent pas : les tests du projet
   verrouillent la STRUCTURE (classes, ordre, liens), cet habillage ne joue que
   sur la forme.
   ========================================================================== */
body.client-app {
  --cx-r: 12px;            /* rayon courant : cartes de liste, boutons */
  --cx-r-lg: 16px;         /* rayon des grandes surfaces (bandeau, fenetres) */
  --cx-r-sm: 9px;          /* rayon des vignettes (icones d'en-tete, pastilles) */
  --cx-cerne: var(--slate-200);   /* le cerne de 1 px qui remplace les ombres */
  --cx-flat: 0 1px 2px rgba(26, 22, 23, .04);
}

/* ---------- surfaces : plates, a cerne, sans relief ---------- */
body.client-app .card,
body.client-app .panel {
  border-radius: var(--cx-r-lg); border: 1px solid var(--cx-cerne);
  box-shadow: var(--cx-flat);
}
body.client-app .modal-card { border-radius: var(--cx-r-lg); }
body.client-app .sheet-card { border-radius: var(--cx-r-lg) var(--cx-r-lg) 0 0; }
body.client-app .btn { border-radius: 999px; box-shadow: none; }
body.client-app .input, body.client-app .select, body.client-app textarea {
  border-radius: var(--cx-r);
}
body.client-app .sheet { background: rgba(8, 20, 40, .55); }
body.client-app .modal { background: rgba(8, 20, 40, .55); }

/* ---------- en-tete : barre d'outils a cerne, trait de marque en bas ---------- */
body.client-app .topbar {
  background: var(--surface); border-bottom: 1px solid var(--cx-cerne); padding: 12px 14px;
}
/* BANDE DE LA BARRE D'ETAT (symptome client « le haut est flou », capture du
   30/09/2026) : dans une APPLICATION WEB installee, le systeme dessine sa barre
   d'etat PAR-DESSUS la page (mode autonome + `viewport-fit=cover`) et lave ce
   qu'elle recouvre — le pseudo et la pastille passaient sous l'heure et la
   batterie. La reserve est donc portee par l'EN-TETE, dont le fond est clair
   (`--surface`) : sous un fond clair, un voile clair ne se voit plus. Meme
   traitement que le tchat (`.tg`). L'inset vaut 0 dans un onglet de navigateur ET
   dans notre application Android (sa barre d'etat est OPAQUE, bleu de marque : le
   WebView commence dessous) : rien ne change dans ces deux cas. */
body.client-app .topbar { padding-top: calc(12px + env(safe-area-inset-top)); }
/* Sur ecran large, la reserve du bloc grand ecran (`calc(40px + env(safe-area-inset-top))`)
   etait elle aussi ECRASEE par le `padding: 9px 14px` du client — meme piege de
   specificite que la barre du bas (0,2,1 contre 0,1,0) : le pseudo et la pastille
   restaient sous l'heure et la batterie. On la repose ici, apres la regle du
   telephone (a specificite egale, la plus BASSE gagne). */
@media (min-width: 721px) {
  body.client-app .topbar { padding-top: calc(40px + env(safe-area-inset-top)); }
}
/* le panneau du compte est ancre SOUS l'en-tete : il suit donc la reserve, sinon
   il recouvre la derniere ligne de l'en-tete quand la bande grandit. Au-dela de
   721 px c'est le bloc grand ecran qui le place (102 px), cette regle ne
   s'applique pas. */
@media (max-width: 720px) {
  body.client-app .cx-acc { top: calc(73px + env(safe-area-inset-top)); }
}
body.client-app .topbar::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: -1px; height: 2px; pointer-events: none;
  background: linear-gradient(90deg, var(--brand-600), var(--brand-300) 52%, transparent 88%);
}
:root[data-theme="dark"] body.client-app .topbar { background: var(--surface); }
body.client-app .cx-logo { width: 36px; height: 36px; border-radius: 10px; background: var(--brand-600); }
body.client-app .cx-name { font-size: 17px; letter-spacing: .005em; display: block; }
body.client-app .cx-top .who {
  font-size: 10.5px; text-transform: uppercase; letter-spacing: .14em; color: var(--slate-500);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Demande du client (capture du 02/10/2026) : « reduit le nom du client si c est
   trop long ». Le nom de l'EN-TETE porte deja la coupe en points de suspension ;
   au-dela de 16 caracteres (classe posee par app.js, `nomLong`) on REDUIT aussi la
   taille et le tracking — c'est ce qui mange la largeur de la barre. Le bandeau du
   PROFIL, lui, n'avait aucune coupe : le nom y tient desormais sur UNE ligne,
   reduit et coupe de la meme facon. */
body.client-app .cx-top .who.who-long { font-size: 9px; letter-spacing: .06em; }
body.client-app .pf-nom { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
body.client-app .pf-nom.pf-nom-long { font-size: 15px; }
body.client-app .cx-ico {
  width: 35px; height: 35px; border-radius: 999px;
  border: 1px solid var(--cx-cerne); background: var(--surface);
}
/* les icones sont DESSINEES (trait) : a 22 px elles restaient grises ; le trait
   passe a 2,2 comme sur la barre du haut du panneau (01/10/2026). */
body.client-app .cx-ico svg { stroke-width: 2; }
body.client-app .cx-ico:hover { background: var(--brand-50); }
body.client-app .cx-avatar { border-radius: 999px; }

/* ---------- carte du haut : LE CADRE DEMANDE PAR LE CLIENT (02/10/2026) -------
   Le client a montre la carte qu'il veut — bleu nuit, grand rayon, posee sur fond
   pale — et demande « change le cadre … exactement comme sur l'image ». L'habillage
   2 repeignait cette carte en SURFACE CLAIRE (fond de page, liseré de 1 px, coche
   de marque a gauche) : on lui rend son DESSIN D'ORIGINE, le degrade bleu nuit de
   la marque et son orbe de lumiere, en GARDANT la geometrie du 01/10 (rayon 26,
   rembourrage 13/15/17, titre 16 px, bouton de copie 34 px). */
body.client-app .cx-hero {
  position: relative; overflow: hidden; border-radius: var(--cx-r-lg);
  padding: 14px 16px 14px 20px;
  /* encre et couleur viennent du DESSIN DE BASE de la carte (encre blanche) ;
     le theme sombre garde lui aussi SA carte bleu nuit, celle de la base. */
  background: linear-gradient(150deg, var(--brand-900), var(--night) 62%);
  border: 0; box-shadow: 0 22px 50px -26px rgba(26, 22, 23, .8);
}
/* l'orbe de lumiere de la carte bleu nuit revient (l'image du client le porte) */
body.client-app .cx-hero::after { display: block; }
/* la coche de marque a gauche a QUITTE cette carte le 02/10/2026 : l'image montree
   par le client n'en porte pas (elle reste sur les autres surfaces du socle). */
body.client-app .cx-hero::before { display: none; }
/* (pas de variante sombre ici : celle de la base peint deja cette carte.) */
/* La pastille reprend celle de l'image : arrondie, contour clair translucide, texte
   blanc — le dessin du socle (fond pale, texte bleu) la rendait illisible sur la
   carte bleu nuit. Seul l'empilement au-dessus de l'orbe est garde. */
body.client-app .cx-pill { position: relative; z-index: 1; }
body.client-app .cx-hello-row { margin-top: 10px; }
/* Le titre garde sa TAILLE du 01/10 ; sa couleur vient du dessin bleu nuit
   (encre blanche de la carte). Le mot de marque prend le bleu clair de l'image,
   celui de la carte visiteuse : « exactement comme sur l'image ». */
body.client-app .cx-hello { font-size: 18px; }
/* 02/10/2026 — capture du client : un pseudo long passait sur TROIS lignes et faisait
   grandir la carte du haut ; la salutation tenait donc sur UNE ligne, coupee par des
   points de suspension (le pseudo entier restait copiable par le bouton d'a cote).
   MEME JOUR, demande suivante : « supprime Bonjour <pseudo> ». La salutation a donc
   disparu et c'est le TITRE de bienvenue qui occupe cette ligne, avec le meme bouton
   de copie — la regle ci-dessous sert desormais au titre : si la marque s'allonge un
   jour, elle est coupee au lieu de faire grandir la carte. `cx-hello-long` n'est plus
   pose par personne : sa regle dort, prete si la salutation revient. */
body.client-app .cx-hello-row .cx-hello {
  display: flex; align-items: baseline; gap: 6px; min-width: 0; overflow-wrap: normal;
}
body.client-app .cx-hello-row .cx-hello > b {
  min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}
body.client-app .cx-hello-row .cx-hello.cx-hello-long { font-size: 14px; }
/* Le bouton de copie redevient le CARRE BLANC de la carte bleu nuit (fond blanc
   assume, deja dans la liste des blancs autorises d'ui_check) ; sa TAILLE reste
   celle du 01/10 (38 puis 34 px sur telephone). */
body.client-app .cx-copy {
  width: 38px; height: 38px; border-radius: var(--cx-r-sm); border: 0;
  background: var(--surface); color: var(--slate-900);
}

/* ---------- Depot / Retrait : deux CARTES teintees cote a cote ----------
   Habillage de l'espace client : memes cartes que partout (voir plus haut), mais
   angles francs et cerne de l'habillage, et sans ombre portee. Le bleu et l'or
   sont ceux de la maison. */
body.client-app .cx-acts { gap: 10px; margin-top: 16px; }
body.client-app .cx-act {
  border-radius: var(--cx-r-lg); border: 1px solid var(--cx-cerne); box-shadow: var(--cx-flat);
  padding: 12px 12px 14px;
}
body.client-app .cx-act-ico { width: 38px; height: 38px; border-radius: 999px; margin-bottom: 9px; }

/* CARTES D'ACTION EN VERRE (demande du client, 30/09/2026 : « maintenant rend le
   transparent comme du verre »). Du verre, ce sont DEUX choses ensemble, jamais l'une
   sans l'autre : une TEINTE translucide (les jetons --act-* a 45 % : le fond de page
   compose la couleur) ET un FLOU de ce qu'il y a derriere (backdrop-filter) — sans le
   flou, une transparence ne se lit pas comme du verre, juste comme une couleur delavee.
   L'ENCRE, elle, change avec le THEME, et c'est obligatoire : la vitre claire du jour
   exige une encre SOMBRE (du blanc sur une vitre pale tombe a 2:1, illisible) et la
   vitre composee sur la nuit, elle, est foncee : elle exige une encre BLANCHE. Ce sont
   donc les deux seules lignes du client qui basculent la nuit. Mesures ui_check
   9quinquies : 4,9:1 a 10,8:1 le jour, 7,8:1 a 12,5:1 la nuit (AA demande 4,5:1). */
body.client-app .cx-act { backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px); }
body.client-app .cx-act-dep { color: var(--brand-900); }
body.client-app .cx-act-wd { color: var(--act-encre-vert); }
body.client-app .cx-act-ico { background: rgba(255, 255, 255, .55); }
/* UNE REGLE PAR CARTE, sur une seule ligne : les controles de ui_check ne lisent que
   la DERNIERE ligne d'un selecteur etale (une liste « .cx-act-dep, .cx-act-wd { » fait
   disparaitre la premiere des deux). */
:root[data-theme="dark"] body.client-app .cx-act-dep { color: var(--slate-800); }
:root[data-theme="dark"] body.client-app .cx-act-wd { color: var(--slate-800); }
:root[data-theme="dark"] body.client-app .cx-act-ico { background: rgba(255, 255, 255, .18); }
body.client-app .cx-msg { border-radius: var(--cx-r); border-color: var(--cx-cerne); box-shadow: var(--cx-flat); }
body.client-app .cx-msg-ico { border-radius: 999px; }
body.client-app .cx-suivi { border-radius: var(--radius-lg); border-color: var(--cx-cerne); box-shadow: var(--cx-flat); }
body.client-app .cx-suivi-ico { border-radius: 999px; }
body.client-app .cx-suivi-go { border-radius: 999px; }

/* ---------- raccourcis : boutons courts, en pastilles ---------- */
body.client-app .cx-racc-bas { margin-top: 14px; }
body.client-app .cx-racc-a {
  display: inline-flex; align-items: center; gap: 8px; padding: 8px 15px;
  border-radius: 999px; font: inherit; font-size: 13.5px; font-weight: 600;
  color: var(--slate-700); background: var(--surface); border: 1px solid var(--cx-cerne);
  box-shadow: var(--cx-flat); -webkit-backdrop-filter: none; backdrop-filter: none;
}
body.client-app .cx-racc-a svg { color: var(--brand-600); }
:root[data-theme="dark"] body.client-app .cx-racc-a svg { color: var(--brand-300); }

/* ---------- reseaux sociaux : vignettes carrees ---------- */
body.client-app .cx-social { margin-top: 22px; }
body.client-app .cx-social-t {
  font-size: 11px; text-transform: uppercase; letter-spacing: .14em; color: var(--slate-500);
}
body.client-app .cx-soc {
  width: 46px; height: 46px; border-radius: 14px; border: 1px solid var(--cx-cerne);
  box-shadow: var(--cx-flat);
}

/* ---------- carte de tournoi : angles francs, cerne ---------- */
body.client-app .cx-tournoi {
  border-radius: var(--cx-r-lg); border: 1px solid var(--cx-cerne); box-shadow: var(--cx-flat);
}

/* ---------- barre du bas : pilule d'accueil a gauche, icones a droite ----------
   (30/09/2026, 2e demande du client : « colle exactement a leur barre »). La barre
   est un BANDEAU DETACHE des bords, comme la leur : elle flotte a 10 px du bord
   gauche et du bord droit, et se pose 10 px au-dessus du bord bas. L'entree
   active y est la pilule teintee, les autres des icones seules. */
/* La reserve suit la ZONE DE GESTES comme la barre elle-meme (`margin: 0 10px
   calc(10px + env(safe-area-inset-bottom))` juste en dessous) : sans ce terme,
   la barre descend plus bas que la reserve et la derniere ligne de la page
   reste coincee sous la barre (signale par le client le 03/10/2026). */
body.client-app .app-shell { padding-bottom: calc(104px + env(safe-area-inset-bottom)); }
/* BARRE DU BAS : pastille flottante arrondie, entree active en pilule pleine.
   (01/10/2026 — le client a laisse la main : « c'est pas joli, tu peux faire a ta
   guise ». La ligne en vallee est retiree.) Une seule capsule, arrondie aux DEUX
   bouts, posee a 10 px des bords : le fond commun RELIE les trois entrees, et
   l'active s'y detache en pilule pleine a la couleur de la maison. Fin, opaque,
   ombre douce : rien de decoratif qui puisse alourdir. */
body.client-app .bottomnav {
  background: var(--surface);
  border: 1px solid var(--cx-cerne);
  border-radius: 999px;
  margin: 0 10px calc(10px + env(safe-area-inset-bottom));
  padding: 6px 8px;
  -webkit-backdrop-filter: none; backdrop-filter: none;
  box-shadow: 0 16px 32px -22px rgba(38, 34, 35, .50);
}
body.client-app .bottomnav .item { border-radius: 999px; padding: 9px 14px; }
body.client-app .bottomnav .item.active {
  background: var(--brand-600);
  color: var(--on-brand);
  padding: 9px 16px;
  box-shadow: 0 10px 20px -14px rgba(38, 34, 35, .75);
}
:root[data-theme="dark"] body.client-app .bottomnav {
  background: var(--surface);
  border-color: rgba(255, 255, 255, .10);
}
:root[data-theme="dark"] body.client-app .bottomnav .item.active { background: var(--brand-500); }
/* LARGE ECRAN (>= 721 px) : la barre bornee doit etre RECENTREE ICI.
   Le bloc « grand ecran » (plus haut dans la feuille) la pose par une MARGE
   NEGATIVE (`left: 50%; margin-left: -344px; width: 688px`). Or la regle du client
   juste au-dessus porte un `margin: 0 10px ...` PLUS SPECIFIQUE (0,2,1 contre
   0,1,0) : elle ecrasait ce -344px et la barre partait du MILIEU de l'ecran en
   debordant a droite — « Historique » hors ecran, seule la pastille « Accueil » et
   l'icone du milieu restaient visibles. Constat du client le 30/09/2026, capture a
   l'appui : bord gauche de la barre mesure a 382 px sur une page de 744 px, soit
   exactement 50 % + les 10 px de marge annonces par le calcul du CSS.
   On repose donc la geometrie bornee du client en ecrasant sa marge LATERALE ; sa
   marge BASSE (10 px + zone de gestes) n'est pas touchee, et sur telephone
   (< 721 px) cette regle ne s'applique pas : la barre reste bord a bord. */
@media (min-width: 721px) {
  body.client-app .bottomnav {
    left: 50%; right: auto; margin-left: -344px; margin-right: 0;
    width: 688px; max-width: calc(100% - 32px);
  }
}
/* (la silhouette « vallees et montagnes » de la reference est retiree partout depuis
   le 30/09/2026 : le bord haut de la barre est arrondi, elle depasserait dans les
   coins. La regle du bloc habillage 2 qui la masquait dans l'espace client n'a plus
   d'objet et a ete retiree avec elle.) */
/* ---------- panneau du compte : angles francs, cerne ---------- */
body.client-app .cx-acc {
  border-radius: var(--cx-r-lg); border: 1px solid var(--cx-cerne);
  box-shadow: 0 18px 40px -20px rgba(26, 22, 23, .5);
}
body.client-app .cx-acc-head { border-bottom: 1px solid var(--cx-cerne); }
body.client-app .cx-acc-row + .cx-acc-row { border-top: 1px solid var(--cx-cerne); }
body.client-app .cx-acc-sep { border-top: 1px solid var(--cx-cerne); }

/* ---------- ecrans de connexion / inscription (habillage 2) ---------- */
/* Le fond constelle de la reference (un reseau de points relies) disparait : la
   page reste sombre, sobre, avec son seul halo de marque. */
body.client-app.auth-page .auth-shell::before { display: none; }
/* la coche de marque, la meme que sur le bandeau d'accueil */
body.client-app.auth-page .auth-card::before {
  content: ''; position: absolute; left: 0; right: 0; top: 0; height: 3px; pointer-events: none;
  background: linear-gradient(90deg, var(--brand-600), var(--brand-300) 62%, transparent);
}
body.client-app.auth-page .auth-logo { border-radius: 11px; box-shadow: none; }
/* champs : angles francs de la maison (la reference etait en rayon 20) */
body.client-app.auth-page .fx-in { border-radius: var(--cx-r); }
body.client-app.auth-page .auth-soc-row a { border-radius: 14px; }


/* =====================================================================
   ESPACE CLIENT — socle d'habillage commun (30/09/2026)
   Demande du client : « moderniser l'interface client, toutes ses pages ».
   Plutot que de repeindre chaque ecran a la main, on remonte le SOCLE que
   tous les ecrans partagent deja (.card, .card-hd, .card-bd, .list-item,
   .tabs, .notice, .kpi, .btn) : chaque page herite du meme air sans qu'on
   touche a son contenu. Tout est borne a `body.client-app` — le panneau
   d'administration et les ecrans de connexion ne bougent pas d'un pixel.
   Aucune couleur neuve : uniquement les variables de la palette (et les
   familles emerald/rose/sky/amber ont leur variante de nuit, verifiee par
   les controles de contraste de ui_check).
   ===================================================================== */

/* ---- en-tete d'ecran : tuile d'icone, titre, sous-titre ---- */
body.client-app .ui-head { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; }
/* ---- tuile d'icone : en-tete d'ecran ET en-tete de carte ----
   La palette fait tout le travail : --brand-50 bascule seule en bleu nuit. */
body.client-app .ui-ico { flex: 0 0 auto; width: 42px; height: 42px; border-radius: 14px;
  display: grid; place-items: center; background: var(--brand-50); color: var(--brand-600); }
body.client-app .ui-ico.sm { width: 32px; height: 32px; border-radius: 10px; }
body.client-app .ui-ico.sm svg { width: 18px; height: 18px; }
body.client-app .ui-head .ui-t { font-size: 21px; font-weight: 700; letter-spacing: -.012em; line-height: 1.15; }
body.client-app .ui-head .ui-s { font-size: 12.5px; color: var(--slate-500); margin-top: 2px; }

/* ---- cartes : un seul air dans tout l'espace client ---- */
body.client-app .card { border-radius: 18px;
  box-shadow: 0 1px 2px rgba(26, 22, 23, .05), 0 16px 32px -26px rgba(26, 22, 23, .55); }
body.client-app .card-hd { padding: 14px 16px; min-height: 52px; }
body.client-app .card-bd { padding: 16px; }
body.client-app .card-ft { padding: 12px 16px; }

/* ---- lignes de liste : cible tactile, tuile d'icone, etat presse ---- */
/* Depuis le 01/10/2026 l'historique n'utilise plus « .list-item » : ses
   operations vivent dans « .hist-card ». La cible de doigt, l'ecart et l'etat
   presse se posent donc AUSSI sur cette classe — sinon les cartes de
   l'historique perdent 62 px de hauteur et le retour au toucher. */
body.client-app .list-item, body.client-app .hist-card { min-height: 62px; padding: 13px 16px; gap: 12px;
  transition: background .15s ease; }
body.client-app .list-item:active, body.client-app .list-item:hover,
body.client-app .hist-card:active, body.client-app .hist-card:hover { background: var(--slate-50); }
body.client-app .li-ico { flex: 0 0 auto; width: 40px; height: 40px; border-radius: 13px;
  display: grid; place-items: center; background: var(--brand-50); color: var(--brand-600); }
body.client-app .li-ico.i-emerald { background: var(--emerald-50); color: var(--emerald-600); }
body.client-app .li-ico.i-rose { background: var(--rose-50); color: var(--rose-600); }
body.client-app .li-ico.i-sky { background: var(--sky-50); color: var(--sky-600); }
body.client-app .li-ico.i-amber { background: var(--amber-50); color: var(--amber-600); }

/* ---- onglets de filtre : pilules plus franches, doigt compris ---- */
body.client-app .tabs { gap: 8px; padding-bottom: 4px; }
body.client-app .tab { min-height: 38px; display: inline-flex; align-items: center; padding: 8px 14px; }

/* ---- bandeaux d'information : memes couleurs d'etat, plus ronds ---- */
body.client-app .notice { border-radius: 16px; padding: 13px 14px; }
body.client-app .empty { padding: 30px 16px; }
body.client-app .empty .strong { font-size: 15px; }

/* ---- compteurs : alignes sur les tuiles de « Mon compte » ---- */
body.client-app .kpi { border-radius: 16px; padding: 14px; }

/* ---- champs et boutons : hauteur de doigt, coins coherents ---- */
body.client-app .input, body.client-app .select, body.client-app textarea.input { min-height: 46px; }
body.client-app .btn { min-height: 42px; }
body.client-app .btn-sm { min-height: 34px; }

/* ---- accueil : la carte du haut, les tuiles rondes et la banniere de tournoi
   prennent les memes rayons et la meme lumiere que le reste de l'espace client
   (la silhouette de la barre du bas et la disposition, elles, ne bougent pas). ---- */
/* CARTE DU HAUT : COMPACTE ET PLUS RONDE (01/10/2026, capture du client :
   « reduit et arrondit le »). Le socle a le DERNIER MOT sur cette carte —
   c'est ICI qu'on change ses mesures, jamais dans l'habillage 2 plus haut.
   Rayon 22 -> 26 px ; rembourrage 20 -> 13/17 px ; et les trois textes qui
   faisaient la hauteur : titre 18 -> 16 px, question 26 -> 19 px, phrase de
   service 13,5 -> 12 px. Le bouton de copie suit la meme echelle (38 -> 34 px,
   et son icone 22 -> 18 via homeView dans app.js). */
body.client-app .cx-hero { border-radius: 26px; padding: 13px 15px 13px 17px; }
body.client-app .cx-hello-row { margin-top: 7px; }
body.client-app .cx-hello { font-size: 16px; }
body.client-app .cx-copy { width: 34px; height: 34px; border-radius: 11px; }
body.client-app .cx-ask { margin-top: 9px; font-size: 19px; }
body.client-app .cx-ask-sub { margin-top: 5px; font-size: 12px; }
body.client-app .cx-hero::before { top: 10px; bottom: 10px; }
/* les deux cartes d'action de l'accueil (30/09/2026) : memes rayons et meme
   lumiere que le reste de l'espace client.
   ARRONDI (30/09/2026, demande du client : « arrondit bien les boutons de
   l'interface ») : 18 px -> 22 px, le rayon de la carte du haut. CE BLOC EST LE
   DERNIER MOT sur les rayons de l'accueil (il vient apres le bloc habillage 2) :
   c'est ICI qu'on change celui des deux boutons Depot / Retrait, pas plus haut. */
body.client-app .cx-act { border-radius: 22px; }
body.client-app .cx-msg { border-radius: 22px; }
body.client-app .cx-suivi { border-radius: 22px; }
body.client-app .cx-tournoi { border-radius: 22px; }
/* Les deux raccourcis « Mes IDs » et « Parrainage » gardent LEUR TAILLE ET LEUR
   FORME D'ORIGINE (petits boutons cote a cote, `.cx-racc-a` plus haut). Une
   version « carte » plus haute a ete essayee le 30/09/2026 et refusee par le
   client : « c'est trop gros ». Ne pas la remettre. */

/* =====================================================================
   LE CLAVIER DU TELEPHONE (30/09/2026)
   Capture du client au depôt, étape 3 : le champ « Numero mobile money » et sa
   phrase etaient CACHES SOUS la barre du bas, clavier ouvert. La barre est
   `position: fixed` : le navigateur remonte bien le champ juste au-dessus du
   clavier… et la barre se posait exactement là.
   Des qu'un champ de saisie prend le focus, la barre s'efface donc
   (`data-clavier="1"` sur <body>, posé par suivreClavier() dans app.js) ; elle
   revient quand le champ est quitte.
   La regle est bornee au client (`body.client-app[...]`) comme TOUT ce bloc : c'est
   aussi ce qui la fait gagner sur `body.client-app .bottomnav`, avec une
   specificite superieure. Ne pas la remonter plus haut.
   ===================================================================== */
body.client-app[data-clavier="1"] .bottomnav { display: none; }
