@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@300;400;500;600;700&display=swap');

/* ==========================================================================
   EKBANKING — DESIGN SYSTEM DÉFINITIF
   --------------------------------------------------------------------------
   Langage visuel Saham Bank : thème CLAIR, vert forêt + crème, Montserrat,
   titres légers, boutons pilule, cartes à plat, sections alternées blanc/crème.

   Fichier AUTONOME : seule dépendance externe = la police Google Fonts.
   Sert les 3 frontends : /  (vitrine)  ·  /app/  (client)  ·  /admin/ (admin).

   DISTINCTION CLIENT / ADMIN
   La seule différence est la topbar : blanche côté client, vert forêt plein
   côté admin. Elle est déclenchée par `<body class="admin">` — et, en filet de
   sécurité, par la présence du `<small>ADMIN</small>` dans la marque
   (`.topbar:has(.brand small)`), présent uniquement dans admin-panel/.

   CÂBLAGE HTML ATTENDU (à faire par les agents de conversion)
   1. Les 11 pages d'app remplacent leur <link href="style.css"> par
      <link rel="stylesheet" href="/shared/theme.css">
   2. public-site/index.html SUPPRIME son bloc <style> (l.7-47, thème sombre)
      et charge <link rel="stylesheet" href="/shared/theme.css">
   3. Les 6 pages de admin-panel/ portent <body class="admin">
      (login.html compris : `body.admin .auth-container`).

   SECTIONS
    1. Tokens              8. Tableaux
    2. Base / Typographie  9. Badges, messages, états vides
    3. Layout             10. KPI (back-office)
    4. Topbar & nav       11. Modale
    5. Boutons            12. Vitrine
    6. Formulaires        13. Variante admin
    7. Cartes             14. Accessibilité & préférences système
                          15. Responsive  ·  15 bis. Cibles tactiles
                          16. Impression
                          17. Utilitaires optionnels
   ========================================================================== */


/* ==========================================================================
   1. TOKENS
   ========================================================================== */

:root {
  /* --- Couleurs de marque (valeurs mesurées sur sahambank.com) ----------- */
  --ek-green:        #213A38;  /* vert forêt profond — couleur signature     */
  --ek-green-hover:  #2C504D;  /* survol des aplats verts                    */
  --ek-green-press:  #172A29;  /* état pressé                                */
  --ek-green-soft:   #E8EDEC;  /* voile vert très pâle                       */
  --ek-green-050:    #F2F5F4;
  --ek-mint:         #5CA785;  /* vert menthe — 2e CTA                       */
  --ek-mint-hover:   #4E9273;
  --ek-mint-ink:     #2E7D57;  /* menthe assombri : lisible en TEXTE (5,0:1) */
  --ek-cream:        #F0EDDE;  /* crème chaud — bandes de sections           */
  --ek-cream-soft:   #FAF8F1;  /* crème dilué — survol de ligne              */
  --ek-cream-line:   #E4DFCA;  /* filet de la bande crème                    */
  --ek-gold:         #F1D600;  /* or — accent ponctuel, focus sur vert       */
  --ek-gold-warm:    #FBBE0A;
  --ek-red:          #BC2F1E;  /* alertes (5,9:1 sur blanc)                  */
  --ek-red-hover:    #A02718;

  /* --- Neutres ----------------------------------------------------------- */
  --ek-ink:          #0C1414;  /* encre quasi-noire — titres, corps          */
  --ek-ink-soft:     #33403F;  /* encre adoucie — labels                     */
  --ek-gray:         #666666;  /* gris texte de référence (5,7:1 sur blanc)  */
  --ek-gray-strong:  #5A5A52;  /* gris des très petits textes (7,0:1)        */
  --ek-placeholder:  #6E6A60;  /* placeholders — 5,4:1 sur blanc (AA)        */
  --ek-white:        #FFFFFF;
  --ek-line:         #E4E1D6;  /* filet fin, teinté crème                    */
  --ek-line-soft:    #EEEBE0;
  --ek-line-strong:  #CFCBBC;  /* séparateur marqué                          */
  --ek-field:        #FFFFFF;
  /* Bordure de champ : seul indice visuel du contrôle (fond du champ = fond
     de page) → doit tenir WCAG 1.4.11. 3,99:1 sur blanc, 3,75:1 sur
     --ek-cream-soft, 3,39:1 sur --ek-cream. Ne pas éclaircir au-delà. */
  --ek-field-line:   #857F70;  /* bordure de champ                           */
  --ek-field-line-hover: #6F6A5C;  /* survol : toujours plus foncé que ci-dessus */
  --ek-field-disabled:   #F5F4EF;  /* fond du champ désactivé                */

  /* --- Vert « validation » : aplat lisible en blanc (6,4:1) -------------- */
  --ek-ok-solid:       #1B6B4C;
  --ek-ok-solid-hover: #155A3E;

  /* --- États (fond pâle + encre saturée, tous >= 6:1) -------------------- */
  --ek-warn-bg:  #FDF3DA;  --ek-warn-ink:  #7A5205;  --ek-warn-line:  #E9D08A;
  --ek-ok-bg:    #DCEEE4;  --ek-ok-ink:    #1B5E43;  --ek-ok-line:    #B7DCC6;
  --ek-bad-bg:   #FBE4E0;  --ek-bad-ink:   #93251A;  --ek-bad-line:   #EFC0B7;
  --ek-info-bg:  #E8EDEC;  --ek-info-ink:  #1D3634;  --ek-info-line:  #CBD8D6;

  /* --- Désactivé : couple explicite, 5,3:1 (jamais d'opacity) ------------ */
  --ek-disabled-bg:   #E9E7DD;
  --ek-disabled-ink:  #5F5D55;

  /* --- Sur aplat vert ---------------------------------------------------- */
  --ek-on-green:        #FFFFFF;
  --ek-on-green-muted:  #C6D6D1;  /* 8,1:1 sur #213A38                       */
  --ek-on-green-accent: #9FD3B8;
  --ek-on-green-link:   #BFE3D1;  /* liens posés sur aplat vert              */

  /* --- Typographie ------------------------------------------------------- */
  --ek-font: 'Montserrat', 'Segoe UI', system-ui, -apple-system,
             BlinkMacSystemFont, Roboto, Helvetica, Arial, sans-serif;
  --ek-font-mono: ui-monospace, SFMono-Regular, 'Cascadia Mono', Menlo,
                  Consolas, monospace;

  --ek-fs-xs:   0.6875rem;  /* 11px — sur-titres, labels de tableau, badges  */
  --ek-fs-sm:   0.8125rem;  /* 13px — boutons, mentions, tableaux            */
  --ek-fs-base: 0.9375rem;  /* 15px — corps                                  */
  --ek-fs-md:   1.0625rem;  /* 17px — chapô                                  */
  --ek-fs-h3:   1.375rem;   /* 22px                                          */
  --ek-fs-h2:   1.875rem;   /* 30px — titre de section, poids 400            */
  --ek-fs-h1:   2.25rem;    /* 36px                                          */

  --ek-lh:        1.65;
  --ek-lh-tight:  1.2;
  --ek-track:      0.02em;
  --ek-track-caps: 0.09em;

  /* --- Rayons ------------------------------------------------------------ */
  --ek-r-card:  10px;   /* signature Saham                                   */
  --ek-r-field:  8px;
  --ek-r-pill: 999px;   /* boutons pilule                                    */

  /* --- Ombres (la banque est « à plat » : le filet porte la profondeur) --- */
  --ek-shadow-none:  none;
  --ek-shadow-soft:  0 1px 2px rgba(12, 20, 20, 0.04);
  --ek-shadow-lift:  0 6px 20px rgba(12, 20, 20, 0.10);
  --ek-shadow-modal: 0 24px 60px rgba(12, 20, 20, 0.22);

  /* --- Espacements ------------------------------------------------------- */
  --ek-sp-1:  4px;   --ek-sp-2:  8px;   --ek-sp-3: 12px;   --ek-sp-4: 16px;
  --ek-sp-5: 24px;   --ek-sp-6: 32px;   --ek-sp-7: 48px;   --ek-sp-8: 72px;

  /* --- Divers ------------------------------------------------------------ */
  --ek-container: 1080px;
  --ek-focus:     #2E7D57;  /* anneau de focus : 5,0:1 sur blanc             */
  --ek-focus-ring: 0 0 0 3px rgba(92, 167, 133, 0.30);
  --ek-t-fast: 130ms cubic-bezier(0.4, 0, 0.2, 1);
  --ek-t:      180ms cubic-bezier(0.4, 0, 0.2, 1);

  /* ======================================================================
     ALIAS DE COMPATIBILITÉ — NE PAS RENOMMER
     Le JS et les gabarits écrivent des styles EN LIGNE qui consomment ces
     noms hérités du thème sombre :
       app.js:66      <span style="color:var(--text-dim)">
       dashboard.html <td style="color:var(--success)|var(--danger)">
       login.html:11  <span style="color:var(--accent-2)">
     Ils sont ici remappés sur la palette CLAIRE, tous >= 4,5:1 sur blanc.
     ====================================================================== */
  --bg:        var(--ek-white);
  --surface:   var(--ek-white);
  --surface-2: var(--ek-cream);
  --border:    var(--ek-line);
  --text:      var(--ek-ink);
  --text-dim:  var(--ek-gray);        /* 5,7:1 sur blanc                     */
  --accent:    var(--ek-green);
  --accent-2:  var(--ek-mint-ink);    /* 5,0:1 sur blanc                     */
  --success:   var(--ek-ok-solid);    /* 6,4:1 sur blanc                     */
  --danger:    var(--ek-red);         /* 5,9:1 sur blanc                     */
  --warning:   var(--ek-warn-ink);
  --radius:    var(--ek-r-card);

  font-family: var(--ek-font);
  color-scheme: light;
}


/* ==========================================================================
   2. BASE / TYPOGRAPHIE
   ========================================================================== */

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

/* scroll-behavior est posé ICI et non sur `body` : c'est l'élément de
   défilement du document. Il est neutralisé au § 14 sous
   prefers-reduced-motion (scroll-behavior: auto !important). */
html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  min-height: 100vh;
  background: var(--ek-white);
  color: var(--ek-ink);
  font-family: var(--ek-font);
  font-size: var(--ek-fs-base);
  font-weight: 400;
  line-height: var(--ek-lh);
  /* Un IBAN, un email ou un numéro de compte sont des chaînes SANS espace :
     sur un écran de 320 px ils élargiraient la page entière. On autorise la
     coupure en dernier recours — `white-space: nowrap` continue de primer
     là où une valeur ne doit surtout pas être coupée (montants, badges). */
  overflow-wrap: break-word;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

::selection { background: var(--ek-mint); color: var(--ek-white); }

img, svg, video { max-width: 100%; height: auto; }

hr { border: 0; border-top: 1px solid var(--ek-line); margin: var(--ek-sp-5) 0; }

