/* ============================================================
   HRT — DESIGN SYSTEM CSS MULTI-SOCIÉTÉ
   Source de vérité : /docs/project/custom-brand-theme.css
   Copie déployée   : HRT/PUBLIC/assets/css/custom-brand-theme.css
   ATTENTION : éditer la SOURCE, puis répliquer 1:1.
   Ne JAMAIS éditer uniquement la copie déployée.
   ============================================================ */

/* ============================================================
   1. TOKENS COMMUNS — :root global
   Communs aux deux sociétés (Ray Assainissement + Techni-cana)
   ============================================================ */
:root {
  /* Gris d'en-tete, hors palettes societe : c'est un gris de structure et non une couleur de marque,
     il vaut donc la meme chose sur les cinq themes. Sert au thead des listings et a la bande de
     regroupement de l'ecran "A facturer". */
  --brand-bg-entete:          #FAFBFD;

  /* Violet du badge de numero d'affaire, hors palettes societe : l'affaire traverse les cinq
     societes, elle se lit donc a l'identique partout. Meme construction que les paires
     --brand-info / --brand-info-soft : teinte lisible sur son fond pastel. */
  --brand-violet:             #5B34A0;
  --brand-violet-soft:        #EDE3FC;
  --brand-violet-ring:        #CBB4F2;

  --brand-shadow-sm:          0 1px 3px rgba(0, 0, 0, 0.06);
  --brand-shadow-md:          0 2px 8px rgba(0, 0, 0, 0.10);
  --brand-shadow-lg:          0 4px 16px rgba(0, 0, 0, 0.12);
  --brand-transition:         0.15s ease;
  --brand-font-size-base:     13px;
  --brand-font-size-sm:       12px;
  --brand-font-size-lg:       16px;
  --brand-line-height:        1.5;
  --brand-sidebar-width:      240px;
  --brand-sidebar-condensed:  70px;
  --brand-topbar-height:      70px; /*Originalement 60px mais ne s'aligné pas parfaitement avec la sidebar*/

  /* Familles typographiques globales — chargées via Google Fonts dans base.php
     et login.php. Inter pour body dense ERP, Archivo pour display affirmé,
     JetBrains Mono pour figures tabulaires. */
  --brand-font-display:       'Archivo', 'Inter', system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
  --brand-font-mono:          'JetBrains Mono', 'SF Mono', Consolas, 'Courier New', monospace;
}

/* ============================================================
   2. THEME RAY ASSAINISSEMENT
   Scope : [data-societe-theme="ray"]
   Primaire : #497A2D Vert sapin DOMINANT (correction utilisateur 2026-04-27)
   Le vert est la couleur dominante de Ray (logo officiel + signalétique).
   Le navy #1D3557 passe en secondaire pour les boutons d'action neutre,
   les en-têtes de tableau et les éléments structurels.
   Source : /docs/project/brand-theme-overrides-ray.md
   ============================================================ */
[data-societe-theme="ray"] {

  /* --- COULEURS PRIMAIRES — Vert sapin dominant Ray --- */
  --brand-primary:          #497A2D;
  --brand-primary-dark:     #3A6324;
  --brand-primary-soft:     #E8F2DD;
  --brand-on-primary:       #FFFFFF;

  /* --- COULEURS SECONDAIRES — Navy Ray (rôle secondaire) --- */
  --brand-secondary:        #1D3557;
  --brand-secondary-dark:   #142740;
  --brand-secondary-soft:   #E8EDF3;
  --brand-on-secondary:     #FFFFFF;

  /* --- ACCENT BRAND — Navy Ray pour signatures formelles, en-têtes, dividers --- */
  --brand-accent:           #1D3557;
  --brand-accent-dark:      #142740;
  --brand-accent-soft:      #E8EDF3;
  --brand-on-accent:        #FFFFFF;

  /* --- SURFACES ET FONDS --- */
  --brand-bg-app:           #F2F5F0;
  --brand-bg-surface:       #FFFFFF;

  /* --- TYPOGRAPHIE --- */
  --brand-text-default:     #1A1F2E;
  --brand-text-muted:       #6B7280;
  --brand-border:           #D8DED2;

  /* --- COULEURS SÉMANTIQUES --- */
  --brand-success:          #497A2D;
  --brand-success-soft:     #E8F2DD;
  --brand-warning:          #B45309;
  --brand-warning-soft:     #FEF3C7;
  --brand-danger:           #C0392B;
  --brand-danger-soft:      #FDECEA;
  --brand-info:             #1D6FA4;
  --brand-info-soft:        #E8F4FD;

  /* --- TYPOGRAPHIE FONT —
     --brand-font-display et --brand-font-mono sont définis globalement
     dans :root (Archivo + JetBrains Mono). Seul body Inter est défini
     ici per-thème par cohérence sémantique. --- */
  --brand-font-sans:        'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;

  /* --- FORME --- */
  --brand-radius:           6px;

  /* --- ASSETS — logo officiel Ray (PNG) sur panneau blanc dans la sidebar --- */
  --brand-logo-url:         url('/assets/images/logo-ray.png');
  --brand-logo-bg:          #FFFFFF;
  --brand-logo-fg:          var(--brand-text-default);
  --brand-logo-icon:        var(--brand-primary);
  --brand-sidebar-bg:       #497A2D;
  --brand-sidebar-text:     #FFFFFF;
  --brand-sidebar-active-bg: rgba(255,255,255,0.18);
  --brand-sidebar-hover-bg: rgba(255,255,255,0.10);
  --brand-onglet-bg:         #E8F2DD;
}

/* ============================================================
   3. THEME TECHNI-CANA
   Scope : [data-societe-theme="technicana"]
   Primaire : #242B3D Navy charbon DOMINANT (correction utilisateur 2026-04-27)
   Le navy charbon est la couleur dominante du wordmark "TECHNICANA" et
   de la top-bar du site officiel. Le vert vif #6CB543 (le "C" du logo)
   passe en accent décoratif et le vert ERP #4A8C28 reste utilisé pour
   les états positifs (success, validation).
   Source : /docs/project/brand-theme-overrides-technicana.md
   ============================================================ */
[data-societe-theme="technicana"] {

  /* --- COULEURS PRIMAIRES — Navy charbon dominant Techni-cana --- */
  --brand-primary:          #242B3D;
  --brand-primary-dark:     #161B28;
  --brand-primary-soft:     #E5E7EC;
  --brand-on-primary:       #FFFFFF;

  /* --- COULEURS SECONDAIRES — Vert Techni-cana (rôle secondaire) --- */
  --brand-secondary:        #6CB543;
  --brand-secondary-dark:   #3A6E1F;
  --brand-secondary-soft:   #E8F5DD;
  --brand-on-secondary:     #FFFFFF;

  /* --- ACCENT — Vert vif signature (le C du logo officiel) --- */
  --brand-accent:           #6CB543;
  --brand-accent-dark:      #4A8C28;
  --brand-accent-soft:      #EAF7DD;
  --brand-on-accent:        #FFFFFF;

  /* --- SURFACES ET FONDS --- */
  --brand-bg-app:           #F5F6F8;
  --brand-bg-surface:       #FFFFFF;

  /* --- TEXTE --- */
  --brand-text-default:     #1A2433;
  --brand-text-muted:       #64748B;
  --brand-border:           #D5D8DE;

  /* --- COULEURS SÉMANTIQUES --- */
  --brand-success:          #4A8C28;
  --brand-success-soft:     #E8F5DD;
  --brand-warning:          #B45309;
  --brand-warning-soft:     #FEF3C7;
  --brand-danger:           #DC2626;
  --brand-danger-soft:      #FEE2E2;
  --brand-info:             #1380A5;
  --brand-info-soft:        #E0F0F5;

  /* --- TYPOGRAPHIE FONT —
     --brand-font-display et --brand-font-mono sont définis globalement
     dans :root (Archivo + JetBrains Mono). --- */
  --brand-font-sans:        'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;

  /* --- FORME --- */
  --brand-radius:           6px;

  /* --- ASSETS — logo officiel Techni-cana (PNG) sur panneau blanc --- */
  --brand-logo-url:         url('/assets/images/logo-technicana.png');
  --brand-logo-bg:          #FFFFFF;
  --brand-logo-fg:          var(--brand-text-default);
  --brand-logo-icon:        var(--brand-primary);
  --brand-sidebar-bg:       #242B3D;
  --brand-sidebar-text:     #FFFFFF;
  --brand-sidebar-active-bg: rgba(255,255,255,0.12);
  --brand-sidebar-hover-bg: rgba(255,255,255,0.08);
  --brand-onglet-bg:         #E5E7EC;
}

/* ============================================================
   4. THEME TECHNI-FUITE
   Scope : [data-societe-theme="technifuite"]
   Source : /docs/project/technifuite/brand-theme-overrides.md
   ============================================================ */
[data-societe-theme="technifuite"] {

  --brand-primary:           #1D70B7;
  --brand-primary-dark:      #155A96;
  --brand-primary-soft:      #E3F0F9;
  --brand-on-primary:        #FFFFFF;

  --brand-secondary:         #74cbc5;
  --brand-secondary-dark:    #D4581A;
  --brand-secondary-soft:    #FEF0E8;
  --brand-on-secondary:      #FFFFFF;

  --brand-accent:            #F56E28;
  --brand-accent-dark:       #D4581A;
  --brand-accent-soft:       #FEF0E8;
  --brand-on-accent:         #FFFFFF;

  --brand-bg-app:            #F4F6F8;
  --brand-bg-surface:        #FFFFFF;

  --brand-text-default:      #1A1C20;
  --brand-text-muted:        #6B7280;
  --brand-border:            #D1D9E0;

  --brand-success:           #1A5C35;
  --brand-success-soft:      #D4EDDA;
  --brand-warning:           #A8430F;
  --brand-warning-soft:      #FEF0E8;
  --brand-danger:            #8B2020;
  --brand-danger-soft:       #FBEAEA;
  --brand-info:              #0E4275;
  --brand-info-soft:         #E3F0F9;

  --brand-font-sans:         'Source Sans 3', 'Source Sans Pro', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;

  --brand-radius:            6px;

  --brand-logo-url:          url('/assets/images/logo-technifuite.png');
  --brand-logo-bg:           #DEE5EE;
  --brand-logo-fg:          var(--brand-text-default);
  --brand-logo-icon:        var(--brand-primary);
  --brand-sidebar-bg:        #11416A;
  --brand-sidebar-text:      #FFFFFF;
  --brand-sidebar-active-bg: rgba(29, 112, 183, 0.20);
  --brand-sidebar-hover-bg:  rgba(255, 255, 255, 0.08);
  --brand-onglet-bg:         #E3F0F9;
}

/* ============================================================
   5. THEME DETECT RÉSEAUX
   Scope : [data-societe-theme="detectreseaux"]
   Source : /docs/project/detectreseaux/brand-theme-overrides.md
   ============================================================ */
[data-societe-theme="detectreseaux"] {

  --brand-primary:           #1D70B7;
  --brand-primary-dark:      #165A96;
  --brand-primary-soft:      #E8F2FA;
  --brand-on-primary:        #FFFFFF;

  --brand-secondary:         #000000;
  --brand-secondary-dark:    #D44E43;
  --brand-secondary-soft:    #FEF0EF;
  --brand-on-secondary:      #FFFFFF;

  --brand-accent:            #F16358;
  --brand-accent-dark:       #D44E43;
  --brand-accent-soft:       #FEF0EF;
  --brand-on-accent:         #FFFFFF;

  --brand-bg-app:            #F4F5F7;
  --brand-bg-surface:        #FFFFFF;

  --brand-text-default:      #2D2D2D;
  --brand-text-muted:        #6B7280;
  --brand-border:            #D1D5DB;

  --brand-success:           #065F46;
  --brand-success-soft:      #D1FAE5;
  --brand-warning:           #92400E;
  --brand-warning-soft:      #FEF3C7;
  --brand-danger:            #991B1B;
  --brand-danger-soft:       #FEE2E2;
  --brand-info:              #1D4ED8;
  --brand-info-soft:         #E8F2FA;

  --brand-font-sans:         'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;

  --brand-radius:            6px;

  --brand-logo-url:          url('/assets/images/logo-detectreseaux.png');
  --brand-logo-bg:           #FFFFFF;
  --brand-logo-fg:          var(--brand-text-default);
  --brand-logo-icon:        var(--brand-primary);
  --brand-sidebar-bg:        #1A1C20;
  --brand-sidebar-text:      #FFFFFF;
  --brand-sidebar-active-bg: rgba(29, 112, 183, 0.18);
  --brand-sidebar-hover-bg:  rgba(255, 255, 255, 0.06);
  --brand-onglet-bg:         #E8F2FA;
}

/* ============================================================
   6. THEME RAY TPI
   Scope : [data-societe-theme="raytpi"]
   Logo officiel : "RAY" blanc + "TPI" azur sur champ navy.
   Couleurs extraites du logo vectoriel :
     Azur   #008ADD (signature, dominante)
     Navy   #00152F (champ de fond du logo, structure)
     Blanc  #FFFFFF
   Primaire = azur legerement approfondi (#0A78C2) pour garantir
   le contraste AA du texte blanc sur les boutons (4.7:1) ; l'azur
   pur #008ADD reste vivant dans les surbrillances de la sidebar.
   Secondaire + accent = navy #00152F (en-tetes, dividers, KPI).
   ATTENTION logo : contrairement a Ray/Technicana (panneau blanc),
   le logo RAY TPI est concu pour fond sombre -> --brand-logo-bg navy.
   ============================================================ */
[data-societe-theme="raytpi"] {

  /* --- COULEURS PRIMAIRES - Azur RAY TPI (signature du logo) --- */
  --brand-primary:          #0A78C2;
  --brand-primary-dark:     #085E99;
  --brand-primary-soft:     #E1F1FB;
  --brand-on-primary:       #FFFFFF;

  /* --- COULEURS SECONDAIRES - Navy RAY TPI (champ du logo) --- */
  --brand-secondary:        #00152F;
  --brand-secondary-dark:   #000B1C;
  --brand-secondary-soft:   #E2E6EC;
  --brand-on-secondary:     #FFFFFF;

  /* --- ACCENT - Navy RAY TPI (en-tetes, dividers, KPI) --- */
  --brand-accent:           #00152F;
  --brand-accent-dark:      #000B1C;
  --brand-accent-soft:      #E2E6EC;
  --brand-on-accent:        #FFFFFF;

  /* --- SURFACES ET FONDS --- */
  --brand-bg-app:           #F3F6F9;
  --brand-bg-surface:       #FFFFFF;

  /* --- TYPOGRAPHIE --- */
  --brand-text-default:     #0F1B2D;
  --brand-text-muted:       #64748B;
  --brand-border:           #D5DEE6;

  /* --- COULEURS SEMANTIQUES --- */
  --brand-success:          #1F8B4C;
  --brand-success-soft:     #E2F4EA;
  --brand-warning:          #B45309;
  --brand-warning-soft:     #FEF3C7;
  --brand-danger:           #C0392B;
  --brand-danger-soft:      #FDECEA;
  --brand-info:             #0E7490;
  --brand-info-soft:        #E0F2F7;

  /* --- TYPOGRAPHIE FONT - Inter (defini globalement dans :root) --- */
  --brand-font-sans:        'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;

  /* --- FORME --- */
  --brand-radius:           6px;

  /* --- ASSETS - logo blanc+azur sur navy : panneau NAVY (pas blanc) --- */
  --brand-logo-url:         url('/assets/images/logo-raytpi.png');
  --brand-logo-bg:          #00152F;
  --brand-logo-fg:          #FFFFFF;
  --brand-logo-icon:        #FFFFFF;
  --brand-sidebar-bg:       #00152F;
  --brand-sidebar-text:     #FFFFFF;
  --brand-sidebar-active-bg: rgba(0, 138, 221, 0.28);
  --brand-sidebar-hover-bg: rgba(0, 138, 221, 0.14);
  --brand-onglet-bg:         #E1F1FB;
}

/* ============================================================
   6. BASE APPLICATIVE — BODY + TYPOGRAPHIE
   ============================================================ */
body {
  font-family:   var(--brand-font-sans);
  font-size:     var(--brand-font-size-base);
  line-height:   var(--brand-line-height);
  color:         var(--brand-text-default);
  background:    var(--brand-bg-app);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* --- Barres de defilement du projet ---
   Sans selecteur : s'applique a la fenetre et a tout element scrollable (modale, tiroir,
   textarea, panneau, liste d'autocomplete...). Les elements qui masquent volontairement leur
   barre (.table-hrt-scroll, .onglet-hrt) restent prioritaires, leur selecteur est plus specifique.
   Ne jamais poser scrollbar-width ni scrollbar-color ici : Chrome ignorerait alors tout ce bloc
   et rendrait ses barres natives (cf. .table-hrt-scrollbar). */
::-webkit-scrollbar {
  width:      12px;
  height:     12px;
  background: var(--brand-bg-app);
}
::-webkit-scrollbar-track {
  background:    var(--brand-bg-app);
  border-radius: 8px;
}
::-webkit-scrollbar-thumb {
  background:    var(--brand-text-muted);
  border:        3px solid var(--brand-bg-app);
  border-radius: 8px;
}
::-webkit-scrollbar-thumb:hover { background: var(--brand-primary); }
::-webkit-scrollbar-corner { background: var(--brand-bg-app); }

/* Firefox n'a pas ces pseudo-elements : scrollbar-color est heritable, le poser sur html
   suffit a habiller toutes les barres du projet. */
@supports not selector(::-webkit-scrollbar) {
  html { scrollbar-color: var(--brand-text-muted) var(--brand-bg-app); }
}

/* ============================================================
   5. OVERRIDES HYPER — UNIVERSELS (valent pour les deux thèmes)
   ============================================================ */

/* Override 2 — Navbar double margin-left Hyper + alignement hamburger
   FEEDBACK_LOG META_css_source_of_truth_drift — correctif obligatoire.
   Sans display:flex sur .container-fluid, le hamburger reste en haut
   à gauche tandis que .navbar-right s'aligne sur la baseline du texte
   à droite — décalage vertical visible. On force l'alignement central
   sur toute la barre.
   Les -12px annulent le padding de .content-page, pas celui de la navbar :
   Hyper pose aussi `.navbar-custom { padding: 0 .75rem }`, qui reste et
   donne au hamburger sa gouttière de 12px. Elle l'aligne sur le bord
   gauche du contenu de la page, qui porte le même padding — ne pas la
   doubler d'un padding sur .container-fluid. */
.navbar-custom {
  margin-left:  -12px !important;
  margin-right: -12px !important;
  width:        calc(100% + 24px) !important;
  background-color: var(--brand-bg-surface) !important;
  box-shadow:   var(--brand-shadow-sm) !important;
  display:      flex !important;
  align-items:  stretch !important;
  min-height:   var(--brand-topbar-height) !important;
}
.navbar-custom > .container-fluid {
  display:      flex !important;
  align-items:  center !important;
  width:        100%;
  padding-right: 16px;
}
.navbar-custom .button-toggle-menu {
  display:         inline-flex;
  align-items:     center;
  justify-content: center;
  width:           56px;
  height:          var(--brand-topbar-height);
  padding:         0;
  margin:          0;
  background:      transparent;
  border:          0;
  color:           var(--brand-text-default);
  font-size:       22px;
  cursor:          pointer;
  flex-shrink:     0;
  transition:      background var(--brand-transition), color var(--brand-transition);
}
.navbar-custom .button-toggle-menu:hover {
  background: var(--brand-bg-app);
  color:      var(--brand-primary);
}
.navbar-custom .button-toggle-menu:focus-visible {
  outline:        2px solid var(--brand-primary);
  outline-offset: -4px;
}
.navbar-custom .navbar-right {
  align-items: center;
  height:      var(--brand-topbar-height);
}

/* Menu du profil sur téléphone. Hyper étire tous les dropdowns de la topbar d'un bord à l'autre
   sous 576px : `.navbar-custom .dropdown .dropdown-menu { left: 10px !important; right: 10px
   !important }`. C'est écrit pour ses panneaux de notifications, pleine largeur par nature. Le
   menu du profil, lui, fait sept lignes et pend d'un avatar de 32px calé en haut à droite :
   étiré, il faisait 355px sur un écran de 375 et allait raser le bord gauche, très loin de son
   déclencheur.
   On ne peut pas se contenter de rendre les deux à auto : Popper pose son ancrage en style inline
   (`inset: 0 0 auto auto`, soit right: 0) puis décale le menu par un translate3d négatif. Le
   !important d'Hyper battant l'inline, cet ancrage était déjà mort ; le remettre à auto laissait
   le menu à sa position statique, et le translate le poussait alors hors de l'écran à droite.
   On rend donc à Popper exactement l'ancrage qu'il attend : left auto, right 0, son translate
   faisant le reste. Largeur bornée à l'écran pour qu'un libellé long ne déborde pas à son tour.
   La règle vise .navbar-right et non tous les dropdowns de la barre : un futur panneau pleine
   largeur garderait le comportement d'Hyper. */
@media (max-width: 575.98px) {
  .navbar-custom .navbar-right .dropdown .dropdown-menu {
    left:      auto !important;
    right:     0    !important;
    max-width: calc(100vw - 20px);
  }
}

/* Champ posé dans la topbar. .field-hrt porte une marge basse de 16px prévue pour les
   formulaires : dans une barre alignée au centre, elle décale le champ de 8px vers le haut.
   La largeur est explicite parce que .field-input-hrt est en width: 100% : dans un conteneur
   flex en colonne sans largeur propre, il retombe sur sa taille intrinsèque et reste étroit.
   min-width: 0 pour qu'il puisse se réduire sur petit écran au lieu de pousser la zone droite. */
.navbar-custom .hrt-navbar-champ {
  width:         400px;
  min-width:     0;
  margin-bottom: 0;
  margin-left:   8px;
}

/* --- Sur telephone, les boutons de la barre mangeaient toute la largeur : quatre boutons a 56px
   consomment 224px des 375px de l'ecran, et .hrt-navbar-champ etant en min-width: 0, c'est la
   recherche qui absorbait tout le manque et devenait inutilisable. Les boutons passent a 40px et
   leur icone a 17px, ce qui rend 64px au champ. --- */
@media (max-width: 575.98px) {
  .navbar-custom .button-toggle-menu {
    width:     40px;
    font-size: 17px;
  }

  /* --- Le ressort .flex-grow-1 place apres le champ tombe a zero des que celui-ci se comprime : sans
     marge droite, la recherche se retrouve collee a l'avatar du menu utilisateur. --- */
  .navbar-custom .hrt-navbar-champ {
    margin-left:  4px;
    margin-right: 10px;
  }
}

/* Override 3 — Sidebar 100vh fixed */
.leftside-menu {
  position:          fixed !important;
  top:               0 !important;
  bottom:            0 !important;
  height:            100vh !important;
  display:           flex;
  flex-direction:    column;
  background-color:  var(--brand-sidebar-bg) !important;
  padding-bottom: 0 !important;
}
.leftside-menu .logo {
  flex: 0 0 70px;
}
#leftside-menu-container {
  flex:       1 1 auto;
  min-height: 0;
}
.leftside-menu .side-nav {
  display:        flex;
  flex-direction: column;
  flex:           1 1 auto;
}

