/* =============================================================================
   COURTIER — COCKPIT CLIENTS « Liquid Glass »
   Spec : docs/superpowers/specs/2026-08-23-clients-cockpit-design.md
   Chargé APRÈS extranet-theme.css et select-theme.css (pattern comparateur).
   Préfixe .cl-*. Consomme uniquement les tokens --em-* (+ color-mix) : zéro
   hex de marque en dur. Règles héritées de la fondation Liquid Glass :
   blur sur les fonds jamais sur le texte, encre pleine, bordures 1px.

   Sommaire :
      1. Mesh chaud local (#clPage) — porte aussi les tokens palette funnel (T5)
      2. Chrome sticky (recherche + filtres + en-tête de colonnes)
      3. Toolbar — recherche & filtres (desktop + panneau mobile) — inclut T3
         (confort Tom Select toolbar : chevron/padding, clear-button, dropdown)
      4. Grille partagée en-tête / lignes (.cl-head / .cl-row) — inclut T4
         (curseur pointer sur la latte) et T2 (empilement du dropdown d'étape)
      5. Cellules communes (client, contact, montant, activité, collab)
      6. Actions de ligne (icônes, révélation au survol, tactile)
      7. Select-badge d'étape (.cl-stage-wrap) — palette vive T5 + confort/AA
         du dropdown T3 (option courante lisible)
      8. Chips rappel (.cl-rappel, 4 états + pulse)
      9. En-tête de page (actions, menu « Ajouter », segmenté vues)
     10. Pills macro (.cl-pills) — palette vive T5 (actives/inactives)
     11. Bulk bar flottante (.cl-bulkbar)
     12. Pagination (.cl-pagination)
     13. Mode cartes mobile (<1024px, grille 3 lignes)
     14. Kanban restylé (additif, ne casse pas le dnd) — palette vive T5 des
         en-têtes de colonnes + T8 (.cl-kanban-wrap / .cl-kan-nav)
     15. Modale rappel — étape 2 (pictos canal + chips résultat)
     16. T1 — État de chargement du fragment (#clResults.is-loading)
     17. T6 — Modale « verre flottant » (.cl-modal-veil / .cl-modal-panel)
     18. T7 — Modale Relance : segmenté canal, aperçu email/SMS, pied d'actions
============================================================================= */

/* =============================================================================
   1. MESH CHAUD LOCAL
   Même recette que #phaseResults::before (comparateur), tons resserrés à 12 %
   pour rester discret derrière des lattes déjà très blanches.
============================================================================= */
/* La nappe chaude d'en-tête est posée au niveau du SHELL (body), pas de
   #clPage : ce dernier est plafonné à max-w-6xl et <main> porte un
   overflow-x:clip, donc tout halo local resterait borné à la colonne de
   contenu — l'orange se voyait « en boîte ». Le pseudo du shell est
   position:fixed inset:0 0 auto 0 : pleine largeur de page, barre latérale
   comprise. On ne fait qu'amplifier ici la nappe déjà définie par
   extranet-theme.css (body.em-shell::after), scopée à cette page. */
body:has(#clPage)::after {
    height: 560px;
    background:
        radial-gradient(1250px 470px at 74% -14%, color-mix(in srgb, var(--em-primary) 15%, transparent), transparent 64%),
        radial-gradient(950px 400px at 16% -18%, color-mix(in srgb, var(--em-accent) 13%, transparent), transparent 62%);
}

#clPage {
    position: relative;
    /* T5 — Palette vive du funnel Dashboard (funnelPalette de dashboard.php),
       source unique consommée par le badge-select d'étape (§7), les pills
       macro (§10) et les en-têtes de colonnes kanban (§14). Ces 12 hex sont
       explicitement autorisés par le contrat (palette funnel) : ce n'est PAS
       la couleur de marque (--em-primary/--wl-*), donc aucune dérive white
       label ici — la même palette « joyeuse » s'affiche pour tous les
       cabinets, comme sur le Dashboard. */
    --cl-lead-from: #60A5FA;      --cl-lead-to: #6366F1;
    --cl-contact-from: #FF9A76;   --cl-contact-to: #FF5E6D;
    --cl-devis-from: #C48AFC;     --cl-devis-to: #8B5CF6;
    --cl-signature-from: #FDD85E; --cl-signature-to: #F59E0B;
    --cl-gagne-from: #34D399;     --cl-gagne-to: #059669;
    --cl-perdu-from: #94A3B8;     --cl-perdu-to: #64748B;
}
/* Reste du mesh : profondeur froide en pied de liste uniquement (les halos
   chauds du haut vivent désormais sur le shell). Débordé en 100vw pour
   qu'aucune arête ne trahisse la largeur de la colonne ; <main> le rogne. */
#clPage::before {
    content: "";
    position: absolute;
    top: -40px;
    bottom: -40px;
    left: 50%;
    width: 100vw;
    margin-left: -50vw;
    z-index: -1;
    pointer-events: none;
    background: radial-gradient(52% 40% at 50% 104%, rgba(62, 146, 204, .09), transparent 58%);
}

/* =============================================================================
   2. CHROME STICKY
   Verre « chrome » (le plus opaque des 3 recettes) : recherche + filtres +
   en-tête de colonnes collés en haut de viewport pendant le scroll de liste.
============================================================================= */
.cl-chrome {
    position: sticky;
    top: 10px;
    z-index: 40;
    border-radius: var(--em-r-lg);
    padding: 12px 14px;
    margin-bottom: 10px;
    background: rgba(255, 255, 255, .6);
    -webkit-backdrop-filter: blur(22px) saturate(170%);
            backdrop-filter: blur(22px) saturate(170%);
    border: 1px solid rgba(255, 255, 255, .55);
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .85),
        0 12px 30px -14px rgba(14, 42, 61, .26),
        0 2px 6px rgba(14, 42, 61, .05);
}
/* Filet dégradé marque en tête de chrome (pattern .cr-toolbar::after). */
.cl-chrome::after {
    content: "";
    position: absolute;
    top: 0; left: 26px; right: 26px;
    height: 2px;
    border-radius: 999px;
    background: linear-gradient(90deg,
        transparent,
        color-mix(in srgb, var(--em-primary) 55%, transparent),
        color-mix(in srgb, var(--em-accent) 50%, transparent),
        transparent);
}
@supports not (backdrop-filter: blur(1px)) {
    .cl-chrome { background: rgba(255, 255, 255, .95); }
}
@media (max-width: 1023px) {
    .cl-chrome { top: 66px; } /* sous la topbar mobile fixe (pattern comparateur) */
}

/* =============================================================================
   3. TOOLBAR — RECHERCHE & FILTRES
============================================================================= */
.cl-toolbar {
    position: relative;
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: nowrap;
}