/* --- Titres : LÉGERS. C'est la signature du modèle. --------------------- */
h1, h2, h3, h4 {
  color: var(--ek-ink);
  margin: 0 0 var(--ek-sp-4);
  line-height: var(--ek-lh-tight);
  letter-spacing: -0.005em;
}
h1 { font-size: clamp(1.75rem, 1.2rem + 2vw, var(--ek-fs-h1)); font-weight: 300; }
h2 { font-size: clamp(1.5rem, 1.1rem + 1.4vw, var(--ek-fs-h2)); font-weight: 400; line-height: 1.2; }
h3 { font-size: var(--ek-fs-h3); font-weight: 600; letter-spacing: 0; }
h4 { font-size: 1rem; font-weight: 600; }

p { margin: 0 0 var(--ek-sp-4); }
p:last-child { margin-bottom: 0; }

small { font-size: var(--ek-fs-sm); }
strong, b { font-weight: 600; }

/* Les liens restent SOULIGNÉS au repos : la couleur seule ne suffit pas
   à les identifier (WCAG 1.4.1). Le soulignement est retiré uniquement sur
   les éléments qui ont une autre affordance : .brand, .nav a, .btn, .badge. */
a {
  color: var(--ek-green);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-decoration-color: color-mix(in srgb, var(--ek-green) 40%, transparent);
  text-underline-offset: 3px;
  transition: color var(--ek-t-fast), text-decoration-color var(--ek-t-fast);
}
a:hover { color: var(--ek-mint-ink); text-decoration-color: currentColor; }

/* Numéros de compte, IBAN, identifiants techniques */
code, kbd, samp {
  font-family: var(--ek-font-mono);
  font-size: 0.92em;
  background: var(--ek-cream);
  border-radius: 4px;
  padding: 1px 5px;
}

/* --- Focus clavier global. On n'y met NI border-radius NI background :
       ces propriétés écraseraient la pilule des boutons au focus. -------- */
:focus-visible {
  outline: 3px solid var(--ek-focus);
  outline-offset: 2px;
}
:focus:not(:focus-visible) { outline: none; }


/* ==========================================================================
   3. LAYOUT — .container / .auth-container / .row / .section-title / .actions
   ========================================================================== */

.container {
  max-width: var(--ek-container);
  margin: 0 auto;
  padding: var(--ek-sp-6) clamp(16px, 4vw, 24px) var(--ek-sp-8);
}
.container > h1:first-child { margin-top: 0; margin-bottom: var(--ek-sp-5); }

/* --- Écran d'authentification (login client, register, login admin) ----- */
.auth-container {
  max-width: 430px;
  margin: 7vh auto;
  padding: clamp(24px, 5vw, 40px);
  background: var(--ek-white);
  border: 1px solid var(--ek-line);
  border-top: 3px solid var(--ek-green);
  border-radius: var(--ek-r-card);
  box-shadow: var(--ek-shadow-soft);
}
/* Le <h1> de ces pages EST le logotype (soit du texte brut côté admin,
   soit un <a class="brand"> côté client) : on le traite comme tel. */
.auth-container h1 {
  margin: 0 0 var(--ek-sp-1);
  font-size: 1.625rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--ek-green);
  text-align: center;
}
.auth-container h1 span { color: var(--ek-mint-ink); font-weight: 400; }
.auth-container h1 .brand { font-size: inherit; letter-spacing: inherit; }
.auth-container > p { text-align: center; }
.auth-container form { margin-top: var(--ek-sp-4); }
.auth-container button[type="submit"],
.auth-container .btn { width: 100%; margin-top: var(--ek-sp-5); }
.auth-container .hint { text-align: center; }
/* La carte d'authentification est étroite (430px) : sans cette réduction, la
   paire Prénom / Nom passe à la ligne au lieu de rester côte à côte. */
.auth-container .row { gap: var(--ek-sp-3); }
.auth-container .row > * { flex: 1 1 130px; min-width: 130px; }

/* --- Rangée souple : deux champs côte à côte, empilés en mobile -------- */
.row {
  display: flex;
  gap: var(--ek-sp-5);
  flex-wrap: wrap;
}
.row > * { flex: 1 1 220px; min-width: 200px; }
/* Cas réel : <div style="flex:0;"><button>Appliquer</button></div> dans le
   formulaire d'ajustement. Le flex:0 EN LIGNE + un min-width:0 ferait
   déborder le bouton ; on rend cette cellule auto-dimensionnée. */
.row > *:not(:only-child):has(> button:only-child) {
  flex: 0 0 auto !important;
  min-width: 0;
}

/* --- Titre de section : filet de séparation, actions alignées à droite -- */
.section-title {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--ek-sp-4);
  flex-wrap: wrap;
  margin: var(--ek-sp-7) 0 var(--ek-sp-4);
  padding-bottom: var(--ek-sp-3);
  border-bottom: 1px solid var(--ek-line);
}
.section-title h1,
.section-title h2,
.section-title h3 { margin: 0; }

/* --- Groupe de boutons -------------------------------------------------- */
.actions {
  display: flex;
  align-items: center;
  gap: var(--ek-sp-2);
  flex-wrap: wrap;
}
/* GARDE-FOU : <td class="actions"> existe réellement (dashboard, transfers,
   cards). Un display:flex sortirait la cellule du modèle de table (perte du
   vertical-align, filet de ligne brisé). On la remet en table-cell. */
td.actions {
  display: table-cell;
  vertical-align: middle;
  white-space: nowrap;
}
td.actions > button,
td.actions > .btn { margin: 2px 4px 2px 0; }


/* ==========================================================================
   4. TOPBAR & NAV
   ========================================================================== */

.topbar,
body > header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ek-sp-4);
  flex-wrap: wrap;
  padding: 16px clamp(16px, 4vw, 40px);
  background: var(--ek-white);
  border-bottom: 1px solid var(--ek-line);
  position: sticky;
  top: 0;
  z-index: 40;
}

/* --- Marque : « EKBANKING » sur UNE ligne, mention sur la suivante ------
   Markup réel : EK<span>BANKING</span><small>ADMIN</small>. Un display:flex
   ferait de « EK » un item séparé et empilerait le logotype sur 2 ou 3
   lignes : inline-block + small en block donne exactement le rendu voulu. */
.brand {
  display: inline-block;
  line-height: 1.1;
  font-size: 1.2rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--ek-green);
  text-decoration: none;
}
.brand:hover { color: var(--ek-green); text-decoration: none; }
/* Logo téléversé par l'administrateur (data-ek="logo") : posé en premier
   enfant de .brand, il précède le nom écrit sur la même ligne. */
.brand img {
  height: 28px;
  width: auto;
  margin-right: var(--ek-sp-2);
  vertical-align: middle;
}
.brand span { color: var(--ek-mint-ink); font-weight: 400; }
.brand small {
  display: block;
  margin-top: 3px;
  font-size: 0.5625rem;
  font-weight: 600;
  letter-spacing: 0.20em;
  text-transform: uppercase;
  color: var(--ek-gray);
}

/* --- Navigation : libellés en petites capitales (repère Saham) --------- */
.nav,
body > header nav {
  display: flex;
  align-items: center;
  gap: clamp(12px, 2vw, 26px);
  flex-wrap: wrap;
}

.nav a,
body > header nav a {
  position: relative;
  display: inline-flex;
  align-items: center;
  /* 44 px de haut : c'est la cible tactile minimale. Le padding vertical
     seul donnait 34 px — un doigt rate une cible de cette hauteur. */
  min-height: 44px;
  padding: 8px 0;
  color: var(--ek-ink-soft);
  font-size: var(--ek-fs-xs);
  font-weight: 500;
  letter-spacing: var(--ek-track-caps);
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  transition: color var(--ek-t-fast);
}
.nav a::after,
body > header nav a::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 2px;
  /* Le filet de survol est ROUGE : c'est la touche d'accent demandée, et elle
     ne sert QU'à ça. Le rouge reste réservé au survol et aux alertes — l'utiliser
     aussi pour l'onglet courant brouillerait les deux significations. */
  background: var(--ek-red);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--ek-t);
}
.nav a:hover,
body > header nav a:hover { color: var(--ek-green); text-decoration: none; }
.nav a:hover::after,
body > header nav a:hover::after { transform: scaleX(1); }
.nav a.active { color: var(--ek-green); font-weight: 600; }
/* L'onglet courant garde le vert de la marque : c'est un état, pas une action. */
.nav a.active::after { transform: scaleX(1); background: var(--ek-green); }
/* Sur la topbar verte de l'admin, le rouge foncé serait illisible : on l'éclaircit. */
body.admin .topbar .nav a::after { background: #F0705E; }

/* Le nom de l'utilisateur est injecté par renderNav() AVEC un style EN LIGNE
   (color:var(--text-dim);font-size:0.85rem). Deux protections cumulées :
   1) la variable --text-dim est redéfinie dans body.admin .topbar (§13) ;
   2) le !important ci-dessous garantit la taille et la résolution correcte. */
.nav span {
  color: var(--text-dim) !important;
  font-size: var(--ek-fs-xs) !important;
  letter-spacing: 0.04em;
}

/* Les CTA pilule logés dans un en-tête restent compacts et sans soulignement */
.topbar .btn,
body > header .btn { padding: 9px 22px; font-size: var(--ek-fs-sm); }
.topbar .btn::after,
body > header .btn::after { display: none; }


/* ==========================================================================
   5. BOUTONS — pilule, poids 500. Les <button> NUS sont primaires.
   ========================================================================== */

button,
.btn,
input[type="submit"],
input[type="button"] {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--ek-sp-2);
  padding: 10px 26px;
  border: 1px solid var(--ek-green);
  border-radius: var(--ek-r-pill);
  background: var(--ek-green);
  color: var(--ek-white);
  font-family: var(--ek-font);
  font-size: var(--ek-fs-sm);
  font-weight: 500;
  line-height: 1.35;
  letter-spacing: var(--ek-track);
  text-align: center;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color var(--ek-t-fast), border-color var(--ek-t-fast),
              color var(--ek-t-fast), transform var(--ek-t-fast);
}

button:hover,
.btn:hover,
input[type="submit"]:hover,
input[type="button"]:hover {
  background: var(--ek-green-hover);
  border-color: var(--ek-green-hover);
  color: var(--ek-white);
  text-decoration: none;
}
button:active,
.btn:active {
  background: var(--ek-green-press);
  border-color: var(--ek-green-press);
  transform: translateY(1px);
}
button:focus-visible,
.btn:focus-visible,
input[type="submit"]:focus-visible,
input[type="button"]:focus-visible {
  outline: 3px solid var(--ek-focus);
  outline-offset: 3px;
}

/* --- Secondaire : pilule ajourée. « Annuler », « Bloquer », « Voir la
       fiche ». Neutre par défaut — surtout PAS un aplat menthe. ---------- */
button.secondary,
.btn.secondary {
  background: transparent;
  color: var(--ek-green);
  border-color: var(--ek-line-strong);
}
button.secondary:hover,
.btn.secondary:hover {
  background: var(--ek-green-soft);
  border-color: var(--ek-green);
  color: var(--ek-green);
}
button.secondary:active,
.btn.secondary:active { background: var(--ek-green-soft); }