/* Override 4 — Zone logo : panneau blanc pour les logos officiels
   Les vrais logos Ray (block teal/vert) et Techni-cana (navy + vert)
   sont conçus pour fond clair. Sur sidebar foncée, on les place dans
   un panneau blanc avec une fine séparation de la sidebar. */
.leftside-menu .logo {
  display:         flex !important;
  align-items:     center !important;
  justify-content: center !important;
  height:          var(--brand-topbar-height) !important;
  padding:         4px 12px !important;
  overflow:        hidden;
  background-color: var(--brand-logo-bg) !important;
  text-decoration:  none !important;
  border-bottom:    1px solid var(--brand-border);
}
/* IMPORTANT : NE PAS forcer display:flex/inline-flex sur .logo-lg /.logo-sm.
   Hyper toggle nativement display:block/none entre les deux variantes
   selon data-sidenav-size (default → lg visible / sm caché ;
   condensed → lg caché / sm visible). Un override display ici fait
   apparaître les DEUX variantes côte à côte. */
.leftside-menu .logo .logo-lg,
.leftside-menu .logo .logo-sm {
  max-width:   100%;
  max-height:  100%;
  line-height: 0;
  text-align:  center;
}
.leftside-menu .logo .logo-img-lg {
  max-width:  200px;
  max-height: 58px;
  width: auto; height: auto;
  object-fit: contain;
}
.leftside-menu .logo .logo-img-sm {
  max-width:  52px;
  max-height: 52px;
  width: auto; height: auto;
  object-fit: contain;
}

/* Override — Side-nav links couleurs brand */
.leftside-menu .side-nav-link {
  color:       var(--brand-sidebar-text) !important;
  opacity:     0.82;
  font-size:   13px;
  font-weight: 400;
  transition:  background-color var(--brand-transition), opacity var(--brand-transition);
}
.leftside-menu .side-nav-link:hover {
  background-color: var(--brand-sidebar-hover-bg) !important;
  opacity:          1;
}
.leftside-menu .side-nav-link.active,
.leftside-menu .mm-active > .side-nav-link {
  background-color: var(--brand-sidebar-active-bg) !important;
  color:            var(--brand-sidebar-text) !important;
  opacity:          1;
  font-weight:      600;
}
.leftside-menu .side-nav-link i,
.leftside-menu .side-nav-link svg {
  color: inherit !important;
  opacity: 0.9;
}
.leftside-menu .side-nav-title {
  color:          rgba(255,255,255,0.5) !important;
  font-size:      10px !important;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight:    600;
}

/* Menus depliables sidebar (HRT) */
.leftside-menu .side-nav-item.hrt-nav-group {
  position: relative;
}

.leftside-menu .hrt-nav-link {
  display: flex;
  align-items: center;
  gap: 10px;
  padding-top: 6px;
  padding-bottom: 6px;
}

.leftside-menu .hrt-nav-arrow-btn {
  margin-left: auto;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 6px;
  border-radius: var(--brand-radius);
  cursor: pointer;
  flex-shrink: 0;
}

.leftside-menu .hrt-nav-arrow-btn:hover {
  background-color: var(--brand-sidebar-hover-bg);
}

.leftside-menu .hrt-nav-arrow {
  font-size: 11px;
  transition: transform 0.2s ease;
}

.leftside-menu .side-nav-item.hrt-nav-group.is-open .hrt-nav-arrow {
  transform: rotate(180deg);
}

.leftside-menu .hrt-nav-sub {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.25s ease;
}

.leftside-menu .side-nav-item.hrt-nav-group.is-open > .hrt-nav-sub {
  max-height: 320px;
}

.leftside-menu .hrt-nav-sub-inner {
  margin: 2px 0 6px 34px;
  padding-left: 12px;
  border-left: 1px solid rgba(255, 255, 255, 0.15);
}

.leftside-menu .hrt-nav-sub-link {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 40px;
  padding: 7px 12px;
  border-radius: var(--brand-radius);
  font-size: 12.5px;
  color: var(--brand-sidebar-text);
  opacity: 0.72;
  text-decoration: none;
  transition: background-color var(--brand-transition), opacity var(--brand-transition);
}

.leftside-menu .hrt-nav-sub-link:hover {
  background-color: var(--brand-sidebar-hover-bg);
  opacity: 1;
}

.leftside-menu .hrt-nav-sub-link.active {
  color: var(--brand-primary-soft);
  opacity: 1;
  font-weight: 600;
}

.leftside-menu .hrt-nav-sub-link .hrt-nav-dot {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.6;
  flex-shrink: 0;
}

.leftside-menu .hrt-nav-sub-link.active .hrt-nav-dot {
  opacity: 1;
}

@media (max-width: 991.98px) {
  .leftside-menu .hrt-nav-sub-link {
    min-height: 44px;
  }
}

/* Mode condensed : sous-menu en flyout au survol */
html[data-sidenav-size="condensed"] .wrapper .leftside-menu .hrt-nav-arrow-btn {
  display: none;
}

html[data-sidenav-size="condensed"] .wrapper .leftside-menu .hrt-nav-sub {
  max-height: none;
  position: absolute;
  left: 100%;
  top: 0;
  min-width: 210px;
  padding: 6px;
  background-color: var(--brand-sidebar-bg);
  border-radius: 0 var(--brand-radius) var(--brand-radius) 0;
  box-shadow: var(--brand-shadow-lg);
  display: none;
}

html[data-sidenav-size="condensed"] .wrapper .leftside-menu .side-nav-item.hrt-nav-group:hover .hrt-nav-sub {
  display: block;
}

html[data-sidenav-size="condensed"] .wrapper .leftside-menu .hrt-nav-sub-inner {
  margin: 0;
  padding-left: 0;
  border-left: 0;
}

/* Override — Éliminer le purple Hyper par défaut dans la sidebar */
.leftside-menu .mm-active > a,
.leftside-menu li.active > a {
  color: var(--brand-sidebar-text) !important;
  background-color: var(--brand-sidebar-active-bg) !important;
}

