/* =========================================================================
   PC-ERP — Design system "Pacific Editorial"
   Direction : éditorial / refined / pacific. Serif déplacée pour les titres,
   sans-serif technique pour le corps, accent terre brûlée comme contrepoint
   au bleu marine du logo. Densité contrôlée, tabular-nums sur les montants.
   ========================================================================= */

/* Fonts — chargées via <link rel="preload"> dans le layout pour éviter le FOUT.
   Fallbacks system stack pour que rien ne casse si la requête CDN échoue. */

:root {
    --control-height: 2.5rem;
    /* === Couleurs : marque PC + accent terre brûlée === */
    --color-primary:       #204B75;
    --color-primary-hover: #2B5E8F;
    --color-primary-dark:  #163654;
    --color-primary-ultra: #F3F7FB;
    --color-primary-soft:  #E2EBF4;
    --color-primary-text:  var(--color-primary-dark);
    --color-focus-ring:    var(--color-primary);

    /* Accent éditorial : terre cuite chaude (NC, lagune, soleil sans cliché) */
    --color-accent:        #C8623A;
    --color-accent-hover:  #B05530;
    --color-accent-soft:   #FBEEE6;

    --color-secondary:     #807D7D;
    --color-secondary-light:#ECEBEB;

    --color-success:       #2E8B57;
    --color-success-hover: #267548;
    --color-success-dark:  #1E7842;  /* texte sur fond -soft */
    --color-success-soft:  #E5F4EA;
    --color-warning:       #C99A2E;
    --color-warning-hover: #A87D1F;
    --color-warning-dark:  #7D5E15;  /* texte sur fond -soft */
    --color-warning-soft:  #FBF2DF;
    --color-danger:        #B33A3A;
    --color-danger-hover:  #962F2F;
    --color-danger-dark:   #7E2828;  /* texte sur fond -soft */
    --color-danger-soft:   #F9E5E5;
    --color-info:          #1E78C2;
    --color-info-hover:    #195F9C;
    --color-info-dark:     #13547F;  /* texte sur fond -soft */
    --color-info-soft:     #E1F0FB;

    /* Textes sur fonds pleins, distincts des couleurs de texte semantiques. */
    --color-on-solid:      #FFFFFF;
    --color-on-warning:    #0F141B;
    --color-success-solid:#287B4D;

    --color-text:          #1A2332;
    --color-text-soft:     #4A5566;
    --color-text-muted:    #626F80;
    --color-border:        #E2E6EC;
    --color-border-soft:   #EEF0F4;
    --color-control-border:#808A99;
    --color-bg:            #F5F7FA;
    --color-bg-subtle:     #FAFBFC;
    --color-surface:       #FFFFFF;
    --color-field-bg:      var(--color-surface);
    --color-overlay:       rgba(15, 23, 42, 0.55);  /* scrim des modales (backdrop) */

    /* === Sprint S6 — Aliases legacy (Tailwind/Bootstrap) ===
       Conservés à l'identique pour compat visuelle, mais permettent l'audit
       et la migration progressive. À terme : préférer les tokens sémantiques. */
    --color-gray-50:   #f8fafc;
    --color-gray-100:  #f1f5f9;
    --color-gray-200:  #e2e8f0;
    --color-gray-300:  #cbd5e1;
    --color-gray-400:  #94a3b8;
    --color-gray-500:  #64748b;
    --color-gray-600:  #475569;
    --color-gray-700:  #334155;
    --color-gray-800:  #1e293b;
    --color-gray-900:  #0f172a;
    /* Bootstrap legacy gray (101 occurrences): */
    --color-gray-bs:   #6c757d;

    /* === Échelle border-radius === */
    --radius-xs:  3px;
    --radius-sm:  4px;
    --radius:     6px;
    --radius-md:  8px;     /* sprint S6: combler le gap 6→10 (cards, badges) */
    --radius-lg:  10px;
    --radius-2xl: 12px;    /* sprint S6: combler le gap 10→16 (modales mid-size) */
    --radius-xl:  16px;
    --radius-pill: 999px;

    /* Courbes d'easing (design engineering, Emil Kowalski) : les easings CSS par défaut sont
       trop faibles — ces courbes donnent du « punch » aux micro-interactions. ease-out pour
       l'entrée/feedback (démarre vite = réactif), ease-in-out pour un déplacement sur l'écran. */
    --ease-out:    cubic-bezier(0.23, 1, 0.32, 1);
    --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);

    /* === Ombres : plus subtiles, teintées primary === */
    --shadow-xs: 0 1px 2px rgba(22, 54, 84, 0.04);
    --shadow-sm: 0 1px 3px rgba(22, 54, 84, 0.06), 0 1px 2px rgba(22, 54, 84, 0.04);
    --shadow:    0 4px 12px rgba(22, 54, 84, 0.07), 0 2px 4px rgba(22, 54, 84, 0.04);
    /* [ux-lot1] Alias du jeton d'ombre « moyen » (menus déroulants Ventes/Achats) :
       il était référencé (var(--shadow-md)) sans jamais être défini. */
    --shadow-md: 0 4px 12px rgba(22, 54, 84, 0.07), 0 2px 4px rgba(22, 54, 84, 0.04);
    --shadow-lg: 0 16px 32px rgba(22, 54, 84, 0.10), 0 4px 8px rgba(22, 54, 84, 0.05);
    --shadow-inset: inset 0 1px 0 rgba(255, 255, 255, .6);

    /* === Échelle d'espacement (4px base) === */
    --sp-0:    0;
    --sp-px:   1px;     /* hairline borders */
    --sp-0-5:  2px;     /* sprint S6: micro-padding (badges) */
    --sp-1:    4px;
    --sp-1-5:  6px;     /* sprint S6: badges, chips compacts */
    --sp-2:    8px;
    --sp-2-5:  10px;    /* sprint S6: padding inputs/buttons standard ERP (168 occurrences) */
    --sp-3:    12px;
    --sp-3-5:  14px;    /* sprint S6: cellules table denses */
    --sp-4:    16px;
    --sp-5:    20px;
    --sp-6:    24px;
    --sp-7:    32px;
    --sp-8:    40px;
    --sp-8-5:  48px;    /* sprint S6: empty-state, modal headers */
    --sp-9:    56px;
    --sp-10:   72px;
    --sp-11:   96px;    /* sprint S6: hero sections */

    /* === Échelle typographique (rem) === */
    --text-xs:   0.75rem;     /* 12px — meta, labels secondaires */
    --text-sm:   0.8125rem;   /* 13px — texte secondaire */
    --text-base: 0.875rem;    /* 14px — corps de texte (par défaut body) */
    --text-md:   0.9375rem;   /* 15px — texte légèrement plus grand */
    --text-lg:   1rem;        /* 16px — H4 */
    --text-xl:   1.125rem;    /* 18px — H3 */
    --text-2xl:  1.375rem;    /* 22px — H2 */
    --text-3xl:  1.75rem;     /* 28px — H1 */
    --text-4xl:  2.25rem;     /* 36px — Display KPI */
    --text-5xl:  3rem;        /* 48px — Display large */

    /* === Polices ===
       Une seule police sans-serif sur tout l'ERP : Geist Sans (Vercel).
       Lisible, moderne, dense, parfaite pour les UIs métier.
       Geist Mono pour les références (FAC-XXX, RIDET, codes). */
    --font-display: "Geist", system-ui, -apple-system, "Segoe UI", "Helvetica Neue", sans-serif;
    --font-body:    "Geist", system-ui, -apple-system, "Segoe UI", "Helvetica Neue", sans-serif;
    --font-mono:    "Geist Mono", ui-monospace, SFMono-Regular, "SF Mono", Consolas, Menlo, monospace;
    /* Alias historique conservé pour rétro-compat */
    --font-sans:    var(--font-body);

    /* === Layout === */
    --header-h: 60px;
    --sidebar-w: 260px;
}

*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
html { scroll-behavior: smooth; }
body {
    font-family: var(--font-body);
    font-size: var(--text-base);
    line-height: 1.55;
    color: var(--color-text);
    background: var(--color-bg);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    font-feature-settings: "ss01", "ss02", "cv11";
    text-rendering: optimizeLegibility;
}

/* === Titres : Geist Sans (même police que le corps), poids varié ===
   - Une seule police pour tout l'ERP → cohérence et lisibilité maximale
   - Hiérarchie marquée par taille + poids + letter-spacing serré
   - Pas de variations exotiques type optical sizing : sobriété + perf */
h1, h2, h3, h4, h5 {
    margin: 0 0 var(--sp-3);
    color: var(--color-text);
    font-family: var(--font-body);
    font-weight: 600;
    line-height: 1.2;
    letter-spacing: -0.015em;
}
h1 {
    font-size: var(--text-3xl);
    font-weight: 700;
    letter-spacing: -0.025em;
}
h2 {
    font-size: var(--text-2xl);
    font-weight: 600;
    letter-spacing: -0.02em;
}
h3 {
    font-size: var(--text-xl);
    font-weight: 600;
    letter-spacing: -0.01em;
}
h4 { font-size: var(--text-lg); font-weight: 600; letter-spacing: -0.005em; }
h5 { font-size: var(--text-base); font-weight: 600; letter-spacing: 0; text-transform: uppercase; color: var(--color-text-soft); }

p { margin: 0 0 var(--sp-3); }
a { color: var(--color-primary); text-decoration: none; transition: color .15s var(--ease-out); }
a:hover { color: var(--color-primary-hover); text-decoration: underline; }

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--color-border); border-radius: 5px; border: 2px solid var(--color-bg); }
::-webkit-scrollbar-thumb:hover { background: var(--color-text-muted); }

/* ============ Layout ============ */
.container { max-width: min(96vw, 2400px); margin: 0 auto; padding: var(--sp-6); }
.layout {
    display: grid;
    grid-template-columns: var(--sidebar-w) 1fr;
    min-height: calc(100vh - var(--header-h));
}
.main-content { padding: var(--sp-6); max-width: 100%; overflow-x: hidden; }

/* ============ Header ============ */
.app-header {
    position: sticky; top: 0; z-index: 40;
    height: var(--header-h);
    display: flex; align-items: center; gap: var(--sp-4);
    padding: 0 var(--sp-5);
    background: var(--color-surface);
    border-bottom: 1px solid var(--color-border);
}
.app-header .menu-toggle {
    display: none;
    background: none; border: none; cursor: pointer;
    padding: 8px; color: var(--color-text-soft);
    border-radius: var(--radius-sm);
}
.app-header .menu-toggle:hover { background: var(--color-bg); color: var(--color-primary); }

.app-header .brand {
    display: flex; align-items: center; gap: var(--sp-3);
    font-weight: 700; font-size: 1.05rem;
    color: var(--color-primary);
    text-decoration: none;
}
.app-header .brand:hover { text-decoration: none; }
/* ⭐ FIX 2026-06-26 — préserver le ratio aspect du logo client (companies.logo_path peut être rectangulaire). Avant : width:34 height:34 → logo écrasé/étiré. */
.app-header .brand-logo { width: auto; height: 34px; max-width: 80px; flex-shrink: 0; object-fit: contain; }
.app-header .brand-text { color: var(--color-primary-dark); font-weight: 700; letter-spacing: -0.01em; }
.app-header .brand-accent { color: var(--color-primary); font-weight: 500; }

.header-spacer { flex: 1; }

.app-header .user { display: flex; align-items: center; gap: var(--sp-2); }
.app-header .icon-btn {
    display: inline-flex; align-items: center; justify-content: center;
    width: 36px; height: 36px;
    background: transparent; border: none;
    border-radius: var(--radius);
    color: var(--color-text-soft);
    cursor: pointer; transition: all .15s;
    text-decoration: none;
}
.app-header .icon-btn:hover { background: var(--color-primary-soft); color: var(--color-primary); }

/* ============ Header : quick-links / search / suite-switcher ============ */
.header-quick-links {
    display: flex; align-items: center; gap: 4px;
    margin-left: var(--sp-2);
}

.header-search {
    position: relative;
    flex: 0 1 320px;
    max-width: 380px;
    margin: 0 var(--sp-3);
}
.header-search-icon {
    position: absolute; left: 10px; top: 50%; transform: translateY(-50%);
    color: var(--color-text-muted); pointer-events: none;
}
.header-search input[type="search"] {
    width: 100%;
    padding: 7px 12px 7px 32px;
    font-size: .85rem;
    color: var(--color-text);
    background: var(--color-bg-subtle);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    outline: none;
    transition: all .15s;
}
.header-search input[type="search"]:focus {
    background: var(--color-surface);
    border-color: var(--color-primary);
    box-shadow: 0 0 0 3px var(--color-primary-soft);
}