/* --- Menthe pleine : 2e CTA de la VITRINE uniquement (fidélité Saham).
   Scope volontairement étroit : .btn.secondary sert AUSSI de bouton
   « Annuler » dans la modale, qui doit rester ajouré.
   ⚠ Ne pas ajouter d'action secondaire discrète dans .topbar : elle
   basculerait en aplat menthe. Utiliser .btn.mint pour un menthe explicite. */
.hero .btn.secondary,
.topbar .btn.secondary,
body > header .btn.secondary,
.btn.mint {
  background: var(--ek-mint);
  border-color: var(--ek-mint);
  color: var(--ek-ink);
  font-weight: 600;
}
.hero .btn.secondary:hover,
.topbar .btn.secondary:hover,
body > header .btn.secondary:hover,
.btn.mint:hover {
  background: var(--ek-mint-hover);
  border-color: var(--ek-mint-hover);
  color: var(--ek-ink);
}

/* --- Validation / approbation ------------------------------------------ */
button.success,
.btn.success {
  background: var(--ek-ok-solid);
  border-color: var(--ek-ok-solid);
  color: var(--ek-white);
}
button.success:hover,
.btn.success:hover {
  background: var(--ek-ok-solid-hover);
  border-color: var(--ek-ok-solid-hover);
  color: var(--ek-white);
}

/* --- Refus / action destructive ---------------------------------------- */
button.danger,
.btn.danger {
  background: var(--ek-red);
  border-color: var(--ek-red);
  color: var(--ek-white);
}
button.danger:hover,
.btn.danger:hover {
  background: var(--ek-red-hover);
  border-color: var(--ek-red-hover);
  color: var(--ek-white);
}

/* --- DÉSACTIVÉ ----------------------------------------------------------
   Couple explicite (5,3:1) plutôt qu'une opacity, qui délave les pilules.
   PAS de pointer-events:none : il annulerait le cursor:not-allowed et tout
   title/tooltip d'explication.
   Ce bloc est placé APRÈS toutes les variantes ET répète chaque variante au
   survol : sans cela, `button:disabled:hover` et `button.danger:hover` ont la
   même spécificité (0,2,1) et un « Rejeter » désactivé virerait au vert. */
button:disabled,
.btn:disabled,
.btn.disabled,
button[aria-disabled="true"],
.btn[aria-disabled="true"],
button.secondary:disabled,
button.success:disabled,
button.danger:disabled,
.btn.secondary:disabled,
.btn.success:disabled,
.btn.danger:disabled,
.btn.mint:disabled,
button:disabled:hover,
.btn:disabled:hover,
.btn.disabled:hover,
button[aria-disabled="true"]:hover,
.btn[aria-disabled="true"]:hover,
button.secondary:disabled:hover,
button.success:disabled:hover,
button.danger:disabled:hover,
.btn.secondary:disabled:hover,
.btn.success:disabled:hover,
.btn.danger:disabled:hover,
.btn.mint:disabled:hover {
  background: var(--ek-disabled-bg);
  border-color: var(--ek-disabled-bg);
  color: var(--ek-disabled-ink);
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
}

/* --- Densité : boutons en cellule de tableau et en barre d'actions ------ */
td button, td .btn,
.actions button, .actions .btn {
  padding: 7px 16px;
  font-size: var(--ek-fs-xs);
  letter-spacing: 0.04em;
}


/* ==========================================================================
   6. FORMULAIRES
   ========================================================================== */

label {
  display: block;
  margin: var(--ek-sp-4) 0 6px;
  font-size: var(--ek-fs-sm);
  font-weight: 500;
  color: var(--ek-ink-soft);
}

/* Libellé ENVELOPPANT (le champ est imbriqué dans le <label>) : utilisé
   là où un id fixe créerait des doublons — bloc répété pour chaque compte.
   Le rythme vertical reste celui du couple label + champ séparés. */
label > input,
label > select,
label > textarea { display: block; margin-top: 6px; }
/* Règle isolée : le bas du libellé enveloppant est le bas du champ, sinon la
   ligne .row (align-items:flex-end) désaligne le bouton de 6px. Sur un
   navigateur sans :has(), le seul effet est ce décalage de 6px. */
label:has(> input),
label:has(> select),
label:has(> textarea) { margin-bottom: 0; }

input, select, textarea {
  width: 100%;
  padding: 11px 14px;
  background: var(--ek-field);
  border: 1px solid var(--ek-field-line);
  border-radius: var(--ek-r-field);
  color: var(--ek-ink);
  font-family: var(--ek-font);
  font-size: var(--ek-fs-base);
  font-weight: 400;
  line-height: 1.4;
  transition: border-color var(--ek-t-fast), box-shadow var(--ek-t-fast);
}

input::placeholder,
textarea::placeholder { color: var(--ek-placeholder); opacity: 1; }

input:hover, select:hover, textarea:hover { border-color: var(--ek-field-line-hover); }

input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--ek-green);
  box-shadow: var(--ek-focus-ring);
}
input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: 3px solid var(--ek-focus);
  outline-offset: 1px;
}

input:disabled, select:disabled, textarea:disabled, input[readonly] {
  background: var(--ek-field-disabled);
  color: var(--ek-gray);
  cursor: not-allowed;
}

textarea { min-height: 96px; line-height: 1.55; resize: vertical; }

/* Chevron tracé en SVG : net à toutes les échelles, contrairement à un
   biseau fabriqué avec deux linear-gradient (arêtes crénelées à 5px). */
select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 38px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5' fill='none' stroke='%23213A38' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 13px center;
  cursor: pointer;
}

/* Cases et radios : ne doivent pas hériter du width:100% */
input[type="checkbox"],
input[type="radio"] {
  width: 17px;
  height: 17px;
  padding: 0;
  vertical-align: -3px;
  accent-color: var(--ek-green);
  cursor: pointer;
}
input[type="file"]  { padding: 8px; }
input[type="color"] { width: 48px; padding: 4px; }

fieldset {
  margin: 0 0 var(--ek-sp-5);
  padding: var(--ek-sp-4) var(--ek-sp-5) var(--ek-sp-5);
  border: 1px solid var(--ek-line);
  border-radius: var(--ek-r-card);
}
legend {
  padding: 0 var(--ek-sp-2);
  font-size: var(--ek-fs-sm);
  font-weight: 600;
  color: var(--ek-green);
}

/* Premier label d'une colonne de .row : pas de marge haute parasite */
.row > * > label:first-child { margin-top: 0; }


/* ==========================================================================
   7. CARTES — .card / .balance-card
   ========================================================================== */

.card {
  background: var(--ek-white);
  border: 1px solid var(--ek-line);
  border-radius: var(--ek-r-card);
  padding: var(--ek-sp-5);
  margin-bottom: var(--ek-sp-4);
  box-shadow: var(--ek-shadow-none);
  /* Bloc conteneur pour les descendants en position:absolute
     (.visually-hidden des <th> d'actions) : sans lui, ils échappent au
     rognage du conteneur de défilement et élargissent la PAGE entière
     au lieu de rester dans la carte. */
  position: relative;
  /* Les tableaux larges défilent DANS la carte, jamais dans la page.
     La <table> conserve ainsi son modèle de mise en page natif. */
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  /* Arrivé au bout du tableau, le geste ne doit PAS se propager au document :
     sans cela, un balayage horizontal dans le relevé fait reculer d'un cran
     dans l'historique du navigateur sur iOS et Chrome Android. */
  overscroll-behavior-x: contain;
}
/* Carte porteuse d'un tableau large : elle défile horizontalement, donc elle
   doit être atteignable au CLAVIER (WCAG 2.1.1). Le markup lui pose
   tabindex="0" + role="region" ; ici on rend le focus visible. */
.card[tabindex] { scroll-behavior: auto; }
.card[tabindex]:focus-visible {
  outline: 3px solid var(--ek-focus);
  outline-offset: 2px;
}

.card > h2:first-child,
.card > h3:first-child { margin-top: 0; }
.card > *:last-child { margin-bottom: 0; }
.card > h3 {
  padding-bottom: var(--ek-sp-2);
  border-bottom: 1px solid var(--ek-line);
}

/* --- Carte de solde : le seul aplat vert de l'espace client ------------- */
.balance-card {
  /* Alias redéfinis : un style en ligne color:var(--text-dim) posé dans
     cette carte doit rester lisible sur le vert. */
  --text: var(--ek-white);
  --text-dim: rgba(255, 255, 255, 0.80);
  background: var(--ek-green);
  border: 1px solid var(--ek-green);
  border-radius: var(--ek-r-card);
  padding: var(--ek-sp-5);
  margin-bottom: var(--ek-sp-4);
  color: var(--ek-white);
}
.balance-card .account-number {
  display: flex;
  align-items: center;
  gap: var(--ek-sp-2);
  flex-wrap: wrap;
  font-size: var(--ek-fs-xs);
  font-weight: 500;
  letter-spacing: var(--ek-track-caps);
  text-transform: uppercase;
  color: var(--ek-on-green-muted);
}
.balance-card .amount {
  margin: var(--ek-sp-3) 0 0;
  font-size: clamp(1.9rem, 1.2rem + 2.4vw, 2.5rem);
  font-weight: 300;
  line-height: 1.1;
  letter-spacing: -0.015em;
  font-variant-numeric: tabular-nums;
  color: var(--ek-white);
}
.balance-card a { color: var(--ek-on-green-link); }
.balance-card .badge { border-color: transparent; }


/* ==========================================================================
   8. TABLEAUX — aérés, filets fins, chiffres à chasse fixe
   ========================================================================== */

table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--ek-fs-sm);
  color: var(--ek-ink);
  /* Sans chasse fixe, les colonnes Montant / Solde après ne s'alignent pas */
  font-variant-numeric: tabular-nums;
}

th {
  padding: 10px 12px;
  text-align: left;
  font-weight: 600;
}
thead th {
  padding: 10px 12px;
  background: transparent;
  border-bottom: 1px solid var(--ek-line-strong);
  color: var(--ek-gray-strong);
  font-size: var(--ek-fs-xs);
  font-weight: 600;
  letter-spacing: var(--ek-track-caps);
  text-transform: uppercase;
  text-align: left;
  white-space: nowrap;
}

td {
  padding: 14px 12px;
  text-align: left;
  vertical-align: middle;
  border-bottom: 1px solid var(--ek-line);
  font-variant-numeric: tabular-nums;
}

tbody tr { transition: background-color var(--ek-t-fast); }
tbody tr:hover { background: var(--ek-cream-soft); }
tbody tr:last-child td { border-bottom: 0; }

caption {
  caption-side: top;
  padding-bottom: var(--ek-sp-3);
  text-align: left;
  font-size: var(--ek-fs-sm);
  color: var(--ek-gray);
}


/* ==========================================================================
   9. BADGES, MESSAGES, ÉTATS VIDES, MENTIONS
   ========================================================================== */