/* Override 5 — Déconnexion sticky en bas de sidebar */
.side-nav-item-logout {
  margin-top:       auto;
  position:         sticky;
  bottom:           0;
  background-color: var(--brand-sidebar-bg);
  border-top:       1px solid rgba(255,255,255,0.10);
  padding:          6px 0 8px 0;
  z-index:          2;
}
.side-nav-link-logout {
  color:      var(--brand-danger-soft, #f0a0a0) !important;
  transition: background-color var(--brand-transition), color var(--brand-transition);
}
.side-nav-link-logout i { color: var(--brand-danger-soft, #f0a0a0) !important; }
.side-nav-link-logout:hover,
.side-nav-link-logout:focus {
  color:            #ffffff !important;
  background-color: rgba(192, 57, 43, 0.22) !important;
}
.side-nav-link-logout:hover i { color: #ffffff !important; }

/* Condensed sidebar — bloque l'expansion Hyper au hover.
   Hyper force width:--ct-leftbar-width + visibility:visible sur le span au hover,
   ce qui fait déborder le lien hors du cadre condensed (70px).
   On annule ces deux règles pour rester dans les bornes. */
html[data-sidenav-size="condensed"]:not([data-layout="topnav"]) .wrapper .leftside-menu .side-nav .side-nav-item:hover .side-nav-link {
  width: var(--ct-leftbar-width-sm) !important;
  background-color: var(--brand-sidebar-hover-bg) !important;
}
html[data-sidenav-size="condensed"]:not([data-layout="topnav"]) .wrapper .leftside-menu .side-nav .side-nav-item:hover .side-nav-link span {
  visibility: hidden !important;
}

/* En mode condensed, on ne touche PAS au padding de .side-nav-link-logout —
   Hyper applique nativement padding:10px sur tous les .side-nav-link, ce qui
   centre l'icône (50px) dans la sidebar (70px). Forcer padding:0 décale
   le logout de ~8px vers la gauche par rapport aux autres items. */

/* Override — Boutons brand (remplacent btn-primary Hyper violet) */
.btn-primary,
.btn-brand-primary {
  background-color: var(--brand-primary) !important;
  border-color:     var(--brand-primary-dark) !important;
  color:            var(--brand-on-primary) !important;
  border-radius:    var(--brand-radius) !important;
  font-size:        13px;
  font-weight:      500;
}
.btn-primary:hover,
.btn-brand-primary:hover {
  background-color: var(--brand-primary-dark) !important;
  border-color:     var(--brand-primary-dark) !important;
  color:            var(--brand-on-primary) !important;
}
.btn-primary:focus-visible,
.btn-brand-primary:focus-visible {
  box-shadow: 0 0 0 4px rgba(var(--brand-primary-rgb, 29,53,87), 0.18) !important;
}

/* Override — Liens couleur brand */
a { color: var(--brand-primary); }
a:hover { color: var(--brand-primary-dark); }

/* Override — Inputs focus ring brand */
.form-control:focus,
.form-select:focus {
  border-color: var(--brand-primary) !important;
  box-shadow:   0 0 0 3px color-mix(in srgb, var(--brand-primary) 15%, transparent) !important;
}

/* Override — Tooltips à la couleur de la société : Hyper les peint en var(--ct-body-color), */
/* soit le gris du texte du body. Les flèches lisent le même token, redéfinir suffit pour tout */
.tooltip {
  --ct-tooltip-bg:            var(--brand-primary);
  --ct-tooltip-color:         #fff;
  --ct-tooltip-font-size:     12px;
  --ct-tooltip-padding-y:     4px;
  --ct-tooltip-padding-x:     8px;
  --ct-tooltip-max-width:     260px;
  --ct-tooltip-border-radius: var(--brand-radius);
}

/* Override 1 — .small sur éléments block (Hyper force inline-block) */
/* FEEDBACK_LOG META_css_source_of_truth_drift — correctif obligatoire */
dl.small, dt.small, dd.small, p.small, div.small, section.small, article.small,
header.small, footer.small, aside.small, nav.small, main.small, form.small,
fieldset.small, legend.small, label.small, ul.small, ol.small, li.small,
table.small, thead.small, tbody.small, tfoot.small, tr.small, td.small, th.small,
h1.small, h2.small, h3.small, h4.small, h5.small, h6.small {
  display: revert;
}

/* Override 6 — Cache-buster : id="app-style" sera sur la balise CSS dans base.php */

/* ============================================================
   6. COMPOSANTS — CARDS
   ============================================================ */
.card {
  border:        1px solid var(--brand-border);
  border-radius: var(--brand-radius);
  box-shadow:    var(--brand-shadow-sm);
  background:    var(--brand-bg-surface);
}
.card-header {
  background:    linear-gradient(180deg, #fafbfd 0%, #f6f8fb 100%);
  border-bottom: 1px solid var(--brand-border);
  min-height:    44px;
  display:       flex;
  align-items:   center;
  justify-content: space-between;
  padding:       0 20px;
  border-radius: var(--brand-radius) var(--brand-radius) 0 0;
}
.card-title {
  font-size:   14px;
  font-weight: 600;
  color:       var(--brand-text-default);
  margin:      0;
}
.card-body {
  padding: 20px;
}

/* ============================================================
   7. COMPOSANTS — BADGES
   ============================================================ */
.badge-hrt {
  display:       inline-flex;
  align-items:   center;
  gap:           5px;
  padding:       3px 8px;
  border-radius: 999px;
  font-size:     11px;
  font-weight:   600;
  line-height:   1;
  letter-spacing: 0.02em;
  white-space:   nowrap;
  /* Remise a zero, pas un choix esthetique : .form-subcard-title-hrt porte text-transform:uppercase
     et un badge pose dans un titre en heritait, ce qui le faisait lire comme un bout du titre. */
  text-transform: none;
}
.badge-hrt .badge-dot {
  width:         6px;
  height:        6px;
  border-radius: 50%;
  background:    currentColor;
  flex-shrink:   0;
}
.badge-success  { color: var(--brand-success); background: var(--brand-success-soft); }
.badge-warning  { color: var(--brand-warning); background: var(--brand-warning-soft); }
.badge-danger   { color: var(--brand-danger);  background: var(--brand-danger-soft); }
.badge-info     { color: var(--brand-info);    background: var(--brand-info-soft); }
.badge-neutral  { color: var(--brand-text-muted); background: var(--brand-primary-soft); }
.badge-affaire  { color: var(--brand-violet);     background: var(--brand-violet-soft); }


/* Badges cliquables (button.badge-hrt) */
button.badge-hrt {
  border:      none;
  font-family: inherit;
  cursor:      pointer;
  transition:  filter .15s ease, box-shadow .15s ease;
}
button.badge-hrt:hover  { filter: brightness(.92); box-shadow: var(--brand-shadow-sm); }
button.badge-hrt:active { transform: scale(.97); }
button.badge-hrt:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }

/* Rangee de badges dans une cellule de listing : passe a la ligne au lieu d'elargir la colonne */
.hrt-cell-badges {
  display:   flex;
  flex-wrap: wrap;
  gap:       4px;
}

/* Pastille de couleur (parametrage : activite, type d'absence...) posee devant le nom de la couleur */
.hrt-pastille-couleur {
  display:        inline-block;
  width:          14px;
  height:         14px;
  border-radius:  4px;
  border:         1px solid var(--brand-border);
  margin-right:   6px;
  vertical-align: -2px;
}

/* ============================================================
   COMPOSANTS — ALERTES / CALLOUTS  (réutilisable)
   ============================================================ */
.alert-hrt {
  display:           flex;
  align-items:       flex-start;
  gap:               10px;
  border:            1px solid var(--brand-border);
  border-left-width: 4px;
  border-radius:     var(--brand-radius);
  padding:           12px 14px;
  font-size:         13px;
  line-height:       1.45;
}
.alert-hrt > i          { margin-top: 2px; flex-shrink: 0; }
.alert-hrt-corps        { flex: 1; min-width: 0; }
.alert-hrt-title        { font-weight: 600; color: var(--brand-text-default); }
.alert-hrt-desc         { color: var(--brand-text-muted); margin-top: 2px; }
.alert-hrt-chips        { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }

.alert-hrt--warning { background: var(--brand-warning-soft); border-color: var(--brand-warning); color: var(--brand-warning); }
.alert-hrt--danger  { background: var(--brand-danger-soft);  border-color: var(--brand-danger);  color: var(--brand-danger); }
.alert-hrt--info    { background: var(--brand-info-soft);    border-color: var(--brand-info);    color: var(--brand-info); }
.alert-hrt--success { background: var(--brand-success-soft); border-color: var(--brand-success); color: var(--brand-success); }

/* --- Sortie technique brute (trace SMTP, retour d'API) : monospace, defilable, jamais elargissante --- */
.hrt-log-block {
  max-height:     180px;
  overflow:       auto;
  margin:         0;
  padding:        10px 12px;
  background:     var(--brand-bg-app);
  border:         1px solid var(--brand-border);
  border-radius:  var(--brand-radius);
  font-family:    var(--brand-font-mono);
  font-size:      11px;
  line-height:    1.5;
  color:          var(--brand-text-default);
  white-space:    pre-wrap;
  overflow-wrap:  anywhere;
}

/* ============================================================
   8. COMPOSANTS — TABLES
   ============================================================ */
.table-hrt-wrapper {
  background:    var(--brand-bg-surface);
  border:        1px solid var(--brand-border);
  border-radius: var(--brand-radius);
  box-shadow:    var(--brand-shadow-sm);
  /* clip et non hidden : hidden ferait de la carte un conteneur de defilement,
     ce qui neutraliserait le position:sticky de la barre de defilement horizontale. */
  overflow:      clip;
}
/* Le defilement horizontal porte sur le tableau seul, pas sur la carte : la barre de recherche
   et le pied de listing doivent garder la largeur de la carte meme quand le tableau deborde.
   La barre native est masquee, c'est .table-hrt-scrollbar qui la remplace. */
.table-hrt-scroll {
  overflow-x: auto;
  scrollbar-width: none;
}
.table-hrt-scroll::-webkit-scrollbar { height: 0; }

/* --- Tableau defilant hors listing, en modale ou en drawer : la barre native reprend sa place.
   Le listing la masque parce qu'il la remplace par .table-hrt-scrollbar, collee en bas d'ecran et
   pilotee par initListingScrollbar(). Une modale n'a pas cette mecanique : masquer la barre sans
   remplacant ne laisserait plus rien annoncer les colonnes hors champ, et sur telephone la moitie
   d'un tableau resterait invisible. --- */
.modal-body .table-hrt-scroll,
.drawer-html .table-hrt-scroll {
  scrollbar-width: thin;
}
.modal-body .table-hrt-scroll::-webkit-scrollbar,
.drawer-html .table-hrt-scroll::-webkit-scrollbar {
  height: 8px;
}
.modal-body .table-hrt-scroll::-webkit-scrollbar-thumb,
.drawer-html .table-hrt-scroll::-webkit-scrollbar-thumb {
  background:    var(--brand-text-muted);
  border-radius: 4px;
}

/* --- Barre de defilement horizontale collee en bas de l'ecran ---
   Elle pilote .table-hrt-scroll via initListingScrollbar() et reste visible tant que
   le listing est a l'ecran : sans elle, rien n'indique que des colonnes sont hors champ.
   Aucun scrollbar-width / scrollbar-color ici : des que l'une de ces proprietes standard est
   posee, Chrome ignore tous les pseudo-elements ::-webkit-scrollbar de l'element et retombe
   sur sa barre native. Le style ci-dessous ne s'applique qu'a cette condition.
   z-index au-dessus du footer sticky des liste.php (.form-footer-sticky-hrt, z-index 99) :
   ce footer n'a pas de fond mais sa boite couvre le bas de l'ecran et capterait les clics
   destines a la barre. Le bouton du footer reste visible juste au-dessus d'elle. */
.table-hrt-scrollbar {
  position:   sticky;
  bottom:     0;
  z-index:    100;
  height:     18px;
  overflow-x: auto;
  overflow-y: hidden;
  background: var(--brand-bg-surface);
  border-top: 1px solid var(--brand-border);
}
.table-hrt-scrollbar > div { height: 1px; }
.table-hrt-scrollbar::-webkit-scrollbar {
  height:     16px;
  background: var(--brand-bg-app);
}
.table-hrt-scrollbar::-webkit-scrollbar-track {
  background:    var(--brand-bg-app);
  border-radius: 8px;
}
.table-hrt-scrollbar::-webkit-scrollbar-thumb {
  background:    var(--brand-text-muted);
  border:        3px solid var(--brand-bg-app);
  border-radius: 8px;
}
.table-hrt-scrollbar::-webkit-scrollbar-thumb:hover { background: var(--brand-primary); }

/* Firefox n'a pas les pseudo-elements webkit : on lui donne les proprietes standard,
   sans quoi il afficherait sa barre par defaut. */
@supports not selector(::-webkit-scrollbar) {
  .table-hrt-scrollbar {
    scrollbar-width: auto;
    scrollbar-color: var(--brand-text-muted) var(--brand-bg-app);
  }
}
.table-hrt {
  width: 100%;
  border-collapse: separate;
  border-spacing:  0;
  font-size: 13px;
}
.table-hrt thead th {
  background:     var(--brand-bg-entete);
  border-bottom:  1px solid var(--brand-border);
  padding:        10px 12px;
  font-size:      11px;
  font-weight:    600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color:          var(--brand-text-muted);
  white-space:    nowrap;
  user-select:    none;
}
.table-hrt thead th.sortable { cursor: pointer; }
.table-hrt thead th.sortable:hover { background: var(--brand-primary-soft); color: var(--brand-primary); }
.table-hrt tbody tr { border-bottom: 1px solid var(--brand-border); transition: background var(--brand-transition); }
.table-hrt tbody tr:last-child { border-bottom: none; }
.table-hrt tbody tr:hover { background: var(--brand-primary-soft); }
.table-hrt tbody td { padding: 10px 12px; color: var(--brand-text-default); vertical-align: middle; }

/* --- Separateurs de lignes pour un tableau pose hors de .table-hrt-wrapper ---
   Le border-bottom sur tr ci-dessus n'est jamais peint : en border-collapse: separate,
   les bordures des lignes sont ignorees par le navigateur. Il faut les porter par les cellules. */
.table-hrt--lignes tbody td { border-bottom: 1px solid var(--brand-border); }
.table-hrt--lignes tbody tr:last-child td { border-bottom: none; }

/* --- Lignes de hauteur constante ---
   Le retour a la ligne est ce qui fait varier la hauteur d'une ligne a l'autre : on le
   supprime et on ellipse. Deux tableaux cote a cote deviennent alors comparables ligne
   a ligne, puisque leurs colonnes tombent au meme endroit.

   table-layout: fixed n'est pas un detail de mise en page, c'est ce qui rend l'ellipse
   possible : en layout auto la largeur d'une cellule est dictee par son contenu, donc
   rien ne depasse jamais et text-overflow n'a aucun effet - le tableau s'elargit a la
   place. Les largeurs de colonnes doivent donc etre portees par les <th>.

   Les 50px valent le contenu le plus haut d'une ligne : un bouton .row-action-icon de
   30px entre les 10px de padding haut et bas de .table-hrt tbody td. */
.table-hrt--lignes-fixes { table-layout: fixed; }
.table-hrt--lignes-fixes tbody td {
  height:        50px;
  overflow:      hidden;
  white-space:   nowrap;
  text-overflow: ellipsis;
}

/* Cellule dont le contenu ne se coupe pas : un badge ou une pastille tronques ne veulent plus rien dire, et
   ce sont des contenus courts et bornes qui debordent rarement. Le nowrap reste, sans quoi un contenu sur
   deux lignes ferait grandir la ligne au-dela des 50px. */
.table-hrt--lignes-fixes tbody td.hrt-cellule-sans-ellipse {
  overflow:      visible;
  text-overflow: clip;
}

/* ============================================================
   9. COMPOSANTS — FORMULAIRES
   ============================================================ */
.field-hrt {
  display:       flex;
  flex-direction: column;
  gap:           5px;
  margin-bottom: 16px;
}
.field-label-hrt {
  font-size:      12px;
  font-weight:    500;
  color:          var(--brand-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
/* --- Colonnes cote a cote sur telephone : les champs restent alignes sur leur saisie --- */
/* --- Un libelle un peu long passe sur deux lignes dans une colonne etroite, et poussait sa --- */
/* --- seule saisie 18px plus bas que celles d'a cote ("Prix unitaire HT" contre "Quantite"). --- */
/* --- La colonne est deja etiree a la hauteur de la rangee par le flex de .row : il suffit que --- */
/* --- le champ la remplisse et que le libelle absorbe le surplus, la saisie se cale alors en --- */
/* --- bas de chaque colonne. Aucune hauteur n'est ajoutee, contrairement a une reserve de deux --- */
/* --- lignes en dur, et un libelle sur trois lignes est couvert de la meme facon. --- */
/* --- Exclut les seules colonnes deja pleine largeur en mobile, les col-12 : elles n'ont pas de --- */
/* --- voisine avec qui s'aligner. Une col-md-6 sans classe de base l'est aussi et se retrouve --- */
/* --- seule sur sa ligne de flex, la regle est alors sans effet sur elle. Le :has borne la --- */
/* --- bascule en flex aux colonnes qui portent vraiment un champ. --- */
@media (max-width: 767.98px) {
  .row > [class*="col-"]:not([class*="col-12"]):has(> .field-hrt) {
    display:        flex;
    flex-direction: column;
  }
  .row > [class*="col-"]:not([class*="col-12"]) > .field-hrt {
    flex: 1 1 auto;
  }
  .row > [class*="col-"]:not([class*="col-12"]) > .field-hrt > .field-label-hrt,
  .row > [class*="col-"]:not([class*="col-12"]) > .field-hrt > .form-label {
    flex: 1 0 auto;
  }
}

.field-input-hrt,
.field-select-hrt,
.field-textarea-hrt {
  width:         100%;
  height:        38px;
  padding:       0 12px;
  font-family:   var(--brand-font-sans);
  font-size:     13px;
  font-weight:   400;
  color:         var(--brand-text-default);
  background:    var(--brand-bg-surface);
  border:        1px solid var(--brand-border);
  border-radius: var(--brand-radius);
  outline:       none;
  transition:    border-color var(--brand-transition), box-shadow var(--brand-transition);
  appearance:    none;
  -webkit-appearance: none;
}
.field-textarea-hrt {
  height:   auto;
  padding:  8px 12px;
  resize:   vertical;
  min-height: 80px;
}
.field-input-hrt::placeholder,
.field-select-hrt::placeholder {
  color: var(--brand-text-muted);
  opacity: 0.7;
}
.field-input-hrt:focus,
.field-select-hrt:focus,
.field-textarea-hrt:focus {
  border-color: var(--brand-primary);
  box-shadow:   0 0 0 3px color-mix(in srgb, var(--brand-primary) 15%, transparent);
}
.field-input-hrt:disabled,
.field-select-hrt:disabled {
  background: var(--brand-bg-app);
  color:      var(--brand-text-muted);
  cursor:     not-allowed;
}
.form-section-hrt {
  background:    var(--brand-bg-surface);
  border:        1px solid var(--brand-border);
  border-radius: var(--brand-radius);
  box-shadow:    var(--brand-shadow-sm);
  margin-bottom: 16px;
  overflow:      hidden;
}
.form-section-header-hrt {
  display:        flex;
  align-items:    center;
  gap:            8px;
  min-height:     44px;
  padding:        0 20px;
  background:     linear-gradient(180deg, #fafbfd 0%, #f6f8fb 100%);
  border-bottom:  1px solid var(--brand-border);
  font-size:      13px;
  font-weight:    600;
  color:          var(--brand-text-default);
}
.form-section-body-hrt {
  padding: 20px;
}

/* ============================================================
   10. COMPOSANTS — BOUTONS HRT PROJET
   ============================================================ */
.btn-hrt-primary {
  display:        inline-flex;
  align-items:    center;
  gap:            6px;
  padding:        7px 16px;
  background:     var(--brand-primary);
  color:          var(--brand-on-primary);
  border:         1px solid var(--brand-primary-dark);
  border-radius:  var(--brand-radius);
  font-family:    var(--brand-font-sans);
  font-size:      13px;
  font-weight:    500;
  line-height:    1;
  cursor:         pointer;
  text-decoration: none;
  transition:     background var(--brand-transition), box-shadow var(--brand-transition), transform var(--brand-transition);
  white-space:    nowrap;
  -webkit-font-smoothing: antialiased;
}
.btn-hrt-primary:hover {
  background:  var(--brand-primary-dark);
  color:       var(--brand-on-primary);
  transform:   translateY(-1px);
  box-shadow:  0 2px 8px rgba(0,0,0,0.15);
}
.btn-hrt-primary:active { transform: scale(0.97); }
.btn-hrt-primary:focus-visible { outline: 2px solid var(--brand-primary); outline-offset: 2px; }
.btn-hrt-primary:disabled { opacity: 0.45; cursor: not-allowed; transform: none; }

.btn-hrt-accent {
  display:        inline-flex;
  align-items:    center;
  gap:            6px;
  padding:        7px 16px;
  background:     var(--brand-accent);
  color:          var(--brand-on-accent);
  border:         1px solid var(--brand-accent-dark);
  border-radius:  var(--brand-radius);
  font-family:    var(--brand-font-sans);
  font-size:      13px;
  font-weight:    500;
  line-height:    1;
  cursor:         pointer;
  text-decoration: none;
  transition:     background var(--brand-transition), box-shadow var(--brand-transition), transform var(--brand-transition);
  white-space:    nowrap;
  -webkit-font-smoothing: antialiased;
}
.btn-hrt-accent:hover {
  background:  var(--brand-accent-dark);
  color:       var(--brand-on-accent);
  transform:   translateY(-1px);
  box-shadow:  0 2px 8px rgba(0,0,0,0.15);
}
.btn-hrt-accent:active { transform: scale(0.97); }
.btn-hrt-accent:focus-visible { outline: 2px solid var(--brand-accent); outline-offset: 2px; }
.btn-hrt-accent:disabled { opacity: 0.45; cursor: not-allowed; transform: none; }

.btn-hrt-secondary {
  display:        inline-flex;
  align-items:    center;
  gap:            6px;
  height:         38px;
  padding:        0 14px;
  background:     var(--brand-bg-surface);
  color:          var(--brand-text-default);
  border:         1px solid var(--brand-border);
  border-radius:  var(--brand-radius);
  font-family:    var(--brand-font-sans);
  font-size:      13px;
  font-weight:    500;
  line-height:    1;
  cursor:         pointer;
  text-decoration: none;
  transition:     background var(--brand-transition), border-color var(--brand-transition);
  white-space:    nowrap;
}
.btn-hrt-secondary:hover {
  background:    var(--brand-bg-app);
  border-color:  var(--brand-primary);
  color:         var(--brand-primary);
}
.btn-hrt-secondary:disabled { opacity: 0.45; cursor: not-allowed; }
.btn-sm-hrt { padding: 5px 10px; font-size: 12px; height: auto; }
.btn-md-hrt { padding: 7px 14px; height: auto; }

/* --- Bouton à icône seule accolé à un champ : largeur fixe pour que deux champs superposés --- */
/* --- se terminent au même pixel, les icônes Font Awesome n'ayant pas toutes la même largeur --- */
.btn-icon-hrt {
  width:           38px;
  padding:         0;
  justify-content: center;
  flex-shrink:     0;
}

.btn-hrt-ghost {
  display:        inline-flex;
  align-items:    center;
  gap:            6px;
  padding:        7px 12px;
  background:     transparent;
  color:          var(--brand-text-muted);
  border:         1px solid transparent;
  border-radius:  var(--brand-radius);
  font-family:    var(--brand-font-sans);
  font-size:      13px;
  font-weight:    500;
  line-height:    1;
  cursor:         pointer;
  text-decoration: none;
  transition:     background var(--brand-transition), color var(--brand-transition);
}
.btn-hrt-ghost:hover {
  background: var(--brand-primary-soft);
  color:      var(--brand-primary);
}
/* Bouton ghost servant de bascule : même habillage que le survol, mais permanent tant que l'état est actif */
.btn-hrt-ghost.is-active {
  background: var(--brand-primary-soft);
  color:      var(--brand-primary);
}
.btn-hrt-ghost:disabled {
  opacity:    0.35;
  cursor:     not-allowed;
  background: transparent;
  color:      var(--brand-text-muted);
}

.btn-hrt-danger {
  display:        inline-flex;
  align-items:    center;
  gap:            6px;
  padding:        8px 18px;
  height:         38px;
  font-family:    var(--brand-font-ui);
  font-size:      13px;
  font-weight:    600;
  letter-spacing: 0.02em;
  background:     var(--brand-danger);
  color:          #fff;
  border:         1px solid var(--brand-danger);
  border-radius:  var(--brand-radius);
  cursor:         pointer;
  text-decoration: none;
  transition:     background var(--brand-transition), border-color var(--brand-transition);
  white-space:    nowrap;
  -webkit-font-smoothing: antialiased;
}
.btn-hrt-danger:hover {
  background:   color-mix(in srgb, var(--brand-danger) 85%, black);
  border-color: color-mix(in srgb, var(--brand-danger) 85%, black);
  color:        #fff;
  transform:    translateY(-1px);
  box-shadow:   0 2px 8px rgba(0,0,0,0.15);
}
.btn-hrt-danger:active  { transform: scale(0.97); }
.btn-hrt-danger:disabled { opacity: 0.45; cursor: not-allowed; transform: none; }

/* Variante contour, au gabarit de .btn-hrt-primary : une suppression posee a cote d'un Enregistrer
   sans lui voler la vedette */
.btn-hrt-danger-outline {
  display:        inline-flex;
  align-items:    center;
  gap:            6px;
  padding:        7px 16px;
  background:     transparent;
  color:          var(--brand-danger);
  border:         1px solid var(--brand-danger);
  border-radius:  var(--brand-radius);
  font-family:    var(--brand-font-sans);
  font-size:      13px;
  font-weight:    500;
  line-height:    1;
  cursor:         pointer;
  text-decoration: none;
  transition:     background var(--brand-transition), color var(--brand-transition);
  white-space:    nowrap;
  -webkit-font-smoothing: antialiased;
}
.btn-hrt-danger-outline:hover {
  background: color-mix(in srgb, var(--brand-danger) 10%, transparent);
  color:      var(--brand-danger);
}
.btn-hrt-danger-outline:active { transform: scale(0.97); }
.btn-hrt-danger-outline:disabled { opacity: 0.45; cursor: not-allowed; transform: none; }

/* ============================================================
   11. COMPOSANTS — PAGE TITLE ET TOOLBAR
   ============================================================ */
.page-title-hrt {
  font-size:      20px;
  font-weight:    600;
  line-height:    1.3;
  letter-spacing: -0.01em;
  color:          var(--brand-text-default);
  margin:         0 0 2px 0;
}
.page-subtitle-hrt {
  font-size:  13px;
  color:      var(--brand-text-muted);
  margin:     0;
}
.listing-toolbar {
  display:        flex;
  align-items:    center;
  justify-content: space-between;
  gap:            12px;
  flex-wrap:      wrap;
  margin-bottom:  16px;
}
.listing-toolbar-title { flex: 1 1 auto; min-width: 0; }
.listing-toolbar-actions {
  display:     flex;
  align-items: center;
  gap:         8px;
  flex-shrink: 0;
}

/* ── Onglets HRT — Toggle / Segment control ─────────────────────
   Remplace nav-tabs "soulignement" par un contrôle segmenté :
   conteneur pill neutre, onglet actif rempli en primary.
   ──────────────────────────────────────────────────────────────── */
.onglet-hrt {
  display:       flex;
  flex-wrap:     wrap;
  gap:           2px;
  padding:       3px;
  background:    var(--brand-bg-app);
  border:        1px solid var(--brand-border);
  border-radius: 8px;
}
.onglet-hrt .nav-link {
  margin-bottom: 0;
  padding:       6px 14px;
  font-size:     13px;
  font-weight:   500;
  color:         var(--brand-text-muted);
  background:    transparent;
  border:        1px solid transparent;
  border-radius: 6px;
  text-decoration: none;
  white-space:   nowrap;
  line-height:   1.4;
  transition:    background var(--brand-transition), color var(--brand-transition), box-shadow var(--brand-transition);
}
.onglet-hrt .nav-link:hover,
.onglet-hrt .nav-link:focus {
  color:        var(--brand-primary);
  background:   var(--brand-primary-soft);
  border-color: transparent;
  outline:      none;
}
.onglet-hrt .nav-link.active {
  color:        var(--brand-on-primary) !important;
  background:   var(--brand-primary) !important;
  border-color: var(--brand-primary-dark) !important;
  box-shadow:   0 1px 4px rgba(0,0,0,0.14);
  font-weight:  600;
}
.onglet-hrt .nav-link.active:hover {
  color:        var(--brand-on-primary) !important;
  background:   var(--brand-primary-dark) !important;
  border-color: var(--brand-primary-dark) !important;
}

/* --- Compteur d'onglet : le fond de l'onglet passe du gris clair au primaire fonce
   quand il devient actif, le badge inverse donc ses couleurs pour rester lisible. --- */
.onglet-hrt .nav-link .onglet-badge-hrt {
  background: var(--brand-info);
  color:      var(--brand-on-primary);
  padding:    2px 8px;
  font-size:  11px;
  font-weight: 700;
}
.onglet-hrt .nav-link.active .onglet-badge-hrt {
  background: var(--brand-bg-surface);
  color:      var(--brand-primary);
}

/* ============================================================
   12. COMPOSANTS — CHIP SOCIÉTÉ (topbar)
   ============================================================ */
.chip-societe {
  display:        inline-flex;
  align-items:    center;
  gap:            6px;
  padding:        4px 10px;
  background:     var(--brand-primary-soft);
  color:          var(--brand-primary);
  border:         1px solid var(--brand-border);
  border-radius:  999px;
  font-size:      12px;
  font-weight:    600;
  white-space:    nowrap;
}
.chip-societe i { font-size: 13px; }

/* ============================================================
   13. COMPOSANTS — PAGE PLACEHOLDER (module à venir)
   ============================================================ */
.placeholder-module {
  display:        flex;
  flex-direction: column;
  align-items:    center;
  justify-content: center;
  min-height:     60vh;
  text-align:     center;
  color:          var(--brand-text-muted);
  padding:        40px 20px;
}
.placeholder-module-icon {
  width:           64px;
  height:          64px;
  border-radius:   50%;
  background:      var(--brand-primary-soft);
  color:           var(--brand-primary);
  display:         inline-flex;
  align-items:     center;
  justify-content: center;
  font-size:       28px;
  margin-bottom:   20px;
}
.placeholder-module h2 {
  color:       var(--brand-text-default);
  font-size:   18px;
  font-weight: 600;
  margin-bottom: 8px;
}
.placeholder-module p {
  font-size:    14px;
  color:        var(--brand-text-muted);
  max-width:    360px;
  line-height:  1.6;
  margin-bottom: 24px;
}

/* ============================================================
   14. COMPOSANTS — LOGIN FORM
   ============================================================ */
.login-page {
  min-height:      100vh;
  display:         flex;
  align-items:     center;
  justify-content: center;
  background:      var(--brand-bg-app);
  font-family:     var(--brand-font-sans);
}
.login-box {
  width:         100%;
  max-width:     420px;
  padding:       40px;
  background:    var(--brand-bg-surface);
  border:        1px solid var(--brand-border);
  border-radius: 10px;
  box-shadow:    var(--brand-shadow-md);
}
.login-logo {
  display:       block;
  text-align:    center;
  margin-bottom: 28px;
}
.login-logo img,
.login-logo svg {
  max-height: 48px;
  width:      auto;
}
.login-title {
  font-size:      18px;
  font-weight:    600;
  color:          var(--brand-text-default);
  text-align:     center;
  margin-bottom:  4px;
}
.login-subtitle {
  font-size:  13px;
  color:      var(--brand-text-muted);
  text-align: center;
  margin-bottom: 28px;
}
.login-field {
  margin-bottom: 16px;
}
.login-field label {
  display:        flex;
  align-items:    center;
  gap:            6px;
  font-size:      12px;
  font-weight:    500;
  color:          var(--brand-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom:  6px;
}
.login-field label i { font-size: 13px; }
.login-field input,
.login-field select {
  width:         100%;
  height:        44px;
  padding:       0 14px;
  font-family:   var(--brand-font-sans);
  font-size:     14px;
  color:         var(--brand-text-default);
  background:    var(--brand-bg-surface);
  border:        1px solid var(--brand-border);
  border-radius: var(--brand-radius);
  outline:       none;
  transition:    border-color var(--brand-transition), box-shadow var(--brand-transition);
  appearance:    none;
  -webkit-appearance: none;
}
.login-field input:focus,
.login-field select:focus {
  border-color: var(--brand-primary);
  box-shadow:   0 0 0 4px color-mix(in srgb, var(--brand-primary) 12%, transparent);
}
.login-error {
  display:       none;
  padding:       10px 14px;
  background:    var(--brand-danger-soft);
  border:        1px solid var(--brand-danger);
  border-radius: var(--brand-radius);
  color:         var(--brand-danger);
  font-size:     13px;
  margin-bottom: 16px;
}
.login-error.visible { display: block; }
.login-btn {
  width:          100%;
  height:         44px;
  background:     var(--brand-primary);
  color:          var(--brand-on-primary);
  border:         1px solid var(--brand-primary-dark);
  border-radius:  var(--brand-radius);
  font-family:    var(--brand-font-sans);
  font-size:      14px;
  font-weight:    600;
  cursor:         pointer;
  letter-spacing: 0.01em;
  transition:     background var(--brand-transition), transform var(--brand-transition);
  margin-top:     8px;
}
.login-btn:hover {
  background: var(--brand-primary-dark);
  transform:  translateY(-1px);
}
.login-btn:active { transform: scale(0.98); }
.login-dev-notice {
  margin-top:   20px;
  padding-top:  16px;
  border-top:   1px solid var(--brand-border);
  font-size:    11px;
  color:        var(--brand-text-muted);
}

/* ============================================================
   15. MODALES — Cards imbriquées sobres
   ============================================================ */
.modal-body .form-section-hrt,
.modal-body .card {
  border:        1px solid var(--brand-border) !important;
  border-radius: var(--brand-radius) !important;
  box-shadow:    none !important;
  background:    #fbfcfe !important;
  margin-bottom: 12px !important;
}
.modal-body .form-section-header-hrt,
.modal-body .card-header {
  background:    transparent !important;
  border-bottom: 1px solid var(--brand-border) !important;
  padding:       10px 14px !important;
  min-height:    36px !important;
  font-size:     11px !important;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color:         var(--brand-text-muted) !important;
}

/* Modal structure brand overrides — header, title, body, footer, close */
#modal .modal-content {
  border:        1px solid var(--brand-border);
  border-radius: 10px;
  overflow:      visible;
}
#modal .modal-header {
  background:    linear-gradient(180deg, #fafbfd 0%, #f6f8fb 100%);
  border-bottom: 1px solid var(--brand-border);
  padding:       7px 14px;
  min-height:    38px;
  display:       flex;
  align-items:   center;
}
#modal .modal-title {
  font-family:    var(--brand-font-sans);
  font-size:      14px;
  font-weight:    600;
  letter-spacing: -0.01em;
  color:          var(--brand-text-default);
  margin:         0;
}
#modal .modal-body {
  padding:     18px;
  font-size:   13px;
  line-height: 1.55;
  color:       var(--brand-text-default);
}
#modal .modal-footer {
  border-top:      1px solid var(--brand-border);
  padding:         8px 14px;
  background:      var(--brand-bg-surface);
  display:         flex;
  align-items:     center;
  justify-content: flex-end;
  gap:             8px;
}
#modal .modal-footer .btn-hrt-secondary {
  height:  auto;
  padding: 7px 14px;
}
/* Modifieur : force les 2 boutons du footer aux extrémités (à poser sur .modal-footer) */
#modal .modal-footer.hrt-footer-split {
  justify-content: space-between;
}
.modal-close-hrt {
  display:         inline-flex;
  align-items:     center;
  justify-content: center;
  width:           28px;
  height:          28px;
  border-radius:   var(--brand-radius);
  background:      transparent;
  border:          none;
  color:           var(--brand-text-muted);
  font-size:       18px;
  cursor:          pointer;
  margin-left:     auto;
  flex-shrink:     0;
  transition:      background var(--brand-transition), color var(--brand-transition);
}
.modal-close-hrt:hover {
  background: var(--brand-danger-soft);
  color:      var(--brand-danger);
}

/* Ecran complet (fiche client, formulaire de creation) charge en iframe dans la grande modale */
.hrt-modal-iframe {
  display: block;
  width: 100%;
  height: 75vh;
  border: 0;
}

/* ============================================================
   16. ROW ACTION ICONS
   ============================================================ */
.row-action-icon {
  display:         inline-flex;
  align-items:     center;
  justify-content: center;
  width:           30px;
  height:          30px;
  border-radius:   var(--brand-radius);
  border:          none;
  background:      transparent;
  color:           var(--brand-text-muted);
  font-size:       15px;
  cursor:          pointer;
  transition:      background var(--brand-transition), color var(--brand-transition);
}
.row-action-icon:hover {
  background: var(--brand-primary-soft);
  color:      var(--brand-primary);
}
.row-action-icon.danger:hover {
  background: var(--brand-danger-soft);
  color:      var(--brand-danger);
}
.row-action-icon.info:hover {
  background: var(--brand-info-soft);
  color:      var(--brand-info);
}

/* --- Colonne Actions contenant un bouton libelle (addColAction is_icon = 0) :
   largeur plancher pour que le bouton respire. Le nowrap de la cellule
   l'elargit tout seul au-dela si le libelle est plus long. --- */
.table-hrt th.col-actions-libelle,
.table-hrt td.col-actions-libelle {
  min-width: 150px;
}

/* --- Tableau qui ne doit pas se comprimer sous une largeur exploitable. .table-hrt est en
   width: 100% : sans plancher, ses colonnes se repartissent la largeur disponible aussi petite
   soit-elle, et le conteneur .table-hrt-scroll n'a jamais rien a faire defiler. Avec ce plancher,
   le tableau depasse et defile au lieu de s'ecraser. A poser avec .table-hrt-scroll sur le parent.
   Deux motifs a ce jour :
   - listing des alertes de l'accueil, ou la cellule Etat est en .hrt-cellule-sans-ellipse
     (overflow visible, pose justement pour ne pas tronquer son badge) et debordait sur la colonne
     Actions des que sa colonne devenait trop etroite ;
   - tableaux de composition d'un article pack / matrice, dont les champs de saisie devenaient
     inutilisables sous 400px. --- */
.table-hrt--largeur-mini {
  min-width: 520px;
}

/* --- Listing de detail des articles (devis, contrat, intervention, pack) : dix colonnes en
   pourcentage, dimensionnees pour un ecran de bureau. Le conteneur n'avait pas de defilement
   horizontal et la table etait en width: 100%, donc sur telephone les dix colonnes se partageaient
   ~388px, soit une trentaine de pixels chacune - illisible. Le plancher les remet a leur mesure et
   .table-hrt-scroll pose sur le conteneur fait defiler.
   table-layout et width viennent d'un style="" retire du markup : ils appartiennent au composant. --- */
.table-hrt-articles {
  table-layout: fixed;
  width:        100%;
  min-width:    860px;
}

/* --- Colonne Actions épinglée à droite sur tous les listings, quelle que soit la taille :
   elle reste atteignable même quand le tableau déborde et scrolle horizontalement. --- */
.table-hrt th.col-actions,
.table-hrt td.col-actions {
  position: sticky;
  right:    0;
  z-index:  2;
  background: var(--brand-bg-surface);
  transition: background var(--brand-transition);
}
.table-hrt thead th.col-actions {
  background: #fafbfd;
  z-index:    3;
}
.table-hrt tbody tr:hover td.col-actions {
  background: var(--brand-primary-soft);
}

/* --- Ligne de listing en alerte (element arrete, expire, en erreur) : la colonne Actions
   etant sticky, elle porte son propre fond opaque et doit reprendre celui de la ligne,
   sinon elle reste blanche au milieu d'une ligne coloree. --- */
.table-hrt tbody tr.hrt-row-danger,
.table-hrt tbody tr.hrt-row-danger td.col-actions {
  background: var(--brand-danger-soft);
}
.table-hrt tbody tr.hrt-row-danger:hover,
.table-hrt tbody tr.hrt-row-danger:hover td.col-actions {
  background: color-mix(in srgb, var(--brand-danger-soft) 88%, var(--brand-danger) 12%);
}

/* --- Toast flash : rendu par base.php quand l'URL porte un parametre success= ou error= --- */
.hrt-flash-toast {
  position:      fixed;
  bottom:        24px;
  right:         24px;
  z-index:       9999;
  display:       flex;
  align-items:   center;
  gap:           10px;
  max-width:     360px;
  padding:       12px 16px;
  background:    var(--brand-bg-card, #fff);
  border:        1px solid var(--brand-border, #e3e6ea);
  border-radius: var(--brand-radius, 6px);
  box-shadow:    var(--brand-shadow-md);
  font-size:     13px;
  font-weight:   500;
  color:         var(--brand-text-default);
  opacity:       0;
  transform:     translateY(8px);
  transition:    opacity .4s ease, transform .4s ease;
}
.hrt-flash-toast.is-visible {
  opacity:   1;
  transform: translateY(0);
}
.hrt-flash-toast-icon {
  flex-shrink: 0;
  font-size:   16px;
}
.hrt-flash-toast-success { border-left: 4px solid var(--brand-success, #22c55e); }
.hrt-flash-toast-success .hrt-flash-toast-icon { color: var(--brand-success, #22c55e); }

.hrt-flash-toast-danger { border-left: 4px solid var(--brand-danger, #ef4444); }
.hrt-flash-toast-danger .hrt-flash-toast-icon { color: var(--brand-danger, #ef4444); }

/* ============================================================
   17. RESPONSIVE — MOBILE OVERRIDES
   ============================================================ */
@media (max-width: 991px) {
  /* --- La toolbar reste une rangee. Elle passait en flex-direction: column, ce qui posait le bouton
     d'action sous le titre et cale a gauche. Le titre cede la largeur (flex: 1 1 auto + min-width: 0)
     et le bouton garde la sienne (flex-shrink: 0), ils tiennent donc sur la meme ligne.
     align-items: flex-start pour que le bouton s'aligne sur la premiere ligne du titre et non sur le
     milieu du bloc titre + sous-titre.
     margin-left: auto couvre le cas ou un titre long fait quand meme passer le bouton a la ligne :
     seul sur la sienne, le justify-content: space-between du parent le recalerait a gauche. --- */
  .listing-toolbar { align-items: flex-start; }
  .listing-toolbar-actions { margin-left: auto; }
  .col-hide-mobile { display: none !important; }
  .placeholder-module { min-height: 40vh; }
}

/* ============================================================
   18. PRESENTATION LAYER — Composants premium ERP
   Ajoutés 2026-04-27 dans le cadre de la passe "améliorer la
   présentation". Aesthetic : instrument technique premium.
   Ces composants peuvent vivre à côté des composants ERP de
   base (cards, tables, forms) sans les remplacer.
   ============================================================ */

/* --- Eyebrow label : micro-titre uppercase au-dessus d'une zone --- */
.section-eyebrow {
  display:        inline-flex;
  align-items:    center;
  gap:            8px;
  font-family:    var(--brand-font-sans);
  font-size:      10px;
  font-weight:    600;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color:          var(--brand-text-muted);
  margin-bottom:  10px;
}
.section-eyebrow::before {
  content: '';
  display: inline-block;
  width:   24px;
  height:  2px;
  background: var(--brand-primary);
  border-radius: 1px;
}

/* --- Hero welcome : zone d'accueil avec gradient mesh + grain + watermark --- */
.hero-welcome {
  position:      relative;
  overflow:      hidden;
  border:        1px solid var(--brand-border);
  border-radius: 12px;
  padding:       28px 32px 30px;
  margin-bottom: 24px;
  background:
    radial-gradient(circle at 0% 0%, color-mix(in srgb, var(--brand-primary) 8%, transparent) 0%, transparent 55%),
    radial-gradient(circle at 100% 0%, color-mix(in srgb, var(--brand-secondary) 6%, transparent) 0%, transparent 50%),
    linear-gradient(180deg, #FFFFFF 0%, var(--brand-bg-app) 100%);
  box-shadow:    var(--brand-shadow-sm);
}
.hero-welcome::after {
  /* Grain texture SVG inline — ne dépend d'aucun asset */
  content: '';
  position: absolute; inset: 0;
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.04 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  pointer-events: none;
  opacity: 0.55;
  mix-blend-mode: multiply;
}
.hero-welcome > * { position: relative; z-index: 1; }
.hero-welcome .hero-eyebrow {
  display:        inline-flex;
  align-items:    center;
  gap:            10px;
  font-family:    var(--brand-font-sans);
  font-size:      11px;
  font-weight:    600;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color:          var(--brand-primary);
  margin-bottom:  12px;
}
.hero-welcome .hero-title {
  font-family:    var(--brand-font-display);
  font-size:      32px;
  font-weight:    700;
  line-height:    1.1;
  letter-spacing: -0.025em;
  color:          var(--brand-text-default);
  margin:         0 0 6px 0;
}
.hero-welcome .hero-title em {
  font-style: normal;
  color:      var(--brand-primary);
}
.hero-welcome .hero-subtitle {
  font-family: var(--brand-font-sans);
  font-size:   14px;
  color:       var(--brand-text-muted);
  max-width:   620px;
  margin:      0;
  line-height: 1.55;
}
.hero-welcome .hero-meta {
  display:     flex;
  align-items: center;
  gap:         18px;
  margin-top:  18px;
  flex-wrap:   wrap;
}
.hero-welcome .hero-meta-item {
  display:     inline-flex;
  align-items: center;
  gap:         6px;
  font-family: var(--brand-font-mono);
  font-size:   11px;
  font-weight: 500;
  color:       var(--brand-text-muted);
  letter-spacing: 0.04em;
}
.hero-welcome .hero-meta-item i { font-size: 13px; color: var(--brand-primary); }

/* Watermark décoratif — initiale brand en bas à droite, très estompée */
.hero-welcome .hero-watermark {
  position:    absolute;
  right:       -20px;
  bottom:      -40px;
  font-family: var(--brand-font-display);
  font-size:   180px;
  font-weight: 800;
  line-height: 1;
  color:       var(--brand-primary);
  opacity:     0.05;
  pointer-events: none;
  letter-spacing: -0.04em;
  user-select: none;
  z-index:     0;
}

/* --- Live dot : indicateur pulsant pour signal d'activité temps réel --- */
.live-dot {
  display:       inline-block;
  width:         8px;
  height:        8px;
  border-radius: 50%;
  background:    var(--brand-success);
  position:      relative;
}
.live-dot::after {
  content:    '';
  position:   absolute;
  inset:      -4px;
  border-radius: 50%;
  background: var(--brand-success);
  opacity:    0.4;
  animation:  livePulse 2.4s ease-in-out infinite;
}
@keyframes livePulse {
  0%   { transform: scale(0.6); opacity: 0.5; }
  60%  { transform: scale(2.4); opacity: 0; }
  100% { transform: scale(2.4); opacity: 0; }
}

/* --- KPI Card : carte chiffre clé avec display font + accent rule --- */
.kpi-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 16px;
  margin-bottom: 24px;
  align-items: stretch;
}
.kpi-card {
  position:      relative;
  background:    var(--brand-bg-surface);
  border:        1px solid var(--brand-border);
  border-radius: 10px;
  padding:       18px 20px 20px;
  box-shadow:    var(--brand-shadow-sm);
  overflow:      hidden;
  transition:    border-color var(--brand-transition), box-shadow var(--brand-transition), transform var(--brand-transition);
}
.kpi-card:hover {
  border-color: color-mix(in srgb, var(--brand-primary) 30%, var(--brand-border));
  box-shadow:   var(--brand-shadow-md);
  transform:    translateY(-1px);
}
.kpi-card::before {
  /* Accent rule verticale gauche */
  content: '';
  position: absolute;
  left: 0; top: 14px; bottom: 14px;
  width: 3px;
  background: var(--brand-primary);
  border-radius: 0 2px 2px 0;
  opacity: 0.85;
}
.kpi-card.kpi-secondary::before { background: var(--brand-secondary); }
.kpi-card.kpi-accent::before    { background: var(--brand-accent, var(--brand-primary)); }
.kpi-card.kpi-warning::before   { background: var(--brand-warning); }
.kpi-card.kpi-muted::before     { background: var(--brand-border); }

.kpi-card .kpi-label {
  font-family:    var(--brand-font-sans);
  font-size:      11px;
  font-weight:    600;
  text-transform: uppercase;
  letter-spacing: 0.10em;
  color:          var(--brand-text-muted);
  margin:         0 0 10px 0;
  display:        flex;
  align-items:    center;
  justify-content: space-between;
  gap:            8px;
}
.kpi-card .kpi-label i {
  font-size: 14px;
  color:     var(--brand-text-muted);
  opacity:   0.7;
}
.kpi-card .kpi-value {
  display:        flex;
  align-items:    baseline;
  gap:            8px;
  flex-wrap:      wrap;
  font-family:    var(--brand-font-display);
  font-size:      15px;
  line-height:    1.05;
  letter-spacing: -0.025em;
  color:          var(--brand-text-default);
  font-variant-numeric: tabular-nums;
  margin:         0;
}
.kpi-card .kpi-value .kpi-number,
.kpi-card .kpi-value-number {
  font-family: var(--brand-font-sans);
  font-weight: bold;
  font-size: 1.2rem;
}
.kpi-card .kpi-value .kpi-libelle,
.kpi-card .kpi-value-label {
  font-weight: 500;
}
.kpi-value:hover .kpi-number,
.kpi-value:hover .kpi-libelle {
  color: var(--brand-secondary);
}
.kpi-card .kpi-value.kpi-empty {
  color:       var(--brand-text-muted);
  font-weight: 500;
  opacity:     0.6;
}
.kpi-card .kpi-value-number {
  display: inline-flex;
  align-items: baseline;
}
.kpi-card .kpi-value-label {
  display: inline-flex;
  align-items: center;
  min-height: 1em;
  font-family: var(--brand-font-sans);
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--brand-text-muted);
  opacity: 0.88;
}
/* --- Carte KPI multi-lignes : chiffre et libellé en colonnes --- */
.kpi-card.hrt-kpi-lignes {
  display: flex;
  flex-direction: column;
}
/* Les lignes sont isolées dans leur propre conteneur pour être centrées sans emporter le titre :
   un align-content sur la carte entière décalerait aussi le label vers le bas, et les titres des
   cartes courtes ne seraient plus au même niveau que ceux des cartes hautes. */
.hrt-kpi-lignes-corps {
  flex: 1;
  display: grid;
  grid-template-columns: auto 1fr;
  align-content: center;
}
/* La colonne du chiffre est dimensionnée par le conteneur, pas par la ligne : en subgrid toutes
   les lignes partagent la même, donc les libellés se calent au même x quelle que soit la largeur
   du chiffre. La ligne reste un bloc pleine largeur, ce qui préserve la zone de clic et le :hover. */
.kpi-card.hrt-kpi-lignes .kpi-value {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: subgrid;
}

.kpi-card .kpi-row-action {
  width: 100%;
  justify-content: center;
  margin-top: 12px;
}
.kpi-card .kpi-trend {
  display:       inline-flex;
  align-items:   center;
  gap:           4px;
  margin-top:    10px;
  font-family:   var(--brand-font-mono);
  font-size:     11px;
  font-weight:   500;
  letter-spacing: 0.02em;
}
.kpi-card .kpi-trend.up   { color: var(--brand-success); }
.kpi-card .kpi-trend.down { color: var(--brand-danger); }
.kpi-card .kpi-trend.flat { color: var(--brand-text-muted); }
.kpi-card .kpi-trend i { font-size: 13px; }
.kpi-card .kpi-foot {
  margin-top: 10px;
  font-family: var(--brand-font-sans);
  font-size: 11px;
  color: var(--brand-text-muted);
  letter-spacing: 0.02em;
}

@media (max-width: 767.98px) {
  .kpi-card .kpi-value {
    font-size: 24px;
  }
}

/* --- Activity timeline : liste d'événements récents avec rule verticale --- */
.activity-timeline {
  position: relative;
  padding-left: 0;
  margin: 0;
  list-style: none;
}
.activity-item {
  position: relative;
  padding: 14px 0 14px 28px;
  border-bottom: 1px dashed var(--brand-border);
}
.activity-item:last-child { border-bottom: none; }
.activity-item::before {
  /* point timeline */
  content: '';
  position: absolute;
  left: 5px; top: 20px;
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--brand-bg-surface);
  border: 2px solid var(--brand-primary);
  z-index: 1;
}
.activity-item::after {
  /* rule verticale */
  content: '';
  position: absolute;
  left: 8px; top: 28px; bottom: -2px;
  width: 1px;
  background: var(--brand-border);
}
.activity-item:last-child::after { display: none; }
.activity-item .activity-time {
  font-family: var(--brand-font-mono);
  font-size: 11px;
  color: var(--brand-text-muted);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.activity-item .activity-title {
  font-family: var(--brand-font-sans);
  font-size: 13px;
  font-weight: 500;
  color: var(--brand-text-default);
  margin: 2px 0 0 0;
  line-height: 1.4;
}
.activity-item .activity-meta {
  font-family: var(--brand-font-sans);
  font-size: 12px;
  color: var(--brand-text-muted);
  margin-top: 2px;
}
.activity-item.activity-empty {
  padding-left: 0;
  text-align: center;
  font-size: 13px;
  color: var(--brand-text-muted);
  border-bottom: none;
}
.activity-item.activity-empty::before,
.activity-item.activity-empty::after { display: none; }

/* --- Action tiles : raccourcis modulaires vers les modules --- */
.action-tile-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 12px;
}
.action-tile {
  display:       flex;
  align-items:   center;
  gap:           14px;
  padding:       16px 18px;
  background:    var(--brand-bg-surface);
  border:        1px solid var(--brand-border);
  border-radius: 10px;
  text-decoration: none;
  color:         var(--brand-text-default);
  transition:    border-color var(--brand-transition), background var(--brand-transition), transform var(--brand-transition);
  position: relative;
  overflow: hidden;
}
.action-tile:hover {
  border-color: var(--brand-primary);
  background:   color-mix(in srgb, var(--brand-primary) 4%, var(--brand-bg-surface));
  transform:    translateY(-1px);
  color:        var(--brand-text-default);
}
.action-tile-icon {
  flex-shrink: 0;
  width:  44px; height: 44px;
  border-radius: 8px;
  background: var(--brand-primary-soft);
  color:      var(--brand-primary);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 20px;
  transition: background var(--brand-transition);
}
.action-tile:hover .action-tile-icon {
  background: var(--brand-primary);
  color:      var(--brand-on-primary);
}
.action-tile-body { flex: 1 1 auto; min-width: 0; }
.action-tile-title {
  font-family: var(--brand-font-sans);
  font-size:   14px;
  font-weight: 600;
  color:       var(--brand-text-default);
  margin: 0 0 2px 0;
}
.action-tile-desc {
  font-family: var(--brand-font-sans);
  font-size:   12px;
  color:       var(--brand-text-muted);
  margin: 0;
  line-height: 1.4;
}
.action-tile-arrow {
  flex-shrink: 0;
  font-size: 18px;
  color: var(--brand-text-muted);
  transition: transform var(--brand-transition), color var(--brand-transition);
}
.action-tile:hover .action-tile-arrow {
  color: var(--brand-primary);
  transform: translateX(2px);
}
.action-tile.is-disabled {
  opacity: 0.6;
  pointer-events: none;
}
.action-tile.is-disabled .action-tile-icon {
  background: var(--brand-bg-app);
  color: var(--brand-text-muted);
}

/* --- Page hero — version compacte pour pages internes --- */
.page-hero-hrt {
  position: relative;
  border-radius: 10px;
  padding: 18px 22px;
}
.page-hero-hrt .page-hero-title {
  font-family:    var(--brand-font-display);
  font-size:      24px;
  font-weight:    700;
  letter-spacing: -0.02em;
  line-height:    1.15;
  color:          var(--brand-text-default);
  margin: 0 0 4px 0;
}
.page-hero-hrt .page-hero-subtitle {
  font-family: var(--brand-font-sans);
  font-size: 13px;
  color: var(--brand-text-muted);
  margin: 0;
}

/* --- Roadmap empty state : remplace le placeholder-module mou --- */
.empty-state-pro {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0;
  padding: 0;
  background: var(--brand-bg-surface);
  border-radius: 10px;
  overflow: hidden;
}
@media (min-width: 768px) {
  .empty-state-pro { grid-template-columns: minmax(280px, 360px) 1fr; }
}
.empty-state-visual {
  position: relative;
  background:
    radial-gradient(circle at 30% 30%, color-mix(in srgb, var(--brand-primary) 12%, transparent) 0%, transparent 60%),
    linear-gradient(135deg, var(--brand-bg-app) 0%, color-mix(in srgb, var(--brand-primary) 6%, var(--brand-bg-app)) 100%);
  min-height: 220px;
  padding: 32px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  border-right: 1px solid var(--brand-border);
}
.empty-state-visual::after {
  content: '';
  position: absolute; inset: 0;
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.05 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  pointer-events: none;
  opacity: 0.6;
}
.empty-state-visual > * { position: relative; z-index: 1; }
.empty-state-icon {
  width: 64px; height: 64px;
  border-radius: 14px;
  background: var(--brand-bg-surface);
  border: 1px solid var(--brand-border);
  color: var(--brand-primary);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 28px;
  box-shadow: var(--brand-shadow-sm);
}
.empty-state-status {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--brand-font-mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--brand-text-muted);
}
.empty-state-body {
  padding: 32px;
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.empty-state-eyebrow {
  font-family:    var(--brand-font-sans);
  font-size:      10px;
  font-weight:    600;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color:          var(--brand-primary);
  margin-bottom:  10px;
}
.empty-state-title {
  font-family:    var(--brand-font-display);
  font-size:      24px;
  font-weight:    700;
  letter-spacing: -0.02em;
  line-height:    1.15;
  color:          var(--brand-text-default);
  margin: 0 0 10px 0;
}
.empty-state-desc {
  font-family: var(--brand-font-sans);
  font-size: 13px;
  color: var(--brand-text-muted);
  line-height: 1.55;
  margin: 0 0 18px 0;
  max-width: 520px;
}
.empty-state-roadmap {
  list-style: none;
  padding: 0;
  margin: 0 0 22px 0;
  display: grid;
  gap: 8px;
}
.empty-state-roadmap li {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--brand-font-sans);
  font-size: 12px;
  color: var(--brand-text-muted);
}
.empty-state-roadmap li i {
  font-size: 14px;
  color: var(--brand-primary);
  flex-shrink: 0;
}
.empty-state-roadmap li.done i { color: var(--brand-success); }
.empty-state-roadmap li.done { color: var(--brand-text-default); }

/* --- Login premium two-pane --- */
.login-shell {
  min-height: 100vh;
  display: grid;
  grid-template-columns: 1fr;
  font-family: var(--brand-font-sans);
}
@media (min-width: 992px) {
  .login-shell { grid-template-columns: minmax(380px, 480px) 1fr; }
}
.login-brand-pane {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: 40px;
  color: #FFFFFF;
  background:
    radial-gradient(circle at 80% 0%, color-mix(in srgb, var(--brand-secondary) 35%, transparent) 0%, transparent 55%),
    radial-gradient(circle at 0% 100%, color-mix(in srgb, var(--brand-accent, var(--brand-secondary)) 35%, transparent) 0%, transparent 55%),
    linear-gradient(160deg, var(--brand-primary) 0%, var(--brand-primary-dark) 100%);
  overflow: hidden;
  min-height: 220px;
}
.login-brand-pane::after {
  content: '';
  position: absolute; inset: 0;
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.7' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.06 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  pointer-events: none;
  mix-blend-mode: overlay;
  opacity: 0.6;
}
.login-brand-pane > * { position: relative; z-index: 1; }
.login-brand-logo {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  font-family: var(--brand-font-display);
  font-size: 18px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: #FFFFFF;
  text-decoration: none;
}
.login-brand-logo span {
  width: 36px; height: 36px;
  border-radius: 9px;
  background: rgba(255,255,255,0.12);
  border: 1px solid rgba(255,255,255,0.18);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 16px;
}
.login-brand-tagline {
  max-width: 360px;
}
.login-brand-tagline .login-brand-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--brand-font-sans);
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: rgba(255,255,255,0.7);
  margin-bottom: 16px;
}
.login-brand-tagline .login-brand-title {
  font-family: var(--brand-font-display);
  font-size: 36px;
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -0.025em;
  color: #FFFFFF;
  margin: 0 0 16px 0;
}
.login-brand-tagline .login-brand-desc {
  font-family: var(--brand-font-sans);
  font-size: 14px;
  color: rgba(255,255,255,0.78);
  line-height: 1.55;
  margin: 0;
}
.login-brand-foot {
  display: flex;
  align-items: center;
  gap: 14px;
  font-family: var(--brand-font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  color: rgba(255,255,255,0.65);
  text-transform: uppercase;
}
/* Séparateur entre les deux mentions du pied : un point aussi opaque que le texte se lirait
   comme une puce de liste. */
.login-brand-foot-separateur {
  opacity: 0.4;
}
.login-brand-foot .live-dot {
  background: #FFFFFF;
}
.login-brand-foot .live-dot::after {
  background: #FFFFFF;
}
.login-form-pane {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 40px 24px;
  background: var(--brand-bg-app);
  position: relative;
}
.login-form-pane::before {
  /* texture grain subtile sur le fond clair */
  content: '';
  position: absolute; inset: 0;
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.025 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  pointer-events: none;
  opacity: 0.7;
}
.login-form-pane .login-box {
  position: relative;
  z-index: 1;
  background: var(--brand-bg-surface);
  border-radius: 14px;
  box-shadow: var(--brand-shadow-md);
  padding: 36px 32px;
  width: 100%;
  max-width: 420px;
}
.login-form-pane .login-eyebrow {
  font-family: var(--brand-font-sans);
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--brand-primary);
  margin-bottom: 8px;
  text-align: left;
  display: block;
}
.login-form-pane .login-title {
  font-family: var(--brand-font-display);
  font-size: 26px;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--brand-text-default);
  text-align: left;
  margin: 0 0 6px 0;
}
.login-form-pane .login-subtitle {
  text-align: left;
  font-size: 13px;
  color: var(--brand-text-muted);
  margin-bottom: 24px;
}

/* --- Login mono-colonne (app mobile technicien) --- */
.login-shell.hrt-login-single {
  grid-template-columns: 1fr;
  min-height: 100dvh;
}
@media (min-width: 992px) {
  .login-shell.hrt-login-single { grid-template-columns: 1fr; }
}
.hrt-login-single .login-form-pane {
  padding: 32px 20px calc(32px + env(safe-area-inset-bottom));
}
.hrt-login-single .login-field input,
.hrt-login-single .login-field select {
  height: 48px;
  font-size: 16px;
}
.hrt-login-single .login-btn {
  height: 50px;
  font-size: 15px;
}
.hrt-login-brand {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 26px;
}
.hrt-login-brand span {
  width: 42px;
  height: 42px;
  border-radius: 12px;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  color: #FFFFFF;
  background: linear-gradient(160deg, var(--brand-primary) 0%, var(--brand-primary-dark) 100%);
}
.hrt-login-brand strong {
  display: block;
  font-family: var(--brand-font-display);
  font-size: 17px;
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.2;
  color: var(--brand-text-default);
}
.hrt-login-brand small {
  display: block;
  font-family: var(--brand-font-sans);
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--brand-text-muted);
}
.hrt-login-pass {
  position: relative;
}
.hrt-login-pass input {
  padding-right: 48px;
}
.hrt-login-pass-toggle {
  position: absolute;
  right: 0;
  bottom: 0;
  width: 48px;
  height: 48px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--brand-text-muted);
  font-size: 15px;
  cursor: pointer;
}
.hrt-login-pass-toggle:hover {
  color: var(--brand-primary);
}
.hrt-login-support-tag {
  font-size: 10px;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  color: var(--brand-warning);
}
.hrt-login-foot {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  margin-top: 24px;
  padding-top: 18px;
  border-top: 1px solid var(--brand-border);
  font-family: var(--brand-font-mono);
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--brand-text-muted);
}
.hrt-login-back {
  margin-top: 16px;
  text-align: center;
  font-size: 12px;
  color: var(--brand-text-muted);
}
.hrt-login-back a {
  color: var(--brand-text-muted);
  text-decoration: underline;
}
.hrt-login-back a:hover {
  color: var(--brand-primary);
}
.login-field input.is-invalid {
  border-color: var(--brand-danger);
}
.login-field input.is-invalid:focus {
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--brand-danger) 12%, transparent);
}
@media (max-width: 575.98px) {
  .hrt-login-single .login-form-pane {
    padding: 20px 14px calc(20px + env(safe-area-inset-bottom));
  }
  .hrt-login-single .login-box {
    padding: 26px 20px;
  }
  .hrt-login-single .login-title {
    font-size: 23px;
  }
}

/* --- Page-level subtle background polish (grain on app bg) --- */
.content-page {
  position: relative;
}

/* --- Listing toolbar h1 : utiliser display font --- */
.page-title-hrt {
  font-family:    var(--brand-font-display);
  font-size:      24px;
  font-weight:    700;
  letter-spacing: -0.02em;
  line-height:    1.2;
}

/* --- Autocomplete suggestions (champs raison sociale, adresse) --- */
.autocomplete-suggestions {
  position:         absolute;
  z-index:          1050;
  top:              100%;
  left:             0;
  right:            0;
  margin-top:       2px;
  background:       var(--brand-bg-surface);
  border:           1px solid var(--brand-border);
  border-radius:    var(--brand-radius-md);
  box-shadow:       var(--brand-shadow-md);
  max-height:       240px;
  overflow-y:       auto;
  overflow-x:       hidden;
}
.autocomplete-item {
  display:          flex;
  flex-direction:   column;
  padding:          8px 12px;
  cursor:           pointer;
  border-bottom:    1px solid var(--brand-border);
  transition:       background 0.1s;
}
.autocomplete-item:last-child {
  border-bottom:    none;
}
.autocomplete-item:hover {
  background:       var(--brand-bg-subtle);
}
.autocomplete-label {
  font-size:        13px;
  font-weight:      500;
  color:            var(--brand-text-default);
  white-space:      nowrap;
  overflow:         hidden;
  text-overflow:    ellipsis;
}
.autocomplete-sub {
  font-size:        11px;
  color:            var(--brand-text-muted);
  margin-top:       1px;
}

/* ============================================================
   19. COMPOSANTS — DATA LIST (pattern label-valeur dense)
   Remplace les <table> inline pour l'affichage fiche / synthèse.
   ============================================================ */
.data-list-hrt {
  margin:  0;
  padding: 0;
}
.data-row-hrt {
  display:               grid;
  grid-template-columns: minmax(110px, 34%) 1fr;
  gap:                   0 16px;
  padding:               7px 0;
  border-bottom:         1px solid var(--brand-border);
  align-items:           baseline;
}
.data-row-hrt:last-child { border-bottom: none; }
.data-list-hrt dt {
  font-size:      11px;
  font-weight:    600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color:          var(--brand-text-muted);
  margin:         0;
  padding-top:    1px;
  white-space:    nowrap;
}
.data-list-hrt dd {
  font-size:   13px;
  font-weight: 500;
  color:       var(--brand-text-default);
  margin:      0;
  word-break:  break-word;
  line-height: 1.45;
}
.data-list-hrt dd a {
  color:           var(--brand-primary);
  text-decoration: none;
}
.data-list-hrt dd a:hover {
  color:           var(--brand-primary-dark);
  text-decoration: underline;
}

/* --- Client fiche — métaligne sous le titre (type, tél, email) --- */
.fiche-meta-line {
  display:     flex;
  align-items: center;
  gap:         18px;
  flex-wrap:   wrap;
  margin-top:  8px;
  font-size:   12px;
  color:       var(--brand-text-muted);
}
.fiche-meta-line a {
  color:           var(--brand-text-muted);
  text-decoration: none;
  transition:      color var(--brand-transition);
}
.fiche-meta-line a:hover { color: var(--brand-primary); }
.fiche-meta-item {
  display:     inline-flex;
  align-items: center;
  gap:         5px;
}
.fiche-meta-item i {
  font-size: 13px;
  color:     var(--brand-primary);
  opacity:   0.8;
}

/* ============================================================
   20. MODULE CLIENT — Haute densité journalière
   Interface utilisée toute la journée → densité max, lisibilité
   préservée, micro-interactions fluides, zéro friction.
   ============================================================ */

/* --- KPI strip horizontal — remplace kpi-grid en liste client ---
   Économise ~70px verticaux vs la grille de 3 cartes.
   Séparateurs | + accent 2px en bas = lecture instantanée. */
.kpi-strip {
  display:       flex;
  background:    var(--brand-bg-surface);
  border:        1px solid var(--brand-border);
  border-radius: var(--brand-radius);
  box-shadow:    var(--brand-shadow-sm);
  overflow:      hidden;
  margin-bottom: 10px;
}
.kpi-strip-item {
  flex:       1 1 0;
  padding:    10px 18px 12px;
  border-right: 1px solid var(--brand-border);
  position:   relative;
  min-width:  0;
  transition: background var(--brand-transition);
}
.kpi-strip-item:last-child { border-right: none; }
.kpi-strip-item.ks-filter:hover { background: var(--brand-bg-app); }
.kpi-strip-item::after {
  content:  '';
  position: absolute;
  bottom: 0; left: 0; right: 0;
  height:   2px;
}
.kpi-strip-item.ks-primary::after { background: var(--brand-primary); }
.kpi-strip-item.ks-success::after { background: var(--brand-success); }
.kpi-strip-item.ks-muted::after   { background: var(--brand-border); }
.kpi-strip-label {
  font-size:      10px;
  font-weight:    600;
  text-transform: uppercase;
  letter-spacing: 0.10em;
  color:          var(--brand-text-muted);
  display:        flex;
  align-items:    center;
  gap:            5px;
  margin:         0 0 5px 0;
  white-space:    nowrap;
  overflow:       hidden;
  text-overflow:  ellipsis;
}
.kpi-strip-label i { font-size: 12px; opacity: 0.7; flex-shrink: 0; }
.kpi-strip-value {
  font-family:          var(--brand-font-sans);
  font-size:            22px;
  font-weight:          700;
  letter-spacing:       -0.02em;
  color:                var(--brand-text-default);
  font-variant-numeric: tabular-nums;
  line-height:          1;
  margin:               0;
}
.kpi-strip-value.ks-empty {
  color:       var(--brand-text-muted);
  font-weight: 400;
  opacity:     0.5;
}
/* Tuile KPI cliquable : ks-filter = filtre cliquable ; ks-filter + ks-success = filtre actif (couleur secondaire société) */
.kpi-strip-item.ks-filter { cursor: pointer; }
.kpi-strip-item.ks-filter:hover::after { height: 3px; }
.kpi-strip-item.ks-filter.ks-success { background: var(--brand-secondary-soft); }
.kpi-strip-item.ks-filter.ks-success::after { height: 3px; background: var(--brand-secondary); }
.kpi-strip-item.ks-filter.ks-success .kpi-strip-label { color: var(--brand-secondary); }
.kpi-strip-item.ks-filter.ks-success .kpi-strip-label i { opacity: 1; }

/* --- Bande KPI sur téléphone ---
   Le padding d'une tuile est fixe : passer de trois à quatre tuiles ne coûte pas un quart de la
   largeur utile mais 40 %, et sous 768px il ne reste que 39px de texte par tuile à quatre. Les
   libellés tombent à trois lettres et un montant se casse sur trois lignes.
   Les strips à trois tuiles tiennent encore sur une ligne, elles ne sont donc pas touchées : la
   règle ci-dessous ne cible que le cas à quatre, par comptage de fratrie. */
@media (max-width: 767.98px) {
  /* Le débordement n'est plus masqué : tant qu'il l'était, un dépassement repartait en silence. */
  .kpi-strip {
    flex-wrap: wrap;
    overflow:  visible;
  }

  /* Quatre tuiles : deux par ligne. Le -1px absorbe l'arrondi de largeur qui ferait passer la
     seconde tuile à la ligne suivante. */
  .kpi-strip-item:first-child:nth-last-child(4),
  .kpi-strip-item:first-child:nth-last-child(4) ~ .kpi-strip-item {
    flex: 1 1 calc(50% - 1px);
  }

  /* Gouttière resserrée : 12px de texte utile récupérés par tuile, ce qui suffit à faire rentrer
     les libellés des strips à trois tuiles. */
  .kpi-strip-item {
    padding: 10px 12px 12px;
  }

  /* Le libellé passe à la ligne au lieu d'être coupé : « Échéance dépassée » réduit à « ÉCHÉAN… »
     ne veut plus rien dire, sur deux lignes il reste lisible. */
  .kpi-strip-label {
    white-space: normal;
    overflow:    visible;
  }

  /* Un montant ne se casse jamais en morceaux, quelle que soit la place restante. */
  .kpi-strip-value {
    white-space: nowrap;
  }
}

/* Cellule montant listing : chiffres tabulaires + gras (réutilisable) */
.hrt-montant-cell {
  font-variant-numeric: tabular-nums;
  font-weight: 700;
}
.kpi-strip-foot {
  font-size:  10px;
  color:      var(--brand-text-muted);
  margin:     3px 0 0 0;
  letter-spacing: 0.02em;
}

/* --- Panel de recherche — animation CSS max-height (plus fluide) ---
   transition max-height évite le flash de layout du display:none,
   donne une impression d'accordéon. */
.search-panel-animated .card-body {
  overflow:   hidden;
  transition: max-height 0.22s cubic-bezier(0.4, 0, 0.2, 1),
              opacity    0.18s ease,
              padding    0.18s ease;
}
.search-panel-animated.panel-open .card-body {
  max-height: 600px;
  opacity:    1;
}
.search-panel-animated.panel-closed .card-body {
  max-height: 0;
  opacity:    0;
  padding-top:    0 !important;
  padding-bottom: 0 !important;
}
.card-header-toggle {
  cursor:      pointer;
  user-select: none;
  transition:  background var(--brand-transition);
}
.card-header-toggle:hover {
  background: linear-gradient(180deg, #f4f6f9 0%, #eff2f6 100%);
}
.panel-chevron-icon {
  transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1);
  font-size:  15px;
  color:      var(--brand-text-muted);
}
.panel-open  .panel-chevron-icon { transform: rotate(0deg); }
.panel-closed .panel-chevron-icon { transform: rotate(-180deg); }

/* Badge filtres actifs dans le header de recherche */
.badge-search-active {
  display:       inline-flex;
  align-items:   center;
  gap:           4px;
  padding:       2px 8px;
  background:    var(--brand-primary-soft);
  color:         var(--brand-primary);
  border-radius: 999px;
  font-size:     10px;
  font-weight:   600;
  letter-spacing: 0.04em;
}

/* --- Onglets fiche — underline moderne (override §11) ---
   Remplace le style "card tabs" par un underline propre,
   plus lisible en navigation rapide entre onglets. */
.onglet-hrt {
  display:    flex;
  gap:        0;
  border-bottom: 1px solid var(--brand-border);
  overflow-x: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
  background: var(--brand-onglet-bg, var(--brand-bg-surface));
  border-radius: 6px 6px 6px 6px;
  margin-bottom: 14px;
}
.onglet-hrt::-webkit-scrollbar { display: none; }
.onglet-hrt .nav-link {
  display:     inline-flex;
  align-items: center;
  gap:         6px;
  padding:     10px 15px;
  font-size:   12px;
  font-weight: 500;
  color:       var(--brand-text-muted);
  border:      none;
  border-bottom: 2px solid transparent;
  border-radius: 0;
  white-space: nowrap;
  margin-bottom: -1px;
  transition:  color var(--brand-transition),
               border-bottom-color var(--brand-transition),
               background var(--brand-transition);
  text-decoration: none;
}
.onglet-hrt .nav-link i { font-size: 13px; opacity: 0.75; }
.onglet-hrt .nav-link:hover {
  color:             var(--brand-primary);
  background:        var(--brand-primary-soft);
  border-bottom-color: transparent;
}
.onglet-hrt .nav-link.active {
  color:             var(--brand-primary);
  border-bottom-color: var(--brand-primary);
  font-weight:       600;
  background:        transparent;
}
.onglet-hrt .nav-link.active i { opacity: 1; }
.onglet-hrt .nav-link:first-child {
  border-top-left-radius:    5px;
  border-bottom-left-radius: 5px;
}
.onglet-hrt .nav-link:last-child {
  border-top-right-radius:    5px;
  border-bottom-right-radius: 5px;
}

/* --- Table rows denses dans la zone listing client ---
   7px au lieu de 10px → +30% de lignes visibles sans scroll. */
#clientListeZone .table-hrt thead th {
  padding: 7px 12px;
}
#clientListeZone .table-hrt tbody td {
  padding: 7px 12px;
}