.cl-search {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 1 1 220px;
    max-width: 420px;
    min-width: 0;
    padding: 8px 14px;
    border-radius: 999px;
    background: rgba(255, 255, 255, .7);
    border: 1px solid rgba(255, 255, 255, .85);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .9);
}
.cl-search i { color: var(--em-ink-3); font-size: 12px; flex: 0 0 auto; }
.cl-search input {
    flex: 1 1 auto;
    min-width: 0;
    border: 0;
    background: transparent;
    outline: none;
    font-size: 13px;
    font-weight: 600;
    color: var(--em-ink);
}
.cl-search input::placeholder { color: var(--em-ink-3); font-weight: 500; }
.cl-search:focus-within {
    border-color: color-mix(in srgb, var(--em-primary) 45%, #fff);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .9), 0 0 0 3px color-mix(in srgb, var(--em-primary) 16%, transparent);
}

/* Bouton « Filtres » : masqué desktop, seule porte d'entrée mobile. */
.cl-filters-toggle {
    display: none;
    align-items: center;
    gap: 6px;
    flex: 0 0 auto;
    min-height: 34px;
    padding: 6px 12px;
    border-radius: 999px;
    border: 1px solid rgba(14, 42, 61, .12);
    background: rgba(255, 255, 255, .7);
    color: var(--em-ink-2);
    font-size: 12px;
    font-weight: 800;
    cursor: pointer;
    transition: color var(--em-dur-fast) ease, border-color var(--em-dur-fast) ease, background-color var(--em-dur-fast) ease;
}
.cl-filters-toggle[aria-expanded="true"] {
    color: var(--em-primary-deep);
    border-color: color-mix(in srgb, var(--em-primary) 40%, #fff);
    background: color-mix(in srgb, var(--em-primary) 8%, #fff);
}
.cl-filters-toggle:focus-visible { outline: 2px solid var(--em-primary-dark); outline-offset: 2px; }
.cl-filters-n {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    border-radius: 999px;
    background: var(--em-primary);
    color: #fff;
    font-size: 10px;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
}

/* Panneau de filtres : selects natifs (Tom Select les adopte au chargement,
   ce style reste actif pour tout navigateur/état sans JS et pendant la
   fraction de seconde qui précède l'adoption). */
.cl-selects {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}
.cl-selects select {
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    min-height: 34px;
    padding: 6px 26px 6px 11px;
    border-radius: 10px;
    border: 1px solid rgba(14, 42, 61, .12);
    background-color: rgba(255, 255, 255, .7);
    background-image:
        linear-gradient(45deg, transparent 50%, var(--em-ink-3) 50%),
        linear-gradient(135deg, var(--em-ink-3) 50%, transparent 50%);
    background-position: right 14px center, right 10px center;
    background-size: 5px 5px, 5px 5px;
    background-repeat: no-repeat;
    color: var(--em-ink-2);
    font-size: 12px;
    font-weight: 700;
    cursor: pointer;
    outline: none;
    transition: border-color var(--em-dur-fast) ease, box-shadow var(--em-dur-fast) ease;
}
.cl-selects select:focus-visible {
    outline: none;
    border-color: var(--em-primary);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--em-primary) 16%, transparent);
}

/* --- T3 : confort des Tom Select de la toolbar (une fois adoptés) ---------
   Cause racine du chevron qui chevauchait le libellé (« Toutes périodes× ») :
   tom-select.css embarque sa PROPRE règle `.ts-control:not(.rtl){ padding-
   right: max(var(--ts-pr-min), …) !important }` — spécificité 0,2,0 — qui
   l'emporte sur le padding-right voulu par select-theme.css (`.ts-control`
   seul, 0,1,0), et retombe à son fallback `--ts-pr-min:.75rem` (12px) faute
   de plugin clear/caret actif ici. Avec seulement 12px de marge, le texte
   déborde sous le chevron dessiné à right:.95rem. On regagne la spécificité
   nécessaire (3 sélecteurs de classe/pseudo-classe) pour ce composant précis,
   SANS toucher select-theme.css (règle scopée à .cl-selects, cf. contrat). */
.cl-selects .ts-control:not(.rtl) {
    padding-right: 2.35rem !important;
}
.cl-selects .ts-control {
    overflow: hidden;
}
.cl-selects .ts-control > .item {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* Le contrôle ne doit plus pouvoir se faire écraser sous la largeur de son
   texte par le flex-shrink par défaut de .cl-selects : c'est ce rétrécisse-
   ment (combiné à l'overflow:hidden de tom-select) qui rognait le libellé
   pile sous le chevron plutôt que de le laisser passer à la ligne. */
.cl-selects .ts-wrapper {
    flex: 1 1 152px;
    min-width: 140px;
}
/* Défensif (contrat T3) : le plugin clear_button n'est pas enregistré dans
   select-init.js aujourd'hui, donc `.clear-button` n'existe pas encore dans
   le DOM — la règle reste sans effet tant que c'est le cas, et absorbe
   silencieusement toute activation future du plugin sans repasser par CSS. */
.cl-selects .ts-control .clear-button {
    display: none;
}

/* Dropdowns toolbar : confort de lecture + AA garanti par des tokens stables
   (--em-primary-deep n'est PAS dérivé de --wl-*, donc jamais pâle même si la
   palette marque blanche d'un cabinet l'est) plutôt que --dd-accent-strong
   (dérivé --wl-primary-dark, potentiellement clair selon la marque). */
.cl-selects .ts-dropdown {
    min-width: 200px;
}
.cl-selects .ts-dropdown .option,
.cl-selects .ts-dropdown .no-results {
    padding: 10px 12px;
    line-height: 1.35;
}
.cl-selects .ts-dropdown .option:hover,
.cl-selects .ts-dropdown .option.active {
    background: color-mix(in srgb, var(--em-primary) 12%, #fff) !important;
    color: var(--em-primary-deep) !important;
}
.cl-selects .ts-dropdown .option.selected {
    background: color-mix(in srgb, var(--em-primary) 18%, #fff) !important;
    color: var(--em-primary-deep) !important;
    font-weight: 800;
}
.cl-selects .ts-dropdown .option.selected:before {
    border-left-color: var(--em-primary-deep);
    border-bottom-color: var(--em-primary-deep);
}
.cl-selects .ts-dropdown .option.selected.active {
    background: color-mix(in srgb, var(--em-primary) 24%, #fff) !important;
}

@media (max-width: 1023px) {
    .cl-toolbar { flex-wrap: wrap; }
    .cl-search { order: 1; flex: 1 1 100%; max-width: none; }
    .cl-filters-toggle { display: inline-flex; order: 2; min-height: 44px; }

    /* Panneau dépliable : max-height/opacity plutôt que le pattern .cr-slot
       (grid-template-rows 0fr→1fr) — ce dernier exige un unique enfant qui
       enveloppe tout le contenu pour mesurer sa hauteur ; le contrat DOM
       place ici 4 <select> à plat, sans wrapper interne. Comportement et
       accessibilité restent équivalents. */
    #clFiltersPanel.cl-selects {
        order: 3;
        flex: 1 1 100%;
        flex-direction: column;
        align-items: stretch;
        max-height: 0;
        opacity: 0;
        overflow: hidden;
        transition: max-height .35s var(--em-ease), opacity .25s ease;
    }
    #clFiltersPanel.cl-selects.is-open {
        max-height: 640px;
        opacity: 1;
        margin-top: 8px;
    }
    #clFiltersPanel.cl-selects select,
    #clFiltersPanel.cl-selects .ts-wrapper { width: 100%; }
    #clFiltersPanel.cl-selects select { min-height: 44px; }
}
@media (prefers-reduced-motion: reduce) {
    #clFiltersPanel.cl-selects { transition: none; }
}

/* =============================================================================
   4. GRILLE PARTAGÉE — EN-TÊTE / LIGNES
   .cl-head et .cl-row partagent exactement les mêmes pistes de colonnes :
   34px · client · contact · étape · montant · activité · rappel · collab. · actions
============================================================================= */
.cl-head,
.cl-row {
    display: grid;
    /* Les deux pistes souples sont en minmax(0, …) et NON minmax(210px, …) :
       avec un minimum en pixels, la somme des pistes (1146px + marges) dépassait
       la colonne de contenu (max-w-6xl = 1152px) et la dernière cellule — les
       boutons d'action — débordait hors de la latte. À 0, elles absorbent le
       manque et le texte s'ellipse (déjà prévu cellule par cellule). */
    grid-template-columns: 30px minmax(0, 1.5fr) minmax(0, 1.15fr) 170px 92px 84px 116px 40px 112px;
    align-items: center;
    gap: 8px;
}

.cl-head {
    margin: 0 -14px -12px;
    padding: 8px 14px 10px;
    border-top: 1px solid rgba(14, 42, 61, .06);
    font-size: 10.5px;
    font-weight: 800;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--em-ink-3);
}

.cl-list { display: flex; flex-direction: column; }

.cl-row {
    position: relative;
    padding: 10px 14px;
    margin-bottom: 8px;
    border-radius: 14px;
    /* Verre SIMULÉ sans backdrop-filter (perf : dizaines de lattes à l'écran) */
    background: rgba(255, 255, 255, .66);
    border: 1px solid rgba(255, 255, 255, .6);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .8), 0 6px 18px -12px rgba(14, 42, 61, .18);
    transition: background var(--em-dur-fast) ease, transform var(--em-dur) var(--em-ease), box-shadow var(--em-dur) var(--em-ease), z-index var(--em-dur-fast) ease;
    /* T4 : toute la latte ouvre la fiche (JS) sur ses zones neutres — les
       éléments réellement interactifs (liens, boutons, select, checkbox…)
       gardent leur propre curseur (natif ou déjà déclaré plus bas), ce
       pointeur hérité ne les « casse » donc pas. */
    cursor: pointer;
}
.cl-row:hover,
.cl-row:focus-within {
    background: rgba(255, 255, 255, .82);
    transform: translateY(-1px);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .9), 0 14px 30px -16px rgba(14, 42, 61, .24);
}
@media (prefers-reduced-motion: reduce) {
    .cl-row:hover, .cl-row:focus-within { transform: none; }
}

/* --- T2 : empilement du dropdown d'étape au-dessus des lattes suivantes ---
   Cause racine : chaque .cl-row est position:relative avec z-index:auto —
   sans contexte d'empilement propre, l'ordre de peinture suit l'ordre DOM :
   une ligne plus bas dans la liste peint TOUJOURS par-dessus le dropdown
   Tom Select (position:absolute) d'une ligne au-dessus d'elle, même si ce
   dropdown déborde visuellement sous elle. On élève la ligne active au-
   dessus de ses sœurs pendant l'ouverture — :has() en primaire (Safari 16+/
   Chrome 105+/Firefox 121+), classe posée par le JS en repli universel. */
.cl-row:has(.ts-wrapper.dropdown-active) {
    z-index: 60;
}
.cl-row.is-stage-open {
    z-index: 60;
}

.cl-cell { min-width: 0; display: flex; align-items: center; }

/* Colonne Activité masquée <1280px (repli : tooltip sur Montant) — la grille
   perd une piste, l'en-tête et les lignes doivent donc s'aligner ensemble. */
@media (max-width: 1279px) {
    .cl-c-activity { display: none; }
}
@media (min-width: 1024px) and (max-width: 1279px) {
    .cl-head, .cl-row {
        grid-template-columns: 30px minmax(0, 1.5fr) minmax(0, 1.15fr) 170px 92px 116px 40px 112px;
    }
    /* L'en-tête n'a pas de classe dédiée par colonne (contrat §4) : la 6e
       piste (position fixe) est « Activité ». */
    .cl-head > span:nth-child(6) { display: none; }
}

/* =============================================================================
   5. CELLULES COMMUNES
============================================================================= */
.cl-c-check { justify-content: center; }
.cl-check {
    width: 18px;
    height: 18px;
    border-radius: 5px;
    accent-color: var(--em-primary-dark);
    cursor: pointer;
}
.cl-check:focus-visible { outline: 2px solid var(--em-primary-dark); outline-offset: 2px; }

/* Case « tout sélectionner » de l'en-tête de colonnes : même gabarit visuel que
   les cases de ligne (elle vit dans .cl-head, pas dans .cl-row). */
.cl-check-all {
    width: 18px;
    height: 18px;
    border-radius: 5px;
    accent-color: var(--em-primary-dark);
    cursor: pointer;
}
.cl-check-all:focus-visible { outline: 2px solid var(--em-primary-dark); outline-offset: 2px; }

.cl-c-client { gap: 10px; }
.cl-client-txt { min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.cl-name {
    display: block;
    font-size: 13px;
    font-weight: 800;
    color: var(--em-ink);
    text-decoration: none;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
}
.cl-name:hover { color: var(--em-primary-deep); text-decoration: underline; }
.cl-name:focus-visible { outline: 2px solid var(--em-primary-dark); outline-offset: 2px; border-radius: 4px; }
.cl-cotag {
    display: block;
    min-width: 0;
    font-size: 11px;
    font-weight: 700;
    color: var(--em-ink-3);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.cl-c-contact { flex-direction: column; align-items: flex-start; gap: 1px; }
.cl-mail, .cl-tel {
    display: block;
    max-width: 100%;
    font-size: 11.5px;
    font-weight: 600;
    color: var(--em-ink-2);
    text-decoration: none;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.cl-mail:hover, .cl-tel:hover { color: var(--em-primary-deep); text-decoration: underline; }
.cl-mail:focus-visible, .cl-tel:focus-visible { outline: 2px solid var(--em-primary-dark); outline-offset: 2px; }

.cl-c-montant {
    align-items: baseline;
    justify-content: flex-end;
    gap: 3px;
    font-size: 13px;
    font-weight: 800;
    color: var(--em-ink);
    font-variant-numeric: tabular-nums;
    cursor: default;
}
.cl-c-montant small { font-size: 10px; font-weight: 700; color: var(--em-ink-3); }

.cl-c-activity {
    font-size: 11.5px;
    font-weight: 600;
    color: var(--em-ink-2);
    font-variant-numeric: tabular-nums;
    cursor: default;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.cl-c-collab { justify-content: center; }
.cl-collab-av { width: 1.85rem; height: 1.85rem; font-size: .64rem; cursor: default; }

/* =============================================================================
   6. ACTIONS DE LIGNE
   Révélées au survol/focus de la latte (bruit visuel réduit sur une liste
   dense) — toujours visibles au tactile et en mode cartes (§13).
============================================================================= */
.cl-c-actions {
    justify-content: flex-end;
    gap: 6px;
    opacity: .45; /* découvrables au repos (pattern espace_compagnies), pleines au survol */
    transition: opacity var(--em-dur-fast) ease;
}
.cl-row:hover .cl-c-actions,
.cl-row:focus-within .cl-c-actions { opacity: 1; }
.cl-c-actions .em-btn-icon:focus-visible { outline: 2px solid var(--em-primary-dark); outline-offset: 2px; }
.cl-act-relance.is-sending { opacity: .6; pointer-events: none; }

@media (pointer: coarse) {
    .cl-c-actions { opacity: 1; }
}

/* =============================================================================
   7. SELECT-BADGE D'ÉTAPE
   Pastille de teinte + fond dégradé très clair — palette vive du funnel
   Dashboard (T5, tokens §1), distincte de .em-stage (non touché, contrat).
   Couvre le <select> natif (avant adoption Tom Select, anti-flash) ET
   .ts-control (après adoption), avec !important scopé pour gagner sur les
   règles !important globales de select-theme.css (spécificité supérieure :
   3 sélecteurs de classe/attribut contre 1).
============================================================================= */
.cl-stage-wrap {
    position: relative;
    display: flex;
    width: 100%;
    min-width: 0;
    --cl-c: var(--em-muted);
    --cl-t: #334155;
}
/* T5 — palette vive du funnel Dashboard (tokens définis sur #clPage, §1).
   --cl-c reste la teinte « solide » de la table du contrat (pastille, bord,
   chevron) ; --cl-t est cette même teinte assombrie via color-mix (jamais un
   hex de marque, jamais --dd-accent-*) pour garantir le contraste AA du
   texte quel que soit --cl-c — un mélange à 55 % couvre la pire combinaison
   (amber #F59E0B sur fond quasi blanc) avec une marge confortable. */
.cl-stage-wrap[data-macro="lead"] {
    --cl-from: var(--cl-lead-from); --cl-to: var(--cl-lead-to); --cl-c: var(--cl-lead-to);
    --cl-t: color-mix(in srgb, var(--cl-lead-to) 55%, black);
}
.cl-stage-wrap[data-macro="contact"] {
    --cl-from: var(--cl-contact-from); --cl-to: var(--cl-contact-to); --cl-c: var(--cl-contact-to);
    --cl-t: color-mix(in srgb, var(--cl-contact-to) 55%, black);
}
.cl-stage-wrap[data-macro="devis"] {
    --cl-from: var(--cl-devis-from); --cl-to: var(--cl-devis-to); --cl-c: var(--cl-devis-to);
    --cl-t: color-mix(in srgb, var(--cl-devis-to) 55%, black);
}
.cl-stage-wrap[data-macro="signature"] {
    --cl-from: var(--cl-signature-from); --cl-to: var(--cl-signature-to); --cl-c: var(--cl-signature-to);
    --cl-t: color-mix(in srgb, var(--cl-signature-to) 55%, black);
}
.cl-stage-wrap[data-macro="gagne"] {
    --cl-from: var(--cl-gagne-from); --cl-to: var(--cl-gagne-to); --cl-c: var(--cl-gagne-to);
    --cl-t: color-mix(in srgb, var(--cl-gagne-to) 55%, black);
}
.cl-stage-wrap[data-macro="perdu"] {
    --cl-from: var(--cl-perdu-from); --cl-to: var(--cl-perdu-to); --cl-c: var(--cl-perdu-to);
    --cl-t: color-mix(in srgb, var(--cl-perdu-to) 55%, black);
}

/* Pastille ronde 7px, communes aux deux états (natif / Tom Select). T5 : en
   dégradé plein (--cl-from → --cl-to) — décorative (accolée au libellé
   textuel de l'étape), la règle de contraste de texte ne s'applique pas ici,
   la pastille peut donc rester pleinement vive. */
.cl-stage-wrap::before {
    content: "";
    position: absolute;
    left: 11px;
    top: 50%;
    transform: translateY(-50%);
    width: 7px;
    height: 7px;
    border-radius: 999px;
    background: linear-gradient(135deg, var(--cl-from, var(--cl-c)), var(--cl-to, var(--cl-c)));
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--cl-c) 20%, transparent);
    z-index: 2;
    pointer-events: none;
}

/* --- Natif (anti-flash avant adoption Tom Select) --- */
.cl-stage-wrap > select.cl-stage-select {
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    width: 100%;
    min-height: 30px;
    padding: 5px 14px 5px 24px;
    border-radius: 999px;
    border: 1px solid color-mix(in srgb, var(--cl-c) 32%, transparent);
    background: linear-gradient(135deg,
        color-mix(in srgb, var(--cl-from, var(--cl-c)) 14%, #fff),
        color-mix(in srgb, var(--cl-to, var(--cl-c)) 11%, #fff));
    color: var(--cl-t);
    font-family: var(--em-font-sans);
    font-size: 11.5px;
    font-weight: 800;
    cursor: pointer;
    outline: none;
}
.cl-stage-wrap > select.cl-stage-select:focus-visible {
    outline: 2px solid var(--em-primary-dark);
    outline-offset: 2px;
}

/* --- Tom Select adopté --- */
.cl-stage-wrap[data-macro] .ts-wrapper { width: 100%; }
.cl-stage-wrap[data-macro] .ts-control {
    background: linear-gradient(135deg,
        color-mix(in srgb, var(--cl-from, var(--cl-c)) 14%, #fff),
        color-mix(in srgb, var(--cl-to, var(--cl-c)) 11%, #fff)) !important;
    border: 1px solid color-mix(in srgb, var(--cl-c) 32%, transparent) !important;
    border-radius: 999px !important;
    padding: 5px 26px 5px 24px !important;
    min-height: 30px !important;
    box-shadow: none !important;
    color: var(--cl-t) !important;
}
.cl-stage-wrap[data-macro] .ts-control .item,
.cl-stage-wrap[data-macro] .ts-control input {
    font-size: 11.5px !important;
    font-weight: 800 !important;
    color: var(--cl-t) !important;
}
.cl-stage-wrap[data-macro] .ts-control:after {
    border-right-color: color-mix(in srgb, var(--cl-c) 60%, transparent);
    border-bottom-color: color-mix(in srgb, var(--cl-c) 60%, transparent);
    width: 6px;
    height: 6px;
    right: .7rem;
}
.cl-stage-wrap[data-macro] .ts-wrapper.focus .ts-control,
.cl-stage-wrap[data-macro] .ts-wrapper.dropdown-active .ts-control {
    border-color: var(--cl-c) !important;
    background: #fff !important;
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--cl-c) 18%, transparent) !important;
}

/* --- T2 : le dropdown d'étape doit dominer tout le reste de la ligne/liste
   (cf. §4 pour la cause racine côté .cl-row) — appliqué ici en plus, au cas
   où .ts-dropdown venait à être reparenté hors de .cl-row par une future
   option dropdownParent. */
.cl-stage-wrap .ts-dropdown {
    z-index: 70;
}

/* --- T3 : confort + AA du dropdown d'étape --------------------------------
   .ts-dropdown N'HÉRITE PLUS silencieusement du thème global : la capture
   montrait un « ✓ Tarification » illisible (option .selected + .active
   simultanément — TomSelect met en évidence la valeur courante à l'ouverture
   — peintes via --dd-accent-tint/--dd-accent-strong, dérivés white-label,
   potentiellement clairs). On resurcharge ici avec les tokens --cl-c/--cl-t
   déjà garantis AA de CETTE ligne (cohérent avec la couleur du badge), sans
   toucher select-theme.css ni .ts-dropdown en dehors de .cl-stage-wrap. */
.cl-stage-wrap[data-macro] .ts-dropdown {
    min-width: 240px;
    max-width: min(320px, calc(100vw - 24px));
}
.cl-stage-wrap[data-macro] .ts-dropdown .option,
.cl-stage-wrap[data-macro] .ts-dropdown .no-results {
    padding: 10px 12px;
    line-height: 1.35;
    white-space: normal;
}
.cl-stage-wrap[data-macro] .ts-dropdown .optgroup-header {
    padding: 6px 12px 4px;
}
.cl-stage-wrap[data-macro] .ts-dropdown .option:hover,
.cl-stage-wrap[data-macro] .ts-dropdown .option.active {
    background: color-mix(in srgb, var(--cl-c) 14%, #fff) !important;
    color: var(--cl-t) !important;
}
.cl-stage-wrap[data-macro] .ts-dropdown .option.selected {
    background: color-mix(in srgb, var(--cl-c) 20%, #fff) !important;
    color: var(--cl-t) !important;
    font-weight: 800;
}
.cl-stage-wrap[data-macro] .ts-dropdown .option.selected:before {
    border-left-color: var(--cl-t);
    border-bottom-color: var(--cl-t);
}
.cl-stage-wrap[data-macro] .ts-dropdown .option.selected.active {
    background: color-mix(in srgb, var(--cl-c) 26%, #fff) !important;
}
@media (max-width: 1023px) {
    /* La grille en mode cartes réduit .cl-stage-wrap à 44vw (§13) : un
       dropdown figé à 240px déborderait le viewport à 390px. On garde le
       confort de lecture (padding/line-height ci-dessus) mais on laisse la
       largeur suivre le contenu, plafonnée à la fenêtre visible. */
    .cl-stage-wrap[data-macro] .ts-dropdown {
        min-width: 0;
        width: max-content;
        max-width: calc(100vw - 24px);
    }
}

/* --- État sauvegarde (POST set_status_kanban en vol) --- */
.cl-stage-wrap.is-saving { pointer-events: none; }
.cl-stage-wrap.is-saving > select.cl-stage-select,
.cl-stage-wrap.is-saving .ts-control { opacity: .6; }
.cl-stage-wrap.is-saving .ts-control:after { opacity: 0; }
.cl-stage-wrap.is-saving::after {
    content: "";
    position: absolute;
    right: 9px;
    top: 50%;
    width: 12px;
    height: 12px;
    margin-top: -6px;
    border-radius: 50%;
    border: 2px solid color-mix(in srgb, var(--cl-c) 30%, #fff);
    border-top-color: var(--cl-c);
    z-index: 3;
    animation: clSpin .7s linear infinite;
}
@keyframes clSpin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
    .cl-stage-wrap.is-saving::after { animation: none; }
}

/* =============================================================================
   8. CHIPS RAPPEL — 4 ÉTATS
============================================================================= */
.cl-rappel {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 30px;
    padding: 0 12px;
    border-radius: 999px;
    border: 1px solid rgba(255, 255, 255, .7);
    background: rgba(255, 255, 255, .66);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .85), 0 2px 5px rgba(14, 42, 61, .05);
    font-size: 11.5px;
    font-weight: 800;
    color: var(--em-ink-2);
    font-variant-numeric: tabular-nums;
    cursor: pointer;
    white-space: nowrap;
    transition: all .16s var(--em-ease);
}
.cl-rappel i { font-size: 10px; }
.cl-rappel:hover { background: rgba(255, 255, 255, .88); color: var(--em-primary-deep); }
.cl-rappel:focus-visible { outline: 2px solid var(--em-primary-dark); outline-offset: 2px; }

.cl-rappel.is-overdue {
    background: color-mix(in srgb, var(--em-danger) 12%, #fff);
    border-color: color-mix(in srgb, var(--em-danger) 32%, #fff);
    color: var(--em-danger);
    animation: clPulse 2s ease-in-out infinite;
}
.cl-rappel.is-today {
    background: color-mix(in srgb, var(--em-warn) 14%, #fff);
    border-color: color-mix(in srgb, var(--em-warn) 36%, #fff);
    color: color-mix(in srgb, var(--em-warn) 75%, black);
}
.cl-rappel.is-future {
    background: rgba(255, 255, 255, .62);
    border-color: rgba(255, 255, 255, .82);
    color: var(--em-ink-2);
}
.cl-rappel.is-empty {
    background: transparent;
    border: 1.5px dashed rgba(14, 42, 61, .22);
    color: var(--em-ink-3);
    font-weight: 700;
    opacity: .55;
}
.cl-rappel.is-empty:hover {
    opacity: 1;
    color: var(--em-primary-deep);
    border-color: color-mix(in srgb, var(--em-primary) 40%, transparent);
    background: color-mix(in srgb, var(--em-primary) 6%, transparent);
}

@keyframes clPulse {
    0%, 100% { box-shadow: inset 0 1px 0 rgba(255, 255, 255, .85), 0 0 0 0 color-mix(in srgb, var(--em-danger) 35%, transparent); }
    50%      { box-shadow: inset 0 1px 0 rgba(255, 255, 255, .85), 0 0 0 6px transparent; }
}
@media (prefers-reduced-motion: reduce) {
    .cl-rappel.is-overdue { animation: none; }
}

/* =============================================================================
   9. EN-TÊTE DE PAGE
============================================================================= */
.cl-head-actions {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}

.cl-add-menu {
    border: 1px solid rgba(255, 255, 255, .6);
    border-radius: var(--em-r);
    background: rgba(255, 255, 255, .9);
    -webkit-backdrop-filter: blur(18px) saturate(160%);
            backdrop-filter: blur(18px) saturate(160%);
    box-shadow: var(--em-sh-lg);
    padding: .4rem;
    font-size: .82rem;
}
.cl-add-menu .dropdown-item {
    border-radius: .6rem;
    padding: .55rem .7rem;
    font-weight: 600;
    color: var(--em-ink-2);
    display: flex;
    align-items: center;
    gap: .5rem;
}
.cl-add-menu .dropdown-item:hover,
.cl-add-menu .dropdown-item:focus {
    background: color-mix(in srgb, var(--em-primary) 10%, #fff);
    color: var(--em-primary-deep);
}

/* Segmenté Liste | Kanban — pattern .cr-seg */
.cl-viewseg {
    display: inline-flex;
    background: rgba(14, 42, 61, .06);
    border-radius: 999px;
    padding: 3px;
    box-shadow: inset 0 1px 2px rgba(14, 42, 61, .08);
    flex-shrink: 0;
}
.cl-viewseg-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-height: 32px;
    padding: 7px 14px;
    border: none;
    border-radius: 999px;
    background: transparent;
    color: var(--em-ink-2);
    font-size: 12px;
    font-weight: 800;
    text-decoration: none;
    cursor: pointer;
    transition: color var(--em-dur-fast) ease, background-color var(--em-dur-fast) ease;
}
.cl-viewseg-btn:hover:not(.is-on) { color: var(--em-primary-deep); }
.cl-viewseg-btn.is-on,
.cl-viewseg-btn[aria-pressed="true"] {
    background: #fff;
    color: var(--em-primary-deep);
    box-shadow: 0 2px 6px rgba(14, 42, 61, .12);
}
.cl-viewseg-btn:focus-visible { outline: 2px solid var(--em-primary-dark); outline-offset: 2px; }

/* =============================================================================
   10. PILLS MACRO
   Réutilise .em-pill du thème (aucune duplication) — conteneur scroll-x
   sans scrollbar visible pour le mobile.
============================================================================= */
.cl-pills {
    display: flex;
    gap: 4px;
    overflow-x: auto;
    scrollbar-width: none;
    padding: 2px 2px 4px;
    margin-bottom: 4px;
}
.cl-pills::-webkit-scrollbar { display: none; }
/* Compact : les 8-9 pills doivent tenir sur une seule ligne sans scroll,
   même sur un écran large (35 clients → labels + compteurs longs). */
.cl-pills .em-pill {
    flex-shrink: 0;
    gap: .3rem;
    padding: .34rem .6rem;
    font-size: .7rem;
}
.cl-pills .em-pill-count {
    min-width: 1.05rem;
    padding: 0 .3rem;
    font-size: .6rem;
}
/* Teinte par défaut : le sélecteur [data-macro] matche AUSSI data-macro=""
   (pill « Tous ») et data-macro="rappel", qui n'ont pas de couleur d'étape.
   Sans repli, --cl-p reste indéfini, les color-mix deviennent invalides et la
   pill se retrouve délavée (fond et texte perdus). */
.cl-pills .em-pill { --cl-p: var(--em-primary); }
.cl-pills .em-pill[data-macro="rappel"] { --cl-p: var(--em-danger); }

/* Étape vide : présente (le pipeline reste lisible d'un bout à l'autre) mais
   visuellement en retrait. La pill active reste pleinement lisible. */
.cl-pills .em-pill.is-zero { opacity: .55; }
.cl-pills .em-pill.is-zero .em-pill-count { color: var(--em-ink-3); }
.cl-pills .em-pill.is-zero.is-active { opacity: 1; }

/* --- T5 : palette vive du funnel sur les 6 pills macro (tokens §1) --------
   Inactive = teinte claire lisible (même recette que le badge-select : fond
   très clair + texte assombri via color-mix, AA garanti). Active = dégradé
   plein SUR LA TEINTE « to » de la table (déjà la plus saturée/foncée du
   duo) plutôt que from → to bruts : le stop « from » (pastel très clair, ex.
   #FDD85E) ne peut passer aucun contraste AA avec un texte blanc quelle que
   soit la teinte retenue, alors qu'un dégradé to → to-assombri (55 % noir)
   reste fidèle à la couleur de la palette (le stop clair EST la teinte
   « to » du contrat, non altérée) tout en garantissant ≥ 4.5:1 sur toute sa
   surface, y compris pour l'amber (signature) et le corail (contact), les
   deux teintes les plus problématiques testées. */
.cl-pills .em-pill[data-macro="lead"],
.cl-pills .em-pill[data-macro="contact"],
.cl-pills .em-pill[data-macro="devis"],
.cl-pills .em-pill[data-macro="signature"],
.cl-pills .em-pill[data-macro="gagne"],
.cl-pills .em-pill[data-macro="perdu"] {
    border-color: transparent;
}
.cl-pills .em-pill[data-macro="lead"]      { --cl-p: var(--cl-lead-to); }
.cl-pills .em-pill[data-macro="contact"]   { --cl-p: var(--cl-contact-to); }
.cl-pills .em-pill[data-macro="devis"]     { --cl-p: var(--cl-devis-to); }
.cl-pills .em-pill[data-macro="signature"] { --cl-p: var(--cl-signature-to); }
.cl-pills .em-pill[data-macro="gagne"]     { --cl-p: var(--cl-gagne-to); }
.cl-pills .em-pill[data-macro="perdu"]     { --cl-p: var(--cl-perdu-to); }

.cl-pills .em-pill[data-macro]:not(.is-active) {
    background: color-mix(in srgb, var(--cl-p) 14%, #fff);
    color: color-mix(in srgb, var(--cl-p) 55%, black);
}
.cl-pills .em-pill[data-macro]:not(.is-active):hover {
    background: color-mix(in srgb, var(--cl-p) 22%, #fff);
    color: color-mix(in srgb, var(--cl-p) 55%, black);
    border-color: transparent;
    box-shadow: none;
}
.cl-pills .em-pill[data-macro]:not(.is-active) .em-pill-count {
    background: color-mix(in srgb, var(--cl-p) 20%, #fff);
    color: color-mix(in srgb, var(--cl-p) 55%, black);
}

.cl-pills .em-pill[data-macro].is-active {
    background-color: var(--cl-p);
    background-image: linear-gradient(180deg, var(--cl-p) 0%, color-mix(in srgb, var(--cl-p) 55%, black) 100%);
    color: #fff;
    box-shadow: 0 10px 24px -12px color-mix(in srgb, var(--cl-p) 55%, transparent);
}
.cl-pills .em-pill[data-macro].is-active .em-pill-count {
    /* Overlay sombre (pas blanc) : assombrit localement au lieu d'éclaircir,
       le texte blanc du compteur reste lisible quelle que soit la teinte. */
    background: rgba(0, 0, 0, .22);
    color: #fff;
}

/* =============================================================================
   11. BULK BAR FLOTTANTE
============================================================================= */
.cl-bulkbar {
    position: fixed;
    left: 50%;
    bottom: 18px;
    transform: translate(-50%, 0);
    z-index: 50;
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    width: min(760px, calc(100vw - 24px));
    border-radius: 999px;
    padding: 10px 16px;
    background: rgba(255, 255, 255, .6);
    -webkit-backdrop-filter: blur(22px) saturate(170%);
            backdrop-filter: blur(22px) saturate(170%);
    border: 1px solid rgba(255, 255, 255, .55);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .85), 0 20px 50px -16px rgba(14, 42, 61, .35);
    color: var(--em-ink);
}
/* Garde-fou : la bulk bar est montrée/masquée en JS via .hidden (Tailwind) —
   on force l'état masqué quelle que soit la spécificité du CDN Tailwind. */
.cl-bulkbar.hidden { display: none !important; }
@supports not (backdrop-filter: blur(1px)) {
    .cl-bulkbar { background: rgba(255, 255, 255, .95); }
}

/* Compteur « N dossier(s) sélectionné(s) » + ⓘ de portée (vue Globale). */
.cl-bulkbar-count {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    flex: 0 0 auto;
    min-width: 0;
    font-size: 14px;
    font-weight: 900;
    color: var(--em-ink);
    font-variant-numeric: tabular-nums;
}
.cl-bulkbar-label {
    font-size: 12px;
    font-weight: 700;
    color: var(--em-ink-2);
    white-space: nowrap;
}
.cl-bulkbar-info {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 22px;
    height: 22px;
    padding: 0;
    border: 0;
    border-radius: 999px;
    background: rgba(14, 42, 61, .06);
    color: var(--em-ink-3);
    font-size: 11px;
    cursor: help;
    transition: color var(--em-dur-fast) ease, background-color var(--em-dur-fast) ease;
}
.cl-bulkbar-info:hover {
    color: var(--em-primary-deep);
    background: color-mix(in srgb, var(--em-primary) 12%, #fff);
}
.cl-bulkbar-info:focus-visible { outline: 2px solid var(--em-primary-dark); outline-offset: 2px; }

/* Groupe d'actions : poussé à droite, la croix de fermeture reste en bout. */
.cl-bulkbar-actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 8px;
    flex: 1 1 auto;
    flex-wrap: wrap;
    min-width: 0;
}

/* Pilules d'action — même grammaire de verre que .cl-viewseg-btn, cible ≥ 40px. */
.cl-bulk-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-height: 40px;
    padding: 8px 14px;
    border-radius: 999px;
    border: 1px solid rgba(255, 255, 255, .8);
    background: rgba(255, 255, 255, .72);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .9), 0 2px 6px rgba(14, 42, 61, .06);
    color: var(--em-ink-2);
    font-size: 12.5px;
    font-weight: 800;
    line-height: 1;
    white-space: nowrap;
    cursor: pointer;
    transition: color var(--em-dur-fast) ease, background-color var(--em-dur-fast) ease;
}
.cl-bulk-btn:hover,
.cl-bulk-btn[aria-expanded="true"] { color: var(--em-primary-deep); background: #fff; }
.cl-bulk-btn:focus-visible { outline: 2px solid var(--em-primary-dark); outline-offset: 2px; }

.cl-bulk-btn--primary {
    border-color: transparent;
    background-color: var(--em-primary);
    background-image: linear-gradient(180deg, var(--em-primary) 0%, var(--em-primary-dark) 100%);
    color: #fff;
    box-shadow: var(--em-sh-warm);
}
.cl-bulk-btn--primary:hover,
.cl-bulk-btn--primary[aria-expanded="true"] {
    color: #fff;
    background-image: linear-gradient(180deg, var(--em-primary-dark) 0%, var(--em-primary-deep) 100%);
}

.cl-bulk-btn.is-disabled,
.cl-bulk-btn:disabled { opacity: .45; cursor: not-allowed; box-shadow: none; }
.cl-bulk-btn.is-disabled:hover,
.cl-bulk-btn:disabled:hover { color: var(--em-ink-2); background: rgba(255, 255, 255, .72); }

.cl-bulk-caret { font-size: 9px; opacity: .75; }

/* Menus déroulants (statut / assignation) — pattern .cl-add-menu, en dropup. */
.cl-bulk-menu {
    min-width: 232px;
    border: 1px solid rgba(255, 255, 255, .6);
    border-radius: var(--em-r);
    background: rgba(255, 255, 255, .94);
    -webkit-backdrop-filter: blur(18px) saturate(160%);
            backdrop-filter: blur(18px) saturate(160%);
    box-shadow: var(--em-sh-lg);
    padding: .4rem;
    font-size: .82rem;
}
.cl-bulk-menu .dropdown-item {
    display: flex;
    align-items: center;
    gap: .5rem;
    min-height: 40px;
    border-radius: .6rem;
    padding: .55rem .7rem;
    font-weight: 600;
    color: var(--em-ink-2);
    white-space: normal;
}
.cl-bulk-menu .dropdown-item:hover,
.cl-bulk-menu .dropdown-item:focus {
    background: color-mix(in srgb, var(--em-primary) 10%, #fff);
    color: var(--em-primary-deep);
}
/* Rappel inerte « Perte : utilisez le select de la ligne » (motif obligatoire). */
.cl-bulk-menu .dropdown-item.is-disabled,
.cl-bulk-menu .dropdown-item:disabled {
    opacity: .55;
    color: var(--em-ink-3);
    cursor: not-allowed;
    font-weight: 700;
    font-size: .78rem;
}
.cl-bulk-menu .dropdown-item.is-disabled:hover,
.cl-bulk-menu .dropdown-item:disabled:hover {
    background: transparent;
    color: var(--em-ink-3);
}
/* Liste de collaborateurs potentiellement longue : on borne et on scrolle. */
.cl-bulk-menu--tall { max-height: min(46vh, 340px); overflow-y: auto; }

.cl-bulkbar-close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 40px;
    height: 40px;
    border-radius: 999px;
    border: 1px solid rgba(14, 42, 61, .10);
    background: rgba(255, 255, 255, .55);
    color: var(--em-ink-3);
    font-size: 13px;
    cursor: pointer;
    transition: color var(--em-dur-fast) ease, background-color var(--em-dur-fast) ease;
}
.cl-bulkbar-close:hover { color: var(--em-primary-deep); background: #fff; }
.cl-bulkbar-close:focus-visible { outline: 2px solid var(--em-primary-dark); outline-offset: 2px; }

/* ≥768px : la pilule épouse son contenu sur UNE ligne, le ✕ ancré en bout.
   Le groupe d'actions doit aussi passer en nowrap/contenu : sinon il wrappe en
   interne (flex 1 1 auto + wrap) et fait grossir la pilule en hauteur. */
@media (min-width: 768px) {
    .cl-bulkbar {
        flex-wrap: nowrap;
        width: max-content;
        max-width: calc(100vw - 24px);
    }
    .cl-bulkbar-actions {
        flex: 0 0 auto;
        flex-wrap: nowrap;
    }
    .cl-bulkbar-close { margin-left: 2px; }
}

@media (max-width: 767px) {
    .cl-bulkbar {
        left: 0;
        right: 0;
        bottom: 0;
        width: auto;
        border-radius: 18px 18px 0 0;
        padding: 10px 12px calc(10px + env(safe-area-inset-bottom, 0px));
    }
    .cl-bulkbar-count { flex: 1 1 auto; }
    .cl-bulkbar-actions { order: 3; flex: 1 1 100%; justify-content: space-between; }
    .cl-bulk-btn { min-height: 44px; flex: 1 1 auto; justify-content: center; padding: 8px 12px; }
    .cl-bulkbar-actions .dropdown { flex: 1 1 auto; }
    .cl-bulkbar-actions .dropdown .cl-bulk-btn { width: 100%; }
    .cl-bulkbar-close { width: 44px; height: 44px; }
}
@media (max-width: 479px) {
    .cl-bulkbar-label { display: none; }
}

/* =============================================================================
   12. PAGINATION & ÉTAT VIDE
============================================================================= */
/* Boutons de rattrapage de l'état vide (ajouter un client / réinitialiser). */
.cl-empty-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    justify-content: center;
    margin-top: 12px;
}

.cl-pagination-info {
    margin: 0;
    font-size: 12px;
    color: var(--em-ink-3);
}

.cl-pagination {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 14px;
}
.cl-pagination a,
.cl-pagination span {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 36px;
    height: 36px;
    padding: 0 10px;
    border-radius: 999px;
    background: rgba(255, 255, 255, .66);
    border: 1px solid rgba(255, 255, 255, .8);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .85), 0 2px 6px rgba(14, 42, 61, .05);
    font-size: 12.5px;
    font-weight: 800;
    color: var(--em-ink-2);
    text-decoration: none;
    font-variant-numeric: tabular-nums;
    transition: color var(--em-dur-fast) ease, background-color var(--em-dur-fast) ease;
}
.cl-pagination a:hover { color: var(--em-primary-deep); background: rgba(255, 255, 255, .92); }
.cl-pagination a:focus-visible { outline: 2px solid var(--em-primary-dark); outline-offset: 2px; }
.cl-pagination .is-active,
.cl-pagination [aria-current="page"] {
    background-color: var(--em-primary);
    background-image: linear-gradient(180deg, var(--em-primary) 0%, var(--em-primary-dark) 100%);
    color: #fff;
    border-color: transparent;
    box-shadow: var(--em-sh-warm);
}
.cl-pagination .is-disabled { opacity: .4; pointer-events: none; }

/* =============================================================================
   13. MODE CARTES MOBILE (<1024px)
   La grille 9 colonnes devient 3 pistes : [contenu 1fr][secondaire][pilotage],
   3 lignes. Zone gauche = infos client/contact/rappel, zone droite = étape/
   montant/actions. La case rappel+collab de la ligne 3 se répartit sur les
   deux premières pistes pour rester côte à côte (2 zones visuelles malgré
   3 pistes techniques). Checkbox détachée en overlay haut-gauche : elle ne
   consomme pas de piste et reste hors du flux des 2 zones de contenu.
============================================================================= */
@media (max-width: 1023px) {
    .cl-head { display: none; }

    .cl-row {
        position: relative;
        display: grid;
        grid-template-columns: 1fr auto auto;
        grid-auto-rows: auto;
        row-gap: 8px;
        column-gap: 10px;
        padding: 14px 14px 14px 42px;
        align-items: center;
    }

    .cl-c-check {
        position: absolute;
        left: 12px;
        top: 14px;
        justify-content: flex-start;
    }
    .cl-check { width: 20px; height: 20px; }

    .cl-c-client  { grid-column: 1 / span 2; grid-row: 1; }
    .cl-c-stage   { grid-column: 3; grid-row: 1; justify-self: end; }

    .cl-c-contact { grid-column: 1 / span 2; grid-row: 2; }
    .cl-c-montant { grid-column: 3; grid-row: 2; justify-self: end; }

    .cl-c-rappel  { grid-column: 1; grid-row: 3; }
    .cl-c-collab  { grid-column: 2; grid-row: 3; justify-self: start; }
    .cl-c-actions {
        grid-column: 3;
        grid-row: 3;
        justify-self: end;
        opacity: 1; /* toujours visibles en mode cartes (contrat §5) */
    }

    /* La piste `auto` du select prendrait sinon la largeur intrinsèque de la
       plus longue option (~200px) et forcerait la largeur min-content de la
       latte — donc de #clPage entier — au-delà du viewport. */
    .cl-stage-wrap {
        width: 158px;
        min-width: 0;
        max-width: 44vw;
    }
    .cl-stage-wrap select,
    .cl-stage-select,
    .cl-stage-wrap .ts-wrapper,
    .cl-stage-wrap .ts-control {
        width: 100%;
        max-width: 100%;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    /* Cibles ≥ 44px (contrat §5 / §9 critère 6). */
    .cl-c-actions .em-btn-icon,
    .cl-act-relance {
        width: 44px;
        height: 44px;
    }
}

/* Très petits écrans : l'en-tête d'actions se resserre pour tenir sans couper,
   et la carte rend quelques pixels au nom du client (troncature moins agressive). */
@media (max-width: 479px) {
    .cl-head-actions { gap: 8px; }
    .cl-head-actions .em-btn,
    .cl-head-actions .em-btn-ghost { padding-left: 13px; padding-right: 13px; }
    .cl-viewseg-btn { padding: 7px 11px; }

    .cl-row { padding-left: 36px; column-gap: 8px; }
    .cl-c-check { left: 9px; }
    .cl-stage-wrap { width: 146px; }
    .cl-c-client { gap: 8px; }
}

/* =============================================================================
   14. KANBAN RESTYLÉ (additif)
   .em-kanban-* est exclusif à cette page : restylage direct sans scoping par
   #clPage — un ancêtre-ID écraserait par erreur la spécificité des états
   .is-over / .is-dragging déjà définis (classes seules) dans le thème
   partagé. Additions cosmétiques uniquement, le drag & drop n'est pas touché.
============================================================================= */
.em-kanban-col {
    background: rgba(255, 255, 255, .6);
    border-color: rgba(255, 255, 255, .6);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .8), var(--em-sh-sm);
}
.em-kanban-head {
    background: rgba(255, 255, 255, .8);
    -webkit-backdrop-filter: blur(10px) saturate(150%);
            backdrop-filter: blur(10px) saturate(150%);
}
.em-kanban-card {
    background: rgba(255, 255, 255, .68);
    border-color: rgba(255, 255, 255, .6);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .8), 0 6px 18px -12px rgba(14, 42, 61, .18);
}
.em-kanban-card:hover {
    background: rgba(255, 255, 255, .85);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .9), 0 10px 24px -14px rgba(14, 42, 61, .22);
}
@supports not (backdrop-filter: blur(1px)) {
    .em-kanban-col, .em-kanban-head { background: rgba(255, 255, 255, .96); }
}

/* --- T5 : palette vive du funnel sur les en-têtes de colonnes kanban ------
   .em-kanban-col porte déjà data-macro (markup existant, cf. #kanbanBoard).
   On NE touche PAS `.em-stage` seul (règle globale, contrat) : le sélecteur
   composé `.em-kanban-col[data-macro] … .em-stage` est scopé à cette page
   (spécificité bien supérieure à la classe utilitaire seule) et laisse
   `.em-stage` intact partout ailleurs (dashboard/fiche/relances). */
.em-kanban-col[data-macro="lead"]      { --cl-k: var(--cl-lead-to);      --cl-k-from: var(--cl-lead-from); }
.em-kanban-col[data-macro="contact"]   { --cl-k: var(--cl-contact-to);   --cl-k-from: var(--cl-contact-from); }
.em-kanban-col[data-macro="devis"]     { --cl-k: var(--cl-devis-to);     --cl-k-from: var(--cl-devis-from); }
.em-kanban-col[data-macro="signature"] { --cl-k: var(--cl-signature-to); --cl-k-from: var(--cl-signature-from); }
.em-kanban-col[data-macro="gagne"]     { --cl-k: var(--cl-gagne-to);     --cl-k-from: var(--cl-gagne-from); }
.em-kanban-col[data-macro="perdu"]     { --cl-k: var(--cl-perdu-to);     --cl-k-from: var(--cl-perdu-from); }

.em-kanban-col[data-macro] .em-kanban-head {
    position: relative;
}
/* Filet dégradé marque en tête de colonne (pattern .cl-chrome::after),
   identité visuelle immédiate de l'étape sans alourdir le fond verre. */
.em-kanban-col[data-macro] .em-kanban-head::before {
    content: "";
    position: absolute;
    top: 0; left: 14px; right: 14px;
    height: 2px;
    border-radius: 999px;
    background: linear-gradient(90deg, var(--cl-k-from), var(--cl-k));
}
.em-kanban-col[data-macro] .em-kanban-head .em-stage {
    background: linear-gradient(135deg,
        color-mix(in srgb, var(--cl-k-from) 22%, #fff),
        color-mix(in srgb, var(--cl-k) 16%, #fff)) !important;
    color: color-mix(in srgb, var(--cl-k) 55%, black) !important;
    border: 1px solid color-mix(in srgb, var(--cl-k) 30%, transparent);
}
.em-kanban-col[data-macro] .em-kanban-head .em-stage .em-stage-count {
    background: color-mix(in srgb, var(--cl-k) 22%, #fff) !important;
    color: color-mix(in srgb, var(--cl-k) 55%, black) !important;
}

/* =============================================================================
   T8 — KANBAN : NAVIGATION RONDE + ISOLATION DE COLONNE
   .cl-kanban-wrap enveloppe #kanbanBoard + les boutons .cl-kan-prev/.cl-kan-
   next (contrat). Le plateau garde sa largeur pleine ; on réserve un
   « gouttière » de chaque côté pour loger les boutons SANS qu'ils
   chevauchent la première/dernière carte (jamais au-dessus du contenu
   cliquable/glissable).
============================================================================= */
.cl-kanban-wrap {
    position: relative;
    padding: 0 52px;
}
.cl-kan-nav {
    position: absolute;
    /* Centrées sur l'en-tête de colonne (hauteur mesurée en JS, cf. clKanInit),
       PAS sur la hauteur totale du plateau : les colonnes ont des hauteurs très
       inégales selon leur nombre de cartes, y compris hors écran (colonne
       scrollée à droite) — un centrage sur 50% du wrap fait flotter les
       flèches loin des cartes visibles. */
    top: calc(var(--cl-kan-head-h, 3rem) / 2);
    transform: translateY(-50%);
    z-index: 5;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border-radius: 999px;
    border: 1px solid rgba(255, 255, 255, .75);
    background: rgba(255, 255, 255, .72);
    -webkit-backdrop-filter: blur(18px) saturate(170%);
            backdrop-filter: blur(18px) saturate(170%);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .9), 0 10px 24px -14px rgba(14, 42, 61, .28);
    color: var(--em-ink-2);
    font-size: 14px;
    cursor: pointer;
    transition: color var(--em-dur-fast) ease, background-color var(--em-dur-fast) ease,
                box-shadow var(--em-dur-fast) ease, opacity var(--em-dur-fast) ease;
}
.cl-kan-prev { left: 4px; }
.cl-kan-next { right: 4px; }
.cl-kan-nav:hover:not([disabled]) {
    color: var(--em-primary-deep);
    background: #fff;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .95), 0 14px 30px -16px rgba(14, 42, 61, .32);
}
.cl-kan-nav:focus-visible {
    outline: 2px solid var(--em-primary-dark);
    outline-offset: 2px;
}
.cl-kan-nav[disabled] {
    opacity: .35;
    cursor: not-allowed;
    box-shadow: none;
}
/* Masquage total (JS) quand le plateau tient entièrement dans la largeur
   visible : pas de flèches inertes à l'écran. Les deux crochets sont acceptés
   (.is-hidden maison et .hidden de Tailwind) : à spécificité égale, l'ordre
   d'injection du CDN Tailwind n'est pas garanti face à ce fichier, donc on
   remporte l'arbitrage explicitement. */
.cl-kan-nav.is-hidden,
.cl-kan-nav.hidden,
.cl-kan-nav[hidden] {
    display: none;
}
@supports not (backdrop-filter: blur(1px)) {
    .cl-kan-nav { background: rgba(255, 255, 255, .96); }
}
/* Gouttière de 52px conservée à toutes les largeurs (contrat T8 : cibles
   ≥ 44px partout) : la réduire sur mobile ferait chevaucher les boutons avec
   les cartes de la première/dernière colonne — jamais au-dessus du contenu
   glissable/cliquable. Le plateau lui-même reste défilable horizontalement
   dans sa fenêtre réduite (comportement kanban normal, ne crée aucun scroll
   horizontal au niveau de la PAGE — seul le plateau interne défile). */

/* =============================================================================
   15. MODALE RAPPEL — ÉTAPE 2 (canal + résultat facultatifs)
   Groupes de boutons à état aria-pressed, pilotés par clients-cockpit.js.
   Cibles ≥ 40px, sélection = teinte marque, focus visibles.
============================================================================= */
.cl-picto-group,
.cl-chip-group {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}
.cl-picto-btn,
.cl-chip-btn {
    border: 1px solid var(--em-line-2);
    background: var(--em-surface-2);
    color: var(--em-ink-2);
    border-radius: 12px;
    min-height: 40px;
    cursor: pointer;
    transition: background var(--em-dur-fast) var(--em-ease),
                border-color var(--em-dur-fast) var(--em-ease),
                color var(--em-dur-fast) var(--em-ease);
}
.cl-picto-btn {
    flex: 1 1 0;
    min-width: 40px;
    font-size: 14px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.cl-chip-btn {
    padding: 0 12px;
    font-size: 12px;
    font-weight: 700;
}
.cl-picto-btn:hover,
.cl-chip-btn:hover {
    border-color: color-mix(in srgb, var(--em-primary) 45%, transparent);
    color: var(--em-primary-deep);
}
.cl-picto-btn[aria-pressed="true"],
.cl-chip-btn[aria-pressed="true"] {
    background: color-mix(in srgb, var(--em-primary) 12%, #fff);
    border-color: color-mix(in srgb, var(--em-primary) 55%, transparent);
    color: var(--em-primary-deep);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .8);
}
.cl-picto-btn:focus-visible,
.cl-chip-btn:focus-visible {
    outline: 2px solid var(--em-primary-dark);
    outline-offset: 1px;
}

/* =============================================================================
   16. T1 — ÉTAT DE CHARGEMENT DU FRAGMENT (#clResults.is-loading)
   Le filtrage devient instantané (JS, fetch fragment) : retour visuel léger
   pendant l'attente réseau, jamais d'écran mort (repli JS : navigation
   normale si le fetch échoue, hors périmètre CSS).
============================================================================= */
#clResults {
    transition: opacity var(--em-dur-fast) ease;
}
#clResults.is-loading {
    opacity: .55;
    pointer-events: none;
}
@media (prefers-reduced-motion: reduce) {
    #clResults { transition: none; }
}

/* =============================================================================
   17. T6 — MODALE « VERRE FLOTTANT » (#rappelModal et modales apparentées)
   Contrat : voile .cl-modal-veil, panneau .cl-modal-panel.cl-glass-float,
   en-tête/corps/pied .cl-modal-head/.cl-modal-body/.cl-modal-foot. Recette
   identique à .cr-glass-float du comparateur (spec cockpit §7.1, même
   valeurs) : rgba(255,255,255,.75), blur(26px) saturate(180%), spéculaire
   inset, ombre profonde, filet dégradé marque, radius 20 (--em-r-lg).
   Générique : réutilisée telle quelle par la modale Relance (§18, T7).
============================================================================= */
.cl-modal-veil {
    position: absolute;
    inset: 0;
    background: color-mix(in srgb, var(--em-ink) 45%, transparent);
    -webkit-backdrop-filter: blur(6px);
            backdrop-filter: blur(6px);
    cursor: pointer;
}
@supports not (backdrop-filter: blur(1px)) {
    .cl-modal-veil { background: color-mix(in srgb, var(--em-ink) 72%, transparent); }
}

.cl-modal-panel.cl-glass-float {
    position: relative;
    background: rgba(255, 255, 255, .75);
    -webkit-backdrop-filter: blur(26px) saturate(180%);
            backdrop-filter: blur(26px) saturate(180%);
    border: 1px solid rgba(255, 255, 255, .7);
    border-radius: var(--em-r-lg);
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .85),
        0 30px 70px -22px rgba(14, 42, 61, .45),
        0 4px 12px rgba(14, 42, 61, .08);
    overflow: hidden;
    animation: clModalPanelIn .28s var(--em-ease);
}
/* Filet dégradé marque en tête (pattern .cl-chrome::after / .cr-toolbar::after). */
.cl-modal-panel.cl-glass-float::before {
    content: "";
    position: absolute;
    top: 0; left: 24px; right: 24px;
    height: 2px;
    border-radius: 999px;
    z-index: 1;
    background: linear-gradient(90deg,
        transparent,
        color-mix(in srgb, var(--em-primary) 55%, transparent),
        color-mix(in srgb, var(--em-accent) 50%, transparent),
        transparent);
}
@supports not (backdrop-filter: blur(1px)) {
    .cl-modal-panel.cl-glass-float { background: rgba(255, 255, 255, .97); }
}
@keyframes clModalPanelIn {
    from { opacity: 0; transform: translateY(10px) scale(.98); }
    to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
    .cl-modal-panel.cl-glass-float { animation: none; }
}

.cl-modal-head {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 16px 20px 14px;
    border-bottom: 1px solid rgba(14, 42, 61, .08);
}
.cl-modal-head h3,
.cl-modal-head .cl-modal-title {
    margin: 0;
    font-size: 14.5px;
    font-weight: 800;
    color: var(--em-ink);
}
.cl-modal-body {
    padding: 18px 20px;
    display: flex;
    flex-direction: column;
    gap: 14px;
    max-height: min(72vh, 640px);
    overflow-y: auto;
}
.cl-modal-body select,
.cl-modal-body .ts-wrapper {
    width: 100%;
}
.cl-modal-foot {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 14px 20px calc(14px + env(safe-area-inset-bottom, 0px));
    border-top: 1px solid rgba(14, 42, 61, .08);
}
.cl-modal-foot > * { flex: 1 1 0; }
.cl-modal-foot [disabled] {
    opacity: .5;
    cursor: not-allowed;
    box-shadow: none;
    pointer-events: none;
}

/* =============================================================================
   18. T7 — MODALE RELANCE : CANAL, APERÇU RÉEL, PIED D'ACTIONS
   Même famille de verre que §17 (le panneau réutilise .cl-modal-panel
   .cl-glass-float — contrat "#msgModal conservé"). Ici : le segmenté canal,
   la ligne destinataires, le cadre d'aperçu (email en iframe / SMS en bulle)
   et les états du pied d'actions.
============================================================================= */

/* --- Segmenté canal (.cl-canal-seg) — pouce glissant -------------------------
   SUR LA CLASSE, PAS SUR L'ID. Cette règle était scopée #msgCanalSeg, l'id de
   la seule modale de clients.php ; la modale de relances.php porte le même
   composant sous l'id #relCanalSeg et se retrouvait donc SANS AUCUN style —
   deux boutons noirs nus. Les deux écrans posent .cl-canal-seg : la classe est
   le seul sélecteur qui les couvre tous les deux.

   Le pouce est un ::before piloté en CSS pur par :has() sur le bouton .is-on —
   le JS existant (clients-cockpit.js, relances.php) se contente de basculer
   cette classe, aucun des deux n'a besoin d'être touché. Même mécanique et
   mêmes variables que .em-seg-toggle du thème (padding 3px, largeur
   calc(50% - 3px), translateX(100%)), pour que la bascule glisse ici comme
   partout ailleurs dans l'extranet. */
.cl-canal-seg {
    position: relative;
    display: grid;
    grid-template-columns: 1fr 1fr;
    /* Centré : c'est le premier élément de la modale, il ne s'aligne sur rien
       à sa gauche. width:max-content pour que la grille 1fr 1fr se dimensionne
       sur le plus large des deux libellés, pas sur toute la largeur du corps. */
    width: max-content;
    margin-inline: auto;
    /* Pas de gap : le pouce fait exactement calc(50% - 3px) et se déplace de
       100% de sa propre largeur — une gouttière décalerait la colonne 2 sans
       décaler le pouce, et il s'arrêterait à côté du libellé. */
    padding: 3px;
    background: rgba(14, 42, 61, .06);
    border-radius: 999px;
    box-shadow: inset 0 1px 2px rgba(14, 42, 61, .08);
}
.cl-canal-seg::before {
    content: "";
    position: absolute;
    z-index: 0;
    top: 3px; bottom: 3px; left: 3px;
    width: calc(50% - 3px);
    background-image: linear-gradient(180deg, var(--em-primary) 0%, var(--em-primary-dark) 100%);
    border-radius: 999px;
    box-shadow: var(--em-sh-warm);
    transform: translateX(0);
    transition: transform var(--em-dur, .28s) cubic-bezier(.4, 0, .2, 1);
    pointer-events: none;
}
.cl-canal-seg:has(.cl-canal-btn[data-canal="sms"].is-on)::before { transform: translateX(100%); }
.cl-canal-btn {
    position: relative;
    z-index: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    min-height: 38px;
    padding: 8px 18px;
    border: none;
    border-radius: 999px;
    background: transparent;
    color: var(--em-ink-3);
    font-size: 12.5px;
    font-weight: 800;
    cursor: pointer;
    transition: color var(--em-dur-fast) ease;
}
.cl-canal-btn:hover:not(:disabled):not(.is-on) { color: var(--em-ink-2); }
/* Le libellé actif passe en blanc : il est posé SUR le pouce coloré. */
.cl-canal-btn.is-on { color: #fff; }
.cl-canal-btn:disabled,
.cl-canal-btn.is-disabled,
.cl-canal-btn[aria-disabled="true"] {
    opacity: .45;
    cursor: not-allowed;
    color: var(--em-ink-3);
}
.cl-canal-btn:focus-visible {
    outline: 2px solid var(--em-primary-dark);
    outline-offset: 2px;
}
@media (prefers-reduced-motion: reduce) {
    .cl-canal-seg::before { transition: none; }
}

/* --- Ligne destinataires discrète (« N destinataire(s) · aperçu sur … ») - */
.cl-msg-dest {
    font-size: 11.5px;
    font-weight: 600;
    color: var(--em-ink-3);
}
.cl-msg-dest strong { color: var(--em-ink-2); font-weight: 800; }

/* --- Aperçu (#msgPreview) : cadre verre + iframe email blanche lisible --- */
#msgPreview {
    display: flex;
    flex-direction: column;
    gap: 8px;
}
#msgPreviewEmail, #msgPreviewSms {
    border-radius: 14px;
    border: 1px solid rgba(255, 255, 255, .75);
    background: rgba(255, 255, 255, .55);
    -webkit-backdrop-filter: blur(14px) saturate(160%);
            backdrop-filter: blur(14px) saturate(160%);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .85), 0 8px 20px -14px rgba(14, 42, 61, .2);
    padding: 10px;
}
@supports not (backdrop-filter: blur(1px)) {
    #msgPreviewEmail, #msgPreviewSms { background: rgba(255, 255, 255, .94); }
}
.cl-msg-subject {
    padding: 0 2px 8px;
    margin-bottom: 8px;
    border-bottom: 1px solid rgba(14, 42, 61, .08);
    font-size: 12.5px;
    font-weight: 800;
    color: var(--em-ink);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
#msgPreviewFrame {
    display: block;
    width: 100%;
    min-height: 380px;
    border: 0;
    border-radius: 10px;
    background: #fff;
}

/* --- Aperçu SMS : bulle façon messagerie + compteur ---------------------- */
.cl-sms-bubble {
    position: relative;
    max-width: 78%;
    margin: 6px 0 6px 4px;
    padding: 10px 13px;
    border-radius: 16px 16px 16px 4px;
    background: #fff;
    border: 1px solid rgba(14, 42, 61, .08);
    box-shadow: 0 2px 6px rgba(14, 42, 61, .06);
    font-size: 13px;
    line-height: 1.4;
    color: var(--em-ink);
    white-space: pre-wrap;
    word-break: break-word;
}
.cl-sms-count {
    text-align: right;
    font-size: 11px;
    font-weight: 700;
    color: var(--em-ink-3);
    font-variant-numeric: tabular-nums;
}
.cl-sms-count.is-over {
    color: var(--em-danger);
}