.badge {
  display: inline-block;
  padding: 4px 12px;
  border: 1px solid transparent;
  border-radius: var(--ek-r-pill);
  background: var(--ek-info-bg);
  color: var(--ek-info-ink);
  font-size: var(--ek-fs-xs);
  font-weight: 600;
  letter-spacing: 0.05em;
  line-height: 1.5;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  vertical-align: middle;
}
/* Le badge de statut est inséré DANS un <h1> sur la fiche client :
   il ne doit pas hériter des 36px du titre. */
h1 .badge, h2 .badge, h3 .badge { font-size: var(--ek-fs-xs); }

.badge.pending {
  background: var(--ek-warn-bg);
  color: var(--ek-warn-ink);
  border-color: var(--ek-warn-line);
}
.badge.completed,
.badge.active {
  background: var(--ek-ok-bg);
  color: var(--ek-ok-ink);
  border-color: var(--ek-ok-line);
}
.badge.blocked,
.badge.rejected,
.badge.suspended {
  background: var(--ek-bad-bg);
  color: var(--ek-bad-ink);
  border-color: var(--ek-bad-line);
}

/* --- Messages ----------------------------------------------------------
   display:block explicite : showMsg() pilote l'élément via
   el.style.display = "block". Aucun display:flex ici, jamais. */
.msg {
  display: block;
  margin: var(--ek-sp-4) 0;
  padding: 12px 16px;
  border: 1px solid var(--ek-info-line);
  border-left: 3px solid var(--ek-green);
  border-radius: var(--ek-r-field);
  background: var(--ek-info-bg);
  color: var(--ek-info-ink);
  font-size: var(--ek-fs-sm);
  line-height: 1.55;
}
/* showMsg(msg, "", "info") rallume un conteneur vide : on l'escamote. */
.msg:empty { display: none !important; }

.msg.error {
  background: var(--ek-bad-bg);
  color: var(--ek-bad-ink);
  border-color: var(--ek-bad-line);
  border-left-color: var(--ek-red);
}
.msg.success {
  background: var(--ek-ok-bg);
  color: var(--ek-ok-ink);
  border-color: var(--ek-ok-line);
  border-left-color: var(--ek-ok-solid);
}
.msg.info {
  background: var(--ek-info-bg);
  color: var(--ek-info-ink);
  border-color: var(--ek-info-line);
  border-left-color: var(--ek-mint);
}

/* --- État vide ---------------------------------------------------------- */
.empty {
  padding: var(--ek-sp-6) var(--ek-sp-4);
  background: var(--ek-cream-soft);
  border: 1px dashed var(--ek-line-strong);
  border-radius: var(--ek-r-card);
  color: var(--ek-gray-strong);
  font-size: var(--ek-fs-sm);
  text-align: center;
}

/* --- Mention secondaire ------------------------------------------------- */
.hint {
  margin-top: 6px;
  color: var(--ek-gray-strong);
  font-size: var(--ek-fs-sm);
  line-height: 1.5;
}
.hint a { color: var(--ek-green); }


/* ==========================================================================
   10. KPI (back-office) — .kpi-grid > .kpi > .value + .label
   ========================================================================== */

/* minmax(min(200px, 100%), 1fr) et non minmax(200px, 1fr) : le plancher de
   200px est un MINIMUM DUR qui, dans un conteneur plus étroit, force une piste
   plus large que la grille et fait déborder la PAGE. Le min(…, 100%) rend ce
   plancher fluide. Même correctif partout où un auto-fit/auto-fill est posé. */
.kpi-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr));
  gap: var(--ek-sp-4);
  margin-bottom: var(--ek-sp-6);
}

.kpi {
  background: var(--ek-white);
  border: 1px solid var(--ek-line);
  border-top: 3px solid var(--ek-green);
  border-radius: var(--ek-r-card);
  padding: var(--ek-sp-5);
}
.kpi .value {
  display: block;
  font-size: 2rem;
  font-weight: 300;
  line-height: 1.1;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  color: var(--ek-green);
}
.kpi .label {
  display: block;
  margin-top: var(--ek-sp-2);
  font-size: var(--ek-fs-xs);
  font-weight: 500;
  letter-spacing: var(--ek-track-caps);
  text-transform: uppercase;
  color: var(--ek-gray);
}


/* ==========================================================================
   11. MODALE
   ========================================================================== */

.modal-backdrop {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--ek-sp-4);
  background: rgba(12, 20, 20, 0.48);
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
  animation: ek-fade var(--ek-t) both;
}

.modal {
  width: 100%;
  max-width: 460px;
  max-height: 88vh;
  overflow-y: auto;
  padding: clamp(20px, 4vw, 32px);
  background: var(--ek-white);
  border: 1px solid var(--ek-line);
  border-radius: var(--ek-r-card);
  box-shadow: var(--ek-shadow-modal);
  animation: ek-rise var(--ek-t) both;
}
.modal h3 { margin-top: 0; font-size: 1.25rem; font-weight: 600; }
.modal label:first-of-type { margin-top: 0; }

@keyframes ek-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes ek-rise {
  from { opacity: 0; transform: translateY(10px) scale(0.99); }
  to   { opacity: 1; transform: none; }
}


/* ==========================================================================
   12. VITRINE — .hero / .notice / .features / .feature / footer
   Alternance de bandes : hero BLANC → notice BLANC → features CRÈME → pied VERT
   ========================================================================== */

.hero {
  max-width: 860px;
  margin: clamp(48px, 9vh, 96px) auto clamp(32px, 6vh, 64px);
  padding: 0 clamp(16px, 6vw, 48px);
  text-align: center;
}
.hero h1 {
  margin-bottom: var(--ek-sp-5);
  font-size: clamp(1.9rem, 1.1rem + 3.2vw, 3rem);
  font-weight: 300;               /* titre très léger : signature du modèle */
  line-height: 1.14;
  letter-spacing: -0.015em;
  color: var(--ek-green);
}
.hero p {
  max-width: 660px;
  margin: 0 auto var(--ek-sp-6);
  color: var(--ek-gray);
  font-size: var(--ek-fs-md);
}
.hero .actions { justify-content: center; gap: var(--ek-sp-3); }
.hero .btn { padding: 13px 38px; font-size: 0.9375rem; }

.notice {
  max-width: 900px;
  margin: 0 auto clamp(40px, 8vh, 80px);
  padding: var(--ek-sp-5) clamp(20px, 4vw, 32px);
  background: var(--ek-cream);
  border: 1px solid var(--ek-cream-line);
  border-left: 3px solid var(--ek-gold-warm);
  border-radius: var(--ek-r-card);
  color: var(--ek-ink-soft);
  font-size: var(--ek-fs-sm);
  line-height: 1.65;
  text-align: left;
}

/* BANDE CRÈME PLEINE LARGEUR, contenu centré — sans toucher au HTML.
   max(6vw, calc(...)) donne le plein-bleed avec une gouttière minimale. */
.features {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr));
  gap: var(--ek-sp-5);
  padding: clamp(40px, 7vh, 72px)
           max(6vw, calc((100% - var(--ek-container)) / 2));
  background: var(--ek-cream);
  border-top: 1px solid var(--ek-cream-line);
  border-bottom: 1px solid var(--ek-cream-line);
}

.feature {
  padding: var(--ek-sp-5);
  background: var(--ek-white);
  border: 1px solid var(--ek-line);
  border-radius: var(--ek-r-card);
}
.feature h3 {
  margin: 0 0 var(--ek-sp-3);
  font-size: 1.125rem;
  font-weight: 600;
  line-height: 1.3;
  color: var(--ek-green);
}
.feature p { margin: 0; color: var(--ek-gray); font-size: var(--ek-fs-sm); }
.feature a {
  display: inline-block;
  margin-top: var(--ek-sp-3);
  font-size: var(--ek-fs-sm);
  font-weight: 500;
  color: var(--ek-green);
  text-decoration: underline;
  text-underline-offset: 4px;
}

body > footer {
  padding: var(--ek-sp-6) clamp(16px, 6vw, 48px);
  background: var(--ek-green);
  color: rgba(255, 255, 255, 0.86);
  font-size: var(--ek-fs-sm);
  text-align: center;
}
body > footer a { color: var(--ek-on-green-link); }
body > footer :focus-visible { outline-color: var(--ek-gold); }


/* ==========================================================================
   13. VARIANTE ADMIN — topbar vert forêt plein.
   Tout le reste (boutons, cartes, tableaux, badges) est STRICTEMENT identique.
   Déclencheur principal : <body class="admin">.
   ========================================================================== */

body.admin .topbar {
  background: var(--ek-green);
  border-bottom-color: var(--ek-green-press);
  /* REDÉFINITION DES ALIAS : indispensable. renderNav() écrit
     style="color:var(--text-dim)" EN LIGNE — aucune règle CSS ordinaire ne
     peut le battre, seule la valeur de la variable peut être changée. */
  --text: var(--ek-white);
  --text-dim: var(--ek-on-green-muted);
  --border: rgba(255, 255, 255, 0.22);
}

body.admin .topbar .brand { color: var(--ek-white); }
body.admin .topbar .brand span { color: var(--ek-on-green-accent); }
body.admin .topbar .brand small { color: rgba(255, 255, 255, 0.78); }

body.admin .topbar .nav a { color: rgba(255, 255, 255, 0.86); }
body.admin .topbar .nav a:hover,
body.admin .topbar .nav a.active { color: var(--ek-white); }
body.admin .topbar .nav a::after { background: var(--ek-on-green-accent); }
body.admin .topbar .nav a.active::after { background: var(--ek-white); }

/* Ceinture ET bretelle sur le nom de l'admin (span à style en ligne) */
body.admin .topbar .nav span { color: var(--ek-on-green-muted) !important; }

/* Focus sur aplat sombre : le vert ne se voit plus, on bascule en or.
   Couvre TOUT descendant focusable (liens, bouton, tabindex). */
body.admin .topbar :focus-visible,
.balance-card :focus-visible {
  outline-color: var(--ek-gold);
  box-shadow: 0 0 0 5px rgba(255, 255, 255, 0.25);
}

/* La page de connexion admin n'a pas de topbar : on marque le liseré. */
body.admin .auth-container { border-top-color: var(--ek-green); }

/* --- FILET DE SÉCURITÉ ---------------------------------------------------
   Si le class="admin" venait à manquer sur une page, la marque admin reste
   reconnaissable : elle seule contient <small>ADMIN</small>.
   Ces règles sont ISOLÉES dans leur propre bloc : `:has()` n'est pas un
   sélecteur « pardonnant », un navigateur qui ne le gère pas invalide toute
   la liste de sélecteurs où il apparaît. Les mêlant aux règles body.admin
   ci-dessus, on perdrait TOUTE l'identité admin sur ces navigateurs. */