/* --- Cellules listing : identité 2 lignes + coordonnées empilées --- */
.cell-2line-hrt {
  display: flex;
  flex-direction: column;
  line-height: 1.3;
}
.cell-2line-hrt__main {
  font-weight: 600;
  color: var(--brand-text-default);
}
.cell-2line-hrt__sub {
  font-size: 11px;
  color: var(--brand-text-muted);
}
.cell-coord-hrt {
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.cell-coord-hrt__item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--brand-text-muted);
}
.cell-coord-hrt__item i {
  width: 13px;
  font-size: 12px;
  color: var(--brand-primary);
  opacity: 0.8;
  flex-shrink: 0;
}
.cell-coord-hrt__item a {
  color: inherit;
  text-decoration: none;
}
.cell-coord-hrt__item a:hover {
  color: var(--brand-primary);
  text-decoration: underline;
}

/* --- Page hero fiche plus compact ---
   Revu à la baisse pour maximiser l'espace contenu. */
.page-hero-hrt {
  padding:       12px 18px;
}
.page-hero-hrt .page-hero-title {
  font-size: 20px;
}
.page-hero-hrt .breadcrumb {
  padding-top: 0;
  padding-bottom: 0;
}

.page-hero-hrt--sticky {
  position: sticky;
  top: 90px;
  z-index: 100;
  background:
    radial-gradient(circle at top right,
      color-mix(in srgb, var(--brand-primary) 12%, transparent) 0%,
      transparent 42%),
    linear-gradient(180deg,
      color-mix(in srgb, var(--brand-bg-surface) 94%, white 6%) 0%,
      var(--brand-bg-surface) 100%);
  border: 1px solid color-mix(in srgb, var(--brand-primary) 20%, var(--brand-border));
  border-top-width: 4px;
  box-shadow:
    0 16px 30px rgba(0, 0, 0, 0.10),
    0 4px 12px color-mix(in srgb, var(--brand-primary) 10%, transparent);
  overflow: hidden;
}