.header-suite-switcher {
    display: flex; align-items: center; gap: 4px;
    margin-right: var(--sp-2);
}
.suite-btn {
    display: inline-flex; align-items: center;
    padding: 5px 10px;
    font-size: .78rem; font-weight: 600;
    color: var(--color-text-soft);
    background: var(--color-bg-subtle);
    border: 1px solid transparent;
    border-radius: var(--radius);
    text-decoration: none;
    transition: all .12s;
}
.suite-btn:hover { text-decoration: none; filter: brightness(.96); }
.suite-btn--gestion  { color: #2A4F76; background: #EEF3F9; }
.suite-btn--compta   { color: #2B6648; background: #ECF5EF; }
.suite-btn--caisse   { color: #A0512B; background: #FBEFE6; }
.suite-btn--rh-paie  { color: #6B4C95; background: #F4ECFA; }
.suite-btn--fleet    { color: #3A4654; background: #ECEFF3; }
.suite-btn--gestion.active { color: #163654; background: #E2EBF4; border-color: #C9D7E6; }
.suite-btn--compta.active  { color: #154E32; background: #DCEEE3; border-color: #B5DBC2; }
.suite-btn--caisse.active  { color: #8B3411; background: #FBE4D7; border-color: #F2C5A8; }
.suite-btn--rh-paie.active { color: #4D2F73; background: #ECE0F7; border-color: #D3BFE6; }
.suite-btn--fleet.active   { color: #232E3A; background: #DBE0E7; border-color: #BCC5D1; }

/* Mobile : on cache search + suite-switcher pour gagner de la place
 * F19 fix Sprint S5 : breakpoints harmonisés sur scale Tailwind standard
 * sm=640 / md=768 / lg=1024 / xl=1280 / 2xl=1536 */
@media (max-width: 1024px) {
    .header-search, .header-suite-switcher { display: none; }
}
@media (max-width: 768px) {
    .header-quick-links { display: none; }
}

.company-selector {
    padding: 7px 32px 7px 14px;
    font-size: .85rem; font-weight: 600;
    color: var(--color-primary-dark);
    background: var(--color-primary-soft);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23204B75' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
    background-repeat: no-repeat; background-position: right 10px center;
    border: 1px solid var(--color-primary-soft);
    border-radius: var(--radius);
    cursor: pointer;
    max-width: 220px;
    appearance: none;
}
.company-selector:hover { border-color: var(--color-primary); }
.company-badge {
    padding: 7px 14px;
    font-size: .85rem; font-weight: 600;
    color: var(--color-primary-dark);
    background: var(--color-primary-soft);
    border-radius: var(--radius);
}

/* ============ Sidebar ============ */
.sidebar {
    position: sticky;
    top: var(--header-h);
    height: calc(100vh - var(--header-h));
    background: var(--color-surface);
    border-right: 1px solid var(--color-border);
    overflow-y: auto;
    z-index: 30;
}
.sidebar-nav { padding: var(--sp-4) var(--sp-3); }
.sidebar-section { margin-bottom: var(--sp-2); }
.sidebar-dashboard { margin-bottom: var(--sp-3); padding-bottom: var(--sp-3); border-bottom: 1px solid var(--color-border-soft); }

/* Bloc contextuel "Dossier client" — cabinet comptable externe (cf. partials/sidebar.php.tpl) */
.sidebar-audit-block {
    padding: var(--sp-3);
    margin: var(--sp-2);
    background: var(--color-primary-soft);
    border-radius: var(--radius);
    color: var(--color-primary-dark);
}
.sidebar-audit-block__label {
    margin: 0 0 var(--sp-1) 0;
    font-size: .625rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--color-primary-dark);
}
.sidebar-audit-block__name {
    margin: 0 0 var(--sp-1) 0;
    font-size: .8125rem;
    font-weight: 600;
    color: var(--color-primary-dark);
}
.sidebar-audit-block__ridet {
    margin: 0 0 var(--sp-2) 0;
    font-size: .625rem;
    font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
    color: var(--color-text-muted);
}
.sidebar-audit-block__switch {
    width: 100%;
    text-align: center;
}
.sidebar-section h4 {
    font-size: .7rem; font-weight: 600;
    color: var(--color-text-muted);
    text-transform: uppercase; letter-spacing: 0.08em;
    margin: 0 var(--sp-3) var(--sp-2); padding: 0;
}

/* ===== Super-sections (C8 2026-10-10) : « Mon activité » vs « Administration » =====
   Simple libellé de regroupement au-dessus des groupes rétractables. Plus petit et
   plus espacé que les en-têtes de groupe pour rester lisible comme niveau supérieur. */
.sidebar-group-label {
    font-size: .64rem; font-weight: 700;
    color: var(--color-text-muted);
    text-transform: uppercase; letter-spacing: 0.12em;
    margin: var(--sp-2) var(--sp-3) var(--sp-1); padding: 0;
    user-select: none;
}
.sidebar-group-label--divider {
    margin-top: var(--sp-4);
    padding-top: var(--sp-3);
    border-top: 1px solid var(--color-border-soft);
}

/* ===== Sections rétractables ===== */
.sidebar-collapsible { margin-bottom: 2px; }

.sidebar-section-header {
    /* Bouton plein-largeur, look identique à un sidebar-item mais sans padding-left du chevron */
    display: flex; align-items: center; gap: 10px;
    width: 100%;
    padding: 8px 12px;
    margin: 1px 0;
    background: transparent;
    border: 0;
    text-align: left;
    cursor: pointer;
    font-family: inherit;
    font-size: .82rem; font-weight: 600;
    color: var(--color-text-muted);
    text-transform: uppercase; letter-spacing: 0.05em;
    border-radius: var(--radius);
    transition: background .12s, color .12s;
}
.sidebar-section-header:hover {
    background: var(--color-primary-ultra);
    color: var(--color-primary-dark);
}
.sidebar-section-header svg { flex-shrink: 0; opacity: .7; transition: opacity .15s, transform .2s; }
.sidebar-section-header:hover svg { opacity: 1; }
.sidebar-section-header span { flex: 1; min-width: 0; }
.sidebar-section-header .chevron {
    margin-left: auto;
    opacity: .55;
    transition: transform .25s ease;
}
.sidebar-collapsible.is-open > .sidebar-section-header .chevron {
    transform: rotate(180deg);
}

/* Container des items : animation max-height + opacité */
.sidebar-section-items {
    max-height: 0;
    overflow: hidden;
    opacity: 0;
    margin-left: 14px;            /* indentation visuelle des sous-items */
    border-left: 1px solid var(--color-border-soft);
    padding-left: 6px;
    transition: max-height .28s ease, opacity .15s ease, margin-bottom .15s ease;
    margin-bottom: 0;
}
.sidebar-collapsible.is-open > .sidebar-section-items {
    /* Couvre les sections à 20+ entrées (Settings) sans tronquer silencieusement.
       Le scroll est géré par .sidebar (overflow-y: auto) — c'est la sidebar
       entière qui scrolle, pas la section individuelle. */
    max-height: 1500px;
    opacity: 1;
    margin-bottom: var(--sp-2);
}

/* Section avec un item actif → bandeau coloré sur le header pour repérage */
.sidebar-collapsible:has(.sidebar-item.active) > .sidebar-section-header {
    color: var(--color-primary-dark);
    background: var(--color-primary-soft);
}
.sidebar-collapsible:has(.sidebar-item.active) > .sidebar-section-header svg {
    opacity: 1; color: var(--color-primary);
}
.sidebar-item {
    display: flex; align-items: center; gap: 10px;
    padding: 8px 12px;
    margin: 2px 0;
    font-size: .875rem; font-weight: 500;
    color: var(--color-text-soft);
    border-radius: var(--radius);
    text-decoration: none;
    transition: all .15s;
    position: relative;
    cursor: pointer; /* fix : force pointer (override de tout cursor: help hérité) */
}
/* Phase 4 hotfix : reset cursor sur tous les conteneurs de menu (sidebar app + menu POS + drawer) */
.sidebar, .sidebar *,
.pos-sidebar, .pos-sidebar *,
.pos-menu, .pos-menu *,
.pos-nav, .pos-nav *,
nav, nav *,
[role="navigation"], [role="navigation"] *,
[role="menu"], [role="menu"] *,
.menu, .menu * { cursor: default !important; }

.sidebar a, .sidebar button,
.pos-sidebar a, .pos-sidebar button,
.pos-menu a, .pos-menu button,
.pos-nav a, .pos-nav button,
nav a, nav button,
[role="navigation"] a, [role="navigation"] button,
[role="menu"] a, [role="menu"] button,
.menu a, .menu button { cursor: pointer !important; }

.sidebar input, .sidebar textarea,
.pos-sidebar input, .pos-sidebar textarea,
nav input, nav textarea,
[role="navigation"] input, [role="navigation"] textarea { cursor: text !important; }
.sidebar-item svg { flex-shrink: 0; opacity: .7; transition: opacity .15s; }
.sidebar-item:hover {
    background: var(--color-primary-ultra);
    color: var(--color-primary-dark);
    text-decoration: none;
}
.sidebar-item:hover svg { opacity: 1; }
.sidebar-item.active {
    background: var(--color-primary-soft);
    color: var(--color-primary-dark);
    font-weight: 600;
}
.sidebar-item.active svg { color: var(--color-primary); opacity: 1; }
.sidebar-item.active::before {
    content: '';
    position: absolute; left: 0; top: 20%; bottom: 20%;
    width: 3px; background: var(--color-primary);
    border-radius: 0 3px 3px 0;
}

/* Overlay cliquable pour fermer la sidebar mobile. Tint primary + blur léger
   plutôt que noir opaque pour rester cohérent avec le thème. */
.sidebar-overlay {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(22, 54, 84, 0.4);
    backdrop-filter: blur(2px);
    z-index: 60;
    cursor: pointer;
}

/* Mobile sidebar drawer (F19 : harmonisé lg breakpoint Tailwind = 1024) */
@media (max-width: 1023px) {
    /* Note : 1023 (max-width = lg-1) intentionnel pour rester strict sous 1024 (lg) */
    :root { --sidebar-w: 0px; }
    .app-header .menu-toggle { display: inline-flex; }
    .app-header .brand-text { display: none; }
    .layout { grid-template-columns: 1fr; }
    .sidebar {
        position: fixed;
        top: var(--header-h); left: 0;
        width: 280px;
        height: calc(100vh - var(--header-h));
        transform: translateX(-100%);
        transition: transform .25s ease-out;
        box-shadow: var(--shadow-lg);
        z-index: 70;
    }
    body.sidebar-open .sidebar { transform: translateX(0); }
    body.sidebar-open .sidebar-overlay { display: block; }
    body.sidebar-open { overflow: hidden; }
    .main-content { padding: var(--sp-4); }
    .company-selector { max-width: 140px; font-size: .8rem; padding: 6px 24px 6px 10px; }
}

/* ============ Cards ============ */
.card {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    padding: var(--sp-5);
    box-shadow: var(--shadow-xs);
    margin-bottom: var(--sp-4);
    transition: box-shadow .2s var(--ease-out);
}
.card:hover { box-shadow: var(--shadow-sm); }
.card-header {
    display: flex; justify-content: space-between; align-items: center;
    gap: var(--sp-3); margin-bottom: var(--sp-4);
}
.card-header h2, .card-header h3 { margin: 0; }

/* ============ Forms ============ */
.form-group { margin-bottom: var(--sp-4); }
.form-group label {
    display: block; font-weight: 500; font-size: .875rem;
    color: var(--color-text-soft); margin-bottom: 6px;
}
.form-control,
input[type=text], input[type=email], input[type=password], input[type=number],
input[type=date], input[type=datetime-local], input[type=time], input[type=tel],
input[type=url], input[type=search], input[type=file],
select, textarea {
    display: block; width: 100%;
    padding: 8px 12px;
    font: inherit; font-size: .925rem;
    line-height: 1.4;
    color: var(--color-text);
    background: var(--color-field-bg);
    border: 1px solid var(--color-control-border);
    border-radius: var(--radius);
    transition: border-color .15s, box-shadow .15s;
    appearance: none;
    -webkit-appearance: none;
    box-sizing: border-box;
}
/* Aligner les inputs sur la hauteur des boutons (38px) pour un rythme vertical
   constant en formulaire/barre de filtres. textarea reste auto. */
input[type=text], input[type=email], input[type=password], input[type=number],
input[type=date], input[type=datetime-local], input[type=time], input[type=tel],
input[type=url], input[type=search], input[type=file],
select { min-height: 38px; }
/* [UX020] Boutons "nus" (sans .btn) dans formulaires / barres de filtres :
   forcent 38px + alignement vertical center, sinon ils flottent au-dessus
   ou au-dessous des inputs dans les layouts horizontaux (form-group--inline,
   .filters, .filter-bar, .form-actions). Les .btn restent prioritaires car
   plus spécifiques (.btn { min-height: 38px } défini plus bas). */
.form-group button:not(.btn):not(.btn-icon),
.form-group input[type=submit]:not(.btn),
.form-group input[type=button]:not(.btn),
.form-group input[type=reset]:not(.btn),
.filters button:not(.btn):not(.btn-icon),
.filters input[type=submit]:not(.btn),
.filters input[type=button]:not(.btn),
.filters input[type=reset]:not(.btn),
.filter-bar button:not(.btn):not(.btn-icon),
.filter-bar input[type=submit]:not(.btn),
.filter-bar input[type=button]:not(.btn),
.filter-bar input[type=reset]:not(.btn),
.filter-grid button:not(.btn):not(.btn-icon),
.filter-grid input[type=submit]:not(.btn),
.filter-grid input[type=button]:not(.btn),
.filter-grid input[type=reset]:not(.btn),
.form-actions button:not(.btn):not(.btn-icon),
.form-actions input[type=submit]:not(.btn),
.form-actions input[type=button]:not(.btn),
.form-actions input[type=reset]:not(.btn) {
    min-height: 38px;
    vertical-align: middle;
    box-sizing: border-box;
}
/* Conteneurs inline (filtres horizontaux + form-group--inline) :
   align-items center garantit l'alignement vertical entre inputs 38px,
   boutons 38px, checkbox/radio (plus petits) et labels. */
.form-group--inline,
.filters,
.filter-bar,
.form-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sp-3);
}
/* Checkbox / radio en ligne : alignés sur la baseline visuelle des inputs */
.form-group--inline input[type=checkbox],
.form-group--inline input[type=radio],
.filters input[type=checkbox],
.filters input[type=radio] {
    vertical-align: middle;
    margin: 0;
}
/* Empêche Safari/Webkit d'imposer une apparence native sur les recherches/dates */
input[type=search]::-webkit-search-decoration,
input[type=search]::-webkit-search-cancel-button,
input[type=search]::-webkit-search-results-button,
input[type=search]::-webkit-search-results-decoration { -webkit-appearance: none; }
input[type=date]::-webkit-calendar-picker-indicator { cursor: pointer; opacity: .6; }
textarea { resize: vertical; min-height: 80px; }
select {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%238892A0' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
    background-repeat: no-repeat; background-position: right 12px center;
    padding-right: 36px;
}
.form-control:hover:not(:disabled), input:hover:not(:disabled), select:hover:not(:disabled), textarea:hover:not(:disabled) { border-color: var(--color-text-muted); }
.form-control:focus, input:focus, select:focus, textarea:focus {
    outline: 2px solid var(--color-focus-ring); outline-offset: 2px;
    border-color: var(--color-focus-ring);
}
.form-control:disabled, input:disabled, select:disabled, textarea:disabled {
    background-color: var(--color-bg-subtle); color: var(--color-text-muted);
    border-color: var(--color-border); cursor: not-allowed; opacity: 1;
    -webkit-text-fill-color: currentColor;
}
.form-control::placeholder, input::placeholder, textarea::placeholder { color: var(--color-text-muted); opacity: 1; }
.form-error { color: var(--color-danger); font-size: .8rem; margin-top: 4px; }
.form-help { color: var(--color-text-muted); font-size: .8rem; margin-top: 4px; }

input[type=checkbox], input[type=radio] {
    appearance: auto; width: 16px; height: 16px;
    margin: 0 6px 0 0; vertical-align: middle;
    accent-color: var(--color-primary);
}

/* ============ Buttons ============
   Contrat de couleur :
     - fonds pleins : texte adapte au theme via --color-on-solid
     - warning : texte sombre ; secondary : texte de la surface
   Hauteur : pilotée par `min-height` pour que tous les boutons d'une même
   variante soient strictement alignés, indépendamment du contenu (icône,
   texte court, label long sur 1 ligne).
*/
.btn {
    --btn-color: var(--color-on-primary, var(--color-on-solid));
    --btn-bg: var(--color-primary);
    --btn-hover-bg: var(--color-primary-hover);
    --btn-border: var(--btn-bg);
    --btn-hover-border: var(--btn-hover-bg);
    display: inline-flex; align-items: center; justify-content: center; gap: 6px;
    min-height: var(--control-height);
    padding: 0 18px;
    font-family: inherit; font-size: .9rem; font-weight: 600; line-height: 1.3;
    color: var(--btn-color);
    background: var(--btn-bg);
    border: 1px solid var(--btn-border);
    border-radius: var(--radius);
    cursor: pointer; transition: background-color .15s var(--ease-out), border-color .15s var(--ease-out), box-shadow .15s var(--ease-out), transform .15s var(--ease-out);
    text-decoration: none; white-space: nowrap;
    box-shadow: var(--shadow-xs);
    vertical-align: middle;
}
.btn:hover:where(:not(:disabled):not([aria-disabled="true"]):not(.disabled):not([aria-busy="true"])) {
    background: var(--btn-hover-bg); border-color: var(--btn-hover-border);
    color: var(--btn-color); text-decoration: none;
    transform: translateY(-1px); box-shadow: var(--shadow-sm);
}
.btn:active { transform: translateY(0); box-shadow: var(--shadow-xs); }
.btn:focus-visible { outline: 2px solid var(--color-focus-ring); outline-offset: 2px; }

/* [ux-lot1] État « occupé » anti-double-soumission : après confirmation d'un
   form[data-confirm], le JS (app.js) pose aria-busy="true" + disabled sur le
   bouton d'envoi pour empêcher la double émission (facture / écriture / mail).
   Un fin spinner remplace visuellement l'action le temps de la requête. */
.btn[aria-busy="true"],
button[aria-busy="true"],
[type="submit"][aria-busy="true"] {
    cursor: progress;
    opacity: .75;
    pointer-events: none;
}
.btn[aria-busy="true"]::before,
button[aria-busy="true"]:not(.btn)::before {
    content: "";
    width: 0.85em; height: 0.85em;
    margin-right: 0.5em;
    border: 2px solid currentColor;
    border-top-color: transparent;
    border-radius: 50%;
    display: inline-block;
    vertical-align: -0.1em;
    animation: pc-spin .6s linear infinite;
}
@keyframes pc-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
    .btn[aria-busy="true"]::before,
    button[aria-busy="true"]:not(.btn)::before { animation-duration: 1.6s; }
}

.btn.secondary {
    --btn-color: var(--color-text);
    --btn-bg: var(--color-surface);
    --btn-hover-bg: var(--color-primary-ultra);
    --btn-border: var(--color-control-border);
    --btn-hover-border: var(--color-focus-ring);
}
.btn.success { --btn-color: var(--color-on-solid); --btn-bg: var(--color-success-solid); --btn-hover-bg: var(--color-success-hover); }
.btn.danger  { --btn-color: var(--color-on-solid); --btn-bg: var(--color-danger); --btn-hover-bg: var(--color-danger-hover); }
.btn.warning {
    --btn-color: var(--color-on-warning);
    --btn-bg: var(--color-warning); --btn-hover-bg: var(--color-warning-hover);
}
.btn.info    { --btn-color: var(--color-on-solid); --btn-bg: var(--color-info); --btn-hover-bg: var(--color-info-hover); }

/* Tailles — chaque variante fixe min-height pour uniformité visuelle */
.btn.sm,
.btn.small { min-height: 32px; padding: 0 12px; font-size: .8rem; }
.btn.xs    { min-height: 26px; padding: 0 10px; font-size: .72rem; gap: 4px; }
.btn.lg    { min-height: 44px; padding: 0 24px; font-size: 1rem; }

/* Alias : .btn.primary == .btn par défaut */
.btn.primary {
    --btn-color: var(--color-on-primary, var(--color-on-solid));
    --btn-bg: var(--color-primary); --btn-hover-bg: var(--color-primary-hover);
}

/* Garde-fou de contraste — les sélecteurs spécifiques à <a> et <button>
   battent les overrides ambiants (table.data a, body a, etc.).
   Inclut <input type=submit/button> qui ne sont pas couverts par button.btn. */
a.btn,
a.btn:hover,
a.btn:visited,
button.btn,
input[type="submit"].btn,
input[type="button"].btn,
input[type="reset"].btn { color: var(--btn-color); }

a.btn:hover { text-decoration: none; }

.btn:is(:disabled, [aria-disabled="true"], .disabled) {
    --btn-color: var(--color-text-muted);
    --btn-bg: var(--color-bg-subtle);
    --btn-border: var(--color-border);
    cursor: not-allowed; box-shadow: none; transform: none;
}

/* Groupe de boutons-toggles (ex: HT / TTC) — même hauteur que .btn */
.btn-toggle-group {
    display: inline-flex;
    align-items: stretch;
    min-height: var(--control-height);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    overflow: hidden;
    background: var(--color-surface);
    box-shadow: var(--shadow-xs);
    line-height: 1.3;
}
.btn-toggle-group .btn-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: calc(var(--control-height) - 2px);
    padding: 0 16px;
    font-family: inherit;
    font-size: .9rem;
    font-weight: 600;
    line-height: 1.3;
    color: var(--color-text);
    background: transparent;
    border: 0;
    cursor: pointer;
    transition: background .15s, color .15s;
    white-space: nowrap;
}
.btn-toggle-group .btn-toggle + .btn-toggle {
    border-left: 1px solid var(--color-border);
}
.btn-toggle-group .btn-toggle:hover {
    background: var(--color-bg-subtle);
}
.btn-toggle-group .btn-toggle.active {
    background: var(--color-primary);
    color: var(--color-on-primary, var(--color-on-solid));
}
/* L'outline reste a l'interieur du groupe, qui masque le debordement. */
.btn-toggle-group .btn-toggle:focus-visible { outline-offset: -3px; }
.btn-toggle-group .btn-toggle.active:focus-visible { outline-color: var(--color-on-primary, var(--color-on-solid)); }
.btn-toggle-group .btn-toggle.active + .btn-toggle,
.btn-toggle-group .btn-toggle:has(+ .active),
.btn-toggle-group:has(.active) .btn-toggle.active { border-left-color: var(--color-primary); }

/* ============ Alerts ============ */
.alert {
    padding: 12px 16px;
    border-radius: var(--radius);
    margin-bottom: var(--sp-4);
    font-size: .9rem;
    border-left: 4px solid;
}
.alert.success { background: var(--color-success-soft); color: var(--color-success-dark); border-color: var(--color-success); }
.alert.error   { background: var(--color-danger-soft);  color: var(--color-danger-dark);  border-color: var(--color-danger); }
.alert.warning { background: var(--color-warning-soft); color: var(--color-warning-dark); border-color: var(--color-warning); }
.alert.info    { background: var(--color-info-soft);    color: var(--color-info-dark);    border-color: var(--color-info); }

/* =====================================================
   Tables — densité contrôlée, tabular-nums systématique
   sur les colonnes numériques, ligne hover plus subtile.
   ===================================================== */
table.data {
    width: 100%;
    background: var(--color-surface);
    border-collapse: collapse;
    font-size: var(--text-base);
    font-feature-settings: "ss01", "cv11";
}
table.data thead th {
    padding: var(--sp-3) var(--sp-4);
    text-align: left;
    font-size: var(--text-xs); font-weight: 600;
    color: var(--color-text-muted);
    text-transform: uppercase; letter-spacing: 0.08em;
    background: var(--color-bg-subtle);
    border-bottom: 1px solid var(--color-border);
    white-space: nowrap;
}
table.data tbody td {
    padding: var(--sp-3) var(--sp-4);
    border-bottom: 1px solid var(--color-border-soft);
    vertical-align: middle;
}
table.data tbody tr:last-child td { border-bottom: none; }
table.data tbody tr { transition: background-color .12s; }
table.data tbody tr:nth-child(even) { background: var(--color-bg-subtle); }
table.data tbody tr:hover { background: var(--color-primary-ultra); }
table.data .num,
table.data th.num { text-align: right; font-variant-numeric: tabular-nums; }
/* Colonne de sélection (case à cocher injectée par app.js) : la contraindre à sa
   largeur de contenu, sinon elle absorbe tout l'espace libre quand la somme des
   largeurs de colonnes est < 100% (gros vide avant la 1re colonne de données). */
table.data th.col-select,
table.data td.col-select { width: 1%; white-space: nowrap; text-align: center; padding-left: 8px; padding-right: 4px; }
table.data .font-mono { font-family: var(--font-mono); font-size: var(--text-sm); letter-spacing: -0.01em; }
/* Exclure .btn : table.data a est plus spécifique que a.btn et écraserait le
   color: #fff du bouton (bug visible : "Modifier" en texte sombre sur fond bleu
   à l'intérieur d'une cellule de tableau). */
table.data a:not(.btn) { color: var(--color-text); font-weight: 500; }
table.data a:not(.btn):hover { color: var(--color-primary-text); }

/* =====================================================
   Page header — entête standardisé sur toutes les pages
   <header class="page-header">
       <div class="page-header-titles">
           <p class="page-header-eyebrow">Ventes</p>
           <h1>Factures</h1>
       </div>
       <div class="page-header-actions"> ... </div>
   </header>
   ===================================================== */
.page-header {
    display: flex;
    justify-content: space-between;
    align-items: flex-end;
    gap: var(--sp-4);
    margin-bottom: var(--sp-6);
    padding-bottom: var(--sp-4);
    border-bottom: 1px solid var(--color-border-soft);
}
.page-header-titles { min-width: 0; }
.page-header-eyebrow {
    margin: 0 0 var(--sp-1);
    font-size: var(--text-xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--color-accent);
    font-feature-settings: "ss01";
}
.page-header h1 {
    margin: 0;
    font-size: var(--text-3xl);
    font-family: var(--font-body);
    font-weight: 700;
    letter-spacing: -0.025em;
    line-height: 1.1;
}
.page-header-subtitle {
    margin: var(--sp-2) 0 0;
    color: var(--color-text-soft);
    font-size: var(--text-md);
    max-width: 60ch;
}
.page-header-actions {
    display: flex; gap: var(--sp-2); align-items: center;
    flex-wrap: wrap; flex-shrink: 0;
}
@media (max-width: 768px) {
    .page-header { flex-direction: column; align-items: flex-start; }
    .page-header h1 { font-size: var(--text-2xl); }
}

/* ============ Badges ============ */
.badge {
    display: inline-flex; align-items: center;
    padding: 3px 10px;
    font-size: .72rem; font-weight: 600;
    color: var(--color-text-soft);
    background: var(--color-bg-subtle);
    border: 1px solid var(--color-border-soft);
    border-radius: 12px;
    text-transform: uppercase; letter-spacing: 0.03em;
}
.badge.success { color: var(--color-success-dark); background: var(--color-success-soft); border-color: transparent; }
.badge.warning { color: var(--color-warning-dark); background: var(--color-warning-soft); border-color: transparent; }
.badge.danger  { color: var(--color-danger-dark);  background: var(--color-danger-soft);  border-color: transparent; }
.badge.info    { color: var(--color-primary-text); background: var(--color-primary-soft); border-color: transparent; }

/* =====================================================
   KPIs — direction éditoriale : valeur en serif Fraunces,
   label en small-caps technique. Bord coloré conservé mais
   plus fin, traitement plus discret pour densité de lecture.
   ===================================================== */
.kpi-grid {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
    gap: var(--sp-4); margin-bottom: var(--sp-5);
}
.kpi {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    padding: var(--sp-5);
    transition: transform .2s var(--ease-out), box-shadow .2s var(--ease-out), border-color .2s var(--ease-out);
    position: relative; overflow: hidden;
}
.kpi:hover { transform: translateY(-1px); box-shadow: var(--shadow); border-color: var(--color-primary-soft); }
.kpi::before {
    content: ''; position: absolute; top: 0; left: 0; right: 0; height: 2px;
    background: var(--color-primary);
    opacity: .7;
}
.kpi.accent::before { background: var(--color-accent); }
.kpi .label {
    font-size: var(--text-xs); font-weight: 600;
    color: var(--color-text-muted);
    text-transform: uppercase; letter-spacing: 0.08em;
    font-feature-settings: "ss01";
}
.kpi .value {
    font-family: var(--font-body);
    font-size: var(--text-4xl); font-weight: 700;
    color: var(--color-text);
    margin-top: var(--sp-2); line-height: 1;
    letter-spacing: -0.03em;
    font-variant-numeric: tabular-nums;
}
.kpi .delta {
    display: inline-flex; align-items: center; gap: 4px;
    font-size: var(--text-xs); font-weight: 600;
    margin-top: var(--sp-1);
}
.kpi .delta.up { color: var(--color-success); }
.kpi .delta.down { color: var(--color-danger); }

/* ============ Utilities ============ */
.flex { display: flex; }
.flex-col { flex-direction: column; }
.gap-1 { gap: var(--sp-1); } .gap-2 { gap: var(--sp-2); }
.gap-3 { gap: var(--sp-3); } .gap-4 { gap: var(--sp-4); }
.items-center { align-items: center; } .items-start { align-items: flex-start; }
.justify-between { justify-content: space-between; } .justify-center { justify-content: center; }
.text-muted { color: var(--color-text-muted); }
/* [ux-integration] Utilitaires de couleur de texte sémantiques : employés par ~13 templates
   sans être définis (même logique que --shadow-md). Les jetons -dark sont ADAPTATIFS
   (sombres en thème clair, clairs en thème sombre), donc lisibles dans les deux modes.
   text-error == text-danger (pas de jeton error distinct). */
.text-success { color: var(--color-success-dark); }
.text-danger,
.text-error   { color: var(--color-danger-dark); }
.text-warning { color: var(--color-warning-dark); }
.text-sm { font-size: .8rem; } .text-xs { font-size: .72rem; }
.text-lg { font-size: 1rem; }
.text-right { text-align: right; } .text-center { text-align: center; }
.font-mono { font-family: var(--font-mono); font-size: 92%; }
.font-bold { font-weight: 700; }
.mt-1 { margin-top: var(--sp-1); } .mt-2 { margin-top: var(--sp-2); }
.mt-3 { margin-top: var(--sp-3); } .mt-4 { margin-top: var(--sp-4); }
.mb-1 { margin-bottom: var(--sp-1); } .mb-2 { margin-bottom: var(--sp-2); }
.mb-3 { margin-bottom: var(--sp-3); } .mb-4 { margin-bottom: var(--sp-4); }
.hidden { display: none; }
.w-full { width: 100%; }

/* ============ Help link inline ============ */
.help-link {
    display: inline-flex; align-items: center; gap: 4px;
    font-size: .78rem; font-weight: 500;
    color: var(--color-primary);
    padding: 3px 10px;
    border-radius: 12px;
    background: var(--color-primary-soft);
    text-decoration: none;
    vertical-align: middle;
    transition: all .15s;
}
.help-link:hover { background: var(--color-primary); color: #fff; text-decoration: none; }
.help-link::before { content: "?"; font-weight: 700; }

/* Les anciens en-tetes ont trois enfants : titre, aide, actions.
   Garder l'aide pres du titre plutot que la distribuer au centre. */
.flex.justify-between:has(> h1 + .help-link) {
    flex-wrap: wrap;
    justify-content: flex-start;
    gap: var(--sp-2) var(--sp-3);
    align-items: center;
}
.flex.justify-between:has(> h1 + .help-link) > h1 {
    min-width: 0;
    /* Reserve du libelle Aide, de son padding et de l'espace entre les deux. */
    max-width: calc(100% - 2rem - 40px);
    margin: 0;
    overflow-wrap: anywhere;
    letter-spacing: 0;
}
.flex.justify-between > h1 + .help-link {
    flex-shrink: 0;
    margin-inline-end: auto;
    white-space: nowrap;
}
.flex.justify-between:has(> h1 + .help-link) > .help-link + * {
    min-width: 0;
    max-width: 100%;
    margin-inline-start: auto;
}
.flex.justify-between:has(> h1 + .help-link) > .help-link + .flex {
    flex-wrap: wrap;
    justify-content: flex-end;
}
@media (max-width: 768px) {
    .flex.justify-between:has(> h1 + .help-link) > .help-link + * {
        flex-basis: 100%;
        margin-inline-start: 0;
    }
    .flex.justify-between:has(> h1 + .help-link) > .help-link + .flex {
        justify-content: flex-start;
    }
}

/* ============ Help-tip badge (partial partials.help_tip) ============
   Badge "?" cliquable à côté des labels KPI / titres de cards. Ouvre un
   popover via Alpine x-teleport (cf. resources/views/partials/help_tip.php.tpl).
   Classe distincte de .help-link (lien externe) et .help-tip (notice astuce). */
.pcerp-help-tip {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 16px;
    height: 16px;
    margin-left: 6px;
    border-radius: 50%;
    background: var(--color-primary-soft);
    color: var(--color-primary-dark);
    font-size: 0.7rem;
    font-weight: 700;
    line-height: 1;
    cursor: help;
    user-select: none;
    vertical-align: middle;
    transition: background-color .15s, color .15s, transform .15s;
}
.pcerp-help-tip:hover {
    background: var(--color-primary);
    color: #fff;
}
.pcerp-help-tip:focus-visible {
    outline: 2px solid var(--color-primary);
    outline-offset: 2px;
    background: var(--color-primary);
    color: #fff;
}

.pcerp-help-tip-popover {
    position: fixed;
    z-index: 9999;
    max-width: 280px;
    width: max-content;
    padding: var(--sp-2) var(--sp-3);
    background: var(--color-surface);
    color: var(--color-text);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm, 6px);
    box-shadow: 0 6px 20px rgba(20, 30, 50, 0.12), 0 2px 6px rgba(20, 30, 50, 0.06);
    font-size: 0.8rem;
    line-height: 1.5;
    font-weight: 400;
    cursor: default;
    user-select: text;
}
.pcerp-help-tip-popover::before {
    content: "";
    position: absolute;
    top: -6px;
    left: 50%;
    transform: translateX(-50%) rotate(45deg);
    width: 10px;
    height: 10px;
    background: var(--color-surface);
    border-top: 1px solid var(--color-border);
    border-left: 1px solid var(--color-border);
}
.pcerp-help-tip-popover-flip::before {
    top: auto;
    bottom: -6px;
    border-top: none;
    border-left: none;
    border-bottom: 1px solid var(--color-border);
    border-right: 1px solid var(--color-border);
}

/* ============ Login ============ */
.login-wrapper {
    min-height: 100vh;
    display: flex; align-items: center; justify-content: center;
    background: linear-gradient(135deg, var(--color-primary-ultra) 0%, #FFFFFF 100%);
    padding: var(--sp-5);
    position: relative;
}
.login-wrapper::before {
    content: '';
    position: absolute; top: 0; left: 0; right: 0; bottom: 0;
    background: radial-gradient(ellipse at top, rgba(32, 75, 117, 0.08), transparent 60%);
    pointer-events: none;
}
.login-card {
    position: relative;
    width: 100%; max-width: 440px;
    background: var(--color-surface);
    border-radius: var(--radius-xl);
    padding: var(--sp-8) var(--sp-7);
    box-shadow: var(--shadow-lg);
    border: 1px solid var(--color-border-soft);
}
.login-card h1 {
    text-align: center;
    color: var(--color-primary-dark);
    margin-bottom: var(--sp-2);
    font-size: 1.5rem;
}
.login-card .subtitle {
    text-align: center;
    color: var(--color-text-muted);
    margin-bottom: var(--sp-6);
    font-size: .9rem;
}

/* Bottom nav mobile retiré (remplacé par drawer) */
.mobile-nav { display: none !important; }

/* ============ Kanban CRM ============ */
.kanban { display: flex; gap: 16px; overflow-x: auto; padding-bottom: 20px; }
.kanban-col {
    flex: 0 0 280px;
    background: var(--color-bg-subtle);
    border-radius: var(--radius-lg); padding: 14px;
    min-height: 400px;
    border: 1px solid var(--color-border-soft);
}
.kanban-col h4 {
    margin: 0 0 12px; padding: 6px 10px;
    background: var(--color-primary-soft);
    color: var(--color-primary-dark);
    border-radius: var(--radius-sm); font-size: .82rem;
}
.kanban-card {
    background: var(--color-surface); border: 1px solid var(--color-border);
    border-radius: var(--radius); padding: 12px; margin-bottom: 8px;
    box-shadow: var(--shadow-xs); transition: all .15s; cursor: pointer;
    display: block;
}
.kanban-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-sm); border-color: var(--color-primary); text-decoration: none; }
.kanban-card h5 { margin: 0 0 4px; font-size: .9rem; }
.kanban-card .meta { font-size: .72rem; color: var(--color-text-muted); }
.kanban-card .amount { font-weight: 700; color: var(--color-primary-dark); margin-top: 6px; }

/* Le chiffre d'affaires conserve son dégradé de marque en mode clair. */
.ecommerce-revenue-card {
    background: linear-gradient(135deg,var(--color-primary,#204B75),var(--color-primary-dark,#163654));
    color: #fff;
}

/* =========================================================================
   🌓 Dark mode — override des variables CSS sur [data-theme="dark"]
   Toutes les surfaces, textes et bordures du système suivent automatiquement
   car les composants utilisent les vars (--color-surface, --color-text…).
   ========================================================================= */
[data-theme="dark"] {
    --color-primary:       #4A90C7;
    --color-primary-hover: #5FA4D8;
    --color-primary-dark:  #6BB5E5;
    --color-primary-ultra: #1A2F44;
    --color-primary-soft:  #243A52;
    /* Le layout produit peut imposer des fonds fonces via !important. */
    --color-primary-text:  #6BB5E5;
    --color-focus-ring:    #6BB5E5;

    --color-secondary:     #B0AFAF;
    --color-secondary-light:#2E2E2E;

    --color-success:       #4FB979;
    --color-success-hover: #66CC8E;
    --color-success-dark:  #A6E3BD;  /* texte clair lisible sur fond -soft sombre */
    --color-success-soft:  #1A3424;
    --color-warning:       #E0B864;
    --color-warning-hover: #ECC97A;
    --color-warning-dark:  #F2D89C;
    --color-warning-soft:  #3A2E16;
    --color-danger:        #E66C6C;
    --color-danger-hover:  #F08080;
    --color-danger-dark:   #F4B0B0;
    --color-danger-soft:   #3A1F1F;
    --color-info:          #5FA4D8;
    --color-info-hover:    #7AB7E3;
    --color-info-dark:     #B0D4EF;
    --color-info-soft:     #1F2E40;

    --color-on-solid:      #0F141B;
    --color-success-solid:var(--color-success);

    --color-text:          #E5E9EE;
    --color-text-soft:     #B8C0CC;
    --color-text-muted:    #8892A0;
    --color-border:        #2E3742;
    --color-border-soft:   #232A33;
    --color-control-border:#748399;
    --color-bg:            #0F141B;
    --color-bg-subtle:     #161C24;
    --color-surface:       #1A2230;
    --color-field-bg:      var(--color-bg-subtle);
    --color-overlay:       rgba(0, 0, 0, 0.62);  /* scrim plus dense en sombre */

    --shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.3);
    --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.4), 0 1px 2px rgba(0, 0, 0, 0.3);
    --shadow:    0 4px 12px rgba(0, 0, 0, 0.4), 0 2px 4px rgba(0, 0, 0, 0.3);
    --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.4), 0 2px 4px rgba(0, 0, 0, 0.3);
    --shadow-lg: 0 12px 24px rgba(0, 0, 0, 0.5), 0 4px 8px rgba(0, 0, 0, 0.4);
}

/* Tweaks dark mode : éléments dont le style natif ne suit pas via les vars */
[data-theme="dark"] body { color-scheme: dark; }
[data-theme="dark"] .login-wrapper {
    background: linear-gradient(135deg, #0B1220 0%, #1A2230 100%);
}
[data-theme="dark"] .login-wrapper::before {
    background: radial-gradient(ellipse at top, rgba(74, 144, 199, 0.15), transparent 60%);
}
[data-theme="dark"] table.data thead th { background: var(--color-bg-subtle); }
[data-theme="dark"] table.data tbody tr:hover { background: var(--color-primary-ultra); }
[data-theme="dark"] .kpi::before {
    background: linear-gradient(90deg, var(--color-primary), var(--color-primary-hover));
    opacity: .8;
}
[data-theme="dark"] ::-webkit-scrollbar-thumb {
    background: var(--color-border);
    border: 2px solid var(--color-bg);
}

/* Overrides ciblés pour les couleurs hardcodées dans les vues métier */
[data-theme="dark"] .kanban-card { background: var(--color-surface); }
[data-theme="dark"] .help-content { background: var(--color-surface); }
[data-theme="dark"] .help-toc { background: var(--color-surface); }
[data-theme="dark"] iframe#preview { background: var(--color-surface); }
/* --color-primary-dark devient un texte clair en sombre, pas un fond de carte. */
[data-theme="dark"] .ecommerce-revenue-card {
    background: linear-gradient(135deg, #204B75, #163654);
}
/* Status breadcrumb : adapter les badges en dark mode */
[data-theme="dark"] .status-breadcrumb > div[style*="background:#fff"] { background: var(--color-surface) !important; }
[data-theme="dark"] .status-breadcrumb > div[style*="background:#dafbe1"] { background: var(--color-success-soft) !important; }
[data-theme="dark"] .status-breadcrumb > div[style*="background:#e1e4e8"] { background: var(--color-bg-subtle) !important; }

/* Toggle bouton dans le header */
.theme-toggle {
    background: transparent; border: 1px solid var(--color-border);
    color: var(--color-text-soft);
    width: 36px; height: 36px;
    border-radius: var(--radius);
    display: inline-flex; align-items: center; justify-content: center;
    cursor: pointer;
    transition: all .15s;
}
.theme-toggle:hover {
    background: var(--color-bg-subtle);
    color: var(--color-primary);
    border-color: var(--color-primary);
}
.theme-toggle .icon-sun  { display: none; }
.theme-toggle .icon-moon { display: block; }
[data-theme="dark"] .theme-toggle .icon-sun  { display: block; }
[data-theme="dark"] .theme-toggle .icon-moon { display: none; }

/* =========================================================================
   📱 Mobile — affinements responsive
   ========================================================================= */
@media (max-width: 768px) {
    .container { padding: var(--sp-3); }
    h1 { font-size: 1.3rem; }
    h3 { font-size: 1rem; }
    .card { padding: var(--sp-3); }
    .kpi { padding: var(--sp-3); }
    .kpi .value { font-size: 1.4rem; }
    .grid[style*="grid-template-columns:repeat(4"] { grid-template-columns: repeat(2, 1fr) !important; }
    .grid[style*="grid-template-columns:repeat(5"] { grid-template-columns: repeat(2, 1fr) !important; }
    .grid[style*="grid-template-columns:repeat(6"] { grid-template-columns: repeat(2, 1fr) !important; }
    .flex.justify-between { flex-wrap: wrap; gap: var(--sp-2); }
    /* WCAG 2.5.5 AAA — touch targets ≥ 44×44px sur mobile (header icon buttons) */
    .app-header .icon-btn,
    .app-header .theme-toggle,
    .theme-toggle {
        min-width: 44px;
        min-height: 44px;
    }
}

/* Print : retire l'UI superflue */
@media print {
    .app-header, .sidebar, .menu-toggle, .theme-toggle, .btn { display: none !important; }
    .layout { grid-template-columns: 1fr !important; }
    .main-content { padding: 0 !important; }
    .card { box-shadow: none !important; border: 1px solid #ccc !important; break-inside: avoid; }
}

/* =====================================================
   Dashboard utilities — Phase UX V2
   Pour remplacer les inline styles répétés dans les dashboards
   (alerts-center, this-week, top-partners, fiches 360°, etc.)
   ===================================================== */

/* Grille auto-fit pour tuiles KPI (alternative compacte à .kpi-grid) */
.kpi-tile-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: var(--sp-3, 1rem);
    margin-top: var(--sp-3, 1rem);
}
.kpi-tile-grid--lg {
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}

/* Tuile KPI compacte (variante de .kpi pour dashboards modules récents) */
.kpi-tile {
    background: var(--color-surface, #fff);
    border: 1px solid var(--color-border, #e5e7eb);
    border-radius: var(--radius, 8px);
    padding: var(--sp-3, 1rem);
}
.kpi-tile-label {
    margin: 0;
    font-size: 0.8rem;
    text-transform: uppercase;
    color: var(--color-text-muted, #6b7280);
    letter-spacing: 0.04em;
}
.kpi-tile-value {
    margin: 0;
    font-size: 1.6rem;
    font-weight: 700;
    color: var(--color-primary, #1F3D6E);
    line-height: 1.2;
    font-variant-numeric: tabular-nums;
}
.kpi-tile-value--success { color: #1F8B3A; }
.kpi-tile-value--danger  { color: #C0392B; }
.kpi-tile-value--warn    { color: #D97706; }
.kpi-tile-value small {
    font-size: 0.85rem;
    font-weight: 400;
    color: var(--color-text-muted, #6b7280);
}
.kpi-tile-hint {
    color: var(--color-text-muted, #6b7280);
    font-size: 0.85rem;
}

/* Grille 2 colonnes auto-fit pour layouts dashboard (top clients/fournisseurs, etc.) */
.dashboard-2col {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(420px, 1fr));
    gap: var(--sp-3, 1rem);
    margin-top: var(--sp-4, 1.5rem);
}

/* Card-header pour les sections de dashboard avec titre + action */
.section-card-header {
    padding: var(--sp-3, 1rem);
    border-bottom: 1px solid var(--color-border, #e5e7eb);
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--sp-2, 0.5rem);
}
.section-card-header h2 { margin: 0; }

/* Filtre form en card (période from/to + bouton Filtrer) */
.filter-form {
    padding: var(--sp-3, 1rem);
}
.filter-form .filter-row {
    display: flex;
    gap: var(--sp-3, 1rem);
    align-items: end;
    flex-wrap: wrap;
}

/* Empty state (carte centrée avec icône + message) */
.empty-state {
    padding: var(--sp-4, 1.5rem);
    text-align: center;
}
.empty-state-icon {
    font-size: 3rem;
    margin: 0 0 var(--sp-2, 0.5rem);
}
.empty-state h2 {
    margin: var(--sp-2, 0.5rem) 0;
}

/* Timeline jour (this-week) */
.timeline-day {
    padding: var(--sp-3, 1rem);
}
.timeline-day--today {
    border-left: 4px solid var(--color-primary, #1F3D6E);
}
.timeline-day--weekend h2 { color: #9CA3AF; }
.timeline-event-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: var(--sp-1, 0.25rem);
}
.timeline-event {
    display: flex;
    align-items: center;
    gap: var(--sp-2, 0.5rem);
    padding: var(--sp-2, 0.5rem);
    text-decoration: none;
    color: inherit;
    border-radius: var(--radius, 8px);
}
.timeline-event--holiday { background: #FEF3C7; border-left: 4px solid #D97706; }
.timeline-event--leave   { background: #DCFCE7; border-left: 4px solid #16A34A; }
.timeline-event--alert   { background: #FEE2E2; border-left: 4px solid #DC2626; }
.timeline-event--info    { background: #DBEAFE; border-left: 4px solid #2563EB; }


/* ============================================================
 * Audit UI/UX 2026-05-11 — Quick wins
 * ============================================================ */

/* === F17 fix Q1 — Skip-link a11y WCAG 2.4.1 === */
.skip-link {
    position: absolute;
    top: -100px;
    left: 0;
    background: var(--color-primary);
    color: #fff;
    padding: var(--sp-2) var(--sp-4);
    z-index: 10000;
    text-decoration: none;
    border-radius: 0 0 var(--radius) 0;
    font-weight: 600;
    box-shadow: var(--shadow-md);
    transition: top .15s;
}
.skip-link:focus,
.skip-link:focus-visible {
    top: 0;
    outline: 3px solid var(--color-primary-dark);
    outline-offset: 2px;
}

/* === F11 fix Q5 — focus-visible global === */
/* Outline visible sur TOUS les éléments interactifs au focus clavier.
 * Souris : pas d'outline (browser respecte :focus-visible). */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[role="button"]:focus-visible,
[tabindex]:focus-visible {
    outline: 2px solid var(--color-focus-ring);
    outline-offset: 2px;
    border-radius: var(--radius-sm);
}

/* === F12 fix Q7 — Empty state component === */
/* Usage :
 *   <div class="empty-state">
 *     <div class="empty-state-icon">📭</div>
 *     <div class="empty-state-title">Aucun résultat</div>
 *     <div class="empty-state-message">Essayez avec d'autres filtres.</div>
 *     <a href="..." class="btn primary">Action</a>
 *   </div>
 */
.empty-state {
    text-align: center;
    padding: var(--sp-7) var(--sp-4);
    color: var(--color-text-muted);
    background: var(--color-bg-subtle);
    border-radius: var(--radius);
    border: 1px dashed var(--color-border-soft);
}
.empty-state-icon {
    font-size: var(--text-4xl);
    margin-bottom: var(--sp-3);
    opacity: 0.6;
    line-height: 1;
}
.empty-state-title {
    font-size: var(--text-lg);
    font-weight: 600;
    color: var(--color-text);
    margin-bottom: var(--sp-2);
}
.empty-state-message {
    font-size: var(--text-base);
    margin-bottom: var(--sp-4);
    max-width: 60ch;
    margin-left: auto;
    margin-right: auto;
    line-height: 1.5;
}

/* === F14 fix bonus — .btn[aria-busy="true"] loading state === */
.btn[aria-busy="true"] {
    position: relative;
    color: transparent !important;
    pointer-events: none;
}
.btn[aria-busy="true"]::after {
    content: "";
    position: absolute;
    width: 16px; height: 16px;
    top: 50%; left: 50%;
    margin: -8px 0 0 -8px;
    border: 2px solid currentColor;
    border-right-color: transparent;
    border-radius: 50%;
    color: var(--btn-color);
    animation: pcerp-btn-spin 0.6s linear infinite;
}
@keyframes pcerp-btn-spin {
    to { transform: rotate(360deg); }
}
@media (prefers-reduced-motion: reduce) {
    .btn { transition: none; }
    .btn[aria-busy="true"]::after { animation: none; }
}

/* === F20 fix Sprint S5 — Tables responsive === */
/* Wrapper qui rend toutes les tables scrollables horizontalement sur mobile.
 * Usage : <div class="table-wrap"><table class="data">...</table></div>
 * Auto-applique aussi aux tables non-wrappées via :has() où supporté */
.table-wrap {
    container: table-scroll / inline-size;
    min-width: 0;
    max-width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    /* Indicateur visuel scroll-shadow quand contenu déborde (right side) */
    background:
        linear-gradient(to right, var(--color-surface), var(--color-surface)),
        linear-gradient(to right, var(--color-surface), transparent),
        linear-gradient(to left, transparent, rgba(0,0,0,0.08)) 100% 0;
    background-repeat: no-repeat;
    background-size: 100% 100%, 16px 100%, 16px 100%;
    background-position: 0 0, 0 0, 100% 0;
    background-attachment: local, local, scroll;
}
.table-wrap table.data {
    min-width: 100%;
}
/* Le parent porte le scroll ; le tableau conserve son display natif. */
.card:has(> table.data),
.container:has(> table.data),
.page-section:has(> table.data),
.main-content:has(> table.data) {
    container: table-scroll / inline-size;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}
/* Les cartes imbriquees dans une grille peuvent retrecir avec leur wrapper. */
.card:has(table.data),
.container:has(table.data),
.page-section:has(table.data) {
    min-width: 0;
}

/* ============================================================================
 * UTILITY CLASSES (2026-05-12) — Élimine ~620 inline styles répétés dans les
 * modules livrés cette session (Ai/Announcements/UpdateProposals/Releases/etc.).
 * ============================================================================ */

/* Callout / Alert box stylisé avec bordure latérale + soft background.
 * Usage : <div class="callout callout-{info|success|warning|danger}">...</div>
 * Remplace : style="background:var(--color-X-soft);border-left:4px solid var(--color-X);padding:var(--sp-3)" */
.callout {
    padding: var(--sp-3);
    border-radius: var(--radius);
    border-left: 4px solid var(--color-border);
    background: var(--color-gray-50);
    margin: var(--sp-2) 0;
}
.callout-info    { border-left-color: var(--color-info);    background: var(--color-info-soft); }
.callout-success { border-left-color: var(--color-success); background: var(--color-success-soft); }
.callout-warning { border-left-color: var(--color-warning); background: var(--color-warning-soft); }
.callout-danger  { border-left-color: var(--color-danger);  background: var(--color-danger-soft); }
.callout-primary { border-left-color: var(--color-primary); background: var(--color-primary-soft); }
.callout > :first-child { margin-top: 0; }
.callout > :last-child  { margin-bottom: 0; }

/* Badge soft (variant subtil pour étiquettes). Pas utilisé encore mais préparé.
 * Usage : <span class="badge badge-soft-info">…</span> */
.badge-soft-info     { background: var(--color-info-soft);    color: var(--color-info-dark); }
.badge-soft-success  { background: var(--color-success-soft); color: var(--color-success-dark); }
.badge-soft-warning  { background: var(--color-warning-soft); color: var(--color-warning-dark); }
.badge-soft-danger   { background: var(--color-danger-soft);  color: var(--color-danger-dark); }
.badge-soft-primary  { background: var(--color-primary-soft); color: var(--color-primary-text); }
.badge-soft-gray     { background: var(--color-bg-subtle);    color: var(--color-text-soft); }

/* Espacement commun des commandes ; dimensions partagees avec .action-bar. */
.page-header-actions {
    display: flex;
    gap: var(--sp-2);
    align-items: center;
    flex-wrap: wrap;
}

/* Workflow buttons row (state machine transitions) — alignement vertical strict */
.workflow-buttons {
    display: flex;
    gap: var(--sp-2);
    align-items: center;
    flex-wrap: wrap;
}
.workflow-buttons .btn {
    margin: 0; /* empêche les override style="margin:..." de casser l'alignement */
}

/* Card sub-header : titre + actions à droite alignés */
.card-header-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: var(--sp-2);
    flex-wrap: wrap;
    margin-bottom: var(--sp-2);
    padding-bottom: var(--sp-2);
    border-bottom: 1px solid var(--color-border);
}
.card-header-row h2,
.card-header-row h3 {
    margin: 0;
}

/* Fix bouton transparent / icon-only — typiquement pour ✕ Masquer dans le fil */
.btn-ghost {
    /* Pilote les variables du .btn pour battre le garde-fou de contraste
       `a.btn { color: var(--btn-color) }` (0,1,1) qui, sinon, force le BLANC
       (couleur texte-sur-bouton-plein) sur un fond transparent → texte
       invisible (bug « 📄 PDF » blanc sur blanc en bout de ligne de liste). */
    --btn-color: var(--color-text-soft);
    --btn-bg: transparent;
    --btn-border: transparent;
    --btn-hover-bg: var(--color-bg-subtle);
    --btn-hover-border: transparent;
    background: transparent;
    border: 1px solid transparent;
    color: var(--color-text-soft);
    padding: 4px 8px;
    border-radius: var(--radius);
    cursor: pointer;
    font-size: 0.85em;
    box-shadow: none;
    transition: background 0.15s, color 0.15s;
}
.btn-ghost:hover {
    --btn-color: var(--color-text);
    background: var(--color-bg-subtle);
    color: var(--color-text);
}

/* Stat / KPI mini-card uniforme (utilisé en haut de plusieurs listes) */
.stat-card {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    padding: var(--sp-3);
    text-align: center;
}
.stat-card .stat-label {
    font-size: 0.8em;
    color: var(--color-text-soft);
    text-transform: uppercase;
    letter-spacing: 0.05em;
}
.stat-card .stat-value {
    font-size: 1.7em;
    font-weight: 700;
    line-height: 1.2;
    margin-top: var(--sp-1);
}
.stat-card.stat-info    { background: var(--color-info-soft); }
.stat-card.stat-success { background: var(--color-success-soft); }
.stat-card.stat-warning { background: var(--color-warning-soft); }
.stat-card.stat-danger  { background: var(--color-danger-soft); }

/* ============================================================================
 * MOBILE RESPONSIVE (2026-05-12 — #17) — Corrections pour les modules récents
 * ============================================================================ */

@media (max-width: 768px) {
    /* Page header : titre + actions empilés verticalement sur mobile */
    .page-header {
        flex-direction: column;
        align-items: stretch;
        gap: var(--sp-2);
    }
    .page-header-actions {
        width: 100%;
        justify-content: flex-start;
    }
    .page-header-actions .btn {
        flex: 1 1 auto;
        min-width: 0;
        justify-content: center;
    }

    /* Card-header-row : titre + actions stack */
    .card-header-row {
        flex-direction: column;
        align-items: stretch;
        gap: var(--sp-1);
    }

    /* Workflow buttons : wrap proprement, chaque bouton prend la largeur dispo */
    .workflow-buttons {
        flex-direction: column;
        align-items: stretch;
    }
    .workflow-buttons .btn {
        width: 100%;
        justify-content: center;
    }

    /* Stat cards en grid : passer en 2 colonnes au lieu de 5+ */
    .grid[style*="grid-template-columns:repeat(5"],
    .grid[style*="grid-template-columns:repeat(6"] {
        grid-template-columns: repeat(2, 1fr) !important;
    }
    .grid[style*="grid-template-columns:repeat(4"] {
        grid-template-columns: repeat(2, 1fr) !important;
    }
    /* Grids 2 colonnes → 1 colonne sur mobile */
    .grid[style*="grid-template-columns:1fr 1fr"],
    .grid[style*="grid-template-columns:2fr 1fr"] {
        grid-template-columns: 1fr !important;
    }
    .grid[style*="grid-template-columns:1fr 1fr 1fr"] {
        grid-template-columns: 1fr !important;
    }

    /* Fil d'actualité Pacific Consulting (changelog) : padding réduit */
    .pcerp-changelog {
        padding: var(--sp-3) !important;
    }
    .pcerp-changelog-timeline {
        padding-left: var(--sp-3) !important;
    }
    .pcerp-changelog-item {
        padding: var(--sp-2) !important;
    }
    /* Cache la date à droite sur mobile (gain de place — déjà visible dans le bucket header) */
    .pcerp-changelog-item header > span:last-child {
        display: none !important;
    }

    /* Help-tip popover : déjà responsive via JS (max-width:calc(100vw - 16px)) mais on s'assure */
    .pcerp-help-tip-popover {
        font-size: 0.85rem;
        line-height: 1.55;
    }

    /* Sidebar : prend toute la largeur quand ouverte */
    .sidebar.open {
        width: 85vw;
        max-width: 320px;
    }

    /* Formulaires : labels en bloc, inputs full-width */
    label > input:not([type=checkbox]):not([type=radio]),
    label > select,
    label > textarea {
        width: 100%;
    }
}

/* Très petits écrans (iPhone SE et inférieur) */
@media (max-width: 380px) {
    .grid[style*="grid-template-columns:repeat(2"] {
        grid-template-columns: 1fr !important;
    }
    .page-header h1 {
        font-size: 1.3rem !important;
    }
}

/* =====================================================
   2026-05-13 UI audit — Largeur tableaux + dropdowns
   - Toutes les tables dans cards/containers prennent 100% de la largeur
     dispo (avant : largeur natives basée sur le contenu → cramped à 30%).
   - Les <select> ont une largeur min lisible (240px) pour éviter les
     listes déroulantes minuscules avec valeurs tronquées.
   - <input list="..."> (datalist HTML5 = dropdown searchable native) reçoit
     la même taille, permet le filtrage tapé instantané sur les longues listes
     (comptes 411, contacts, articles, etc.).
   ===================================================== */
/* Tables génériques dans cards/containers : 100% de la largeur dispo.
   `!important` + `min-width: 100%` pour vaincre le `width: auto` natif des
   <table> et tout style inline qui les bride.
   2026-05-13 : sélecteur élargi à .main-content et `main` pour couvrir les
   pages POS/RH qui n'utilisent pas .container. */
main table,
.main-content table,
.card table,
.container table,
.page-section table {
    width: 100% !important;
    min-width: 100% !important;
    border-collapse: collapse;
}
/* Tables .data — distribution des colonnes :
   Sans cette règle, les browsers (avec table-layout: auto) sizent chaque
   colonne au content nécessaire et laissent TOUT le reste de la largeur
   en whitespace après la dernière colonne. Visuellement : 3-5 colonnes
   bunchées à gauche, vide à droite — exactement le bug remonté par
   l'utilisateur sur Bilan, Compte de résultat, Balance des comptes etc.
   Fix : on force la 2e colonne (typiquement le libellé/description/désignation)
   à `width: 100%`. Cette technique compatible table-layout:auto fait absorber
   tout l'espace dispo à cette colonne ; les autres restent à leur taille
   intrinsèque (code/montants/badge). */
.card table.data thead th:nth-child(2):not(:last-child),
.card table.data tbody td:nth-child(2):not(:last-child),
.card table.data tfoot td:nth-child(2):not(:last-child),
.container table.data thead th:nth-child(2):not(:last-child),
.container table.data tbody td:nth-child(2):not(:last-child),
.main-content table.data thead th:nth-child(2):not(:last-child),
.main-content table.data tbody td:nth-child(2):not(:last-child) {
    width: 100%;
}
/* Pour les tables à 2 colonnes seulement (label/value), c'est la 1ère qui
   doit s'étirer (la 2e étant le montant aligné à droite). */
.card table.data thead tr:has(th:nth-child(2):last-child) th:first-child,
.card table.data tbody tr:has(td:nth-child(2):last-child) td:first-child,
.container table.data thead tr:has(th:nth-child(2):last-child) th:first-child,
.container table.data tbody tr:has(td:nth-child(2):last-child) td:first-child {
    width: 100%;
}
/* 2026-05-13 — Override des inline `max-width: 1100px/1200px/1280px` sur .page-section
   et .container pour permettre aux pages de prendre toute la largeur dispo sur écrans
   wide (avant : centré à 1100px → 800px de vide à gauche/droite sur 2700px). */
.page-section[style*="max-width:1100px"],  .page-section[style*="max-width: 1100px"],
.page-section[style*="max-width:1200px"],  .page-section[style*="max-width: 1200px"],
.page-section[style*="max-width:1280px"],  .page-section[style*="max-width: 1280px"],
.container[style*="max-width:1100px"],     .container[style*="max-width: 1100px"],
.container[style*="max-width:1200px"],     .container[style*="max-width: 1200px"] {
    max-width: min(96vw, 2400px) !important;
}
/* Card avec margin auto + max-width inline : ouvre aussi */
.card[style*="max-width:900px"],   .card[style*="max-width: 900px"],
.card[style*="max-width:1024px"],  .card[style*="max-width: 1024px"],
.card[style*="max-width:1100px"],  .card[style*="max-width: 1100px"] {
    max-width: 100% !important;
}
/* 2026-05-13 — Grids 2-colonnes inline `1fr 1fr` rendues responsives globalement :
   passent en colonne unique sous 900px (utile sur tablette ou DevTools ouvert).
   Couvre les pages Bilan, Compte de résultat, Stats compta, etc. sans devoir
   modifier chaque tpl individuellement. */
[style*="grid-template-columns:1fr 1fr"],
[style*="grid-template-columns: 1fr 1fr"] {
    grid-template-columns: repeat(auto-fit, minmax(420px, 1fr)) !important;
}
[style*="grid-template-columns:1fr 1fr 1fr"],
[style*="grid-template-columns: 1fr 1fr 1fr"] {
    grid-template-columns: repeat(auto-fit, minmax(340px, 1fr)) !important;
}
[style*="grid-template-columns:1fr 1fr 1fr 1fr"],
[style*="grid-template-columns: 1fr 1fr 1fr 1fr"] {
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)) !important;
}
/* Selects de filtrage : largeur lisible mais SANS forcer min-width qui
   casserait les grilles auto-fit (cellules grid 160px). Le `width: auto`
   natif suffit ; on garantit juste l'ergonomie via min-height + padding.
   2026-05-13 : retiré min-width 220/240px qui causait des chevauchements
   dans .filter-grid (cellules grid 1fr) sur les pages /purchases/invoices etc. */
.form-group select,
.form-group input[list],
.filter-grid select,
.filter-grid input[list],
.filter-bar select,
.filters select {
    width: 100%;
    max-width: 100%;
}
/* Input avec datalist (dropdown searchable) : indicateur visuel discret
   du caret pour rappeler que c'est une liste filtrable. */
input[list] {
    background-image:
        linear-gradient(45deg, transparent 50%, var(--color-text-muted) 50%),
        linear-gradient(135deg, var(--color-text-muted) 50%, transparent 50%);
    background-position:
        right 14px top 50%,
        right 10px top 50%;
    background-size: 4px 4px, 4px 4px;
    background-repeat: no-repeat;
    padding-right: 26px;
}
/* Form-group select agrandi (Compta filtrage compte / période) */
.form-group select, .form-group input[type=date], .form-group input[list] {
    min-height: 40px;
    font-size: var(--text-base);
}

/* Accessibilité — texte visible uniquement pour lecteurs d'écran (WCAG) */
.sr-only {
    position: absolute !important;
    width: 1px !important;
    height: 1px !important;
    padding: 0 !important;
    margin: -1px !important;
    overflow: hidden !important;
    clip: rect(0, 0, 0, 0) !important;
    white-space: nowrap !important;
    border: 0 !important;
}

/* Marqueur visuel pour champs obligatoires (cohérence inter-formulaires).
   L'astérisque est masqué aux SR (aria-hidden) — l'info "obligatoire" est portée
   par aria-required="true" sur l'input + texte .sr-only "(obligatoire)" sur le label. */
.required-marker {
    /* l'astérisque est déjà dans le texte, on le différencie juste légèrement */
    color: inherit;
}
.required-marker::after {
    content: "";
}


/* ============================================================
   CHARTE — Alignement des cellules d'une même ligne de formulaire
   RÈGLE : les cellules d'un même rang (label + champ, avec ou sans
   texte d'aide en dessous) s'alignent TOUJOURS EN HAUT. Ne JAMAIS
   centrer/aligner-en-bas un rang de champs : un champ avec aide
   ("Max : …", "optionnel"…) décale alors les autres → très moche.
   ============================================================ */
.flex:has(> .form-group){ align-items: flex-start; }

/* ============================================================
   ACCORDÉONS (data-accordions) — piloté par app.js qui pose
   .acc-card / .acc-head / .acc-chevron / .acc-closed.
   Cette CSS manquait (flèches non stylées + repli inopérant).
   ============================================================ */
.acc-card > .acc-head { cursor: pointer; user-select: none; }
.acc-chevron {
    display: inline-block;
    margin-right: .45rem;
    color: var(--color-text-muted);
    font-size: .72em;
    line-height: 1;
    transition: transform .15s ease;
    transform: rotate(0deg);
}
.acc-card.acc-closed .acc-chevron { transform: rotate(-90deg); }
/* Repli : masquer tout le contenu de la carte SAUF l'en-tête (1er enfant .acc-head) */
.acc-card.acc-closed > *:not(.acc-head) { display: none !important; }
.acc-card.acc-closed > .acc-head { margin-bottom: 0; }

/* ============================================================
   CHARTE — Bouton d'action dans un RANG DE CHAMPS
   RÈGLE : un bouton placé sur la même ligne que des champs
   (label+input) DOIT s'aligner avec les INPUTS, pas avec les
   labels. Comme le rang est en align-items:flex-start, un bouton
   sans label remonte au niveau des labels → moche.
   SOLUTION : envelopper le bouton dans une .form-group avec un
   label espaceur invisible, OU utiliser .form-group.btn-aligned
   qui réserve automatiquement la hauteur d'un label.
   ============================================================ */
.form-group.btn-aligned > label { visibility: hidden; }
.form-group.btn-aligned::before {
    content: "";
    display: block;
    height: 1.15rem;              /* ~ hauteur d'un label + margin-bottom */
}

/* ============================================================
   Barres d'actions : dimensions partagees avec le groupe HT/TTC.
   La hauteur minimale suit le texte agrandi, sans couper un libelle multiligne.
   ============================================================ */
.action-bar { display:flex; gap:var(--sp-2); align-items:center; flex-wrap:wrap; }
.action-bar .btn,
.page-header-actions .btn,
.workflow-buttons .btn,
.flex.justify-between:has(> h1 + .help-link) .btn {
    min-height: var(--control-height); height: auto;
    max-width: 100%;
    padding: 0 14px;
    font-size: .9rem;
    white-space: normal;
    overflow-wrap: anywhere;
    display: inline-flex; align-items: center; justify-content: center;
}

/* ============================================================
   CHARTE ERP-WIDE — Hauteur HOMOGÈNE des boutons dans une barre.
   Règle : quand une rangée flex MÉLANGE un bouton pleine taille
   (.btn) et des boutons réduits (.btn.sm/.small), on aligne les
   petits sur la pleine taille → plus aucun mismatch de hauteur.
   Les barres 100% « petites » restent petites (déjà homogènes).
   Complete les barres d'actions explicites.
   ============================================================ */
.flex:has(> .btn:not(.sm):not(.small):not(.xs):not(.lg)):has(> .btn.sm) > .btn.sm,
.flex:has(> .btn:not(.sm):not(.small):not(.xs):not(.lg)):has(> .btn.small) > .btn.small {
    min-height: var(--control-height); height: auto; padding: 0 14px; font-size: .9rem;
}

/* ============================================================
   CHARTE — Barre compteur + export sous les tableaux .data.
   Espace le « N lignes » du bouton Exporter (étaient collés).
   ============================================================ */
.export-bar {
    display: flex; align-items: center; gap: var(--sp-3, 16px);
    flex-wrap: wrap; margin-top: var(--sp-2, 8px); margin-bottom: var(--sp-4, 24px);
}
.export-count { font-size: .85rem; color: var(--color-text-muted); }
.table-count  { font-size: .85rem; color: var(--color-text-muted); margin-top: var(--sp-2, 8px); }

/* ============================================================
   Menu déroulant d'EXPORT (généré par app.js) — charte propre.
   Remplace les boutons gris « moches » par un menu carte + items
   au style cohérent avec le reste de l'UI.
   ============================================================ */
.export-menu {
    position: absolute; z-index: 70; margin-top: 6px; min-width: 240px;
    background: var(--color-surface, #fff);
    border: 1px solid var(--color-border, #e5e7eb);
    border-radius: var(--radius, 10px);
    box-shadow: 0 12px 28px rgba(16, 24, 40, .16);
    padding: 6px; display: flex; flex-direction: column; gap: 2px;
    animation: exportMenuIn .12s ease-out;
}
@keyframes exportMenuIn { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
.export-menu button {
    all: unset; box-sizing: border-box; cursor: pointer;
    display: flex; align-items: center; gap: 8px;
    padding: 9px 12px; border-radius: 8px;
    font-size: .86rem; font-weight: 500; color: var(--color-text);
    line-height: 1.25; transition: background .12s, color .12s;
}
.export-menu button::before {
    content: "⬇"; font-size: .9em; color: var(--color-primary-text); opacity: .8;
}
.export-menu button:hover, .export-menu button:focus-visible {
    background: var(--color-primary-ultra, #eef4fb); color: var(--color-primary-text);
}
.export-menu button:focus-visible { outline: 2px solid var(--color-focus-ring); outline-offset: -2px; }
.export-menu hr { border: 0; border-top: 1px solid var(--color-border, #eceff3); margin: 4px 2px; }

/* Panneau « Export personnalisé » */
.export-custom {
    position: absolute; z-index: 71; margin-top: 6px; min-width: 300px; max-width: 360px;
    background: var(--color-surface, #fff); border: 1px solid var(--color-border, #e5e7eb);
    border-radius: var(--radius, 10px); box-shadow: 0 12px 28px rgba(16, 24, 40, .18);
    padding: 14px 16px; animation: exportMenuIn .12s ease-out;
}
.export-custom h4 { margin: 0 0 10px; font-size: .92rem; font-weight: 700; color: var(--color-text); }
.export-custom .ec-list { display: flex; flex-direction: column; gap: 2px; max-height: 280px; overflow-y: auto; }
.export-custom .ec-row {
    display: flex; align-items: center; justify-content: space-between; gap: 10px;
    padding: 6px 8px; border-radius: 7px;
}
.export-custom .ec-row:hover { background: var(--color-bg-subtle); }
.export-custom .ec-row label { display: flex; align-items: center; gap: 8px; font-size: .85rem; cursor: pointer; margin: 0; }
.export-custom .ec-move { display: inline-flex; gap: 4px; }
.export-custom .ec-move button {
    all: unset; cursor: pointer; width: 24px; height: 24px; border-radius: 6px;
    display: inline-flex; align-items: center; justify-content: center;
    color: var(--color-text-muted); border: 1px solid var(--color-control-border);
    font-size: .8rem; transition: background .12s, color .12s, border-color .12s;
}
.export-custom .ec-move button:hover:not([disabled]) { background: var(--color-primary-ultra, #eef4fb); color: var(--color-primary-text); border-color: var(--color-focus-ring); }
.export-custom .ec-move button:focus-visible { outline: 2px solid var(--color-focus-ring); outline-offset: 2px; }
.export-custom .ec-move button[disabled] { opacity: .4; cursor: default; }
.export-custom .ec-actions { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--color-border, #eceff3); }
.export-custom .ec-sel { display: flex; align-items: center; gap: 6px; font-size: .82rem; color: var(--color-text-soft); margin: 0 auto 0 0; }

/* ============================================================
   Combobox « client » recherchable (généré par app.js).
   Le <select> natif est masqué mais reste dans le DOM (valeur+binding).
   ============================================================ */
.cbx-wrap { position: relative; width: 100%; min-width: 0; }
.cbx-native { position: absolute !important; width: 1px; height: 1px; opacity: 0; pointer-events: none; overflow: hidden; }
.cbx-input {
    width: 100%; min-width: 0; cursor: text;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%236b7280' d='M2 4l4 4 4-4z'/%3E%3C/svg%3E");
    background-repeat: no-repeat; background-position: right .55rem center; padding-right: 1.6rem;
}
.cbx-panel {
    position: absolute; left: 0; right: 0; top: calc(100% + 2px); z-index: 60;
    background: var(--color-surface, #fff); border: 1px solid var(--color-border, #d1d5db);
    border-radius: var(--radius, 8px); box-shadow: 0 6px 18px rgba(0,0,0,.14);
    max-height: min(280px, 50vh); overflow-y: auto; overscroll-behavior: contain;
    min-width: 0; max-width: 100%;
}
.cbx-opt {
    display: flex; align-items: center; min-height: 44px;
    padding: .5rem .6rem; cursor: pointer; font-size: .875rem; line-height: 1.4;
    white-space: normal; overflow-wrap: anywhere;
}
.cbx-opt:hover, .cbx-opt.cbx-active { background: var(--color-primary-ultra, #eff6ff); }
.cbx-opt.cbx-active { outline: 2px solid var(--color-focus, var(--color-primary, #204b75)); outline-offset: -2px; }
.cbx-opt.cbx-sel { font-weight: 600; }
.cbx-none { padding: .5rem .6rem; color: var(--color-gray-500, #6b7280); font-size: .8rem; }

/* ============================================================
   CHARTE — Tableaux .data : colonne d'ACTIONS jamais sur 2 lignes,
   colonne réf/numéro (mono) ajustée au contenu (pas de colonne
   « Numéro » démesurée qui pousse le reste).
   ============================================================ */
table.data td:has(> .btn), table.data td:has(> a.btn) { white-space: nowrap; }
table.data td.font-mono { width: 1%; white-space: nowrap; }

/* ============================================================
   Listes de documents : taille de lecture stable, scroll dans le parent.
   Le texte tronque reste reserve aux tableaux avec un layout fixe explicite.
   ============================================================ */
table.data.nowrap,
table.data.contracts-list { font-size: var(--text-base); }
/* Certaines vues imposent .7rem sur les cellules : garder l'echelle commune. */
table.data.nowrap tbody td { font-size: var(--text-base) !important; }
table.data.nowrap thead th { font-size: var(--text-xs) !important; }
table.data.nowrap td, table.data.nowrap th { white-space: nowrap; }
table.data.nowrap td:not(:has(.btn)):not(:has(input)) { overflow: hidden; text-overflow: ellipsis; }

/* ============================================================
   CHARTE (OBLIGATOIRE, TOUTES LES PAGES) — Barres de filtres :
   TOUS les contrôles (input quel que soit le type, select, bouton)
   ont EXACTEMENT la même hauteur. Corrige le mismatch input[date]/
   input[text] (40px) vs search/number/select/btn (32px).
   S'applique à toute barre de filtres connue de l'ERP.
   ============================================================ */
.docs-filter input:not([type=checkbox]):not([type=radio]),
.docs-filter select, .docs-filter .btn,
.contracts-filter input:not([type=checkbox]):not([type=radio]),
.contracts-filter select, .contracts-filter .btn,
.filters input:not([type=checkbox]):not([type=radio]),
.filters select, .filters .btn,
.filter-bar input:not([type=checkbox]):not([type=radio]),
.filter-bar select, .filter-bar .btn,
.filter-grid input:not([type=checkbox]):not([type=radio]),
.filter-grid select, .filter-grid .btn {
    height: 36px !important;
    min-height: 36px !important;
    box-sizing: border-box;
    padding-top: 0 !important;
    padding-bottom: 0 !important;
    line-height: 1.2;
}

/* ============================================================
   Listes doc (table.data.nowrap, table-layout AUTO) : la colonne
   réf/numéro (2e) ne s'étire PAS (neutralise nth-child(2){width:100%}).
   Le tableau remplit via width:100%, l'espace va aux colonnes texte
   → plus de vide à droite, colonne Numéro compacte.
   ============================================================ */
table.data.nowrap td:nth-child(2), table.data.nowrap th:nth-child(2) { width: 1% !important; white-space: nowrap; }

/* ---- Listes doc compactes (.nowrap) : récupère l'espace + filet anti-débordement ----
   - padding cellules resserré (moins d'espace perdu)
   - 1re colonne (case à cocher) étroite = plus de marge géante avant la réf
   - le tableau qui dépasse scrolle DANS sa carte → ne sort JAMAIS de la page */
table.data.nowrap th, table.data.nowrap td { padding-left: 8px; padding-right: 8px; }
table.data.nowrap th:first-child, table.data.nowrap td:first-child { width: 1% !important; white-space: nowrap; padding-left: 10px; padding-right: 4px; }
.card:has(> table.data.nowrap) { overflow-x: auto; }

/* Marge de respiration à droite (dernière colonne = actions) : le bouton
   PDF/Ouvrir ne colle pas au bord de la carte. */
table.data.nowrap td:last-child, table.data.nowrap th:last-child { padding-right: 10px; }

/* ============================================================
   Actions sticky seulement si le conteneur laisse assez de place aux donnees.
   Sur mobile, conteneur etroit ou navigateur sans container queries,
   les actions defilent avec les autres colonnes.
   ============================================================ */
@media (min-width: 769px) {
    @container table-scroll (min-width: 48rem) {
        table.data.nowrap thead th:last-child,
        table.data.nowrap tbody td:last-child:not([colspan]) {
            position: sticky; right: 0; z-index: 3;
            box-shadow: -8px 0 8px -6px rgba(0,0,0,.10);
        }
    }
}
table.data.nowrap thead th:last-child { background: var(--color-bg-subtle); }
table.data.nowrap tbody td:last-child { background: var(--color-surface); }
table.data.nowrap tbody tr:nth-child(even) td:last-child { background: var(--color-bg-subtle); }
table.data.nowrap tbody tr:hover td:last-child { background: var(--color-primary-ultra); }

/* ============================================================
   Pilules de sélection de TYPES de documents (page unifiée
   « Documents commerciaux ») — multi-sélection, auto-submit.
   ============================================================ */
.type-pill {
    position: relative;
    display: inline-flex; align-items: center; gap: 5px;
    height: 36px; padding: 0 11px;
    border: 1px solid var(--color-border); border-radius: var(--radius);
    background: var(--color-surface);
    font-size: .72rem; font-weight: 600; white-space: nowrap;
    cursor: pointer; user-select: none; transition: all .12s;
}
.type-pill:hover { border-color: var(--color-primary-soft); }
.type-pill.on { background: var(--color-primary); border-color: var(--color-primary); color: #fff; }
/* !important : bat le <style> inline .docs-filter input{width:100%} du partial */
.type-pill input {
    position: absolute !important; left: 0 !important;
    width: 1px !important; height: 1px !important; min-height: 0 !important;
    opacity: 0 !important; pointer-events: none !important;
}

/* ============================================================
   CHARTE (OBLIGATOIRE, GLOBALE — « une bonne fois pour toutes ») :
   1. AUCUNE cellule de table.data ne passe sur 2 lignes (montants
      « 91 000 / XPF », dates, badges…) — partout, tous les logiciels.
   2. Toute carte contenant une table trop large scrolle EN INTERNE
      (le tableau ne déborde jamais de la page).
   3. Dans une table à cases à cocher (sélection/export), la colonne
      qui suit la case = référence/N° → toujours COMPACTE (jamais
      étirée par la règle « 2e colonne libellé » des tables compta).
   ============================================================ */
table.data td, table.data th { white-space: nowrap; }
/* Exception à la charte : une cellule marquée .cell-wrap PEUT passer sur plusieurs
   lignes (ex. intitulé + description longue d'une ligne de document figé, dans une
   table en table-layout:fixed). Spécificité (table.data td.cell-wrap) > règle nowrap
   ci-dessus, donc l'enroulement est rétabli UNIQUEMENT sur ces cellules. */
table.data td.cell-wrap, table.data th.cell-wrap { white-space: normal; }
.card:has(> table.data) { overflow-x: auto; }
table.data thead tr:has(> th:first-child input[type=checkbox]) > th:nth-child(2),
table.data tbody tr:has(> td:first-child input[type=checkbox]) > td:nth-child(2) {
    width: 1% !important;
}

/* Éditeur de lignes — périodicité/engagement d'abonnement sur UNE ligne avec le mode (x-show efface le display inline) */
.subline-flex { display: inline-flex; gap: .3rem; align-items: center; }
.subline-flex select, .subline-flex input { width: auto; flex: 0 0 auto; }

/* Tri des colonnes — indicateur de flèche (app.js ajoute .sortable / .sort-asc / .sort-desc) — 2026-09-17 */
table.data thead th.sortable{cursor:pointer;user-select:none;white-space:nowrap;position:relative}
table.data thead th.sortable::after{content:"⇅";margin-left:.35em;font-size:.82em;opacity:.32;font-weight:400}
table.data thead th.sortable:hover::after{opacity:.6}
table.data thead th.sort-asc::after{content:"↑";opacity:.95;color:var(--color-primary-text)}
table.data thead th.sort-desc::after{content:"↓";opacity:.95;color:var(--color-primary-text)}

/* Datalist : masquer l'indicateur natif webkit (le caret app.css suffit) → évite la double flèche — 2026-09-17 */
input[list]::-webkit-calendar-picker-indicator{display:none!important;opacity:0}

/* Tri clavier : le bouton remplace uniquement l'indicateur de son propre th. */
table.data thead th.sortable:has(> .table-sort-button) {
    padding-top: 0;
    padding-bottom: 0;
}
table.data thead th.sortable:has(> .table-sort-button)::after { content: none; }
table.data thead .table-sort-button {
    display: inline-flex;
    align-items: center;
    gap: .35em;
    min-width: 44px;
    min-height: 44px;
    padding: 0;
    border: 0;
    border-radius: var(--radius-sm);
    background: transparent;
    color: inherit;
    font: inherit;
    letter-spacing: inherit;
    text-transform: inherit;
    text-align: inherit;
    vertical-align: middle;
    cursor: pointer;
}
table.data thead .table-sort-button:hover {
    color: var(--color-primary-text, var(--color-text));
}
table.data thead .table-sort-button:focus-visible {
    outline: 2px solid var(--color-focus-ring, var(--color-text));
    outline-offset: -2px;
}
table.data thead .table-sort-indicator {
    display: inline-block;
    flex: 0 0 1em;
    width: 1em;
    text-align: center;
    font-weight: 400;
    letter-spacing: 0;
}
table.data thead .table-sort-indicator::after { content: "\2195"; }
table.data thead th.sort-asc .table-sort-indicator::after { content: "\2191"; }
table.data thead th.sort-desc .table-sort-indicator::after { content: "\2193"; }
table.data thead th:is(.sort-asc, .sort-desc) .table-sort-indicator {
    color: var(--color-primary-text, var(--color-text));
}

/* =========================================================================
   Modale — composant unique (chantier UX C10)
   Rapatrie les overlays « réinventés » (position:fixed + inset:0 + rgba inline)
   vers le design system. Les comportements Alpine (x-show/@click/x-cloak) et les
   bascules JS (display:none ↔ flex) restent pilotés par le markup : ces classes
   ne portent QUE l'apparence. Mode sombre automatique via les tokens.
   ========================================================================= */
.modal-overlay {
    position: fixed;
    inset: 0;
    z-index: 1000;
    background: var(--color-overlay);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--sp-7);          /* 32px — marge de respiration autour du panneau */
    overflow: auto;
}
/* Variante alignée en haut (palette de commandes, pop-up « fiche rapide »). */
.modal-overlay--top { align-items: flex-start; }

.modal {
    background: var(--color-surface);
    color: var(--color-text);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    width: 100%;
    max-width: 600px;              /* défaut ; surchargeable en ligne par instance */
    max-height: 90vh;
    overflow-y: auto;
    padding: var(--sp-6);          /* 24px */
}
/* Panneau « plein-bord » : en-tête coloré collé aux bords, le contenu gère son padding. */
.modal--flush { padding: 0; overflow: hidden; }

.modal-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: var(--sp-3);
    margin-bottom: var(--sp-4);
}
.modal-header h1, .modal-header h2, .modal-header h3, .modal-header h4 { margin: 0; }
/* En-tête « barre » pleine largeur (sur .modal--flush), aux couleurs de la marque. */
.modal-header--bar {
    margin-bottom: 0;
    padding: var(--sp-3-5) var(--sp-4);
    background: var(--color-primary);
    color: var(--color-on-solid);
}
.modal-header--bar h1, .modal-header--bar h2,
.modal-header--bar h3, .modal-header--bar h4 { color: var(--color-on-solid); }
/* Bouton de fermeture « × » standard. */
.modal-close {
    background: transparent;
    border: 0;
    font-size: 1.4rem;
    line-height: 1;
    cursor: pointer;
    color: inherit;
}

@media (max-width: 640px) {
    .modal-overlay { padding: var(--sp-3); }
    .modal { max-height: 94vh; padding: var(--sp-4); }
}

/* =========================================================================
   ===== REFONTE : design-system partagé (.pcerp-*) =====
   Socle ADDITIF & OPT-IN de la refonte Karo (réf. scratchpad/refonte/00-design-system.md).
   RÈGLES :
     - Aucun sélecteur existant (.btn, .card, .badge, table.data, .page-header…)
       n'est redéfini ici. Tout est préfixé .pcerp-* ou scopé à table.data.pcerp-rows.
     - Un écran qui n'opte PAS pour ces classes reste strictement inchangé.
     - Aucune couleur en dur : tout passe par les tokens (var(--color-*)).
     - Dark mode via [data-theme="dark"] uniquement (pas de @media prefers-color-scheme).
   Tickets couverts : F1 (tokens) · F2 (table/pager) · F3 (filtres/totaux) ·
   F4 (talon/éditeur) · F5 (menu/toasts).
   ========================================================================= */

/* ----- F1 · Tokens additionnels (aucun existant n'est redéfini) ----- */
:root {
    /* Teinte de SÉLECTION de ligne (plus soutenue que -soft) + bordure forte */
    --color-primary-soft-2: #DBE4F4;    /* fond ligne sélectionnée */
    --color-border-strong:  #D2D8E3;    /* bordure chip/field (talon, en-tête) */

    /* Codage couleur du TYPE DE FACTURATION d'une ligne (badges éditeur) */
    --color-bill-abo: #0F6FB0;  --color-bill-abo-soft: #E3F1FB;   /* Abonnement */
    --color-bill-opt: #8A6D00;  --color-bill-opt-soft: #FBF2D6;   /* Option */
    --color-bill-ini: #4A5568;  --color-bill-ini-soft: #EEF0F4;   /* Frais initiaux */

    /* Codage couleur du TYPE DE DOCUMENT (pills liste Ventes › Documents) */
    --color-doc-quote:    #4A5568;  --color-doc-quote-soft:    #EEF0F4;   /* Devis */
    --color-doc-order:    #1F6FB0;  --color-doc-order-soft:    #E8F1FB;   /* Commande */
    --color-doc-delivery: #6B4FB0;  --color-doc-delivery-soft: #F0ECFB;   /* BL */
    --color-doc-invoice:  #1A8A5A;  --color-doc-invoice-soft:  #E6F3EC;   /* Facture */
    --color-doc-credit:   #C0392B;  --color-doc-credit-soft:   #FDEEEE;   /* Avoir */

    /* Motion additionnel (feedback micro-interactions) */
    --dur-fast: .08s;   /* hover de ligne, feedback :active */
    --dur-base: .16s;   /* ouverture détail, popover */
    --dur-slow: .25s;   /* entrée toast */
    --undo-ttl: 8s;     /* durée de vie d'un toast annulable */

    /* Toast d'annulation (fond sombre inversé, lisible sur les 2 thèmes) */
    --pcerp-toast-bg:   #1A2230;
    --pcerp-toast-fg:   #E5E9EE;
    --pcerp-toast-link: #7FC4EC;
}
[data-theme="dark"] {
    --color-primary-soft-2: #1D2D49;
    --color-border-strong:  #333E4F;
    --pcerp-toast-bg: #26303F;   /* un cran plus clair pour ressortir sur fond sombre */
    --color-bill-abo-soft:  #122534;  --color-bill-opt-soft: #2C2710;  --color-bill-ini-soft: #222A36;
    --color-doc-quote-soft:    #262C38; --color-doc-order-soft: #122534; --color-doc-delivery-soft: #241F38;
    --color-doc-invoice-soft:  #102A1F; --color-doc-credit-soft: #2E1616;
    /* Textes des badges (bill / doc) éclaircis pour rester lisibles sur fond -soft sombre */
    --color-bill-abo: #7FC4EC;  --color-bill-opt: #E0B864;  --color-bill-ini: #AEB7C4;
    --color-doc-quote:   #AEB7C4; --color-doc-order:   #7FC4EC; --color-doc-delivery: #BFA9EC;
    --color-doc-invoice: #74D29E; --color-doc-credit:  #ED9A9A;
}

/* ----- F2 · Table de liste interactive (opt-in : table.data.pcerp-rows) ----- */
table.data.pcerp-rows tbody tr { cursor: pointer; transition: background-color var(--dur-fast) var(--ease-out); }
/* Liseré gauche au survol : posé sur la 1re cellule (case de sélection ou 1re colonne) */
table.data.pcerp-rows tbody tr:hover td:first-child {
    box-shadow: inset 3px 0 0 var(--color-primary);
}
table.data.pcerp-rows tbody tr.is-picked { background: var(--color-primary-soft-2); }
table.data.pcerp-rows tbody tr.is-picked:hover td:first-child {
    box-shadow: inset 3px 0 0 var(--color-primary);
}
/* Cible tactile ≥44px pour la case de sélection (scopé pcerp-rows uniquement) */
table.data.pcerp-rows td.col-select,
table.data.pcerp-rows th.col-select { min-width: 44px; text-align: center; }
table.data.pcerp-rows td.col-select input[type="checkbox"],
table.data.pcerp-rows th.col-select input[type="checkbox"] {
    width: 18px; height: 18px; margin: 0; cursor: pointer;
    /* zone cliquable élargie à 44px sans modifier la taille visuelle */
    padding: 13px; background-clip: content-box;
}
/* Évite la sélection de texte parasite lors d'un Maj+clic de plage */
table.data.pcerp-rows.is-ranging { user-select: none; }

/* Barre « N sélectionnés » (au-dessus de l'export existant) */
.pcerp-selbar {
    display: flex; align-items: center; flex-wrap: wrap; gap: var(--sp-2) var(--sp-3);
    padding: var(--sp-2) var(--sp-3); margin: var(--sp-2) 0;
    background: var(--color-primary-soft-2);
    border: 1px solid var(--color-primary);
    border-radius: var(--radius-md);
    font-size: var(--text-sm); color: var(--color-text);
    animation: pcerp-slideDown var(--dur-base) var(--ease-out);
}
.pcerp-selbar[hidden] { display: none; }
.pcerp-selbar-count { font-weight: 600; }
.pcerp-selbar-count strong { color: var(--color-primary-text); }
.pcerp-selbar-sep { width: 1px; height: 18px; background: var(--color-border-strong); }
.pcerp-selbar-actions { display: flex; align-items: center; gap: var(--sp-2); margin-left: auto; flex-wrap: wrap; }

/* Pagination (pied de .table-wrap) */
.pcerp-pager {
    display: flex; align-items: center; justify-content: space-between;
    flex-wrap: wrap; gap: var(--sp-2) var(--sp-3);
    padding: var(--sp-2) var(--sp-1); margin-top: var(--sp-2);
    font-size: var(--text-sm); color: var(--color-text-soft);
}
.pcerp-pager-info { white-space: nowrap; }
.pcerp-pages { display: flex; align-items: center; gap: var(--sp-1); flex-wrap: wrap; }
.pcerp-pg {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 34px; height: 34px; padding: 0 var(--sp-2);
    border: 1px solid var(--color-border); border-radius: var(--radius-sm);
    background: var(--color-surface); color: var(--color-text);
    font: inherit; font-variant-numeric: tabular-nums; text-decoration: none; cursor: pointer;
    transition: background-color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
}
.pcerp-pg:hover { background: var(--color-primary-ultra); border-color: var(--color-primary); }
.pcerp-pg:focus-visible { outline: 2px solid var(--color-focus-ring); outline-offset: 2px; }
.pcerp-pg.is-on { background: var(--color-primary); border-color: var(--color-primary); color: var(--color-on-solid); font-weight: 600; }
.pcerp-pg[aria-disabled="true"], .pcerp-pg:disabled { opacity: .45; pointer-events: none; }
.pcerp-pg--gap { border: 0; background: none; min-width: 18px; pointer-events: none; color: var(--color-text-muted); }
.pcerp-pager-perpage { display: inline-flex; align-items: center; gap: var(--sp-1-5); white-space: nowrap; }
.pcerp-pager-perpage select { height: 34px; padding: 0 var(--sp-2); }

/* Pill de statut à point coloré (.pcerp-spill) — réutilise currentColor pour le point */
.pcerp-spill {
    display: inline-flex; align-items: center; gap: var(--sp-1-5);
    padding: var(--sp-0-5) var(--sp-2); border-radius: var(--radius-pill);
    font-size: var(--text-xs); font-weight: 600; line-height: 1.4;
    background: var(--color-bg-subtle); color: var(--color-text-muted);
    border: 1px solid var(--color-border);
}
.pcerp-spill::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: 0 0 auto; }
.pcerp-spill.is-draft  { color: var(--color-text-muted); }
.pcerp-spill.is-issued { color: var(--color-info-dark);    background: var(--color-info-soft);    border-color: var(--color-info-soft); }
.pcerp-spill.is-paid   { color: var(--color-success-dark); background: var(--color-success-soft); border-color: var(--color-success-soft); }
.pcerp-spill.is-late   { color: var(--color-warning-dark); background: var(--color-warning-soft); border-color: var(--color-warning-soft); }

/* Badge de TYPE de document (.pcerp-doc-pill.is-{quote|order|delivery|invoice|credit}) */
.pcerp-doc-pill {
    display: inline-flex; align-items: center; gap: var(--sp-1);
    padding: var(--sp-0-5) var(--sp-2); border-radius: var(--radius-sm);
    font-size: var(--text-xs); font-weight: 600; line-height: 1.4;
    background: var(--color-bg-subtle); color: var(--color-text-soft);
}
.pcerp-doc-pill.is-quote    { color: var(--color-doc-quote);    background: var(--color-doc-quote-soft); }
.pcerp-doc-pill.is-order    { color: var(--color-doc-order);    background: var(--color-doc-order-soft); }
.pcerp-doc-pill.is-delivery { color: var(--color-doc-delivery); background: var(--color-doc-delivery-soft); }
.pcerp-doc-pill.is-invoice  { color: var(--color-doc-invoice);  background: var(--color-doc-invoice-soft); }
.pcerp-doc-pill.is-credit   { color: var(--color-doc-credit);   background: var(--color-doc-credit-soft); }

/* Badge de TYPE de ligne (.pcerp-bill-badge.is-{abo|opt|ini}) — « Ponctuel » n'a pas de badge.
   Alias BEM acceptés : .pcerp-badge--abo / --opt / --ini (voir _PCERP-README.md). */
.pcerp-bill-badge, .pcerp-badge--abo, .pcerp-badge--opt, .pcerp-badge--ini {
    display: inline-flex; align-items: center; gap: var(--sp-1);
    padding: 1px var(--sp-1-5); border-radius: var(--radius-xs);
    font-size: var(--text-xs); font-weight: 600; line-height: 1.5; letter-spacing: .01em;
}
.pcerp-bill-badge.is-abo, .pcerp-badge--abo { color: var(--color-bill-abo); background: var(--color-bill-abo-soft); }
.pcerp-bill-badge.is-opt, .pcerp-badge--opt { color: var(--color-bill-opt); background: var(--color-bill-opt-soft); }
.pcerp-bill-badge.is-ini, .pcerp-badge--ini { color: var(--color-bill-ini); background: var(--color-bill-ini-soft); }

/* ----- F3 · Filtrage AJAX + bandeau de totaux par type ----- */
.pcerp-liveflag {
    display: inline-flex; align-items: center; gap: var(--sp-1);
    font-size: var(--text-xs); font-weight: 600; color: var(--color-success-dark);
    background: var(--color-success-soft); padding: var(--sp-0-5) var(--sp-2);
    border-radius: var(--radius-pill);
}
.pcerp-liveflag[hidden] { display: none; }
.pcerp-totstrip {
    display: flex; flex-wrap: wrap; gap: var(--sp-2);
    margin: var(--sp-2) 0;
}
.pcerp-tot {
    display: inline-flex; flex-direction: column; gap: 1px;
    min-width: 120px; padding: var(--sp-2) var(--sp-3);
    border: 1px solid var(--color-border); border-radius: var(--radius-md);
    background: var(--color-surface); color: var(--color-text);
    font: inherit; text-align: left; cursor: pointer;
    transition: border-color var(--dur-fast) var(--ease-out), background-color var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out);
}
.pcerp-tot:hover { border-color: var(--color-primary); }
.pcerp-tot:focus-visible { outline: 2px solid var(--color-focus-ring); outline-offset: 2px; }
.pcerp-tot.is-on { border-color: var(--color-primary); background: var(--color-primary-ultra); box-shadow: inset 0 -2px 0 var(--color-primary); }
.pcerp-tot-label { font-size: var(--text-xs); color: var(--color-text-muted); text-transform: uppercase; letter-spacing: .03em; }
.pcerp-tot-count { font-size: var(--text-sm); font-weight: 600; }
.pcerp-tot-amount { font-size: var(--text-sm); font-variant-numeric: tabular-nums; color: var(--color-text-soft); }

/* ----- F4 · Talon de synthèse + dépli détail de ligne + états ----- */
.pcerp-talon {
    position: sticky; top: calc(var(--header-h) + 4px);
    display: flex; flex-direction: column; gap: var(--sp-3);
    align-self: start;
}
/* Le talon sticky ne tient QUE si aucun ancêtre n'est un conteneur de défilement.
   .main-content a « overflow-x: hidden » (anti-scroll horizontal des tables larges),
   or « hidden » crée un scroll-container qui DÉSACTIVE le sticky (constat Axel #107 :
   « overflow-x:clip … sans quoi rien ne reste collé »). Sur les pages à talon, on passe
   donc en « clip » : même découpe horizontale, mais SANS scroll-container → sticky OK.
   Scopé via :has() pour ne rien changer aux autres pages. */
.main-content:has(.pcerp-talon) { overflow-x: clip; }

/* ----- Modèles de documents (Réglages → document-templates) : grille de cartes + vignette A4 -----
   Restaure la présentation en grille avec aperçu-vignette (le markup .pcerp-tplgrid/.pcerp-thumb
   existait mais son CSS manquait → la page s'affichait « tout à la file » sans vignette). */
.pcerp-tplgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(216px, 1fr)); gap: var(--sp-4); }
.pcerp-tplcard {
    display: flex; flex-direction: column;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    overflow: hidden;
    transition: box-shadow 160ms ease-out, border-color 160ms ease-out, transform 160ms ease-out;
}
.pcerp-tplcard:hover { box-shadow: var(--shadow-md); border-color: var(--color-border-strong); transform: translateY(-1px); }
.pcerp-tplcard.is-official { border-style: dashed; }
/* Vignette = mini page au ratio A4, cliquable (ouvre l'aperçu PDF) */
.pcerp-thumb {
    display: block; position: relative;
    aspect-ratio: 1 / 1.414; max-height: 184px;
    background: var(--color-bg-subtle);
    border-bottom: 1px solid var(--color-border);
    padding: var(--sp-3);
    text-decoration: none;
}
.pcerp-thumb-page {
    display: block; height: 100%;
    background: #fff; border: 1px solid var(--color-border-soft);
    border-radius: var(--radius-xs); box-shadow: var(--shadow-xs);
    padding: var(--sp-2);
}
.pcerp-thumb-bar { display: block; height: 9px; width: 55%; background: var(--color-primary); border-radius: var(--radius-pill); margin-bottom: var(--sp-2); }
.pcerp-thumb-line { display: block; height: 5px; background: var(--color-gray-200); border-radius: var(--radius-pill); margin-bottom: var(--sp-1-5); }
.pcerp-thumb-line.is-short { width: 58%; }
.pcerp-thumb-badge {
    position: absolute; bottom: var(--sp-2); right: var(--sp-2);
    font-size: 0.68rem; font-weight: 600;
    color: var(--color-success-dark); background: var(--color-success-soft);
    border-radius: var(--radius-pill); padding: 2px 8px;
}
.pcerp-tplcard.is-official .pcerp-thumb-badge { color: var(--color-warning-dark); background: var(--color-warning-soft); }
.pcerp-tplcard-body { display: flex; flex-direction: column; gap: 3px; padding: var(--sp-3); flex: 1 1 auto; }
.pcerp-tplcard-title { font-weight: 600; font-size: 0.95rem; color: var(--color-text); line-height: 1.25; }
.pcerp-tplcard-code { font-size: 0.72rem; color: var(--color-text-muted); font-family: ui-monospace, "SF Mono", Menlo, monospace; }
.pcerp-tplcard-actions { display: flex; flex-wrap: wrap; gap: var(--sp-2); padding: 0 var(--sp-3) var(--sp-3); }
.pcerp-authpill { align-self: flex-start; font-size: 0.7rem; font-weight: 600; color: var(--color-primary); background: var(--color-primary-soft); border-radius: var(--radius-pill); padding: 2px 8px; }
.pcerp-field-hint { font-size: 0.72rem; color: var(--color-text-muted); }
.pcerp-fold-sub { font-size: 0.82rem; font-weight: 400; color: var(--color-text-muted); }
.pcerp-lockbanner { display: flex; gap: var(--sp-2); align-items: flex-start; background: var(--color-warning-soft); border: 1px solid var(--color-warning); border-radius: var(--radius-md); padding: var(--sp-3); }
.pcerp-lockbanner-icon { font-size: 1.1rem; line-height: 1.2; flex: 0 0 auto; }

.pcerp-talon .pcerp-talon-total { font-size: var(--text-4xl); font-weight: 700; font-variant-numeric: tabular-nums; line-height: 1.1; color: var(--color-text); }
.pcerp-talon-row { display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-3); padding: var(--sp-1) 0; font-size: var(--text-sm); }
.pcerp-talon-row > span:last-child { font-variant-numeric: tabular-nums; }
.pcerp-talon-row.pcerp-talon-sub { color: var(--color-text-soft); }
.pcerp-talon-warnrow { color: var(--color-warning-dark); }
.pcerp-talon-warnrow a { color: var(--color-warning-dark); font-weight: 600; }
/* Bloc « Dont » (abo/options/frais) */
.pcerp-talon-dont { border: 1px dashed var(--color-border); border-radius: var(--radius-md); padding: var(--sp-2) var(--sp-3); }
/* Marge interne (non imprimée) — carte hachurée discrète */
.pcerp-talon-margin {
    border: 1px solid var(--color-border);
    background:
        repeating-linear-gradient(135deg, var(--color-bg-subtle) 0 6px, transparent 6px 12px);
    border-radius: var(--radius-md); padding: var(--sp-2) var(--sp-3);
}
.pcerp-talon-margin .pcerp-talon-margin-value { color: var(--color-success-dark); font-weight: 700; font-variant-numeric: tabular-nums; }
.pcerp-talon-note { font-size: var(--text-xs); color: var(--color-text-muted); }
/* Prochaine étape — check-list */
.pcerp-step { display: flex; align-items: center; gap: var(--sp-2); font-size: var(--text-sm); padding: var(--sp-1) 0; }
.pcerp-step::before { content: ""; width: 10px; height: 10px; border-radius: 50%; flex: 0 0 auto; background: var(--color-border-strong); }
.pcerp-step.is-now::before  { background: var(--color-primary); box-shadow: 0 0 0 3px var(--color-primary-soft); }
.pcerp-step.is-ok           { color: var(--color-text-soft); }
.pcerp-step.is-ok::before   { content: "✓"; width: auto; height: auto; border-radius: 0; background: none; color: var(--color-success); font-weight: 700; }
.pcerp-step.is-warn::before { content: "⚠"; width: auto; height: auto; border-radius: 0; background: none; color: var(--color-warning); }

/* Dépli détail de ligne dans l'éditeur */
table.data.pcerp-rows tbody tr.pcerp-line.is-open td:first-child { box-shadow: inset 3px 0 0 var(--color-primary); }
table.data.pcerp-rows tbody tr.pcerp-detail > td { padding: 0; background: var(--color-bg-subtle); border-bottom: 2px solid var(--color-primary); }
.pcerp-detail-wrap {
    display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--sp-3) var(--sp-4); padding: var(--sp-3) var(--sp-4);
    animation: pcerp-expand var(--dur-base) var(--ease-out);
}
@media (max-width: 960px) { .pcerp-detail-wrap { grid-template-columns: 1fr; } }
.pcerp-detail-field { display: flex; flex-direction: column; gap: var(--sp-1); min-width: 0; }
.pcerp-detail-field > label { font-size: var(--text-xs); font-weight: 600; color: var(--color-text-soft); }
.pcerp-detail-hint { font-size: var(--text-xs); color: var(--color-text-muted); }

/* Sous-total inséré */
table.data.pcerp-rows tbody tr.pcerp-subtotal > td { background: var(--color-bg-subtle); font-weight: 700; }

/* Ligne « TGC manquante » (alias : .pcerp-tgc--missing) */
.pcerp-tgc.is-missing, .pcerp-tgc--missing {
    background: var(--color-warning-soft) !important;
    box-shadow: inset 3px 0 0 var(--color-warning);
}
.pcerp-tgc.is-fixed { animation: pcerp-flash var(--dur-slow) var(--ease-out); }

/* Grille éditeur : colonne principale (form) + talon sticky (aside).
   Sélecteur NOUVEAU (aucun existant redéfini) — la page n'a qu'à envelopper
   son <form> + son <aside class="pcerp-talon"> dans .pcerp-edit-grid.
   minmax(0,1fr) laisse la table de lignes rétrécir/scroller sans déborder. */
.pcerp-edit-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 340px;
    gap: var(--sp-4);
    align-items: start;
}
.pcerp-edit-grid > form { min-width: 0; }
@media (max-width: 960px) {
    .pcerp-edit-grid { grid-template-columns: 1fr; }
}
/* Carte CTA du talon : actions empilées, pleine largeur */
.pcerp-talon-cta { display: flex; flex-direction: column; gap: var(--sp-2); }
.pcerp-talon-cta .btn { width: 100%; justify-content: center; }
.pcerp-talon-cta .pcerp-talon-note { text-align: center; }
/* Lien d'étape (prochaine étape) — réutilise la couleur primaire */
.pcerp-step-link { color: var(--color-primary-text); text-decoration: none; }
.pcerp-step-link:hover { text-decoration: underline; }

/* Volet « Autres infos » (non imprimé) */
.pcerp-drawer-btn {
    display: inline-flex; align-items: center; gap: var(--sp-1-5);
    font-size: var(--text-sm); color: var(--color-text-soft);
    background: none; border: 1px solid var(--color-border); border-radius: var(--radius-sm);
    padding: var(--sp-1) var(--sp-2); cursor: pointer;
}
.pcerp-drawer-btn[aria-expanded="true"] { background: var(--color-primary-ultra); border-color: var(--color-primary); }
.pcerp-drawer-btn .pcerp-drawer-count { font-weight: 700; color: var(--color-primary-text); }
.pcerp-drawer { border: 1px solid var(--color-border); border-radius: var(--radius-md); padding: var(--sp-3); background: var(--color-bg-subtle); }
.pcerp-drawer[hidden] { display: none; }
.pcerp-drawer-note { font-size: var(--text-xs); color: var(--color-text-muted); }

/* ----- F5 · Menu de ligne, feuille de raccourcis, toasts d'annulation ----- */
/* Déclencheur ⋯ de menu de ligne (apparaît au survol) */
.pcerp-lmenu {
    opacity: 0; background: none; border: 0; cursor: pointer; color: var(--color-text-muted);
    padding: var(--sp-1); border-radius: var(--radius-sm); line-height: 1;
    transition: opacity var(--dur-fast) var(--ease-out), background-color var(--dur-fast) var(--ease-out);
}
table.data.pcerp-rows tbody tr:hover .pcerp-lmenu,
.pcerp-lmenu:focus-visible { opacity: 1; }
/* Éditeurs de lignes (devis/commande/facture) : la table n'est pas .pcerp-rows
   mais le ⋯ doit quand même apparaître au survol de la ligne. */
[data-pcerp-keys] table.data tbody tr:hover .pcerp-lmenu { opacity: 1; }
.pcerp-lmenu:hover { background: var(--color-primary-ultra); color: var(--color-text); }

/* Menu popover origin-aware (.pcerp-menu / .pcerp-rowmenu) */
.pcerp-menu, .pcerp-rowmenu {
    position: fixed; z-index: 10000; min-width: 220px;
    background: var(--color-surface); border: 1px solid var(--color-border);
    border-radius: var(--radius-md); box-shadow: var(--shadow-lg);
    padding: var(--sp-1); margin: 0;
    animation: pcerp-pop var(--dur-base) var(--ease-out);
}
.pcerp-menu[hidden], .pcerp-rowmenu[hidden] { display: none; }
.pcerp-menu button, .pcerp-rowmenu button {
    display: flex; align-items: center; gap: var(--sp-2); width: 100%;
    padding: var(--sp-1-5) var(--sp-2); border: 0; background: none; border-radius: var(--radius-sm);
    font: inherit; color: var(--color-text); text-align: left; cursor: pointer;
}
.pcerp-menu button:hover, .pcerp-menu button:focus-visible,
.pcerp-rowmenu button:hover, .pcerp-rowmenu button:focus-visible { background: var(--color-primary-ultra); outline: none; }
.pcerp-menu button.is-danger, .pcerp-rowmenu button.is-danger { color: var(--color-danger); }
.pcerp-menu-sep, .pcerp-rowmenu-sep { height: 1px; margin: var(--sp-1) 0; background: var(--color-border-soft); }
.pcerp-menu .kbd, .pcerp-rowmenu .kbd, .pcerp-shortcuts .kbd {
    margin-left: auto; font-family: var(--font-mono); font-size: var(--text-xs);
    color: var(--color-text-muted); background: var(--color-bg-subtle);
    border: 1px solid var(--color-border); border-radius: var(--radius-xs); padding: 0 var(--sp-1);
}

/* Feuille de raccourcis (touche ?) */
.pcerp-shortcuts dl { display: grid; grid-template-columns: auto 1fr; gap: var(--sp-2) var(--sp-4); margin: 0; }
.pcerp-shortcuts dt { font-family: var(--font-mono); font-size: var(--text-sm); color: var(--color-text); white-space: nowrap; }
.pcerp-shortcuts dd { margin: 0; font-size: var(--text-sm); color: var(--color-text-soft); }

/* Pile de toasts d'annulation (bas-gauche, non bloquant) */
#pcerp-toast-stack {
    position: fixed; left: var(--sp-4); bottom: var(--sp-4); z-index: 10001;
    display: flex; flex-direction: column; gap: var(--sp-2); max-width: min(380px, calc(100vw - 2 * var(--sp-4)));
}
.pcerp-toast {
    position: relative; overflow: hidden;
    display: flex; align-items: center; gap: var(--sp-3);
    padding: var(--sp-2-5) var(--sp-3); padding-bottom: calc(var(--sp-2-5) + 3px);
    background: var(--pcerp-toast-bg); color: var(--pcerp-toast-fg);
    border-radius: var(--radius-md); box-shadow: var(--shadow-lg);
    font-size: var(--text-sm); line-height: 1.4;
    animation: pcerp-toastIn var(--dur-slow) var(--ease-out);
}
.pcerp-toast.is-leaving { animation: pcerp-toastOut var(--dur-base) var(--ease-in-out) forwards; }
.pcerp-toast-msg { flex: 1 1 auto; }
.pcerp-toast-undo {
    flex: 0 0 auto; background: none; border: 0; cursor: pointer;
    color: var(--pcerp-toast-link); font: inherit; font-weight: 600; text-decoration: underline; padding: var(--sp-1);
}
.pcerp-toast-undo:focus-visible { outline: 2px solid var(--pcerp-toast-link); outline-offset: 2px; border-radius: var(--radius-xs); }
.pcerp-toast-bar { position: absolute; left: 0; bottom: 0; height: 3px; width: 100%; background: var(--color-primary); transform-origin: left; }
.pcerp-toast.is-running .pcerp-toast-bar { animation: pcerp-toastBar var(--undo-ttl) linear forwards; }
/* Refonte lot D : minuteur en pause au survol ou au focus du toast (app.js) → la barre aussi. */
.pcerp-toast.is-paused .pcerp-toast-bar { animation-play-state: paused; }

/* ----- Keyframes (transform/opacity uniquement, sauf barre toast = width assumé) ----- */
@keyframes pcerp-slideDown { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }
@keyframes pcerp-expand    { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
@keyframes pcerp-pop       { from { opacity: 0; transform: scale(.97); } to { opacity: 1; transform: none; } }
@keyframes pcerp-toastIn   { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
@keyframes pcerp-toastOut  { to   { opacity: 0; transform: translateY(12px); } }
@keyframes pcerp-toastBar  { from { width: 100%; } to { width: 0%; } }
@keyframes pcerp-flash     { 0% { background: var(--color-success-soft); } 100% { background: transparent; } }

/* Réduction de mouvement — neutralise toutes les animations .pcerp-* */
@media (prefers-reduced-motion: reduce) {
    .pcerp-selbar, .pcerp-detail-wrap, .pcerp-menu, .pcerp-rowmenu,
    .pcerp-toast, .pcerp-toast.is-leaving, .pcerp-tgc.is-fixed,
    table.data.pcerp-rows tbody tr { animation-duration: .01ms !important; transition-duration: .01ms !important; }
    /* Mouvement réduit : pas de barre animée ; le toast se ferme quand même (timer JS) */
    .pcerp-toast .pcerp-toast-bar { animation: none !important; display: none !important; }
}

/* Responsive : le talon passe sous les lignes sous 960px (grille à gérer côté page) */
@media (max-width: 960px) {
    .pcerp-talon { position: static; }
}

/* ----- Catalogue : pill de TYPE d'article (kind) ----- */
/* Pastille colorée par type d'article — réutilise UNIQUEMENT les tokens doc/bill
   déjà définis (aucune couleur en dur, aucun token nouveau). */
.pcerp-kind {
    display: inline-flex; align-items: center; gap: var(--sp-1);
    padding: var(--sp-0-5) var(--sp-2); border-radius: var(--radius-sm);
    font-size: var(--text-xs); font-weight: 600; line-height: 1.4;
    background: var(--color-bg-subtle); color: var(--color-text-soft);
}
.pcerp-kind.is-product      { color: var(--color-doc-invoice);  background: var(--color-doc-invoice-soft); }
.pcerp-kind.is-service      { color: var(--color-doc-order);     background: var(--color-doc-order-soft); }
.pcerp-kind.is-subscription { color: var(--color-bill-abo);      background: var(--color-bill-abo-soft); }
.pcerp-kind.is-license      { color: var(--color-doc-delivery);  background: var(--color-doc-delivery-soft); }
.pcerp-kind.is-bundle       { color: var(--color-doc-quote);     background: var(--color-doc-quote-soft); }
.pcerp-kind.is-fee          { color: var(--color-bill-ini);      background: var(--color-bill-ini-soft); }

/* Valeur de marge / stock colorée par token (remplace les hex en dur de l'ancienne liste) */
.pcerp-num-pos { color: var(--color-success-dark); font-variant-numeric: tabular-nums; }
.pcerp-num-neg { color: var(--color-danger);       font-variant-numeric: tabular-nums; }

/* Cellule TGC manquante (td) — s'appuie sur .pcerp-tgc.is-missing (défini plus haut) */
.pcerp-tgc.is-missing .pcerp-tgc-flag { color: var(--color-warning-dark); font-weight: 600; }

/* ----- Fiche article : en-tête .dhead-like + sections repliables ----- */
.pcerp-dhead { display: flex; align-items: flex-start; gap: var(--sp-3); flex-wrap: wrap; }
.pcerp-dhead-main { flex: 1 1 auto; min-width: 0; }
.pcerp-dhead-title { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }
.pcerp-dhead-title h1 { margin: 0; }
.pcerp-dhead-code {
    font-family: var(--font-mono); font-size: var(--text-sm);
    color: var(--color-text-muted); background: var(--color-bg-subtle);
    border: 1px solid var(--color-border); border-radius: var(--radius-xs); padding: 0 var(--sp-1-5);
}
.pcerp-dhead-chips { display: flex; gap: var(--sp-1-5); flex-wrap: wrap; margin-top: var(--sp-1-5); }

/* Section repliable mémorisée : <details class="pcerp-fold"> */
.pcerp-fold {
    border: 1px solid var(--color-border); border-radius: var(--radius-md);
    background: var(--color-surface); margin-bottom: var(--sp-4);
}
.pcerp-fold > summary {
    display: flex; align-items: center; gap: var(--sp-2);
    padding: var(--sp-3) var(--sp-4); cursor: pointer; list-style: none;
    font-weight: 600; font-size: var(--text-lg); color: var(--color-text);
}
.pcerp-fold > summary::-webkit-details-marker { display: none; }
.pcerp-fold > summary::before {
    content: "\25B8"; color: var(--color-text-muted); flex: 0 0 auto;
    transition: transform var(--dur-fast) var(--ease-out);
}
.pcerp-fold[open] > summary::before { transform: rotate(90deg); }
.pcerp-fold > summary:hover { color: var(--color-primary-text); }
.pcerp-fold > summary:focus-visible { outline: 2px solid var(--color-focus-ring); outline-offset: -2px; border-radius: var(--radius-md); }
.pcerp-fold-count { margin-left: auto; font-weight: 400; font-size: var(--text-xs); color: var(--color-text-muted); }
.pcerp-fold-body { padding: 0 var(--sp-4) var(--sp-4); }
@media (prefers-reduced-motion: reduce) {
    .pcerp-fold > summary::before { transition-duration: .01ms; }
}

/* ----- Graphe à barres SVG inline (partial partials.pcerp_svg_chart) -----
   Rendu 100 % serveur : aucun CDN, aucune bibliothèque, aucun JS requis.
   Couleurs par TOKENS → vert sous Capi, orange sous Wari, etc. */
.pcerp-chart { margin: 0; }
.pcerp-chart-scroll { overflow-x: auto; overflow-y: hidden; }
.pcerp-chart-svg { display: block; width: 100%; min-width: 440px; height: auto; }
.pcerp-chart-grid { stroke: var(--color-border); stroke-width: 1; }
.pcerp-chart-grid-base { stroke: var(--color-border-strong); }
.pcerp-chart-yaxis,
.pcerp-chart-xaxis { fill: var(--color-text-muted); font-size: 11px; font-family: inherit; }
.pcerp-chart-vlabel { fill: var(--color-text); font-size: 11px; font-weight: 700; font-family: inherit; }
.pcerp-chart-bar.is-primary,
.pcerp-chart-bar.is-hl { fill: var(--color-primary); }
.pcerp-chart-bar.is-muted { fill: var(--color-gray-300); }
/* Valeur NÉGATIVE (CA/encours net des avoirs) : sous la ligne de base, en danger. */
.pcerp-chart-bar.is-neg { fill: var(--color-danger); }
.pcerp-chart-bar.is-muted.is-neg { fill: var(--color-danger); opacity: .5; }
.pcerp-chart-bar { transition: opacity var(--dur-fast) var(--ease-out); }
.pcerp-chart-bar:hover { opacity: .85; }
.pcerp-chart-legend {
    display: flex; flex-wrap: wrap; gap: var(--sp-3);
    margin-top: var(--sp-2); font-size: var(--text-xs); color: var(--color-text-muted);
}
.pcerp-chart-legend .sw { display: inline-block; width: .7rem; height: .7rem; border-radius: 2px; margin-right: .35rem; vertical-align: middle; }
.pcerp-chart-legend .sw.is-primary { background: var(--color-primary); }
.pcerp-chart-legend .sw.is-muted { background: var(--color-gray-300); }
.pcerp-chart-empty { color: var(--color-text-muted); font-size: var(--text-sm); margin: var(--sp-3) 0; }

/* Barre de proportion en cellule de tableau récap (ex. Top clients) */
.pcerp-bar-inline {
    position: relative; height: 8px; min-width: 60px;
    border-radius: var(--radius-pill); background: var(--color-primary-soft); overflow: hidden;
}
.pcerp-bar-inline > span { position: absolute; top: 0; bottom: 0; left: 0; background: var(--color-primary); border-radius: var(--radius-pill); }

/* Barre empilée horizontale (ex. balance âgée) — HTML/CSS pur, sans JS.
   Escalade sémantique par TOKENS : à venir → warning → danger. */
.pcerp-stackbar {
    display: flex; height: 20px; overflow: hidden;
    border-radius: var(--radius-sm); border: 1px solid var(--color-border); background: var(--color-bg-subtle);
}
.pcerp-stackbar > span { display: block; min-width: 0; height: 100%; }
.pcerp-stackbar > span.is-ok   { background: var(--color-primary); }
.pcerp-stackbar > span.is-w1   { background: var(--color-warning); }
.pcerp-stackbar > span.is-w2   { background: var(--color-warning-dark); }
.pcerp-stackbar > span.is-d1   { background: var(--color-danger); }
.pcerp-stackbar > span.is-d2   { background: var(--color-danger-dark); }
/* Segment CRÉDIT (avoir : bucket à valeur négative) — distinct, hachuré en danger. */
.pcerp-stackbar > span.is-credit {
    background: repeating-linear-gradient(45deg, var(--color-danger), var(--color-danger) 4px, var(--color-danger-dark) 4px, var(--color-danger-dark) 8px);
}

/* Pastille récap NON interactive (pcerp-tot servant d'étiquette, pas de filtre) */
.pcerp-tot.is-static { cursor: default; }
.pcerp-tot.is-static:hover { border-color: var(--color-border); }

/* Utilitaire d'accessibilité : contenu réservé aux lecteurs d'écran */
.pcerp-sr-only {
    position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ===== /REFONTE : design-system partagé (.pcerp-*) ===== */