.topbar:has(.brand small) {
  background: var(--ek-green);
  border-bottom-color: var(--ek-green-press);
  --text: var(--ek-white);
  --text-dim: var(--ek-on-green-muted);
  --border: rgba(255, 255, 255, 0.22);
}
.topbar:has(.brand small) .brand { color: var(--ek-white); }
.topbar:has(.brand small) .brand span { color: var(--ek-on-green-accent); }
.topbar:has(.brand small) .brand small { color: rgba(255, 255, 255, 0.78); }
.topbar:has(.brand small) .nav a { color: rgba(255, 255, 255, 0.86); }
.topbar:has(.brand small) .nav a:hover,
.topbar:has(.brand small) .nav a.active { color: var(--ek-white); }
.topbar:has(.brand small) .nav a::after { background: var(--ek-on-green-accent); }
.topbar:has(.brand small) .nav a.active::after { background: var(--ek-white); }
.topbar:has(.brand small) .nav span { color: var(--ek-on-green-muted) !important; }
.topbar:has(.brand small) :focus-visible {
  outline-color: var(--ek-gold);
  box-shadow: 0 0 0 5px rgba(255, 255, 255, 0.25);
}


/* ==========================================================================
   14. ACCESSIBILITÉ & PRÉFÉRENCES SYSTÈME
   ========================================================================== */

/* Lien d'évitement (WCAG 2.4.1 « Contourner des blocs »). L'en-tête de la
   vitrine présente 6 liens tabulables avant le contenu, identiques sur les
   5 pages : sans ce lien, l'utilisateur au clavier les retraverse à chaque
   navigation. C'est un <a> en dur — il fonctionne donc sans JavaScript.
   Hors focus il sort du cadre par la gauche plutôt que par display:none,
   qui le retirerait de l'ordre de tabulation. */
.ek-skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  padding: 12px 20px;
  background: var(--ek-green);
  color: var(--ek-white);
  text-decoration: none;
  border-radius: 0 0 8px 0;
}
.ek-skip:focus { left: 0; }

.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  button:active, .btn:active { transform: none; }
}

/* Contraste renforcé : le système repose sur des filets crème très pâles et
   des cartes sans ombre — on durcit les traits pour ne pas perdre la structure. */
@media (prefers-contrast: more) {
  :root {
    --ek-line:        #BFB89E;
    --ek-line-soft:   #CFC8B0;
    --ek-line-strong: #A8A08A;
    --ek-gray:        #4A4A4A;
    --ek-gray-strong: #3D3D38;
  }
  .badge { border-width: 1.5px; }
  .card, .kpi { border-width: 1px; }
}

/* Contraste forcé Windows : sans ceci, badges, cartes et pilules perdent
   leurs fonds et deviennent indistinguables. */
@media (forced-colors: active) {
  .badge, .card, .kpi, .msg, .modal { border: 1px solid CanvasText; }
  button, .btn { border: 1px solid ButtonText; }
}


/* ==========================================================================
   15. RESPONSIVE
   ========================================================================== */

@media (max-width: 960px) {
  .container { padding-top: var(--ek-sp-5); }
  .topbar, body > header { padding: 14px 20px; }
  .section-title { margin-top: var(--ek-sp-6); }
}

@media (max-width: 720px) {
  .topbar, body > header {
    position: static;
    align-items: flex-start;
    gap: var(--ek-sp-3);
    padding: 14px clamp(12px, 4vw, 16px);
  }
  .nav, body > header nav { width: 100%; gap: 8px 16px; padding-top: 2px; }

  .container { padding: var(--ek-sp-5) clamp(12px, 4vw, 16px) var(--ek-sp-7); }

  /* Empilement. Le !important neutralise l'align-items:flex-end posé EN LIGNE
     sur le formulaire d'ajustement, qui plaquerait les champs à droite. */
  .row {
    flex-direction: column;
    gap: var(--ek-sp-4);
    align-items: stretch !important;
  }
  /* `flex: 0 0 auto` est INDISPENSABLE : le `flex: 1 1 220px` du mode deux
     colonnes garde sa base de 220px une fois l'axe passé en vertical, où
     elle devient une HAUTEUR imposée — chaque champ traînait alors un vide
     de 150px sous lui. La base repasse donc au contenu. */
  .row > * { width: 100%; min-width: 0; flex: 0 0 auto; }
  /* Même correctif pour la carte d'authentification, dont le sélecteur
     `.auth-container .row > *` (§3) est PLUS spécifique que `.row > *` :
     une requête média n'ajoute aucune spécificité, la règle ci-dessus ne
     l'atteignait donc pas et la paire Prénom / Nom traînait 130px de vide
     sous chaque champ. */
  .auth-container .row > * { flex: 0 0 auto; min-width: 0; }

  /* Une tuile KPI porte grid-column:span 2 EN LIGNE : sur une grille à une
     colonne elle créerait une 2e colonne implicite et ferait déborder la page. */
  .kpi-grid { grid-template-columns: 1fr; gap: var(--ek-sp-3); }
  .kpi-grid > .kpi { grid-column: auto / auto !important; }

  .features { grid-template-columns: 1fr; padding-left: 6vw; padding-right: 6vw; }

  .auth-container { margin: 4vh auto; padding: 24px 20px; }

  .card { padding: var(--ek-sp-4); }
  /* Le tableau reste un VRAI tableau et défile dans .card (overflow-x:auto) */
  .card table { min-width: 560px; }
  thead th, td { padding: 12px 10px; }

  .actions { width: 100%; }
  td.actions { width: auto; }        /* la cellule d'actions garde sa largeur */

  .balance-card { padding: var(--ek-sp-4); }
  .hero .actions { flex-direction: column; align-items: stretch; }
  .hero .btn { width: 100%; }
}

/* --- REPLI DE LA BARRE DE NAVIGATION -------------------------------------
   Sous 520px, les sept entrées (quatre libellés + cloche + profil + sortie)
   demandaient TROIS lignes et écrasaient l'en-tête. On bascule en « icônes
   seules » : chaque entrée devient un rond de 44px.

   Le libellé N'EST PAS retiré du DOM — seul son rendu visuel disparaît
   (font-size:0). Le nom accessible du lien reste donc « Virements », lu tel
   quel par un lecteur d'écran. C'est le seul moyen ici : le balisage de la
   nav est construit par app.js, hors du périmètre de ce fichier, et aucun
   aria-label ne peut y être ajouté depuis le CSS.
   Conséquence : l'icône, dimensionnée en `em` par icons.js, serait réduite
   à néant par le font-size:0 — sa taille est donc reprise en dur ci-dessous. */
@media (max-width: 520px) {
  /* space-between : la rangée d'icônes occupe toute la largeur disponible.
     Sous ~340px, sept ronds de 44px (308px) ne tiennent plus dans les 288px
     utiles d'un écran de 320px : la barre passe alors sur DEUX lignes — le
     repli prévu — plutôt que de rogner la cible tactile sous son plancher. */
  .nav, body > header nav { gap: 6px; justify-content: space-between; }

  /* `:has(.ek-icon)` est la CONDITION DE SÛRETÉ de tout ce repli : on
     n'efface le libellé que si l'icône est réellement là. Si icons.js n'a pas
     pu être chargé, ou si le navigateur ne gère pas :has(), la liste de
     sélecteurs est invalidée et les libellés restent affichés — la barre
     repasse simplement sur deux lignes. Jamais de lien vide et muet.
     Ce bloc est donc ISOLÉ : aucune règle sans :has() ne doit s'y trouver. */
  .nav a:has(.ek-icon),
  body > header nav a:has(.ek-icon) {
    justify-content: center;
    width: 44px;
    height: 44px;
    padding: 0;
    /* Le texte reste dans le DOM : le nom accessible du lien (« Virements »)
       est intact pour un lecteur d'écran, seul son rendu visuel disparaît. */
    font-size: 0;
    letter-spacing: normal;
    gap: 0;
    border-radius: 999px;
  }
  /* icons.js dimensionne les SVG en `em` : sans reprise en dur, le font-size:0
     ci-dessus les réduirait à néant. */
  .nav a:has(.ek-icon) .ek-icon,
  body > header nav a:has(.ek-icon) .ek-icon { width: 22px; height: 22px; }
  /* Le filet d'état ne court plus sous un libellé : on le ramène au rond. */
  .nav a:has(.ek-icon)::after,
  body > header nav a:has(.ek-icon)::after { left: 9px; right: 9px; bottom: 3px; }
}

/* Le nom de l'utilisateur (span à style en ligne posé par renderNav côté
   admin) n'a plus sa place dans une rangée d'icônes. Hors du bloc :has()
   ci-dessus, qui doit rester isolé. */
@media (max-width: 520px) {
  .nav span, body > header nav span { display: none; }
}

@media (max-width: 420px) {
  .balance-card .amount { font-size: 1.75rem; }
  button, .btn { padding: 10px 18px; }
  td button, td .btn { padding: 6px 13px; }
}

/* ==========================================================================
   15 bis. CIBLES TACTILES
   Sur un écran tactile, tout ce qui se clique fait au moins 44×44 px.
   Volontairement borné à `pointer: coarse` : à la souris, ces hauteurs
   alourdiraient inutilement les barres d'actions denses des tableaux.
   ========================================================================== */

@media (pointer: coarse) {
  button,
  .btn,
  input[type="submit"],
  input[type="button"] { min-height: 44px; }

  /* Boutons de cellule et de barre d'actions : le padding reste serré, seule
     la hauteur de la cible remonte au plancher. */
  td button, td .btn,
  .actions button, .actions .btn { min-height: 44px; }

  .icon-btn { width: 44px; height: 44px; }

  /* Champs de saisie : sous 44px, viser un champ au doigt devient hasardeux
     — et sous 16px de corps, iOS zoome de force à la mise au point, ce qui
     décale toute la page. `max()` garde la valeur du système si elle grandit.
     Les cases et radios gardent leur boîte de 17px : c'est leur LABEL, posé
     en block sur toute la largeur, qui sert de cible. */
  input, select, textarea { min-height: 44px; font-size: max(16px, var(--ek-fs-base)); }
  input[type="checkbox"], input[type="radio"] { min-height: 0; }

  /* Lien-logotype : c'est une cible cliquable comme une autre. */
  .brand { padding-block: 8px; }

  /* Lien EN LIGNE dans une phrase (« Ajoutez d'abord un bénéficiaire »).
     WCAG 2.5.8 l'exempte du gabarit minimal — mais c'est parfois la seule
     issue de la page. Un padding vertical sur un élément en ligne agrandit la
     zone de test de pointage SANS déplacer une seule ligne de texte : la
     mise en page reste identique, la cible passe d'environ 18px à 30px. */
  .hint a, .empty a, .form-note a { padding-block: 6px; }
}


/* ==========================================================================
   16. IMPRESSION
   ========================================================================== */