.page-hero-hrt--sticky::before {
  content: '';
  position: absolute;
  inset: 0;
  background:
    linear-gradient(90deg,
      color-mix(in srgb, var(--brand-primary) 10%, transparent) 0%,
      transparent 18%,
      transparent 82%,
      color-mix(in srgb, var(--brand-primary) 08%, transparent) 100%);
  pointer-events: none;
}

.page-hero-hrt--sticky::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  background: color-mix(in srgb, var(--brand-primary) 16%, var(--brand-border));
  pointer-events: none;
}

.page-hero-hrt {
  border-color: #000000 !important;
}

/* --- Tableau pack article : séparateurs nets + colonne action centrée --- */
.table-pack-hrt tbody td {
  padding-top: 14px;
  padding-bottom: 14px;
  vertical-align: middle;
  border-bottom: 1px solid color-mix(in srgb, var(--brand-border) 88%, white 12%);
}

.table-pack-hrt #article-pack-empty-row td {
  border-top: none;
  border-bottom: none;
}

.table-pack-hrt th.col-actions,
.table-pack-hrt td.col-actions {
  width: 84px;
  text-align: center !important;
  vertical-align: middle;
}

.table-pack-hrt .table-pack-hrt__action-cell {
  padding-left: 8px;
  padding-right: 8px;
  display: table-cell;
}

.table-pack-hrt .table-pack-hrt__action-inner {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 38px;
}

.table-pack-hrt .table-pack-hrt__action-cell .row-action-icon {
  margin: 0;
}

.table-pack-hrt tbody tr:last-child td {
  border-bottom: none;
}

/* --- Listing toolbar plus serrée --- */
.listing-toolbar {
  margin-bottom: 10px;
}

/* --- Kbd shortcut hint (discret, pour power users) --- */
.kbd-hint {
  display:      inline-flex;
  align-items:  center;
  padding:      1px 5px;
  font-family:  var(--brand-font-mono);
  font-size:    10px;
  font-weight:  500;
  color:        var(--brand-text-muted);
  background:   var(--brand-bg-app);
  border:       1px solid var(--brand-border);
  border-radius: 3px;
  line-height:  1.5;
  user-select:  none;
  opacity:      0.75;
}

/* ============================================================
   22. QUICK SEARCH BAR + FILTRES DRAWER + RADIO GROUPE
   ============================================================ */

/* ── Quick search bar (entre KPI et listing) ── */
.listing-quick-bar {
  display:     flex;
  align-items: center;
  gap:         8px;
  margin-bottom: 8px;
}
.listing-quick-bar-search {
  position: relative;
  flex:     1;
  min-width: 0;
}
.listing-quick-bar-search .listing-search-icon {
  position:       absolute;
  left:           10px;
  top:            50%;
  transform:      translateY(-50%);
  font-size:      14px;
  color:          var(--brand-text-muted);
  pointer-events: none;
}
.listing-quick-bar-search .field-input-hrt {
  padding-left:  34px;
  padding-right: 30px;
}
.listing-quick-clear {
  position:    absolute;
  right:       8px;
  top:         50%;
  transform:   translateY(-50%);
  border:      none;
  background:  none;
  color:       var(--brand-text-muted);
  cursor:      pointer;
  padding:     2px 4px;
  font-size:   15px;
  line-height: 1;
  border-radius: 3px;
}
.listing-quick-clear:hover {
  color:      var(--brand-text-default);
  background: var(--brand-bg-app);
}

/* ── Filtres drawer (Bootstrap 5 offcanvas) ── */
.filtres-drawer {
  width:          clamp(320px, 90vw, 520px) !important;
  display:        flex;
  flex-direction: column;
}
.filtres-drawer .offcanvas-header {
  border-bottom: 1px solid var(--brand-border);
  padding:       14px 20px;
  flex-shrink:   0;
}
.filtres-drawer .offcanvas-title {
  font-family: var(--brand-font-display);
  font-size:   15px;
  font-weight: 600;
  color:       var(--brand-text-default);
}
.filtres-drawer .offcanvas-body {
  padding:    18px 20px;
  flex:       1 1 auto;
  overflow-y: auto;
}
.filtres-drawer-footer {
  padding:     12px 20px;
  border-top:  1px solid var(--brand-border);
  display:     flex;
  gap:         8px;
  background:  var(--brand-bg-surface);
  flex-shrink: 0;
}

/* --- Filtres drawer moins large --- */
.filtres-drawer-small {
  width: clamp(280px, 85vw, 360px) !important;
}
.filtres-drawer-small .filtres-drawer-footer {
  flex-wrap: wrap;
}
.filtres-drawer-small .filtres-drawer-footer > button {
  flex: 1 1 auto;
}

/* ── Radio groupe statut ── */
/* --- Ligne de question a reponse courte : libelle a gauche, controle a droite --- */
/* Les labels de .radio-group-hrt sont en flex: 1. Pose dans un .field-hrt pleine largeur, le groupe
   s'etire donc sur toute la ligne et deux boutons enormes ecrasent la question qu'ils repondent.
   Ici le controle garde sa taille propre et la question recupere la place. */
.hrt-ligne-question {
  display:         flex;
  align-items:     center;
  justify-content: space-between;
  gap:             12px;
  padding:         8px 0;
  border-bottom:   1px solid var(--brand-border);
  font-size:       13px;
}
.hrt-ligne-question:last-child { border-bottom: none; }

.radio-group-hrt {
  display:       flex;
  border:        1px solid var(--brand-border);
  border-radius: 6px;
  overflow:      hidden;
}
.radio-group-hrt input[type="radio"] { display: none; }
.radio-group-hrt label {
  flex:        1;
  text-align:  center;
  padding:     6px 10px;
  font-size:   13px;
  cursor:      pointer;
  border-right: 1px solid var(--brand-border);
  color:       var(--brand-text-default);
  margin:      0;
  transition:  background var(--brand-transition), color var(--brand-transition);
  user-select: none;
  line-height: 1.6;
  /* Remise a zero, pas un choix esthetique : pose dans un en-tete de sous-carte, le groupe heritait
     du uppercase et de l'interlettrage de .form-subcard-title-hrt et ne ressemblait plus a celui des
     drawers de recherche. Meme piege que celui deja traite sur .badge-hrt. */
  text-transform: none;
  letter-spacing: normal;
}
.radio-group-hrt label:last-child { border-right: none; }
.radio-group-hrt input[type="radio"]:checked + label {
  background:  var(--brand-primary);
  color:       var(--brand-on-primary);
  font-weight: 600;
}
.radio-group-hrt label:hover { background: var(--brand-primary-soft); }
.radio-group-hrt input[type="radio"]:checked + label:hover { background: var(--brand-primary-dark); }

/* --- Variante compacte : groupe pose dans un en-tete de carte, a cote d'un titre en 11px, ou le 13px
   par defaut du composant prend le dessus sur le titre. Le nowrap va avec : un libelle en deux mots
   passait a la ligne et doublait la hauteur de l'en-tete. --- */
.radio-group-hrt--sm label {
  padding:     4px 10px;
  font-size:   12px;
  white-space: nowrap;
}

/* --- Compteur accole au libelle d'un choix : efface pour rester secondaire, et en chiffres tabulaires
   pour que la largeur du groupe ne bouge pas d'un rendu a l'autre. --- */
.radio-group-hrt-compteur {
  font-weight:          400;
  font-variant-numeric: tabular-nums;
  opacity:              0.75;
}

/* ============================================================
   21. COMPOSANTS — LISTING GÉNÉRIQUE (classe Listing)
   Couvre : sort indicator, thead sticky, empty state,
            barre de recherche, footer compteur.
   ============================================================ */

/* --- Sort indicator — deux chevrons SVG superposés ---
   Le chevron actif passe à opacité 1, l'autre à 0.25. */
.table-hrt thead th .sort-indicator {
  display:       inline-flex;
  margin-left:   4px;
  vertical-align: middle;
  opacity:       0.35;
  transition:    opacity var(--brand-transition);
}
.table-hrt thead th.sortable:hover .sort-indicator { opacity: 0.6; }

/* Chevron haut actif (ASC) */
.table-hrt thead th.sort-asc .sort-indicator { opacity: 1; }
.table-hrt thead th.sort-asc  .sort-indicator svg path:first-child { opacity: 1; }
.table-hrt thead th.sort-asc  .sort-indicator svg path:last-child  { opacity: 0.2; }

/* Chevron bas actif (DESC) */
.table-hrt thead th.sort-desc .sort-indicator { opacity: 1; }
.table-hrt thead th.sort-desc .sort-indicator svg path:first-child { opacity: 0.2; }
.table-hrt thead th.sort-desc .sort-indicator svg path:last-child  { opacity: 1; }

/* --- Rang du critère de tri (tri multi-colonnes) ---
   Affiché uniquement quand plusieurs colonnes sont empilées dans le ORDER BY. */
.sort-rank {
  display:         inline-flex;
  align-items:     center;
  justify-content: center;
  min-width:       15px;
  height:          15px;
  margin-left:     4px;
  padding:         0 3px;
  border-radius:   4px;
  background:      var(--brand-primary);
  color:           var(--brand-on-primary);
  font-size:       9px;
  font-weight:     700;
  font-family:     var(--brand-font-mono);
  line-height:     1;
  vertical-align:  middle;
}

/* --- Icones d'export d'un listing, posees a cote du titre de page ---
   Icone seule, sans cadre : la couleur porte l'information, pas un contour. */
.listing-export-hrt {
  display:         inline-flex;
  align-items:     center;
  /* 16px comme le ps-3 que SOS_DEBOUCHE pose sur ses icones d'export */
  margin-left:     16px;
  font-size:       18px;
  line-height:     1;
  vertical-align:  middle;
  text-decoration: none;
  cursor:          pointer;
}
.listing-export-hrt.is-xlsx { color: #1D6F42; }
.listing-export-hrt.is-pdf { color: var(--brand-danger); }

/* Onglets de fiche : pas de titre de page, les icones se posent au-dessus du tableau */
.listing-export-bar-hrt {
  display:         flex;
  align-items:     center;
  justify-content: flex-end;
  margin-bottom:   6px;
}
.listing-export-bar-hrt .listing-export-hrt { font-size: 16px; }

/* --- Barre des critères de tri actifs --- */
.listing-sort-hrt {
  display:       flex;
  align-items:   center;
  flex-wrap:     wrap;
  gap:           6px;
  margin-bottom: 8px;
}
.listing-sort-hrt .listing-sort-label {
  font-size:      11px;
  font-weight:    600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color:          var(--brand-text-muted);
}
.listing-sort-hrt .listing-sort-chip {
  display:       inline-flex;
  align-items:   stretch;
  overflow:      hidden;
  border:        1px solid var(--brand-border);
  border-radius: var(--brand-radius);
  background:    var(--brand-bg-card);
}
.listing-sort-hrt .sort-chip-main,
.listing-sort-hrt .sort-chip-remove,
.listing-sort-hrt .listing-sort-reset {
  display:     inline-flex;
  align-items: center;
  gap:         5px;
  border:      0;
  background:  transparent;
  color:       var(--brand-text-default);
  font-size:   12px;
  cursor:      pointer;
  transition:  background var(--brand-transition), color var(--brand-transition);
}
.listing-sort-hrt .sort-chip-main {
  padding:     4px 8px;
  font-weight: 500;
}
.listing-sort-hrt .sort-chip-main i { font-size: 10px; color: var(--brand-primary); }
.listing-sort-hrt .sort-chip-main:hover { background: var(--brand-primary-soft); color: var(--brand-primary); }
.listing-sort-hrt .sort-chip-remove {
  padding:     4px 7px;
  border-left: 1px solid var(--brand-border);
  color:       var(--brand-text-muted);
}
.listing-sort-hrt .sort-chip-remove:hover { background: var(--brand-danger); color: #fff; }
.listing-sort-hrt .listing-sort-reset {
  padding:   4px 8px;
  color:     var(--brand-text-muted);
  font-size: 11px;
}
.listing-sort-hrt .listing-sort-reset:hover { color: var(--brand-primary); text-decoration: underline; }

/* --- Thead : positionne pour passer au-dessus des cellules du corps ---
   Pas de top: 0 volontairement. La carte est en overflow: clip, donc le conteneur de
   defilement vertical est la page : un thead sticky irait se coller au haut de la fenetre,
   par-dessus la topbar. Pour un en-tete fige, il faudrait un top egal a la hauteur de
   la topbar et un z-index arbitre avec elle. */
.table-hrt-wrapper .table-hrt thead th {
  position: sticky;
  z-index: 2;
}

/* --- Empty state design system ---
   Remplace l'ancien .empty-state-am2s / .empty-state-icon. */
.listing-empty-state {
  display:        flex;
  flex-direction: column;
  align-items:    center;
  justify-content: center;
  padding:        48px 24px;
  text-align:     center;
  color:          var(--brand-text-muted);
}
.listing-empty-icon {
  font-size:     40px;
  line-height:   1;
  margin-bottom: 12px;
  opacity:       0.4;
  color:         var(--brand-primary);
}
.listing-empty-title {
  font-family:   var(--brand-font-display);
  font-size:     15px;
  font-weight:   600;
  color:         var(--brand-text-default);
  margin:        0 0 6px;
}
.listing-empty-desc {
  font-size:  13px;
  color:      var(--brand-text-muted);
  margin:     0;
  max-width:  320px;
}

/* --- Barre de recherche inline (globalSearch) ---
   Utilise field-input-hrt, cohérente avec le reste du design. */
.listing-search-bar {
  display:     flex;
  align-items: center;
  gap:         10px;
  margin-bottom: 8px;
}
.listing-search-bar .listing-search-input-wrap {
  position:    relative;
  flex:        0 0 260px;
}
.listing-search-bar .listing-search-input-wrap i {
  position:   absolute;
  left:       10px;
  top:        50%;
  transform:  translateY(-50%);
  font-size:  14px;
  color:      var(--brand-text-muted);
  pointer-events: none;
}
.listing-search-bar .listing-search-input-wrap .field-input-hrt {
  padding-left: 32px;
  height:       34px;
}
.listing-search-count {
  font-size:   12px;
  color:       var(--brand-text-muted);
  font-family: var(--brand-font-mono);
}

/* --- Footer compteur de résultats --- */
.listing-footer {
  display:      flex;
  align-items:  center;
  justify-content: flex-end;
  padding:      8px 12px;
  border-top:   1px solid var(--brand-border);
  font-size:    11px;
  color:        var(--brand-text-muted);
  font-family:  var(--brand-font-mono);
  background:   var(--brand-bg-surface);
}

.field-input-hrt.is-calculated,
.form-control.is-calculated {
  background-color: color-mix(in srgb, var(--brand-primary-xlight) 58%, white 42%);
  color: var(--brand-text-muted);
  cursor: default;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}

/* ─── Data field — label + value pair for fiches ─── */
.data-field-o2toit {
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.data-field-o2toit .data-label {
  font-family: var(--brand-font);
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--brand-text-muted);
  line-height: 1.3;
}

.data-field-o2toit .data-value {
  font-family: var(--brand-font);
  font-size: 14px;
  font-weight: 500;
  color: var(--brand-text);
  line-height: 1.4;
}

.data-field-o2toit .data-value.is-empty {
  color: var(--brand-text-disabled);
}

/* ─── Detail card — reusable card pattern for fiches ─── */
.detail-card-o2toit {
  background: var(--brand-bg-card);
  border: 1px solid var(--brand-border-light);
  border-radius: var(--brand-radius-lg);
  box-shadow: var(--brand-shadow-sm);
  overflow: hidden;
  margin-bottom: 16px;
  transition: box-shadow 0.2s ease;
}

.detail-card-o2toit:hover {
  box-shadow: var(--brand-shadow);
}

.detail-card-o2toit .detail-card-header {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 20px;
  min-height: 46px;
  background: linear-gradient(180deg, #fafbfd 0%, #f6f8fb 100%);
  border-bottom: 1px solid var(--brand-border-light);
}

.detail-card-o2toit .detail-card-header .detail-card-icon {
  width: 28px;
  height: 28px;
  border-radius: var(--brand-radius-sm);
  background: var(--brand-primary-xlight);
  color: var(--brand-primary-dark);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  flex-shrink: 0;
}

.detail-card-o2toit .detail-card-header h2,
.detail-card-o2toit .detail-card-header h3 {
  font-family: var(--brand-font);
  font-size: 13px;
  font-weight: 800;
  color: var(--brand-secondary-darker);
  margin: 0;
  letter-spacing: 0.01em;
}

.detail-card-o2toit .detail-card-body {
  padding: 18px 20px;
}

/* ─── Breadcrumb enhanced ─── */
.breadcrumb-o2toit {
  display: flex;
  align-items: center;
  gap: 6px;
  list-style: none;
  padding: 0;
  margin: 0 0 16px 0;
  font-family: var(--brand-font);
  font-size: 13px;
}

.breadcrumb-o2toit li {
  display: flex;
  align-items: center;
  gap: 6px;
}

.breadcrumb-o2toit li + li::before {
  content: '';
  display: block;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--brand-border);
  flex-shrink: 0;
}

.breadcrumb-o2toit a {
  color: var(--brand-primary-dark);
  text-decoration: none;
  font-weight: 500;
  transition: color 0.15s ease;
}

.breadcrumb-o2toit a:hover {
  color: var(--brand-primary-darker);
}

.breadcrumb-o2toit .breadcrumb-current {
  color: var(--brand-text-muted);
  font-weight: 500;
}

/* ─── Sidebar info row (vertical label-value for sidebar) ─── */
.info-row-o2toit {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 9px 0;
  border-bottom: 1px solid var(--brand-border-light);
}

.info-row-o2toit:last-child {
  border-bottom: none;
}

.info-row-o2toit .info-label {
  font-family: var(--brand-font);
  font-size: 12px;
  font-weight: 600;
  color: var(--brand-text-muted);
  flex-shrink: 0;
}

.info-row-o2toit .info-value {
  font-family: var(--brand-font);
  font-size: 13px;
  font-weight: 500;
  color: var(--brand-text);
  text-align: right;
  min-width: 0;
}

.info-row-o2toit .info-value.is-empty {
  color: var(--brand-text-disabled);
}

.info-row-o2toit .info-value.is-danger {
  color: var(--brand-danger-text);
}

/* ============================================================
   SELECTS HRT — indicateur visuel natif de liste déroulante
   Appliqué à la classe commune déjà utilisée dans le projet :
   .field-input-hrt sur les balises <select>.
   ============================================================ */
select.field-input-hrt {
  padding-right: 38px;
  cursor: pointer;
  background-image:
    linear-gradient(45deg, transparent 43%, var(--brand-text-muted) 44%, var(--brand-text-muted) 56%, transparent 57%),
    linear-gradient(-45deg, transparent 43%, var(--brand-text-muted) 44%, var(--brand-text-muted) 56%, transparent 57%);
  background-position:
    calc(100% - 19px) calc(50% + 2px),
    calc(100% - 13px) calc(50% + 2px);
  background-size: 8px 8px, 8px 8px;
  background-repeat: no-repeat;
}

select.field-input-hrt:focus {
  background-image:
    linear-gradient(45deg, transparent 43%, var(--brand-primary) 44%, var(--brand-primary) 56%, transparent 57%),
    linear-gradient(-45deg, transparent 43%, var(--brand-primary) 44%, var(--brand-primary) 56%, transparent 57%);
}

select.field-input-hrt:disabled {
  cursor: not-allowed;
  background-image: none;
}

/* ============================================================
   ARTICLE PACK HEADER ACTION
   Bouton compact aligné au titre de card, 100% piloté par les
   variables --brand-* pour s'adapter au thème société actif.
   ============================================================ */
.form-subcard-title-hrt--with-action {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}

.form-subcard-title-main-hrt {
  display: inline-flex;
  align-items: flex-start;
  gap: 8px;
  min-width: 0;
}

.form-subcard-title-content-hrt {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  min-width: 0;
}

.form-subcard-title-label-hrt {
  font-size: 11px;
  font-weight: 700;
  line-height: 1.25;
  color: var(--brand-primary-darker);
}

.form-subcard-title-desc-hrt {
  font-size: 12px;
  line-height: 1.4;
  color: var(--brand-text-muted);
}

.article-composition-note {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin: 12px 0 0;
  padding: 12px 14px;
  border: 1px solid var(--brand-border-light);
  border-radius: var(--brand-radius);
  background: var(--brand-secondary-xlight);
  color: var(--brand-text-muted);
  font-size: 12px;
  line-height: 1.5;
}

.article-composition-note i {
  flex-shrink: 0;
  font-size: 15px;
  color: var(--brand-primary-dark);
  margin-top: 1px;
}

.article-composition-note > div {
  min-width: 0;
}

.article-composition-note strong {
  display: block;
  margin-bottom: 2px;
  color: var(--brand-text);
}

.article-price-note {
  margin-top: 8px;
  font-size: 12px;
  line-height: 1.45;
  color: var(--brand-text-muted);
}

.article-price-note strong {
  color: var(--brand-text);
  font-weight: 600;
}

.article-tva-indicator {
  background: var(--brand-secondary-xlight);
  border: 1px solid var(--brand-border-light);
  border-radius: var(--brand-radius);
  padding: 10px 12px;
  min-height: 38px;
  display: flex;
  align-items: center;
  font-size: 13px;
  color: var(--brand-text-muted);
  line-height: 1.35;
}

.article-tva-indicator.is-active {
  background: var(--brand-primary-xlight);
  color: var(--brand-text);
  border-color: color-mix(in srgb, var(--brand-primary) 32%, var(--brand-border-light) 68%);
}

.article-calc-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-left: 6px;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--brand-primary-xlight);
  color: var(--brand-primary-dark);
  font-size: 11px;
  font-weight: 600;
  vertical-align: middle;
  white-space: nowrap;
}

.article-quick-read .detail-card-body {
  padding-top: 16px;
  padding-bottom: 16px;
}

.article-quick-read .data-value {
  font-size: 15px;
  font-weight: 600;
}

.btn-hrt-inline-action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  min-height: 34px;
  padding: 0 14px;
  border-radius: 999px;
  white-space: nowrap;
  box-shadow: var(--brand-shadow-sm);
}

.btn-hrt-inline-action i {
  font-size: 14px;
  line-height: 1;
}

@media (max-width: 767.98px) {
  .form-subcard-title-hrt--with-action {
    align-items: stretch;
  }

  .form-subcard-title-main-hrt {
    width: 100%;
  }

  .article-composition-note {
    padding: 11px 12px;
  }

  .btn-hrt-inline-action {
    width: 100%;
  }
}

/* Article ajout UX refinements */
.article-quick-read-title {
  color: var(--brand-text);
  font-size: 18px;
  font-weight: 800;
  letter-spacing: -0.01em;
  line-height: 1.15;
}

.article-quick-read .detail-card-header {
  align-items: flex-start;
  background: linear-gradient(180deg, var(--brand-primary-xlight) 0%, rgba(253, 243, 220, 0) 100%);
}

.article-quick-read .detail-card-body {
  padding-top: 16px;
}

.article-quick-read .data-label {
  color: var(--brand-secondary-darker);
}

.article-quick-read .data-value {
  font-size: 17px;
  font-weight: 800;
  letter-spacing: -0.01em;
}

.article-section-title {
  font-size: 16px;
  font-weight: 800;
  letter-spacing: -0.01em;
  line-height: 1.15;
}

.article-section-title--identity {
  color: var(--brand-text);
}

.article-section-title--classification {
  color: var(--brand-primary-dark);
}

.article-section-title--pricing {
  color: var(--brand-secondary-darker);
}

.article-section-title--pack {
  color: var(--brand-primary-darker);
}

.article-section-title--matrix {
  color: var(--brand-text-muted);
}

.article-price-label-main {
  color: var(--brand-text);
}

.article-price-note {
  background: var(--brand-primary-xlight);
  border: 1px solid var(--brand-border-light);
  border-radius: var(--brand-radius);
  color: var(--brand-text);
  padding: 10px 12px;
}

.article-price-note strong {
  color: var(--brand-primary-darker);
}

.article-tva-indicator {
  background: var(--brand-secondary-xlight);
  border: 1px solid var(--brand-border-light);
  border-radius: var(--brand-radius);
  color: var(--brand-text-muted);
  padding: 10px 12px;
}

.article-tva-indicator.is-active {
  background: var(--brand-primary-xlight);
  border-color: var(--brand-primary-light);
  color: var(--brand-text);
}

.article-calc-badge {
  background: var(--brand-primary-light);
  border-radius: var(--brand-radius-pill);
  color: var(--brand-text);
  display: inline-flex;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.02em;
  line-height: 1;
  padding: 3px 8px;
  text-transform: uppercase;
}
.client-adresse-toolbar {
   display: flex;
   justify-content: flex-end;
   align-items: end;
   margin: 0 0 12px;
 }

.client-adresse-toolbar .btn-hrt-primary {
  white-space: nowrap;
}

.client-adresse-listing {
  margin-top: 0;
}

@media (max-width: 767.98px) {
  .client-adresse-toolbar {
    margin-bottom: 10px;
  }
}

/* Devis ajout sidebar / recap */
.devis-layout-hrt {
  align-items: flex-start;
}