@media print {
  .topbar, body > header, body > footer, .actions, .modal-backdrop {
    display: none !important;
  }
  body { background: #fff; color: #000; font-size: 11pt; }
  .card, .kpi, .feature { border-color: #999; box-shadow: none; }
  .balance-card {
    background: #fff !important;
    color: #000 !important;
    border: 1px solid #999;
  }
  .balance-card .amount,
  .balance-card .account-number,
  .kpi .value { color: #000 !important; }
  .features { background: #fff; }
}


/* ==========================================================================
   17. UTILITAIRES OPTIONNELS (hors contrat de classes)
   Aucun HTML actuel ne les porte : ils sont proposés aux agents de conversion.
   ========================================================================== */

/* Bande pleine largeur crème, contenu centré — pour une future section
   alternée. Se pose sur un bloc enfant direct de <body>. */
.ek-band-cream {
  background: var(--ek-cream);
  border-top: 1px solid var(--ek-cream-line);
  border-bottom: 1px solid var(--ek-cream-line);
  padding: clamp(40px, 7vh, 72px)
           max(6vw, calc((100% - var(--ek-container)) / 2));
}

/* CTA menthe plein EXPLICITE (hors .hero / .topbar où .btn.secondary suffit) */
/* → voir § 5 : .btn.mint */

/* Grand format pilule : hero, page d'accueil, appels à l'action isolés */
.btn.large { padding: 13px 40px; font-size: 1rem; }

/* Bouton discret, sans cadre : actions tertiaires dans une carte */
button.link,
.btn.link {
  background: transparent;
  border-color: transparent;
  color: var(--ek-green);
  padding: 6px 4px;
  text-decoration: underline;
}
button.link:hover,
.btn.link:hover { background: transparent; color: var(--ek-mint-ink); }

/* Cellule numérique : montants alignés à droite, chasse fixe */
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; }

/* Conteneur de défilement pour un tableau posé HORS d'une .card.
   Comme .card, il doit porter tabindex="0" + role="region" + aria-label
   dans le markup dès qu'il défile réellement. */
.table-wrap {
  width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-x: contain;
}
.table-wrap:focus-visible {
  outline: 3px solid var(--ek-focus);
  outline-offset: 2px;
}

/* ─────────────────────────────────────────────────────────────
   ICÔNES (shared/icons.js)
   Les icônes héritent de la couleur et de la taille du texte.
   ───────────────────────────────────────────────────────────── */
.ek-icon {
  display: inline-block;
  vertical-align: -0.15em;
  flex: none;
}
/* Un élément porteur d'icône met de l'air entre l'icône et son libellé */
[data-icon] {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
}
/* Icône SEULE (nav profil, déconnexion, cloche) : cible tactile confortable.
   44 px est le plancher — en dessous, un doigt rate la cible. */
.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 44px;
  height: 44px;
  padding: 0;
  border-radius: 999px;
  background: transparent;
  border: 1px solid transparent;
  color: inherit;
  cursor: pointer;
  transition: background-color var(--ek-t-fast);
}
.icon-btn:hover { background: rgba(33, 58, 56, 0.07); }
body.admin .icon-btn:hover { background: rgba(255, 255, 255, 0.14); }
.icon-btn:focus-visible { outline: 2px solid var(--ek-mint); outline-offset: 2px; }

/* Pastille de notifications non lues, posée sur l'icône cloche */
.icon-btn { position: relative; }
.badge-count {
  position: absolute;
  top: 4px;
  right: 3px;
  min-width: 17px;
  height: 17px;
  padding: 0 4px;
  border-radius: 999px;
  background: var(--ek-danger, #BC2F1E);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  line-height: 17px;
  text-align: center;
}

/* --- Pastille de comptage sur une entrée TEXTE de la barre ----------------
   `.badge-count` ci-dessus est calée dans le COIN d'un bouton rond de 44px
   (la cloche des notifications) : elle est en position absolue. Posée sur une
   entrée large comme « MESSAGES », elle atterrirait au-dessus des lettres.

   `.nav-count` en est la variante EN LIGNE : elle suit le libellé comme un
   mot de plus, et se comporte donc correctement dans les trois régimes de la
   barre — rangée horizontale, tiroir mobile pleine largeur (§19), et repli
   « icônes seules » sous 520px (§15) où `.nav a` passe à font-size: 0.
   C'est pour ce dernier cas que la taille est redonnée en dur ici, comme le
   fait déjà §15 pour les SVG : sans elle, la pastille disparaîtrait avec le
   libellé qu'elle accompagne.

   `hidden` est la seule commande d'affichage — un compteur à zéro n'existe
   pas à l'écran, et aucune classe n'est à synchroniser. */
.nav-count {
  display: inline-block;
  min-width: 18px;
  height: 18px;
  margin-left: 7px;
  padding: 0 5px;
  border-radius: 999px;
  background: var(--ek-danger, #BC2F1E);
  color: #fff;
  font-size: 10px;
  font-style: normal;
  font-weight: 700;
  letter-spacing: 0;
  line-height: 18px;
  text-align: center;
  vertical-align: middle;
}
.nav-count[hidden] { display: none; }

/* Dans le tiroir mobile (§19), l'entrée occupe toute la largeur : la pastille
   est repoussée au bout de la ligne, là où l'œil la cherche. */
@media (max-width: 900px) {
  .topbar[data-ek-nav-js][data-ek-nav="open"] > .nav > a > .nav-count { margin-left: auto; }
}


/* ==========================================================================
   18. VITRINE PUBLIQUE — SOCLE COMMUN AUX 5 PAGES
   index.html · quotidien.html · epargne.html · emprunter.html · assurer.html

   PÉRIMÈTRE STRICT. Ne vivent ici que les règles PARTAGÉES par ces cinq
   pages : l'en-tête, son repli sur petit écran, le pied de page, le bloc
   centré et les cartes de rubrique. Rien de propre à UNE page — ces
   styles-là restent dans le <style> local de la page concernée.

   ISOLATION vis-à-vis de /app/ et /admin/ : ces deux espaces bâtissent leur
   barre avec <div class="topbar">, jamais avec <header>. Tous les sélecteurs
   d'en-tête ci-dessous sont ancrés sur `body > header` ou sur les classes
   .head-right / .site-nav, qui n'existent que dans la vitrine.
   ========================================================================== */

/* --- Bloc de contenu centré, à la largeur du design system ------------- */
.ek-wrap {
  max-width: var(--ek-container);
  margin: 0 auto;
  padding-left: clamp(16px, 5vw, 24px);
  padding-right: clamp(16px, 5vw, 24px);
}


/* --------------------------------------------------------------------------
   18.1 EN-TÊTE COMMUN
   Markup : <header> = marque à gauche, .head-right à droite (nav.site-nav
   puis les 2 CTA pilule). Écrit EN DUR dans chaque page — jamais injecté par
   du JavaScript : sans script, l'en-tête reste entier et navigable.

   REPLI SUR PETIT ÉCRAN — deux régimes.
     > 900px  la barre se réorganise en plusieurs lignes, 100 % CSS :
                ≤1080px  la marque garde sa ligne, .head-right prend la suivante.
     ≤ 900px  .head-right devient le PANNEAU du menu à trois traits — voir
              §18.4, qui reprend la main sur les règles ci-dessous. Les paliers
              ≤720px et ≤420px n'y servent plus qu'aux navigateurs restés sans
              JavaScript, où le panneau demeure déplié.
   -------------------------------------------------------------------------- */

.head-right {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: clamp(14px, 2.4vw, 30px);
  flex-wrap: wrap;
}

/* Les 2 CTA sont GROUPÉS, et c'est structurant : sans ce conteneur, la
   largeur intermédiaire (autour de 768px) laissait passer « Devenir client »
   au bout de la rangée de rubriques et rejetait « Accéder à mon compte » à la
   ligne — une paire de boutons coupée en deux. Groupés, ils passent à la
   ligne ENSEMBLE ou pas du tout. */
.head-cta {
  display: flex;
  align-items: center;
  gap: var(--ek-sp-3);
  flex-wrap: wrap;
}

/* La nav de la vitrine est purement TEXTUELLE : aucune de ses entrées ne
   porte d'icône. Le repli « icônes seules » de §15 est verrouillé par
   `:has(.ek-icon)` et ne peut donc pas l'atteindre — mais §15 lui applique
   tout de même `justify-content: space-between`, qui écarterait quatre
   libellés de longueurs très inégales aux deux bords. On reprend la main.
   Spécificité égale (0,1,0), c'est l'ordre du fichier qui tranche : ce
   bloc-ci est le dernier, il l'emporte. */
.site-nav {
  justify-content: flex-start;
  gap: clamp(12px, 2vw, 26px);
}
/* Un libellé de rubrique ne se coupe jamais en son milieu : c'est la RANGÉE
   qui passe à la ligne, pas le mot. */
.site-nav a { white-space: nowrap; }

/* La rubrique courante porte `class="active" aria-current="page"`. Le style
   vient de §4 (.nav a.active) ; l'attribut est repris ici pour que la page
   reste signalée même si la classe venait à manquer sur l'une des cinq. */
.site-nav a[aria-current="page"] { color: var(--ek-green); font-weight: 600; }
.site-nav a[aria-current="page"]::after { transform: scaleX(1); background: var(--ek-green); }

/* Palier 1 — la marque et le reste de l'en-tête ne tiennent plus côte à côte */
@media (max-width: 1080px) {
  .head-right {
    width: 100%;
    justify-content: space-between;
    gap: var(--ek-sp-3) clamp(12px, 2.4vw, 24px);
  }
}

/* Palier 2 — la nav prend sa propre rangée, les 2 CTA la suivante */
@media (max-width: 720px) {
  .head-right { width: 100%; gap: var(--ek-sp-3); }
  .site-nav {
    flex: 1 1 100%;
    gap: 4px 18px;
    padding-top: 2px;
  }
  /* Les 2 CTA prennent la largeur plutôt que de se serrer l'un contre
     l'autre sur une ligne de 288px. */
  .head-cta { flex: 1 1 100%; }
  .head-cta > .btn { flex: 1 1 46%; }
}

@media (max-width: 420px) {
  .head-cta > .btn { flex: 1 1 100%; }
  .site-nav { gap: 0 14px; }
}

/* Cibles tactiles de l'en-tête. `.nav a` fait déjà 44px de haut (§4) ; il
   reste les 2 CTA pilule, que §15bis ne remonte qu'au pointeur grossier —
   or la règle doit aussi être vérifiable en réduisant une fenêtre de bureau. */
@media (pointer: coarse), (max-width: 900px) {
  body > header .btn { min-height: 44px; }
  /* Le lien-logotype est une cible comme une autre : 21px de haut au repos.
     On l'épaissit par le PADDING et jamais par un display:flex — §4 rappelle
     qu'un conteneur flex ferait de « EK » un item séparé et empilerait le
     logotype sur deux ou trois lignes. */
  body > header .brand { padding-block: 12px; }
}


/* --------------------------------------------------------------------------
   18.2 PIED DE PAGE COMMUN
   Trois colonnes : identité + coordonnées | rubriques | accès.
   Écrit EN DUR lui aussi ; site-config.js n'y pose que la marque et les
   coordonnées (data-ek). Les trois lignes de coordonnées arrivent masquées
   et ne sont révélées que si l'administrateur les a renseignées : jamais de
   « Tél. : » suivi du vide, jamais de lien mort. Le repli, lui, est écrit en
   dur (.foot-note) et reste vrai dans les deux cas.
   -------------------------------------------------------------------------- */

.foot-inner {
  display: grid;
  /* min() : à 320px, une piste de 260px ne doit pas imposer sa largeur à la
     grille — sinon la PAGE défile latéralement. */
  grid-template-columns:
    minmax(min(260px, 100%), 1.7fr)
    repeat(2, minmax(min(150px, 100%), 1fr));
  gap: clamp(24px, 4vw, 56px);
  max-width: var(--ek-container);
  margin: 0 auto;
  text-align: left;
}

.foot-brand {
  /* inline-flex + min-height : le seul line-height plafonnait la cible
     tactile à 43,7 px, juste sous les 44 px requis. */
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  margin-bottom: var(--ek-sp-2);
  color: var(--ek-white);
  font-size: 1.05rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-decoration: none;
}
.foot-brand:hover { color: var(--ek-white); text-decoration: none; }
.foot-brand span { color: var(--ek-on-green-accent); font-weight: 400; }
/* LOGO DU PIED DE PAGE = LOGO DE L'EN-TÊTE, jamais un second visuel.
   Le markup est strictement celui de .brand (§4) : <img data-ek="logo"> posé
   en premier enfant de l'élément data-ek="brand". Les deux suivent donc le
   même réglage d'administration et ne peuvent pas diverger.
   Si aucun logo n'est configuré, site-config.js masque l'image (display:none)
   et le rendu TEXTUEL de la marque reste seul : jamais de trou, jamais
   d'alternative vide. La hauteur est celle de l'en-tête, réduite de 28 à 26px
   pour rester à l'échelle du logotype du pied (1,05rem contre 1,2rem). */
.foot-brand img {
  height: 26px;
  width: auto;
  margin-right: var(--ek-sp-2);
  flex: none;
}

.foot-text { max-width: 42ch; line-height: 1.6; }

.foot-legal {
  margin-top: var(--ek-sp-3);
  font-size: var(--ek-fs-xs);
  letter-spacing: 0.03em;
}
/* Lien de politique des cookies : il vit sur la ligne de mentions, pas dans
   une colonne de navigation — ce n'est ni une rubrique ni un espace. Il reste
   une cible cliquable à part entière, d'où l'inline-flex et la hauteur. */
.foot-legal a {
  display: inline-flex;
  align-items: center;
  min-height: 34px;
}

.foot-contact {
  margin: var(--ek-sp-3) 0 0;
  padding: 0;
  list-style: none;
  font-size: var(--ek-fs-xs);
  line-height: 1.6;
  letter-spacing: 0.03em;
}
.foot-contact li { margin-bottom: 2px; }

/* Repli des coordonnées : phrase écrite en dur, vraie que l'administrateur
   ait renseigné ses coordonnées ou non. */
.foot-note {
  margin: var(--ek-sp-3) 0 0;
  font-size: var(--ek-fs-xs);
  line-height: 1.6;
  color: var(--ek-on-green-muted);
}

.foot-title {
  margin: 0 0 var(--ek-sp-2);
  color: var(--ek-white);
  font-size: var(--ek-fs-xs);
  font-weight: 600;
  letter-spacing: var(--ek-track-caps);
  text-transform: uppercase;
}

.foot-links { display: flex; flex-direction: column; align-items: flex-start; gap: 0; }
.foot-links a {
  display: inline-flex;
  align-items: center;
  min-height: 34px;
  font-size: var(--ek-fs-sm);
}

@media (max-width: 720px) {
  .foot-inner {
    grid-template-columns: 1fr;
    justify-items: center;
    text-align: center;
  }
  .foot-text { max-width: 46ch; }
  .foot-links { align-items: center; }
}

/* Cibles tactiles du pied de page */
@media (pointer: coarse), (max-width: 900px) {
  .foot-links a,
  .foot-legal a,
  .foot-contact a { display: inline-flex; align-items: center; min-height: 44px; }
  /* .foot-brand n'a plus rien à faire ici : il porte désormais
     min-height: 44px en permanence (règle de base). */
}


/* --------------------------------------------------------------------------
   18.3 CARTES DE RUBRIQUE
   Le renvoi d'une page vers les autres rubriques. La carte ENTIÈRE est le
   lien : la cible tactile est le bloc, pas les quelques mots du libellé.
   Se pose sur la grille .features (§12), dont elle hérite carte et gouttières.
   -------------------------------------------------------------------------- */

.ek-rubrique {
  display: flex;
  flex-direction: column;
  color: inherit;
  text-decoration: none;
  transition: border-color var(--ek-t-fast), transform var(--ek-t-fast);
}
.ek-rubrique:hover {
  color: inherit;
  text-decoration: none;
  border-color: var(--ek-mint);
  transform: translateY(-2px);
}
.ek-rubrique h3 { transition: color var(--ek-t-fast); }
.ek-rubrique:hover h3 { color: var(--ek-mint-ink); }
.ek-rubrique p { flex: 1 1 auto; }

/* Affordance de lien : le libellé souligné en bas de carte. Ce n'est PAS un
   lien imbriqué (interdit dans un <a>) mais un simple <span>. */
.ek-rubrique .ek-rubrique-go {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: var(--ek-sp-4);
  color: var(--ek-green);
  font-size: var(--ek-fs-sm);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  text-decoration: underline;
  text-decoration-color: currentColor;
  text-underline-offset: 5px;
}
.ek-rubrique .ek-rubrique-go::after {
  content: "\2192";                 /* → */
  text-decoration: none;
  transition: transform var(--ek-t-fast);
}
.ek-rubrique:hover .ek-rubrique-go::after { transform: translateX(3px); }

/* La rubrique où l'on se trouve déjà n'est pas proposée comme destination :
   elle reste dans la grille, en retrait, et n'est pas un lien. */
.ek-rubrique.is-current {
  background: var(--ek-cream);
  border-color: var(--ek-cream-line);
}

@media (prefers-reduced-motion: reduce) {
  .ek-rubrique:hover { transform: none; }
  .ek-rubrique:hover .ek-rubrique-go::after { transform: none; }
}


/* --------------------------------------------------------------------------
   18.4 MENU REPLIABLE — LE BOUTON À TROIS TRAITS, À GAUCHE
   Commun aux 5 pages de la vitrine. N'atteint NI /app/ NI /admin/ : tous les
   sélecteurs sont ancrés sur .ek-burger, .head-right, .site-nav, .head-cta ou
   `body > header`, qui n'existent que dans public-site/.

   MARKUP ATTENDU (écrit en dur, identique sur les 5 pages) :
     <header id="ek-header" data-ek-menu="open">
       <button class="ek-burger" id="ek-burger" aria-controls="ek-menu"
               aria-expanded="true" aria-label="Ouvrir le menu"> …3 traits… </button>
       <a class="brand" data-ek="brand"> … </a>
       <div class="head-right" id="ek-menu"> nav.site-nav + div.head-cta </div>
     </header>

   ⚠️ RÈGLE DE SÛRETÉ — SANS JAVASCRIPT, LE MENU RESTE OUVERT.
   L'attribut `data-ek-menu="open"` est écrit EN DUR dans le HTML : c'est le
   SCRIPT qui le bascule sur « closed » au chargement, pas le CSS. Un script
   bloqué, en échec ou lent laisse donc un panneau déplié — moins joli, mais
   entièrement navigable. L'inverse (replié par défaut, déplié par le script)
   rendrait les 4 rubriques et les 2 boutons INATTEIGNABLES dès que le script
   ne s'exécute pas. Ne jamais inverser ce sens.
   -------------------------------------------------------------------------- */

.ek-burger {
  /* Au-dessus du point de rupture, il n'y a rien à replier : la barre reste
     exactement telle qu'elle est aujourd'hui et le bouton n'existe pas. */
  display: none;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 44px;                    /* cible tactile, pleine et entière */
  height: 44px;
  padding: 0;
  background: transparent;
  border: 1px solid var(--ek-line-strong);
  border-radius: var(--ek-r-field);
  color: var(--ek-green);
}
.ek-burger:hover {
  background: var(--ek-green-soft);
  border-color: var(--ek-green);
  color: var(--ek-green);
}
.ek-burger:active { background: var(--ek-green-soft); border-color: var(--ek-green); }
.ek-burger svg { display: block; width: 22px; height: 22px; }

/* Les deux pictogrammes sont écrits en dur dans le bouton ; c'est l'état
   aria-expanded — la SEULE source de vérité — qui décide lequel s'affiche.
   Aucune classe à synchroniser, donc aucune dérive possible entre ce que
   voit l'œil et ce qu'annonce le lecteur d'écran. */
.ek-burger .ek-burger-close { display: none; }
.ek-burger[aria-expanded="true"] .ek-burger-open { display: none; }
.ek-burger[aria-expanded="true"] .ek-burger-close { display: block; }

@media (max-width: 900px) {
  /* Sans JavaScript l'attribut n'est jamais posé : le bouton reste caché et le
     panneau reste déplié — pas de commande morte à l'écran. C'est le script
     qui pose `data-ek-js` juste avant le repli initial. */
  body > header[data-ek-js] .ek-burger { display: inline-flex; }

  /* L'EN-TÊTE DÉFILE AVEC LA PAGE SUR TOUTE LA BANDE DU MENU REPLIABLE.
     Le panneau vit DANS LE FLUX de l'en-tête : déplié, l'en-tête peut être
     plus haut que la fenêtre (téléphone tenu en paysage). Épinglé à top:0,
     il ne défile pas en son sein et ses dernières entrées — dont
     « Accéder à mon compte » — deviendraient définitivement inatteignables.
     §15 le fait déjà sous 720px ; on aligne toute la bande ≤900px. */
  body > header { position: static; }

  /* Le bouton est le premier enfant de l'en-tête : il est donc à GAUCHE de
     l'écran, avant la marque, à la fois à l'œil et dans l'ordre de tabulation.
     `margin-right: auto` colle la marque contre lui plutôt que de la renvoyer
     au bord opposé par le space-between de §4. */
  body > header > .brand { margin-right: auto; }

  /* LE PANNEAU. Il reste DANS LE FLUX de l'en-tête : rien ne recouvre le
     contenu, rien ne se superpose, et la page ne défile pas horizontalement. */
  .head-right {
    flex: 1 1 100%;
    width: 100%;
    flex-direction: column;
    align-items: stretch;
    justify-content: flex-start;
    gap: var(--ek-sp-2);
    margin-top: var(--ek-sp-2);
    padding-top: var(--ek-sp-3);
    border-top: 1px solid var(--ek-line);
  }

  /* Les 4 rubriques ET les 2 boutons : sur mobile ils quittent la barre, ils
     doivent donc TOUS être atteignables ici. Une entrée par ligne, pleine
     largeur — `justify-content` est repris car §15 pose `space-between` sur
     `.nav` sous 520px, ce qui écarterait les entrées dans l'axe vertical. */
  .site-nav {
    flex: 1 1 auto;
    flex-direction: column;
    align-items: stretch;
    justify-content: flex-start;
    gap: 0;
    padding-top: 0;
  }
  .site-nav a { width: 100%; }

  .head-cta {
    flex: 1 1 auto;
    flex-direction: column;
    align-items: stretch;
    gap: var(--ek-sp-2);
    margin-top: var(--ek-sp-2);
  }
  .head-cta > .btn { flex: 0 0 auto; width: 100%; }

  /* LE REPLI. Posé par le script, jamais par le CSS seul — voir l'avertissement
     en tête de section. */
  body > header[data-ek-menu="closed"] .head-right { display: none; }
}


/* --------------------------------------------------------------------------
   18.5 CADRE MÉDIA À FORMAT FIXE
   Le CADRE impose son rapport (var(--ek-frame-ratio), 4/3 par défaut) ;
   l'image le remplit en `cover`, centrée. Conséquence : quelles que soient la
   taille et les proportions du fichier téléversé par l'administrateur —
   portrait, panoramique, minuscule ou énorme — la géométrie du bloc ne bouge
   pas d'un pixel, et l'image n'est jamais déformée ni débordante.
   Le fond dégradé de la charte tient le cadre si l'image manque, tarde ou
   casse : aucun trou blanc, jamais.
   -------------------------------------------------------------------------- */

.ek-media-frame {
  position: relative;
  width: 100%;
  aspect-ratio: var(--ek-frame-ratio, 4 / 3);
  overflow: hidden;
  border-radius: var(--ek-r-card);
  background: linear-gradient(140deg, var(--ek-green-hover) 0%, var(--ek-green-press) 100%);
}
/* `max-width: none` et `height: 100%` sont indispensables : la règle globale
   `img { max-width: 100%; height: auto }` (§2) laisserait sinon l'image
   reprendre ses proportions natives et ressortir du cadre. */
.ek-media-frame > img {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  max-width: none;
  object-fit: cover;
  object-position: center;
}
/* Navigateur sans `aspect-ratio` : l'image étant hors flux, le cadre serait
   plat. On retombe sur le calage classique par padding (3/4 = 75%). */
@supports not (aspect-ratio: 4 / 3) {
  .ek-media-frame { height: 0; padding-bottom: 75%; }
}

/* =============================================================================
   §19 — MENU MOBILE DE L'ESPACE CLIENT ET DE L'ADMINISTRATION
   -----------------------------------------------------------------------------
   §18.4 replie le menu du SITE PUBLIC, dont l'en-tête est un <header> statique.
   Ici on replie celui de l'APPLICATION, dont la barre est un <div class="topbar">
   rempli en JavaScript. Les deux jeux de règles sont volontairement séparés :
   leurs sélecteurs ne se croisent jamais, on peut toucher l'un sans risquer
   l'autre.

   Piloté par /shared/mobile-nav.js, qui pose sur la barre :
     data-ek-nav-js="1"        le script a pris la main
     data-ek-nav="closed|open" l'état du menu
   Sans JavaScript, aucun de ces attributs n'existe : le bouton reste caché et
   la barre garde exactement le comportement qu'elle a aujourd'hui.
   -------------------------------------------------------------------------- */

.ek-navburger {
  /* Au-dessus du palier il n'y a rien à replier : le bouton n'existe pas. */
  display: none;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 44px;                    /* cible tactile, pleine et entière */
  height: 44px;
  padding: 0;
  background: transparent;
  /* La barre de l'administration est vert plein et redéfinit les alias
     --border / --text (§13). En héritant d'eux, le bouton reste lisible sur le
     fond clair du client COMME sur le fond sombre de l'administration, sans
     règle particulière à maintenir de part et d'autre. */
  border: 1px solid var(--border, var(--ek-line-strong));
  border-radius: var(--ek-r-field);
  color: inherit;
  cursor: pointer;
}
.ek-navburger:hover { background: rgba(127, 127, 127, 0.12); }
.ek-navburger:active { background: rgba(127, 127, 127, 0.2); }
.ek-navburger svg { display: block; width: 22px; height: 22px; }

/* Deux pictogrammes posés ensemble ; `aria-expanded` — seule source de vérité —
   décide lequel s'affiche. Aucune classe à synchroniser, donc aucune dérive
   possible entre ce que voit l'œil et ce qu'annonce le lecteur d'écran. */
.ek-navburger .ek-navburger-close { display: none; }
.ek-navburger[aria-expanded="true"] .ek-navburger-open { display: none; }
.ek-navburger[aria-expanded="true"] .ek-navburger-close { display: block; }

@media (max-width: 900px) {
  .topbar[data-ek-nav-js] .ek-navburger { display: inline-flex; }

  /* ── PIÈGE DU PAYSAGE ────────────────────────────────────────────────────
     §4 épingle la barre (position: sticky; top: 0). §15 ne la relâche qu'à
     partir de 720 px, et le correctif de §18.4 vise `body > header` — un
     sélecteur qui NE PEUT PAS atteindre .topbar, qui est un <div>. Il restait
     donc la bande 721–900 px, soit exactement un téléphone tenu en PAYSAGE
     (~330–380 px de haut) : le menu déplié y dépassait la fenêtre, et un
     élément épinglé ne défile pas en son sein — ses dernières entrées, dont la
     déconnexion, devenaient définitivement inatteignables.
     La barre défile donc avec la page sur TOUTE la bande du menu repliable. */
  .topbar[data-ek-nav-js] { position: static; }

  /* Le bouton est le premier enfant : il est à GAUCHE de l'écran. `auto` colle
     la marque contre lui plutôt que de la renvoyer au bord opposé par le
     space-between de §4. */
  .topbar[data-ek-nav-js] > .brand { margin-right: auto; }

  /* MENU REPLIÉ. `display: none` et non une simple transparence : un conteneur
     seulement invisible garderait ses liens ATTEIGNABLES À LA TABULATION — le
     défaut d'accessibilité classique, où l'on tabule dans un menu fermé. */
  .topbar[data-ek-nav-js][data-ek-nav="closed"] > .nav { display: none; }

  /* MENU DÉPLIÉ. Il reste DANS LE FLUX de la barre : rien ne recouvre le
     contenu, rien ne se superpose, et la page ne défile pas horizontalement. */
  .topbar[data-ek-nav-js][data-ek-nav="open"] > .nav {
    display: flex;
    flex-wrap: wrap;
    width: 100%;
    gap: 2px 8px;
    align-items: center;
    justify-content: flex-start;
    padding-top: 10px;
  }

  /* Les entrées texte prennent la largeur entière : une par ligne, comme dans
     le tiroir d'une application bancaire. Les boutons ronds (cloche, profil,
     déconnexion) gardent leur largeur propre et se regroupent d'eux-mêmes sur
     la dernière ligne, par le simple jeu du retour à la ligne — aucun nœud
     n'est déplacé, l'écouteur de déconnexion reste intact. */
  .topbar[data-ek-nav-js][data-ek-nav="open"] > .nav > a:not(.icon-btn) {
    flex: 0 0 100%;
    justify-content: flex-start;
    padding: 10px 12px;
    border-radius: var(--ek-r-field);
  }
  .topbar[data-ek-nav-js][data-ek-nav="open"] > .nav > .icon-btn {
    flex: 0 0 auto;
    margin-top: 10px;
  }

  /* ── ANNULATION DU REPLI « ICÔNES SEULES » DANS LE TIROIR ────────────────
     §15 réduit chaque entrée à un rond muet sous 520 px (`font-size: 0`) :
     c'était le bon compromis pour une barre horizontale étroite. Dans un
     tiroir vertical, la place ne manque plus — et un menu de ronds sans
     libellé serait un recul. On rétablit donc le texte à côté de l'icône.
     La spécificité de ces sélecteurs dépasse celle de §15 : l'ordre des blocs
     dans le fichier n'entre pas en jeu. */
  .topbar[data-ek-nav-js][data-ek-nav="open"] > .nav > a:not(.icon-btn):has(.ek-icon) {
    width: auto;
    height: auto;
    min-height: 44px;
    font-size: var(--ek-fs-xs);
    letter-spacing: var(--ek-track-caps);
    gap: 12px;
  }
  .topbar[data-ek-nav-js][data-ek-nav="open"] > .nav > a:has(.ek-icon) .ek-icon {
    width: 20px;
    height: 20px;
  }
  /* Le filet d'état retrouve sa place sous le libellé plein. */
  .topbar[data-ek-nav-js][data-ek-nav="open"] > .nav > a:not(.icon-btn):has(.ek-icon)::after {
    left: 12px;
    right: auto;
    width: 22px;
    bottom: 4px;
  }
}


/* ==========================================================================
   AIDE CONTEXTUELLE — le texte explicatif replié derrière une icône « ? »
   Piloté par shared/aide.js. Aucune couleur inventée : tout vient des
   variables déclarées en tête de ce fichier.
   ========================================================================== */

.ek-aide {
  display: flex;
  align-items: flex-start;
  gap: var(--ek-sp-2);
  /* Le texte replié laisse la place du bouton, pas celle d'un paragraphe :
     la marge du .hint est reprise ici pour que rien ne saute à l'ouverture. */
  margin-top: 6px;
}
.ek-aide--en-ligne { display: inline-flex; margin-top: 0; vertical-align: middle; }

/* Le bouton « ? ». Cible tactile de 44×44 px obtenue par min-width/min-height,
   jamais par du rembourrage : la zone reste garantie quel que soit le texte. */
.ek-aide-bouton {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  /* Le rond visible est plus petit que la cible : 26 px dessinés, 44 px
     cliquables. C'est la marge invisible qui fait la différence au doigt. */
  padding: 0;
  margin: -9px 0 0 -9px;
  background: none;
  border: 0;
  color: var(--ek-green);
  font-family: var(--ek-font);
  font-size: var(--ek-fs-sm);
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
  box-shadow: none;
}
.ek-aide-bouton > span[aria-hidden="true"] {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border: 1px solid var(--ek-line-strong);
  border-radius: 50%;
  background: var(--ek-green-050);
  transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.ek-aide-bouton:hover > span[aria-hidden="true"] {
  background: var(--ek-green-soft);
  border-color: var(--ek-green);
}
.ek-aide-bouton:active { transform: none; }
.ek-aide-bouton[aria-expanded="true"] > span[aria-hidden="true"] {
  background: var(--ek-green);
  border-color: var(--ek-green);
  color: var(--ek-white);
}
/* L'anneau de focus se pose sur le rond dessiné, pas sur la cible invisible :
   sinon il flotterait à 9 px du repère visuel. */
.ek-aide-bouton:focus { outline: none; }
.ek-aide-bouton:focus-visible > span[aria-hidden="true"] {
  outline: 2px solid var(--ek-green);
  outline-offset: 2px;
}

/* Le texte révélé garde exactement l'aspect qu'il avait en clair. */
.ek-aide-texte { margin-top: 0; min-width: 0; }
.ek-aide .ek-aide-texte { flex: 1 1 auto; }

/* REPLI D'UNE DESCRIPTION DE CHAMP (cible d'un aria-describedby).
   Rognage visuel et NON `display:none` : le nœud reste dans l'arbre
   d'accessibilité, donc le lecteur d'écran continue de l'annoncer à l'entrée
   dans le champ qu'il décrit — ce que `hidden` supprimerait. */
.ek-aide-texte--rogne {
  position: absolute !important;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* Sur aplat vert (topbar, encarts sombres), le « ? » reprend l'encre claire. */
.topbar .ek-aide-bouton,
.zone-green .ek-aide-bouton { color: var(--ek-on-green); }