.devis-sidebar-hrt {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.devis-sidebar-col-hrt {
  position: sticky;
  top: 92px;
  align-self: flex-start;
  z-index: 20;
}

.devis-nav-link-hrt {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 12px;
  margin-top: 4px;
  border-radius: 10px;
  color: var(--brand-text);
  text-decoration: none;
  font-size: 13px;
  font-weight: 600;
  transition: background-color 120ms ease, color 120ms ease, transform 120ms ease;
}

.devis-nav-link-hrt:first-of-type {
  margin-top: 0;
}

.devis-nav-link-hrt i {
  font-size: 16px;
  color: var(--brand-primary-dark);
  flex-shrink: 0;
}

.devis-nav-link-hrt:hover {
  background: var(--brand-primary-xlight);
  color: var(--brand-primary-darker);
  text-decoration: none;
}

.devis-nav-link-hrt.is-active {
  background: var(--brand-primary-xlight);
  color: var(--brand-primary-darker);
}

.devis-nav-link-hrt.is-active i {
  color: var(--brand-primary-darker);
}

.devis-recap-row-hrt {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  align-items: center;
  padding: 8px 0;
  border-bottom: 1px solid var(--brand-border-light);
  font-size: 13px;
}

.devis-recap-row-hrt:last-child {
  border-bottom: 0;
  padding-bottom: 0;
}

.devis-recap-row-hrt .label {
  color: var(--brand-text-muted);
}

.devis-recap-row-hrt .value {
  color: var(--brand-text);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.devis-recap-row-hrt--final .value {
  color: var(--brand-primary-darker);
  font-size: 16px;
}

.devis-recap-note-hrt {
  color: var(--brand-text-muted);
  font-size: 12px;
  line-height: 1.45;
}

.devis-validite-wrap-hrt {
  position: relative;
}

.devis-validite-input-hrt {
  padding-right: 86px;
}

.devis-validite-addon-hrt {
  position: absolute;
  right: 10px;
  top: 50%;
  transform: translateY(-50%);
  min-height: 26px;
  display: inline-flex;
  align-items: center;
  padding: 0 8px;
  border-radius: 999px;
  background: var(--brand-primary-xlight);
  color: var(--brand-primary-dark);
  font-size: 12px;
  font-weight: 700;
  line-height: 1;
  pointer-events: none;
  white-space: nowrap;
}

@media (max-width: 1199.98px) {
  .devis-sidebar-col-hrt {
    position: static;
  }
}

/* ============================================================
   VALIDATION VISUELLE DES CHAMPS HRT
   ============================================================ */
.field-input-hrt.is-invalid,
.field-select-hrt.is-invalid,
.field-textarea-hrt.is-invalid {
  border-color: var(--brand-danger-border) !important;
  background: var(--brand-danger-bg);
  box-shadow: 0 0 0 3px rgba(139, 32, 32, 0.10);
}

.field-hrt:has(.is-invalid) .field-label-hrt,
.field-hrt:has(.is-invalid) .form-label {
  color: var(--brand-danger-text);
}

/* ============================================================
   23. SYNTHESE / FICHE - Panneau, cartes, tuiles KPI, activités
   Composants génériques sortis de client/synthese.php et
   client/fiche.php (aucune balise <style> dans un fichier PHP).
   Réutilisables sur toute fiche ou tableau de bord.
   ============================================================ */

/* --- Panneau : conteneur de section avec en-tête --- */
.hrt-panel {
  background: var(--brand-bg-surface);
  border: 1px solid var(--brand-border);
  border-radius: 10px;
  overflow: hidden;
}
.hrt-panel-header {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 12px 18px 8px;
  border-bottom: 1px solid var(--brand-border);
}
.hrt-panel-icon {
  font-size: 13px;
  color: var(--brand-primary);
  flex-shrink: 0;
}
.hrt-panel-icon.is-danger { color: var(--brand-danger); }
.hrt-panel-title {
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--brand-text-muted);
  margin: 0;
  white-space: nowrap;
}

/* --- Pilules d'état posées dans un en-tête de panneau ou de carte --- */
.hrt-pill-primary,
.hrt-pill-danger {
  display: inline-flex;
  align-items: center;
  padding: 2px 10px;
  border-radius: 999px;
  margin-left: 4px;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
}
.hrt-pill-primary {
  background: var(--brand-primary-soft);
  color: var(--brand-primary);
  border: 1px solid var(--brand-primary);
}
.hrt-pill-danger {
  background: var(--brand-danger-soft);
  color: var(--brand-danger);
  border: 1px solid var(--brand-danger);
  font-weight: 700;
  animation: hrtPulseDanger 2s ease-in-out infinite;
}
@keyframes hrtPulseDanger {
  0%, 100% { opacity: 1; }
  50% { opacity: .65; }
}

/* --- Grille 2 colonnes séparées par un filet, empilée sous 768px --- */
.hrt-split-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0;
}
.hrt-split-main {
  padding: 16px 18px;
  border-right: 1px solid var(--brand-border);
}
.hrt-split-side {
  padding: 14px 18px 16px;
}

/* --- KPI principal : valeur mise en avant, filet latéral coloré --- */
.hrt-kpi-hero {
  border-left: 3px solid var(--brand-border);
  border-radius: 0 4px 4px 0;
  padding: 10px 14px;
  margin-bottom: 14px;
}
.hrt-kpi-hero.is-danger { border-left-color: var(--brand-danger); }
.hrt-kpi-hero-label {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .1em;
  color: var(--brand-text-muted);
  margin-bottom: 5px;
}
.hrt-kpi-hero.is-danger .hrt-kpi-hero-label { color: var(--brand-danger); }
.hrt-kpi-hero-value {
  font-size: 28px;
  font-weight: 800;
  letter-spacing: -.03em;
  line-height: 1;
  color: var(--brand-text-default);
}
.hrt-kpi-hero.is-danger .hrt-kpi-hero-value { color: var(--brand-danger); }
.hrt-kpi-hero-sub {
  font-size: 11px;
  margin-top: 5px;
}

/* --- Tranches : 4 tuiles à filet supérieur, gradation du niveau 1 au 4 --- */
.hrt-bucket-row {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
  margin-bottom: 10px;
}
.hrt-bucket {
  border-top: 3px solid var(--brand-border);
  border-radius: 0 0 6px 6px;
  padding: 10px 10px 8px;
  background: var(--brand-bg-surface);
}
.hrt-bucket.is-zero { opacity: .4; }
.hrt-bucket.is-niveau-1 { border-top-color: color-mix(in srgb, var(--brand-warning) 55%, var(--brand-bg-surface)); }
.hrt-bucket.is-niveau-2 { border-top-color: var(--brand-warning); }
.hrt-bucket.is-niveau-3 { border-top-color: var(--brand-danger); }
.hrt-bucket.is-niveau-4 { border-top-color: color-mix(in srgb, var(--brand-danger) 75%, black); }
.hrt-bucket-label {
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .06em;
  margin-bottom: 4px;
  color: var(--brand-text-muted);
}
.hrt-bucket.is-niveau-1 .hrt-bucket-label,
.hrt-bucket.is-niveau-2 .hrt-bucket-label { color: var(--brand-warning); }
.hrt-bucket.is-niveau-3 .hrt-bucket-label,
.hrt-bucket.is-niveau-4 .hrt-bucket-label { color: var(--brand-danger); }
.hrt-bucket-value {
  font-size: 15px;
  font-weight: 800;
  line-height: 1.1;
  color: var(--brand-text-default);
}
.hrt-bucket.is-niveau-1 .hrt-bucket-value,
.hrt-bucket.is-niveau-2 .hrt-bucket-value { color: var(--brand-warning); }
.hrt-bucket.is-niveau-3 .hrt-bucket-value { color: var(--brand-danger); }
.hrt-bucket.is-niveau-4 .hrt-bucket-value { color: color-mix(in srgb, var(--brand-danger) 75%, black); }
.hrt-bucket-sub {
  font-size: 9px;
  color: var(--brand-text-muted);
  margin-top: 2px;
}

/* --- Faits chiffrés en ligne sous un bloc de KPI --- */
.hrt-fact-row {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}
.hrt-fact {
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 11px;
  color: var(--brand-text-muted);
}
.hrt-fact i {
  font-size: 13px;
  color: var(--brand-primary);
}
.hrt-fact strong { font-weight: 700; }

/* --- Graphique : en-tête, légende, boîte à hauteur fixe --- */
.hrt-chart-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
}
.hrt-chart-title {
  font-size: 11px;
  font-weight: 700;
  color: var(--brand-text-default);
  text-transform: uppercase;
  letter-spacing: .06em;
}
.hrt-chart-legend {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 10px;
  color: var(--brand-text-muted);
}
.hrt-legend-dot {
  width: 10px;
  height: 10px;
  border-radius: 3px;
  display: inline-block;
}
.hrt-legend-dot.is-primary { background: var(--brand-primary); }
.hrt-legend-dot.is-muted { background: var(--brand-border); }
.hrt-chart-box {
  position: relative;
  height: 160px;
}

/* --- Carte : bloc autonome avec en-tête, action à droite et corps --- */
.hrt-card {
  background: var(--brand-bg-surface);
  border: 1px solid var(--brand-border);
  border-radius: 10px;
  overflow: hidden;
}
.hrt-card-header {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 10px 14px 8px;
  border-bottom: 1px solid var(--brand-border);
}
.hrt-card-icon {
  font-size: 13px;
  color: var(--brand-primary);
  flex-shrink: 0;
}
.hrt-card-icon.is-info { color: var(--brand-info); }
.hrt-card-icon.is-danger { color: var(--brand-danger); }
.hrt-card-title {
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--brand-text-muted);
  margin: 0;
  flex: 1;
  white-space: nowrap;
}
.hrt-card-pill {
  font-size: 10px;
  color: var(--brand-primary);
  background: var(--brand-primary-soft);
  border: 1px solid var(--brand-primary);
  border-radius: 999px;
  padding: 2px 10px;
  white-space: nowrap;
  flex-shrink: 0;
}
.hrt-card-pill--danger {
  color:        var(--brand-danger);
  background:   var(--brand-danger-soft);
  border-color: var(--brand-danger);
}
.hrt-card-link {
  font-size: 10px;
  font-weight: 600;
  color: var(--brand-text-muted);
  text-decoration: none;
  display: flex;
  align-items: center;
  gap: 2px;
  white-space: nowrap;
  flex-shrink: 0;
}
.hrt-card-link:hover { color: var(--brand-primary); }
.hrt-card-body { padding: 12px 14px; }

/* --- Texte libre et état vide dans une carte --- */
.hrt-text-block {
  font-size: 13px;
  color: var(--brand-text-default);
  line-height: 1.6;
  margin: 0;
  white-space: pre-wrap;
}
.hrt-empty-text {
  font-size: 12px;
  color: var(--brand-text-muted);
  margin: 0;
  font-style: italic;
}
.hrt-link-inline {
  color: var(--brand-primary);
  font-weight: 600;
}

/* --- Sous-carte a hauteur contrainte : l'en-tete reste fixe, seul le corps defile --- */
.form-subcard-hrt--scroll {
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.form-subcard-hrt--scroll .hrt-subcard-corps {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}

/* --- Pied de pagination d'une liste : deux chevrons et la position au centre --- */
.hrt-pagination-liste {
  padding-top: 10px;
  margin-top:  6px;
  border-top:  1px solid var(--brand-border);
}
.hrt-pagination-liste-texte {
  font-size:            12px;
  color:                var(--brand-text-muted);
  font-variant-numeric: tabular-nums;
}

/* --- Ressort de la gouttiere d'une .form-subcard-hrt : le fond et les filets vont d'un bord a l'autre
   pendant que le contenu reste aligne sur le reste de la carte. Le 20px reprend son padding. --- */
.hrt-pleine-largeur {
  margin-left:   -20px;
  margin-right:  -20px;
  padding-left:  20px;
  padding-right: 20px;
}

/* --- Listing a fond perdu dans une sous-carte : le titre garde sa gouttiere, le tableau va d'un bord
   a l'autre et se colle sous le titre. Le -20px reprend le padding de .form-subcard-hrt : si ce padding
   change, ces marges doivent suivre. overflow:hidden pour que le tableau respecte le rayon de la carte. */
.form-subcard-hrt--liste-pleine { overflow: hidden; }
.form-subcard-hrt--liste-pleine > .form-subcard-title-hrt { margin-bottom: 0; }
.form-subcard-hrt--liste-pleine > .hrt-liste-pleine { margin: 0 -20px -20px; }

/* --- Liste compacte dans une carte : un libellé, une méta, un badge d'état --- */
.hrt-mini-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.hrt-mini-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  background: var(--brand-bg-app);
  border: 1px solid var(--brand-border);
  border-radius: 8px;
}
.hrt-mini-item-main {
  flex: 1;
  min-width: 0;
}
.hrt-mini-item-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--brand-text-default);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.hrt-mini-item-meta {
  font-size: 11px;
  color: var(--brand-text-muted);
}
.hrt-mini-item--cliquable {
  cursor: pointer;
  transition: border-color .15s ease, background .15s ease;
}
.hrt-mini-item--cliquable:hover {
  border-color: var(--brand-primary);
  background: var(--brand-bg-surface);
}

/* --- Grille de contacts : avatar initiales + coordonnées --- */
.hrt-contact-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 10px;
}
.hrt-contact-card {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  padding: 10px 12px;
  background: var(--brand-bg-app);
  border: 1px solid var(--brand-border);
  border-radius: 8px;
}
.hrt-contact-card.is-inactive {
  background: var(--brand-danger-soft);
  border-color: var(--brand-danger);
  opacity: .85;
}
.hrt-contact-card.is-inactive .hrt-contact-avatar { background: var(--brand-text-muted); }
.hrt-contact-avatar {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  font-weight: 800;
  background: var(--brand-primary);
  color: var(--brand-on-primary);
}
.hrt-contact-info {
  flex: 1;
  min-width: 0;
}
.hrt-contact-name {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  font-weight: 600;
  color: var(--brand-text-default);
  margin-bottom: 1px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.hrt-contact-role {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: .07em;
  color: var(--brand-text-muted);
  margin-bottom: 4px;
}
.hrt-contact-meta {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 11px;
  color: var(--brand-text-muted);
  margin-top: 2px;
}
.hrt-contact-meta i {
  font-size: 12px;
  color: var(--brand-primary);
  flex-shrink: 0;
}
.hrt-contact-meta a {
  color: var(--brand-primary);
  text-decoration: none;
}

/* --- Liste d'activités : une ligne par élément, libellé puis meta --- */
.hrt-activity-list {
  display: flex;
  flex-direction: column;
}
.hrt-activity-row {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 9px 14px;
  border-bottom: 1px solid var(--brand-border);
  transition: background var(--brand-transition);
}
.hrt-activity-row:last-child { border-bottom: none; }
.hrt-activity-row:hover { background: var(--brand-bg-app); }
.hrt-activity-main {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
}
.hrt-activity-ref {
  font-size: 12px;
  font-weight: 600;
  color: var(--brand-text-default);
  font-family: var(--brand-font-mono);
}
.hrt-activity-desc {
  font-size: 12px;
  font-weight: 500;
  color: var(--brand-text-default);
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.hrt-activity-meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 10px;
  color: var(--brand-text-muted);
}
.hrt-activity-meta strong {
  color: var(--brand-text-default);
  font-weight: 700;
}

/* --- Utilitaires de couleur brand --- */
.hrt-text-danger { color: var(--brand-danger) !important; }
.hrt-text-warning { color: var(--brand-warning) !important; }
.hrt-text-muted { color: var(--brand-text-muted) !important; }

/* --- Responsive : la grille 2 colonnes s'empile, les tranches passent à 2 --- */
@media (max-width: 991px) {
  .hrt-bucket-row { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 767px) {
  .hrt-split-grid { grid-template-columns: 1fr; }
  .hrt-split-main {
    border-right: none;
    border-bottom: 1px solid var(--brand-border);
    padding: 14px 14px 12px;
  }
  .hrt-split-side { padding: 12px 14px; }
  .hrt-panel-header,
  .hrt-card-header { flex-wrap: wrap; }
  .hrt-fact-row { gap: 8px; }
}

/* --- Hero sans habillage : le titre de page seul, sans carte ni ombre --- */
.page-hero-hrt--plain {
  background: none;
  border: none;
  box-shadow: none;
  padding: 0 0 4px 0;
}

/* ============================================================
   EN-TETE DE FICHE — ADAPTATION MOBILE
   Rien ici ne touche le rendu bureau : tout est sous breakpoint.
   ============================================================ */

/* --- Colonne gauche du hero de la fiche client sur bureau.
   Sans flex-basis, sa taille hypothetique vaut son max-content : l'adresse tenue sur une seule
   ligne. Des que cette largeur plus celle de la colonne droite (flex-shrink-0) depasse le hero,
   le flex-wrap du parent fait descendre la colonne droite sous l'identite, boutons et tuiles KPI
   compris. flex-basis 0 la sort du calcul de rupture : la colonne gauche prend l'espace restant
   et son texte passe a la ligne au lieu de pousser les actions en dessous.
   min-width: 0 leve le min-content implicite des items flex, sinon le basis 0 reste sans effet. --- */
@media (min-width: 768px) {
  .hrt-fiche-hero-identite {
    flex:          1 1 0;
    min-width:     0;
    overflow-wrap: anywhere;
  }
}

/* --- Colonne droite du hero (boutons + tuiles). Elle porte .flex-shrink-0, donc elle conserve la
   largeur cumulee de ses boutons : passee a la ligne sur telephone, elle depassait du hero et de
   l'ecran au lieu de laisser ses boutons s'empiler. On lui rend le droit de rétrécir et on l'etale
   sur toute la largeur ; ses rangees internes gardent leur alignement a droite. --- */
@media (max-width: 767.98px) {
  .hrt-fiche-hero-cote {
    flex-shrink:  1 !important;
    align-items:  stretch !important;
    width:        100%;
    min-width:    0;
  }

  .hrt-fiche-actions {
    width:     100%;
    min-width: 0;
  }

  /* flex: 0 1 auto au lieu du 0 0 auto implicite : un bouton peut ceder de la largeur plutot que
     de pousser la rangee hors cadre. Le nowrap de .btn-hrt-* garde les libelles sur une ligne. */
  .hrt-fiche-actions > button {
    flex:      0 1 auto;
    min-width: 0;
  }

  /* --- Les quatre tuiles KPI en grille 2 x 2 a colonnes egales. En flex elles portaient
     min-width: 155px (175px pour l'encours en is-danger), donc des largeurs inegales et une
     rangee ragged. La grille fixe les colonnes, les min-width et le flex sont neutralises, et le
     padding renforce de la variante is-danger est ramene au commun pour que les quatre blocs
     aient exactement la meme taille. --- */
  .hrt-kpi-rangee {
    display:               grid !important;
    grid-template-columns: 1fr 1fr;
    gap:                   8px;
  }

  .hrt-kpi-rangee .hrt-kpi-tile,
  .hrt-kpi-rangee .hrt-kpi-tile.is-danger {
    min-width: 0;
    flex:      none;
    padding:   10px 12px;
  }

  .hrt-kpi-rangee .hrt-kpi-tile-value,
  .hrt-kpi-rangee .hrt-kpi-tile-value.is-lead,
  .hrt-kpi-rangee .hrt-kpi-tile.is-danger .hrt-kpi-tile-value.is-lead {
    font-size: 16px;
  }

  /* --- Bloc "Retour a la liste" des fiches contrat, devis, intervention, utilisateur et vehicule.
     Le hero est en justify-content: space-between : une fois passe a la ligne, ce bloc devient seul
     sur la sienne et space-between le cale a gauche, sous le bloc d'identite. margin-left: auto le
     repousse a droite quel que soit le justify-content du parent, et justify-content: flex-end tient
     le cas ou un second bouton viendrait s'y ajouter. --- */
  .hrt-fiche-retour {
    margin-left:     auto;
    justify-content: flex-end;
  }
}

/* --- Onglets de fiche sur telephone : grille de trois colonnes egales au lieu du passage a la
   ligne libre. Le wrap venait du premier bloc .onglet-hrt (ligne ~1286), que le second (~2774) ne
   redeclare pas : les onglets se rangeaient donc par largeur de libelle, d'ou des rangees ou un
   onglet occupe la moitie de la largeur et le suivant un huitieme.
   display: grid l'emporte sur le display: flex des deux blocs et rend l'overflow-x: auto sans
   objet - avec des colonnes en 1fr, la barre ne peut plus deborder.
   Trois colonnes : la fiche client a nOnglets = 9, soit trois rangees pleines.
   Le libelle passe a la ligne au lieu d'etre rogne. Le white-space: nowrap du composant de base le
   tenait sur une ligne, et overflow: hidden le coupait alors des DEUX cotes puisque le contenu est
   centre : "Interventions et recurrence" s'affichait "rventions et recurre", illisible. Aucune
   ellipse possible ici, text-overflow ne s'applique pas au noeud texte d'un .nav-link en
   inline-flex - c'est le retour a la ligne qui regle le cas, pas une troncature plus propre.
   Une colonne fait 97px sur un ecran de 375px : overflow-wrap: anywhere garantit qu'aucun mot ne
   depasse, meme sans espace ou couper. Les onglets d'une meme rangee gardent la meme hauteur, la
   grille les etirant sur la plus haute. --- */
@media (max-width: 575.98px) {
  .onglet-hrt {
    display:               grid;
    grid-template-columns: repeat(3, 1fr);
    gap:                   2px;
  }

  .onglet-hrt .nav-link {
    justify-content: center;
    padding:         8px 4px;
    font-size:       11.5px;
    line-height:     1.25;
    text-align:      center;
    white-space:     normal;
    overflow-wrap:   anywhere;
  }
}

/* --- Badge miniature aligné sur une ligne de texte --- */
.badge-hrt--xs {
  font-size: 9px;
  vertical-align: middle;
}

/* --- Tuile KPI compacte : rangée de chiffres clés sous un en-tête de fiche --- */
.hrt-kpi-tile {
  background: var(--brand-bg-surface);
  border: 1px solid var(--brand-border);
  border-radius: 8px;
  padding: 12px 16px;
  min-width: 155px;
  flex: 1 1 155px;
}
.hrt-kpi-tile.is-danger {
  background: var(--brand-danger-soft);
  border: 1.5px solid var(--brand-danger);
  padding: 14px 18px;
  min-width: 175px;
  flex: 1 1 175px;
}
.hrt-kpi-tile-label {
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--brand-text-muted);
  margin-bottom: 5px;
  white-space: nowrap;
}
.hrt-kpi-tile-label i { font-size: 12px; }
.hrt-kpi-tile.is-danger .hrt-kpi-tile-label { color: var(--brand-danger); }
.hrt-kpi-tile-value {
  font-size: 16px;
  font-weight: 700;
  line-height: 1.2;
  color: var(--brand-text-default);
}
.hrt-kpi-tile-value.is-lead {
  font-size: 18px;
  font-weight: 800;
  line-height: 1.15;
  letter-spacing: -.02em;
}
.hrt-kpi-tile-value.is-muted { color: var(--brand-text-muted); }
.hrt-kpi-tile.is-danger .hrt-kpi-tile-value { color: var(--brand-danger); }
.hrt-kpi-tile.is-danger .hrt-kpi-tile-value.is-lead { font-size: 22px; }
.hrt-kpi-tile-sub {
  font-size: 11px;
  color: var(--brand-text-muted);
  margin-top: 3px;
  line-height: 1.45;
}
.hrt-kpi-tile.is-danger .hrt-kpi-tile-sub {
  color: var(--brand-danger);
  margin-top: 4px;
  opacity: .85;
}

/* --- Listing : conteneur des boutons d'action d'une ligne, sortis des styles en ligne de la classe --- */
.table-hrt td.col-actions {
  white-space: nowrap;
}
.table-row-actions {
  display: inline-flex;
  align-items: center;
  justify-content: flex-end;
  gap: 4px;
  flex-wrap: nowrap;
  white-space: nowrap;
}

/* --- Sentinelle du lazy load : invisible, observee par IntersectionObserver --- */
.listing-lazy-sentinel {
  height: 1px;
  margin: 0;
  padding: 0;
}

/* ============================================================
   24. LISTE MEDIA - vignette + informations + actions de ligne
   Liste d'éléments visuels (photos d'intervention, pièces
   jointes) où la vignette sert à reconnaître le fichier et non
   à l'examiner. Réutilisable partout ou une liste doit montrer
   un aperçu plutôt qu'un nom de fichier.
   ============================================================ */
.hrt-media-list {
  display: flex;
  flex-direction: column;
}

/* --- Variante en bande : les memes .hrt-media-thumb, mais sans la ligne d'informations ni les --- */
/* --- boutons d'action autour. Pour un apercu en lecture seule, ou l'on regarde sans gerer. --- */
.hrt-media-vignettes {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

/* --- Colonne photos calee sur la hauteur de la carte : l'en-tete et l'alerte restent
   fixes, seule la liste defile. min-height 0 est indispensable, sans lui un enfant
   flex refuse de retrecir sous la taille de son contenu et ne defile jamais. --- */
.hrt-photo-colonne {
  height: var(--hrt-carte-hauteur);
  display: flex;
  flex-direction: column;
}
.hrt-photo-colonne .hrt-media-list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
}

.hrt-media-row {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 12px 0;
  border-bottom: 1px solid var(--brand-border);
}
.hrt-media-row:last-child { border-bottom: none; }

/* --- Ligne dont la photo est en cours de positionnement sur la carte.
   Le bleu reprend celui du marqueur temporaire pose sur la carte (couleurPin dans photo.php) :
   l'oeil relie la ligne surlignee au pin qu'il est en train de deplacer. Ne pas passer au vert
   primaire, qui sert deja au survol de toutes les lignes et ne distinguerait plus rien.
   Marges negatives compensees par le padding : la ligne n'a pas de gouttiere laterale, sans elles
   le fond teinte collerait au texte. Le deplacement horizontal net est nul, la ligne ne bouge pas
   quand la classe arrive. --- */
.hrt-media-row.is-being-geolocalised {
  margin-left:   -12px;
  margin-right:  -12px;
  padding-left:  12px;
  padding-right: 12px;
  background:    var(--brand-info-soft);
  box-shadow:    inset 3px 0 0 var(--brand-info);
  border-radius: var(--brand-radius);
  border-bottom-color: transparent;
  transition:    background var(--brand-transition);
}

/* Bouton de geolocalisation de la ligne active : etat enfonce, il rappelle quelle action est en cours */
.hrt-media-row.is-being-geolocalised .row-action-icon.info {
  background: var(--brand-bg-surface);
  color:      var(--brand-info);
  box-shadow: 0 0 0 1px var(--brand-info);
}

/* Badge d'etat present dans toutes les lignes, revele par la seule ligne active */
.hrt-media-badge-geoloc { display: none; }
.hrt-media-row.is-being-geolocalised .hrt-media-badge-geoloc { display: inline-flex; }

/* --- Vignette carrée : accueille portrait comme paysage sans rognage --- */
.hrt-media-thumb {
  width: 110px;
  height: 110px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--brand-border);
  border-radius: var(--brand-radius);
  background: var(--brand-bg-app);
  overflow: hidden;
}
.hrt-media-thumb i {
  font-size: 28px;
  color: var(--brand-text-muted);
}
.hrt-media-thumb img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  cursor: zoom-in;
}

.hrt-media-info {
  flex: 1;
  min-width: 0;
}
.hrt-media-title {
  font-size: 14px;
  font-weight: 600;
  color: var(--brand-text-default);
}
.hrt-media-meta {
  font-size: 12px;
  color: var(--brand-text-muted);
  margin-top: 3px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.hrt-media-coord {
  font-size: 12px;
  font-family: var(--brand-font-mono);
  color: var(--brand-text-muted);
  margin-top: 3px;
  /* Comme .hrt-media-meta juste au-dessus : sans coupure, la chaine de coordonnees passait par-dessus
     la colonne des boutons d'action. Le parent .hrt-media-info est bien en min-width: 0, mais cela ne
     borne que sa boite, pas le texte de ses enfants. */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.hrt-media-badges {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 8px;
}

/* --- Actions de la ligne, empilées à droite de la vignette --- */
.hrt-media-actions {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex-shrink: 0;
}

/* --- Onglet Photos sur telephone --- */
@media (max-width: 575.98px) {
  /* La vignette de 110px est le premier consommateur de la ligne : entre elle, les gouttieres et la
     colonne d'actions, il ne restait qu'une centaine de pixels aux informations. A 84px le bloc
     d'infos en recupere une trentaine, de quoi contenir le badge le plus long
     ("Positionnement en cours"). La galerie plein ecran reste accessible d'un appui sur la vignette. */
  .hrt-media-thumb {
    width:  84px;
    height: 84px;
  }

  .hrt-media-row {
    gap: 10px;
  }

  /* min-width: 0 pour que la rangee de badges puisse retrecir, et badges resserres : .badge-hrt est
     en white-space: nowrap, un badge trop large pour la place restante sortait du cadre au lieu de
     passer a la ligne. */
  .hrt-media-badges {
    min-width: 0;
  }

  .hrt-media-badges .badge-hrt {
    font-size: 10px;
    padding:   2px 6px;
  }
}

/* ============================================================
   MAITRE / DETAIL - liste de cartes selectionnables a gauche,
   contenu de la selection a droite. Generique : utilisable pour
   toute navigation par carte (recurrences, lots, periodes...).
   ============================================================ */
.hrt-master-detail {
  display: grid;
  grid-template-columns: 320px minmax(0, 1fr);
  gap: 16px;
  align-items: start;
}
.hrt-master-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 0;
}
/* Les deux volets portent leur en-tete avec .hrt-section-head + .form-subcard-title-hrt */
.hrt-detail-pane { min-width: 0; }

/* --- Carte selectionnable : bouton pleine largeur, filet lateral d'etat --- */
.hrt-select-card {
  display: block;
  width: 100%;
  text-align: left;
  font: inherit;
  color: inherit;
  background: var(--brand-bg-surface);
  border: 1px solid var(--brand-border);
  border-left: 3px solid var(--brand-border);
  border-radius: 8px;
  padding: 10px 12px;
  cursor: pointer;
  transition: background var(--brand-transition), border-color var(--brand-transition);
}
.hrt-select-card:hover {
  border-color: var(--brand-primary);
  border-left-color: var(--brand-primary);
}
/* L'anneau porte la selection : il reste visible meme quand un etat colore prend le fond */
.hrt-select-card.is-active {
  background: var(--brand-primary-soft);
  border-color: var(--brand-primary);
  border-left-color: var(--brand-primary);
  box-shadow: 0 0 0 1px var(--brand-primary);
}
.hrt-select-card.is-stopped {
  border-left-color: var(--brand-danger);
  background: var(--brand-danger-soft);
}
.hrt-select-card.is-stopped.is-active {
  border-color: var(--brand-danger);
  box-shadow: 0 0 0 1px var(--brand-danger);
}
.hrt-select-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 4px;
}
.hrt-select-card-label {
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--brand-text-muted);
  white-space: nowrap;
}
.hrt-select-card-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--brand-text-default);
  margin-bottom: 6px;
}
.hrt-select-card-meta {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  color: var(--brand-text-muted);
  margin-top: 3px;
  min-width: 0;
}
.hrt-select-card-meta i {
  font-size: 11px;
  color: var(--brand-primary);
  flex-shrink: 0;
}
.hrt-select-card-meta span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* --- Sous 992px : les cartes passent en bandeau defilant au-dessus du detail --- */
/* --- Les deux volets s'empilent sous 992px, la liste au-dessus et le detail en dessous.
   La liste reste VERTICALE, comme sur PC. Elle etait passee en carrousel horizontal de cartes de
   230px : une carte de recurrence porte cinq a six lignes (libelle, periode, duree, articles,
   techniciens, compteur d'interventions) dont aucune ne tenait dans cette largeur, rien
   n'annoncait les cartes hors champ, et l'en-tete de section - premier enfant de la liste - se
   retrouvait embarque dans la piste comme une vignette de plus. Cette liste sert a choisir une
   recurrence, pas a feuilleter des vignettes : en colonne chaque carte se lit d'un coup d'oeil.
   Aucune declaration n'est necessaire, la regle de base est deja en colonne pleine largeur. --- */
@media (max-width: 991.98px) {
  .hrt-master-detail { grid-template-columns: minmax(0, 1fr); }
}
/* --- En-tete de page sans habillage de carte : le titre porte seul la hierarchie. Remplace le
   style="background:none;border:none;box-shadow:none;padding:0 0 4px 0" repete en dur sur les heros --- */
.hrt-hero-plain {
  background: none;
  border: none;
  box-shadow: none;
  padding: 0 0 4px 0;
}

/* --- Panneau carte : hauteur ferme, il ne suit pas la hauteur de la colonne voisine.
   À poser dans une colonne en align-self-start, sinon le flex l'étire quand la
   colonne d'en face est plus haute. --- */
/* Hauteur partagee par le panneau carte et la colonne photos : les deux doivent
   se terminer au meme pixel, une seule valeur a regler. */
:root {
  --hrt-carte-hauteur: 850px;
}

.hrt-carte-panel {
  height: var(--hrt-carte-hauteur);
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--brand-border);
  border-radius: var(--brand-radius);
  background: var(--brand-bg-app);
  position: sticky;
  top: 16px;
  overflow: hidden;
}

/* --- Surface de rendu : Google Maps a besoin d'un conteneur aux dimensions
   définies, une div sans hauteur donne une carte invisible. --- */
.hrt-carte-map {
  width: 100%;
  height: 100%;
}

/* --- Barre de positionnement : posee par-dessus la carte pendant qu'on place une photo.
   Masquee par defaut, revelee par .is-visible. --- */
.hrt-carte-barre {
  display: none;
  position: absolute;
  left: 12px;
  right: 12px;
  bottom: 12px;
  z-index: 5;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  padding: 10px 14px;
  border: 1px solid var(--brand-border);
  border-radius: var(--brand-radius);
  background: var(--brand-bg-surface);
  box-shadow: var(--brand-shadow-md);
}
.hrt-carte-barre.is-visible {
  display: flex;
}

/* --- Barre ancree en bas a droite de l'ecran : elle reste atteignable quel que soit le defilement,
   y compris quand le panneau carte est plus haut que la fenetre.
   left:auto est obligatoire, il annule le left de la regle de base : avec left ET right poses, un
   element fixe n'est plus dimensionne par son contenu mais etire d'un bord a l'autre du viewport.
   z-index 1010 : au-dessus de la topbar Hyper (1005) et de la sidebar (1000), mais sous la galerie
   plein ecran (1080) et sous la modale (4990) - la barre ne doit pas flotter par-dessus une photo
   ouverte en grand. --- */
.hrt-carte-barre--ecran {
  position:  fixed;
  left:      auto;
  right:     43px;
  bottom:    16px;
  max-width: calc(100vw - 32px);
  z-index:   1010;
}

/* --- Sur telephone, right: 50px est une gouttiere reglee pour le bureau : sur 412px le contenu de la
   barre depasse les 362px restants et son bord gauche sortait de l'ecran. Les deux bords sont
   contraints ici, la barre occupe donc la largeur moins 12px de chaque cote, et son flex-wrap laisse
   le libelle, les coordonnees et les boutons s'empiler. Contrairement au defaut d'origine sur
   .hrt-carte-barre, poser left ET right est ici le comportement voulu : il n'y a pas de sidebar a
   eviter sur telephone.
   A garder APRES la regle ci-dessus : specificite identique, et une media query n'en ajoute pas -
   declaree avant, elle serait purement et simplement ecrasee. --- */
@media (max-width: 575.98px) {
  .hrt-carte-barre--ecran {
    left:      12px;
    right:     12px;
    max-width: none;
  }
}

.hrt-carte-barre-libelle {
  font-size: 13px;
  font-weight: 600;
  color: var(--brand-text-default);
}
.hrt-carte-barre-coord {
  font-family: var(--brand-font-mono);
  font-size: 12px;
  color: var(--brand-text-muted);
  flex: 1;
  min-width: 0;
  /* min-width: 0 autorise la boite a retrecir, il n'empeche pas le texte d'en sortir : sans ces trois
     lignes les coordonnees debordaient visuellement du cadre de la barre des qu'elle etait serree. */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.hrt-carte-barre-actions {
  display: flex;
  gap: 8px;
  flex-shrink: 0;
}

@media (max-width: 991.98px) {
  .hrt-carte-panel {
    height: 420px;
    /* annule le sticky : sur colonnes empilees le panneau doit defiler avec la page */
    position: relative;
  }

  /* Colonnes empilees : la liste reprend sa hauteur naturelle, la page defile */
  .hrt-photo-colonne {
    height: auto;
  }
  .hrt-photo-colonne .hrt-media-list {
    overflow-y: visible;
  }
}
/* --- Popup pleine largeur : ecrans plein ecran (planning) qui ne veulent ni gouttiere ni largeur max --- */
/* --- Active par la constante POPUP_PLEINE_LARGEUR posee dans la page, cf. templates/popup.php --- */
.popup-body.hrt-popup-full {
  max-width: none;
  padding: 0;
  margin: 0;
}

/* --- Liste de societes en dropdown (selectSocieteFiltre) : reprend le rendu du switcher de --- */
/* --- base.php en classes, les styles inline n'ayant pas leur place dans un fichier PHP. --- */
.hrt-dropdown-societe-menu {
  min-width: 240px;
  border: 1px solid var(--brand-border);
  border-radius: var(--brand-radius);
  box-shadow: var(--brand-shadow-md);
}
.hrt-dropdown-societe-header {
  padding: 8px 16px 4px;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--brand-text-muted);
}
.hrt-dropdown-societe-item {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
}
.hrt-dropdown-societe-item i {
  font-size: 15px;
}
.hrt-dropdown-societe-item.is-active {
  background: var(--brand-primary-soft);
  color: var(--brand-primary);
  font-weight: 600;
}

/* --- Chip societe rendu cliquable quand il ouvre un dropdown --- */
.chip-societe.hrt-chip-societe-btn {
  cursor: pointer;
}

/* ============================================================
   TOOLTIP GENERIQUE - remplace la bulle native de l'attribut title
   Peinte par js/tooltip/tooltip.js, portée dans body. Position fixed
   et z-index au-dessus de la pile d'overlays (cf. overlay.js), sinon
   la bulle passerait derrière un drawer ou la modal.
   Même habillage que le tooltip Bootstrap (.tooltip plus haut) pour
   n'avoir qu'un seul rendu de tooltip dans l'application.
   ============================================================ */
.hrt-tooltip {
  position:      fixed;
  top:           0;
  left:          0;
  z-index:       calc(var(--hrt-z-flash, 5020) + 10);
  max-width:     280px;
  padding:       6px 10px;
  border-radius: var(--brand-radius);
  background:    var(--brand-primary);
  color:         #fff;
  font-size:     var(--brand-font-size-sm);
  font-weight:   500;
  line-height:   1.45;
  text-align:    left;
  white-space:   pre-line;
  box-shadow:    var(--brand-shadow-lg);
  pointer-events: none;
  opacity:       0;
  visibility:    hidden;
  transform:     translateY(2px);
  transition:    opacity 0.12s ease, transform 0.12s ease, visibility 0.12s;
}
.hrt-tooltip.is-visible {
  opacity:    1;
  visibility: visible;
  transform:  none;
}

/* --- Flèche : sa position horizontale est posée en JS, elle vise l'élément survolé --- */
.hrt-tooltip::after {
  content:            "";
  position:           absolute;
  top:                100%;
  left:               var(--hrt-tooltip-fleche, 50%);
  margin-left:        -5px;
  border:             5px solid transparent;
  border-bottom-width: 0;
  border-top-color:   var(--brand-primary);
}
.hrt-tooltip.is-bas::after {
  top:                 auto;
  bottom:              100%;
  border-top-width:    0;
  border-top-color:    transparent;
  border-bottom-width: 5px;
  border-bottom-color: var(--brand-primary);
}

@media (max-width: 575.98px) {
  .hrt-tooltip { max-width: 220px; }
}

/* ============================================================
   ACCORDÉON PAR PAYEUR — écran "À facturer"
   Une facture = un payeur : le groupe est l'unité de travail, la ligne n'en est qu'un
   composant. La tête porte donc ce qui sert à décider (nom, volumétrie, total), le panneau
   ne sert qu'à choisir les lignes à retenir.
   ============================================================ */

/* La tête est un <button> et non une <div> : c'est une commande, elle doit être atteignable au
   clavier et annoncer son état par aria-expanded sans qu'on ait à recâbler le rôle à la main. */
.hrt-groupe-facturer-tete {
  display:     flex;
  align-items: center;
  gap:         14px;
  width:       100%;
  padding:     12px 14px;
  /* Gris tres clair pour le fond. Il ne pouvait pas porter la distinction tout seul : plus clair il se
     confondait avec les lignes blanches, plus soutenu il prenait la couleur du fond de page et la bande
     se lisait comme un trou dans la carte. C'est le filet en tete du panneau qui delimite, en couleur
     de societe.
     Pas de survol colore : la teinte de survol du projet est --brand-primary-soft, celle que prennent
     les lignes du tableau, une tete survolee se serait confondue avec une ligne survolee. */
  border:      none;
  background:  var(--brand-bg-entete);
  text-align:  left;
  font-family: inherit;
  cursor:      pointer;
}
.hrt-groupe-facturer-tete:focus-visible {
  outline:        2px solid var(--brand-primary);
  outline-offset: -2px;
}

/* Identité du payeur : prend la place restante, le reste de la tête est dimensionné par son contenu */
.hrt-groupe-facturer-identite {
  display:     flex;
  align-items: center;
  gap:         10px;
  flex:        1;
  min-width:   0;
}
.hrt-groupe-facturer-nom {
  font-size:     14px;
  font-weight:   600;
  color:         var(--brand-text-default);
  white-space:   nowrap;
  overflow:      hidden;
  text-overflow: ellipsis;
}

/* Ventilation par nature. Passe à la ligne au lieu d'écraser le total : sur un payeur qui cumule
   les quatre natures, la rangée fait sinon déborder la tête en largeur. */
.hrt-groupe-facturer-natures {
  display:     flex;
  flex-wrap:   wrap;
  gap:         4px;
  justify-content: flex-end;
}

/* Total du groupe : chiffres tabulaires pour que la colonne des totaux reste alignée d'un
   groupe à l'autre, quel que soit le nombre de chiffres. */
.hrt-groupe-facturer-total {
  font-size:            15px;
  font-weight:          700;
  color:                var(--brand-text-default);
  font-variant-numeric: tabular-nums;
  white-space:          nowrap;
  text-align:           right;
  min-width:            110px;
}

.hrt-groupe-facturer-chevron {
  display:         inline-flex;
  align-items:     center;
  justify-content: center;
  width:           28px;
  height:          28px;
  flex-shrink:     0;
  border-radius:   var(--brand-radius);
  color:           var(--brand-text-muted);
  transition:      transform var(--brand-transition), background var(--brand-transition);
}
/* Seul retour de survol restant, donc le seul indice que la bande est cliquable : le chevron passe en
   blanc, qui ressort sur la teinte primaire de la tete. */
.hrt-groupe-facturer-tete:hover .hrt-groupe-facturer-chevron {
  background: var(--brand-bg-surface);
  color:      var(--brand-text-default);
}

/* L'état ouvert vit sur la tête (aria-expanded), pas sur une classe posée en JS : un seul
   attribut à basculer, et la rotation comme l'affichage du corps en découlent. */
.hrt-groupe-facturer-tete[aria-expanded="false"] + .hrt-groupe-facturer-corps { display: none; }
.hrt-groupe-facturer-tete[aria-expanded="false"] .hrt-groupe-facturer-chevron { transform: rotate(-90deg); }

/* Le tableau va d'un bord a l'autre, comme dans un listing classique : un retrait a gauche ne ferait
   que casser l'alignement des colonnes avec le reste de l'ecran.
   Le filet en couleur de societe est porte par le panneau et non par la tete : pose sur la tete, il
   restait visible groupe replie et pendait sous une bande qui n'ouvrait sur rien. Ici il disparait avec
   le panneau, et tombe au meme pixel puisque le panneau n'a pas de padding. */
.hrt-groupe-facturer-corps {
  border-top: 1px solid var(--brand-primary);
}

/* Colonnes du tableau d'un groupe : largeurs et alignements poses une fois plutot que repetes en
   style="" sur chaque cellule, comme le fait Listing qui, lui, ne les connait pas d'avance. */
.hrt-table-a-facturer { table-layout: fixed; }
.hrt-table-a-facturer th:nth-child(2),
.hrt-table-a-facturer td:nth-child(2) { width: 180px; }
.hrt-table-a-facturer th:nth-child(3),
.hrt-table-a-facturer td:nth-child(3) { width: 140px; }
.hrt-table-a-facturer th:nth-child(4),
.hrt-table-a-facturer td:nth-child(4) { width: 140px; text-align: right; }
.hrt-table-a-facturer th:nth-child(5),
.hrt-table-a-facturer td:nth-child(5) { width: 44px; text-align: center; }
