/* ==========================================================================
   360CONTROL ORNAGROUP — Système de design ORNA
   Référence : cahier des charges §16 (palette, typographie, composants),
   §18 (accessibilité), §16.3 (paliers responsive 950 px et 640 px).
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Jetons de conception
   -------------------------------------------------------------------------- */
:root {
    /* Palette ORNA — §16.1, couleurs extraites du logo */
    --orna-blue:        #1a1a6e;
    --orna-blue-dark:   #0d0d3d;
    --orna-blue-light:  #2a2a8e;
    --orna-blue-pale:   #e8e8f4;

    --orna-rose:        #E91E8C;
    --orna-rose-light:  #F5A9D3;
    --orna-rose-pale:   #FCEEF5;
    /* Variante assombrie : le rose #E91E8C n'atteint pas le contraste requis
       pour du texte de petite taille sur fond blanc (§16.1). */
    --orna-rose-text:   #A31264;

    --orna-gold:        #D4A853;
    --orna-gold-dark:   #B8860B;
    --orna-gold-pale:   #FBF4E5;

    /* Neutres */
    --n-0:   #FFFFFF;
    --n-50:  #FAFAFA;
    --n-100: #F5F5F5;
    --n-200: #EDEDED;
    --n-300: #E0E0E0;
    --n-500: #8A8A8A;
    --n-600: #666666;
    --n-900: #333333;

    /* Couleurs fonctionnelles — §16.1 */
    --ok:     #28A745;
    --ok-bg:  #EAF7EE;
    --warn:   #FFC107;
    --warn-bg:#FFF8E1;
    --warn-text: #8A6100;
    --danger: #DC3545;
    --danger-bg: #FDECEE;
    --info:   #17A2B8;
    --info-bg:#E6F6F9;

    /* Typographie — §16.2 */
    --font-ui:      'Poppins', 'Segoe UI', system-ui, -apple-system, 'Helvetica Neue', Arial, sans-serif;
    --font-display: 'Playfair Display', 'Georgia', 'Times New Roman', serif;
    --font-mono:    'JetBrains Mono', 'Consolas', 'SF Mono', 'Courier New', monospace;

    --fs-xs:   0.6875rem;  /* 11px */
    --fs-sm:   0.75rem;    /* 12px */
    --fs-base: 0.8125rem;  /* 13px */
    --fs-md:   0.875rem;   /* 14px */
    --fs-lg:   1rem;       /* 16px */
    --fs-xl:   1.25rem;    /* 20px */
    --fs-2xl:  1.5rem;     /* 24px */
    --fs-3xl:  1.875rem;   /* 30px */

    /* Formes — §16.3 */
    --radius-panel:  13px;
    --radius-button: 9px;
    --radius-input:  8px;
    --radius-pill:   999px;

    /* Espacements */
    --sp-1: 4px;  --sp-2: 8px;  --sp-3: 12px; --sp-4: 16px;
    --sp-5: 20px; --sp-6: 24px; --sp-8: 32px; --sp-10: 40px;

    /* Ombres et transitions */
    --shadow-sm: 0 1px 2px rgba(13, 13, 61, .06);
    --shadow-md: 0 4px 14px rgba(13, 13, 61, .10);
    --shadow-lg: 0 12px 32px rgba(13, 13, 61, .18);
    --ease: 160ms cubic-bezier(.4, 0, .2, 1);

    /* Structure */
    --sidebar-w:           260px;
    --sidebar-w-collapsed: 66px;
    --topbar-h:            60px;
}

/* --------------------------------------------------------------------------
   2. Réinitialisation et base
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
    margin: 0;
    font-family: var(--font-ui);
    font-size: var(--fs-base);
    line-height: 1.55;
    color: var(--n-900);
    background: var(--n-100);
    -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4, h5 { margin: 0; font-weight: 600; color: var(--orna-blue); line-height: 1.25; }
h1 { font-size: var(--fs-2xl); }
h2 { font-size: var(--fs-xl); }
h3 { font-size: var(--fs-lg); }
h4 { font-size: var(--fs-md); }

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

a { color: var(--orna-rose-text); text-decoration: none; }
a:hover { text-decoration: underline; }

ul, ol { margin: 0; padding: 0; list-style: none; }

svg.icon { width: 18px; height: 18px; flex: 0 0 auto; }
svg.icon--sm { width: 15px; height: 15px; }
svg.icon--lg { width: 22px; height: 22px; }

/* Titres de forte hiérarchie et documents imprimés — §16.2 */
.display { font-family: var(--font-display); font-weight: 700; letter-spacing: -.01em; }

/* Identifiants, numéros de compte et montants alignés — §16.2 */
.mono, .num { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.num { text-align: right; white-space: nowrap; }

.muted { color: var(--n-600); }
.text-ok { color: var(--ok); }
.text-danger { color: var(--danger); }
.text-warn { color: var(--warn-text); }

/* Accessibilité — §18 : indicateur de focus visible sur tous les contrôles */
:focus-visible {
    outline: 2px solid var(--orna-rose);
    outline-offset: 2px;
    border-radius: 3px;
}

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

.skip-link {
    position: absolute;
    left: var(--sp-3); top: -100px;
    z-index: 999;
    padding: var(--sp-2) var(--sp-4);
    background: var(--orna-rose);
    color: #fff;
    border-radius: var(--radius-button);
    font-weight: 600;
    transition: top var(--ease);
}
.skip-link:focus { top: var(--sp-3); text-decoration: none; }

/* --------------------------------------------------------------------------
   3. Coquille applicative
   -------------------------------------------------------------------------- */
.app {
    display: grid;
    grid-template-columns: var(--sidebar-w) minmax(0, 1fr);
    min-height: 100vh;
}
.app.is-collapsed { grid-template-columns: var(--sidebar-w-collapsed) minmax(0, 1fr); }

.app__main {
    display: flex;
    flex-direction: column;
    min-width: 0;
    min-height: 100vh;
}

.content {
    flex: 1;
    padding: var(--sp-6);
    min-width: 0;
}

/* --------------------------------------------------------------------------
   4. Barre latérale — §3.1 et §16.3
   -------------------------------------------------------------------------- */
.sidebar {
    position: sticky;
    top: 0;
    height: 100vh;
    display: flex;
    flex-direction: column;
    background: var(--orna-blue);
    color: rgba(255, 255, 255, .82);
    overflow: visible;
    z-index: 40;
}

.sidebar__brand {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    height: var(--topbar-h);
    padding: 0 var(--sp-4);
    border-bottom: 1px solid rgba(255, 255, 255, .10);
    flex: 0 0 auto;
}
.sidebar__logo {
    width: 32px; height: 32px;
    border-radius: 8px;
    object-fit: cover;
    background: #fff;
    flex: 0 0 auto;
}
.sidebar__brand-text { min-width: 0; }
.sidebar__name {
    display: block;
    font-size: var(--fs-md);
    font-weight: 700;
    color: #fff;
    letter-spacing: .01em;
    white-space: nowrap;
}
.sidebar__tagline {
    display: block;
    font-size: var(--fs-xs);
    color: var(--orna-gold);
    white-space: nowrap;
}

.sidebar__nav {
    flex: 1;
    overflow-y: auto;
    overflow-x: hidden;
    padding: var(--sp-4) 0 var(--sp-6);
    scrollbar-width: thin;
    scrollbar-color: rgba(255, 255, 255, .25) transparent;
}
.sidebar__nav::-webkit-scrollbar { width: 6px; }
.sidebar__nav::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, .22); border-radius: 3px; }

.nav-group + .nav-group { margin-top: var(--sp-5); }
.nav-group__title {
    padding: 0 var(--sp-4) var(--sp-2);
    font-size: var(--fs-xs);
    font-weight: 600;
    letter-spacing: .13em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, .45);
}

.nav-item { position: relative; }

.nav-link {
    position: relative;
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    padding: 9px var(--sp-4);
    color: rgba(255, 255, 255, .82);
    font-size: var(--fs-base);
    font-weight: 500;
    white-space: nowrap;
    transition: background var(--ease), color var(--ease);
}
/* Les entrées à sous-menu sont des boutons : on neutralise le style natif. */
button.nav-link {
    width: 100%;
    border: 0;
    background: none;
    font: inherit;
    font-weight: 500;
    text-align: left;
    cursor: pointer;
}

.nav-link:hover,
.nav-link:focus-visible {
    background: var(--orna-blue-dark);
    color: #fff;
    text-decoration: none;
}

/* Entrée active : fond plus clair et liseré d'accent interne — §3.1 */
.nav-link.is-active {
    background: var(--orna-blue-light);
    color: #fff;
    font-weight: 600;
}
.nav-link.is-active::before {
    content: "";
    position: absolute;
    left: 0; top: 6px; bottom: 6px;
    width: 3px;
    border-radius: 0 3px 3px 0;
    background: var(--orna-rose);
}

.nav-link__label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.nav-link__chevron { transition: transform var(--ease); opacity: .6; }
.nav-item.is-open > .nav-link .nav-link__chevron { transform: rotate(180deg); }

/* Badge de niveau requis — §14.1 : la fonctionnalité reste visible mais inactive */
.nav-link__tier {
    font-size: 9px;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    padding: 2px 6px;
    border-radius: var(--radius-pill);
    background: var(--orna-gold);
    color: var(--orna-blue-dark);
}

.nav-sub {
    display: none;
    padding: var(--sp-1) 0 var(--sp-2);
    background: rgba(0, 0, 0, .16);
}
.nav-item.is-open > .nav-sub { display: block; }

.nav-sub__link {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    padding: 7px var(--sp-4) 7px 46px;
    font-size: var(--fs-sm);
    color: rgba(255, 255, 255, .70);
    white-space: nowrap;
}
.nav-sub__link:hover,
.nav-sub__link:focus-visible { color: #fff; background: rgba(255, 255, 255, .06); text-decoration: none; }
.nav-sub__link.is-active { color: #fff; font-weight: 600; }
.nav-sub__link.is-active::before {
    content: "";
    width: 5px; height: 5px;
    border-radius: 50%;
    background: var(--orna-rose);
    margin-left: -13px; margin-right: 8px;
}

.sidebar__footer {
    flex: 0 0 auto;
    padding: var(--sp-3) var(--sp-4);
    border-top: 1px solid rgba(255, 255, 255, .10);
    font-size: var(--fs-xs);
    color: rgba(255, 255, 255, .45);
    white-space: nowrap;
}

/* --------------------------------------------------------------------------
   5. Barre supérieure — §3.2
   -------------------------------------------------------------------------- */
.topbar {
    position: sticky;
    top: 0;
    z-index: 30;
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    height: var(--topbar-h);
    padding: 0 var(--sp-5);
    background: var(--n-0);
    border-bottom: 1px solid var(--n-300);
}

.topbar__toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px; height: 34px;
    border: 1px solid var(--n-300);
    border-radius: var(--radius-button);
    background: var(--n-0);
    color: var(--orna-blue);
    cursor: pointer;
}
.topbar__toggle:hover { background: var(--orna-blue-pale); }

.search {
    position: relative;
    flex: 1 1 320px;
    max-width: 420px;
    min-width: 0;
}
.search__icon {
    position: absolute;
    left: 11px; top: 50%;
    transform: translateY(-50%);
    color: var(--n-500);
    pointer-events: none;
}
.search__input {
    width: 100%;
    height: 36px;
    padding: 0 var(--sp-3) 0 36px;
    font: inherit;
    color: var(--n-900);
    background: var(--n-100);
    border: 1px solid transparent;
    border-radius: var(--radius-input);
    transition: border-color var(--ease), background var(--ease);
}
.search__input::placeholder { color: var(--n-500); }
.search__input:focus {
    background: var(--n-0);
    border-color: var(--orna-blue-light);
    outline: none;
    box-shadow: 0 0 0 3px var(--orna-blue-pale);
}

.topbar__spacer { flex: 1; }

/* Sélecteurs de contexte : société active et exercice comptable */
.context-select {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
    height: 36px;
    padding: 0 var(--sp-3);
    background: var(--n-0);
    border: 1px solid var(--n-300);
    border-radius: var(--radius-button);
    color: var(--orna-blue);
    font-size: var(--fs-sm);
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
    max-width: 230px;
}
.context-select:hover { border-color: var(--orna-blue-light); background: var(--orna-blue-pale); }
.context-select__label {
    display: block;
    font-size: 9px;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--n-500);
    line-height: 1;
}
.context-select__value {
    display: block;
    line-height: 1.2;
    overflow: hidden;
    text-overflow: ellipsis;
}
.context-select__text { min-width: 0; text-align: left; }

.icon-button {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px; height: 36px;
    border: 1px solid var(--n-300);
    border-radius: var(--radius-button);
    background: var(--n-0);
    color: var(--orna-blue);
    cursor: pointer;
}
.icon-button:hover { background: var(--orna-blue-pale); border-color: var(--orna-blue-light); }
.icon-button__count {
    position: absolute;
    top: -6px; right: -6px;
    min-width: 17px; height: 17px;
    padding: 0 4px;
    border-radius: var(--radius-pill);
    background: var(--orna-rose);
    color: #fff;
    font-size: 10px;
    font-weight: 700;
    line-height: 17px;
    text-align: center;
}

/* Bandeau utilisateur */
.userbar {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
    height: 36px;
    padding: 0 var(--sp-2) 0 var(--sp-1);
    border: 1px solid transparent;
    border-radius: var(--radius-button);
    background: transparent;
    cursor: pointer;
    color: inherit;
    font: inherit;
}
.userbar:hover { background: var(--n-100); border-color: var(--n-300); }
.userbar__avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px; height: 30px;
    border-radius: 50%;
    background: var(--orna-blue);
    color: #fff;
    font-size: var(--fs-sm);
    font-weight: 700;
}
.userbar__text { text-align: left; line-height: 1.15; }
.userbar__name { display: block; font-size: var(--fs-sm); font-weight: 600; color: var(--orna-blue); }
.userbar__role { display: block; font-size: var(--fs-xs); color: var(--n-600); }

/* Menus déroulants */
.dropdown { position: relative; }
.dropdown__panel {
    position: absolute;
    right: 0; top: calc(100% + 8px);
    min-width: 260px;
    padding: var(--sp-2);
    background: var(--n-0);
    border: 1px solid var(--n-300);
    border-radius: var(--radius-panel);
    box-shadow: var(--shadow-lg);
    z-index: 60;
}
.dropdown__panel[hidden] { display: none; }
.dropdown__title {
    padding: var(--sp-2) var(--sp-3) var(--sp-1);
    font-size: var(--fs-xs);
    font-weight: 700;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--n-500);
}
.dropdown__item {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    width: 100%;
    padding: var(--sp-2) var(--sp-3);
    border: 0;
    border-radius: var(--radius-input);
    background: none;
    font: inherit;
    color: var(--n-900);
    text-align: left;
    cursor: pointer;
}
.dropdown__item:hover { background: var(--n-100); text-decoration: none; }
.dropdown__item.is-active { background: var(--orna-blue-pale); color: var(--orna-blue); font-weight: 600; }
.dropdown__item small { display: block; color: var(--n-600); font-size: var(--fs-xs); }
.dropdown__sep { height: 1px; margin: var(--sp-2) 0; background: var(--n-200); }

/* --------------------------------------------------------------------------
   6. En-tête de page
   -------------------------------------------------------------------------- */
.page-head {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--sp-4);
    flex-wrap: wrap;
    margin-bottom: var(--sp-5);
}
.page-head__title { display: flex; align-items: center; gap: var(--sp-3); }

/* Filet d'accent sous le titre : il ancre l'en-tête et rappelle la palette
   sans colorer le texte, qui doit rester au contraste maximal. */
.page-head__title h1 { position: relative; padding-bottom: var(--sp-2); }
.page-head__title h1::after {
    content: "";
    position: absolute;
    left: 0; bottom: 0;
    width: 46px; height: 3px;
    border-radius: var(--radius-pill);
    background: linear-gradient(90deg, var(--orna-rose) 0%, var(--orna-gold) 100%);
}
.page-head__subtitle { margin: var(--sp-1) 0 0; color: var(--n-600); font-size: var(--fs-md); }
.page-head__actions { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }

.breadcrumb {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    margin-bottom: var(--sp-2);
    font-size: var(--fs-sm);
    color: var(--n-600);
}
.breadcrumb a { color: var(--n-600); }
.breadcrumb a:hover { color: var(--orna-rose-text); }
.breadcrumb__sep { color: var(--n-300); }

/* --------------------------------------------------------------------------
   7. Panneaux — §16.3 : fond blanc, filet 1 px, rayon 13 px
   -------------------------------------------------------------------------- */
.panel {
    position: relative;
    background: var(--n-0);
    border: 1px solid var(--n-300);
    border-radius: var(--radius-panel);
    box-shadow: var(--shadow-sm);
    overflow: hidden;
    transition: box-shadow var(--ease), border-color var(--ease);
}
.panel:hover { box-shadow: var(--shadow-md); }
.panel + .panel { margin-top: var(--sp-5); }
/* Un panneau suivi d'une grille (ou l'inverse) doit garder le même écart
   qu'entre deux panneaux, sinon les blocs se touchent. */
.panel + .grid,
.grid + .panel,
.grid + .grid { margin-top: var(--sp-5); }

.panel__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-3);
    padding: var(--sp-4) var(--sp-5);
    border-bottom: 1px solid var(--n-200);
    /* Bandeau de tête très légèrement teinté : il détache le titre du corps
       sans ajouter de filet ni de couleur pleine. */
    background: linear-gradient(180deg, var(--orna-blue-pale) 0%, rgba(232, 232, 244, 0) 100%);
}
.panel__title { display: flex; align-items: center; gap: var(--sp-3); font-size: var(--fs-md); font-weight: 600; color: var(--orna-blue); }

/* L'icône du titre devient une pastille pleine : c'est elle qui donne son
   repère visuel au panneau, sans qu'aucun gabarit ait à changer. */
.panel__title > svg.icon {
    box-sizing: content-box;
    width: 15px; height: 15px;
    padding: 6px;
    border-radius: 9px;
    background: linear-gradient(140deg, var(--orna-blue) 0%, var(--orna-blue-light) 100%);
    color: #fff;
    flex: 0 0 auto;
}
.panel__actions { display: flex; align-items: center; gap: var(--sp-2); }
.panel__body { padding: var(--sp-5); }
.panel__body--flush { padding: 0; }
.panel__foot {
    padding: var(--sp-3) var(--sp-5);
    border-top: 1px solid var(--n-200);
    background: var(--n-50);
    font-size: var(--fs-sm);
    color: var(--n-600);
}
/* Défilement interne — §16.3 */
.panel__scroll { max-height: 380px; overflow-y: auto; }

/* Grille de mise en page */
.grid { display: grid; gap: var(--sp-5); }
.grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid--2-1 { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); }

/* Tailles de bloc du tableau de bord — §4.1 */
.span-full { grid-column: 1 / -1; }
.span-half { grid-column: span 2; }
.span-quarter { grid-column: span 1; }

/* --------------------------------------------------------------------------
   8. Indicateurs
   -------------------------------------------------------------------------- */
/*
 * Chaque indicateur porte une teinte, déclinée en trois variables : le ton
 * soutenu qui sert au texte et doit rester lisible sur blanc (§18), le ton
 * clair qui termine les dégradés, et le voile très pâle du fond de carte.
 * Changer de ton, c'est changer ces trois variables — jamais une propriété
 * de mise en forme.
 */
.kpi {
    --kpi-ton:        var(--orna-blue);
    --kpi-ton-clair:  var(--orna-blue-light);
    --kpi-voile:      var(--orna-blue-pale);

    position: relative;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
    padding: var(--sp-4) var(--sp-5);
    /* Le dégradé part du blanc : la valeur reste sur fond clair, quel que
       soit le ton retenu. */
    background: linear-gradient(152deg, var(--n-0) 0%, var(--n-0) 38%, var(--kpi-voile) 100%);
    border: 1px solid var(--n-300);
    border-radius: var(--radius-panel);
    box-shadow: var(--shadow-sm);
    transition: transform var(--ease), box-shadow var(--ease), border-color var(--ease);
}

/* Liseré d'accent : c'est lui qui donne sa couleur à la carte sans toucher
   au contraste du texte. */
.kpi::before {
    content: "";
    position: absolute;
    top: 0; bottom: 0; left: 0;
    width: 4px;
    background: linear-gradient(180deg, var(--kpi-ton) 0%, var(--kpi-ton-clair) 100%);
}

/* Halo décoratif, purement ornemental : aucune information n'y est portée. */
.kpi::after {
    content: "";
    position: absolute;
    top: -46px; right: -46px;
    width: 128px; height: 128px;
    border-radius: 50%;
    background: radial-gradient(circle, var(--kpi-voile) 0%, transparent 70%);
    opacity: .85;
    pointer-events: none;
    transition: transform var(--ease), opacity var(--ease);
}

.kpi:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-md);
    border-color: var(--kpi-ton-clair);
}
.kpi:hover::after { transform: scale(1.15); opacity: 1; }

.kpi__head { position: relative; display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2); }
.kpi__label {
    font-size: var(--fs-xs);
    font-weight: 600;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--n-600);
}
.kpi__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px; height: 32px;
    border-radius: 10px;
    background: linear-gradient(140deg, var(--kpi-ton) 0%, var(--kpi-ton-clair) 100%);
    color: #fff;
    /* Repli pour les navigateurs sans color-mix : une ombre neutre plutôt
       qu'aucune ombre. */
    box-shadow: var(--shadow-sm);
    box-shadow: 0 2px 8px color-mix(in srgb, var(--kpi-ton) 35%, transparent);
    transition: transform var(--ease), box-shadow var(--ease);
}
.kpi:hover .kpi__icon {
    transform: translateY(-1px) scale(1.06);
    box-shadow: var(--shadow-md);
    box-shadow: 0 4px 14px color-mix(in srgb, var(--kpi-ton) 45%, transparent);
}

.kpi__value {
    position: relative;
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: var(--fs-2xl);
    font-weight: 700;
    color: var(--kpi-ton);
    line-height: 1.1;
}
.kpi__foot { position: relative; display: flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-sm); color: var(--n-600); }
.kpi__trend { display: inline-flex; align-items: center; gap: 4px; font-weight: 600; }
.kpi__trend--up { color: var(--ok); }
.kpi__trend--down { color: var(--danger); }

/* Tons disponibles. Le ton soutenu est toujours une couleur de texte validée
   au contraste : le rose vif du logo ne l'est pas, c'est sa variante
   assombrie qui porte les chiffres (§16.1). */
.kpi--rose   { --kpi-ton: var(--orna-rose-text); --kpi-ton-clair: var(--orna-rose);      --kpi-voile: var(--orna-rose-pale); }
.kpi--gold   { --kpi-ton: var(--orna-gold-dark); --kpi-ton-clair: var(--orna-gold);      --kpi-voile: var(--orna-gold-pale); }
.kpi--ok     { --kpi-ton: #1E7A34;               --kpi-ton-clair: var(--ok);             --kpi-voile: var(--ok-bg); }
.kpi--danger { --kpi-ton: #A81B28;               --kpi-ton-clair: var(--danger);         --kpi-voile: var(--danger-bg); }
.kpi--info   { --kpi-ton: #0F7180;               --kpi-ton-clair: var(--info);           --kpi-voile: var(--info-bg); }
.kpi--warn   { --kpi-ton: var(--warn-text);      --kpi-ton-clair: var(--warn);           --kpi-voile: var(--warn-bg); }

/* Une valeur négative reprend le rouge fonctionnel : le ton de la carte ne
   doit pas masquer un solde débiteur. */
.kpi__value.text-danger { color: var(--danger); }

/* Apparition en cascade — §16.3. Décorative : l'ordre de lecture et le
   contenu sont les mêmes sans elle. */
@keyframes kpi-apparition {
    from { opacity: 0; transform: translateY(10px); }
    to   { opacity: 1; transform: none; }
}
.kpi { animation: kpi-apparition 380ms cubic-bezier(.22, 1, .36, 1) backwards; }
.kpi:nth-child(1) { animation-delay: 0ms; }
.kpi:nth-child(2) { animation-delay: 60ms; }
.kpi:nth-child(3) { animation-delay: 120ms; }
.kpi:nth-child(4) { animation-delay: 180ms; }
.kpi:nth-child(5) { animation-delay: 240ms; }
.kpi:nth-child(6) { animation-delay: 300ms; }
.kpi:nth-child(7) { animation-delay: 360ms; }
.kpi:nth-child(8) { animation-delay: 420ms; }

/* Le compteur monte jusqu'à la valeur ; tant qu'il monte, la valeur exacte
   reste annoncée aux technologies d'assistance par l'attribut de secours. */
.kpi__value[data-compteur] { font-variant-numeric: tabular-nums; }

/* --------------------------------------------------------------------------
   Révélation au défilement — §16.3

   Panneaux et lignes de liste montent en place à leur entrée à l'écran. Le
   marquage est posé par le script : sans JavaScript, rien n'est masqué, la
   page s'affiche telle quelle. C'est la règle pour tout ce qui est
   décoratif — on n'entre jamais dans un état où le contenu dépend d'une
   animation pour être visible.
   -------------------------------------------------------------------------- */
[data-reveal] { opacity: 0; transform: translateY(14px); }
[data-reveal].est-visible {
    opacity: 1;
    transform: none;
    transition: opacity 420ms cubic-bezier(.22, 1, .36, 1), transform 420ms cubic-bezier(.22, 1, .36, 1);
}

/* Les lignes d'une même liste se révèlent en cascade. */
[data-reveal-liste] > * { opacity: 0; transform: translateY(8px); }
[data-reveal-liste].est-visible > * {
    opacity: 1;
    transform: none;
    transition: opacity 320ms ease-out, transform 320ms cubic-bezier(.22, 1, .36, 1);
}
[data-reveal-liste].est-visible > *:nth-child(1) { transition-delay: 0ms; }
[data-reveal-liste].est-visible > *:nth-child(2) { transition-delay: 45ms; }
[data-reveal-liste].est-visible > *:nth-child(3) { transition-delay: 90ms; }
[data-reveal-liste].est-visible > *:nth-child(4) { transition-delay: 135ms; }
[data-reveal-liste].est-visible > *:nth-child(5) { transition-delay: 180ms; }
[data-reveal-liste].est-visible > *:nth-child(6) { transition-delay: 225ms; }
[data-reveal-liste].est-visible > *:nth-child(7) { transition-delay: 270ms; }
[data-reveal-liste].est-visible > *:nth-child(n+8) { transition-delay: 315ms; }

/* --------------------------------------------------------------------------
   9. Boutons — §16.3 : rayon 9 px, action principale rose, secondaire blanche bordée
   -------------------------------------------------------------------------- */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-2);
    height: 36px;
    padding: 0 var(--sp-4);
    border: 1px solid transparent;
    border-radius: var(--radius-button);
    font: inherit;
    font-weight: 600;
    line-height: 1;
    cursor: pointer;
    white-space: nowrap;
    transition: background var(--ease), border-color var(--ease), color var(--ease);
}
.btn:hover { text-decoration: none; }
.btn:disabled, .btn[aria-disabled="true"] { opacity: .55; cursor: not-allowed; }

.btn--primary { background: var(--orna-rose); color: #fff; }
.btn--primary:hover:not(:disabled) { background: #cf1279; }

.btn--secondary { background: var(--n-0); color: var(--orna-blue); border-color: var(--n-300); }
.btn--secondary:hover:not(:disabled) { background: var(--orna-blue-pale); border-color: var(--orna-blue-light); }

.btn--blue { background: var(--orna-blue); color: #fff; }
.btn--blue:hover:not(:disabled) { background: var(--orna-blue-dark); }

.btn--ghost { background: transparent; color: var(--orna-blue); }
.btn--ghost:hover:not(:disabled) { background: var(--n-100); }

.btn--danger { background: var(--danger); color: #fff; }
.btn--danger:hover:not(:disabled) { background: #b52d3a; }

.btn--sm { height: 30px; padding: 0 var(--sp-3); font-size: var(--fs-sm); }
.btn--lg { height: 44px; padding: 0 var(--sp-6); font-size: var(--fs-md); }
.btn--block { width: 100%; }

.btn-group { display: inline-flex; gap: var(--sp-2); flex-wrap: wrap; }

/* --------------------------------------------------------------------------
   10. Formulaires — §18 : chaque champ possède une étiquette
   -------------------------------------------------------------------------- */
.field { margin-bottom: var(--sp-4); }
.field__label {
    display: block;
    margin-bottom: 5px;
    font-size: var(--fs-sm);
    font-weight: 600;
    color: var(--n-900);
}
.field__label .req { color: var(--orna-rose-text); }
.field__hint { margin-top: 4px; font-size: var(--fs-xs); color: var(--n-600); }
.field__error { margin-top: 4px; font-size: var(--fs-xs); color: var(--danger); font-weight: 600; }

.input, .select, .textarea {
    width: 100%;
    min-height: 36px;
    padding: 7px var(--sp-3);
    font: inherit;
    color: var(--n-900);
    background: var(--n-0);
    border: 1px solid var(--n-300);
    border-radius: var(--radius-input);
    transition: border-color var(--ease), box-shadow var(--ease);
}
.input:focus, .select:focus, .textarea:focus {
    outline: none;
    border-color: var(--orna-blue-light);
    box-shadow: 0 0 0 3px var(--orna-blue-pale);
}
.input[aria-invalid="true"], .select[aria-invalid="true"] {
    border-color: var(--danger);
    box-shadow: 0 0 0 3px var(--danger-bg);
}
.input:disabled, .select:disabled, .textarea:disabled { background: var(--n-100); color: var(--n-600); cursor: not-allowed; }
.input--num { font-family: var(--font-mono); text-align: right; font-variant-numeric: tabular-nums; }
.textarea { min-height: 84px; resize: vertical; }
.select {
    appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23666' stroke-width='2' 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;
    padding-right: 32px;
}

.form-row { display: grid; gap: var(--sp-4); grid-template-columns: repeat(2, minmax(0, 1fr)); }
.form-row--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }

.checkbox, .radio { display: flex; align-items: flex-start; gap: var(--sp-2); font-size: var(--fs-base); cursor: pointer; }
.checkbox input, .radio input { margin-top: 2px; accent-color: var(--orna-rose); width: 16px; height: 16px; }

.fieldset { border: 1px solid var(--n-200); border-radius: var(--radius-panel); padding: var(--sp-4); margin: 0 0 var(--sp-4); }
.fieldset > legend { padding: 0 var(--sp-2); font-size: var(--fs-sm); font-weight: 700; color: var(--orna-blue); text-transform: uppercase; letter-spacing: .06em; }

/* --------------------------------------------------------------------------
   11. Tableaux — §16.2 : en-têtes en capitales, montants à droite
   -------------------------------------------------------------------------- */
.table-wrap { width: 100%; overflow-x: auto; }

.table { width: 100%; border-collapse: collapse; font-size: var(--fs-base); }
.table th, .table td { padding: 11px var(--sp-4); text-align: left; border-bottom: 1px solid var(--n-200); }
.table thead th {
    position: sticky; top: 0;
    /* Bandeau d'en-tête en dégradé, refermé par un filet d'accent : la ligne
       de titres se détache du corps même quand le tableau défile. */
    background: linear-gradient(180deg, #eeeef8 0%, var(--orna-blue-pale) 100%);
    box-shadow: inset 0 -2px 0 var(--orna-blue-light);
    color: var(--orna-blue);
    font-size: var(--fs-xs);
    font-weight: 700;
    letter-spacing: .09em;
    text-transform: uppercase;
    white-space: nowrap;
    z-index: 1;
}

/* La ligne survolée se signale par un liseré et un voile dégradé, comme les
   lignes de liste : même grammaire d'un bout à l'autre de l'application. */
.table tbody tr { transition: background var(--ease), box-shadow var(--ease); }
.table tbody tr:hover {
    background: linear-gradient(90deg, var(--orna-blue-pale) 0%, rgba(232, 232, 244, 0) 55%);
    box-shadow: inset 3px 0 0 var(--orna-rose);
}
.table tbody tr:last-child td { border-bottom: 0; }
.table td.num, .table th.num { text-align: right; font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.table th.num { font-family: var(--font-ui); }
.table tfoot td {
    background: linear-gradient(180deg, var(--orna-blue-pale) 0%, #dedeee 100%);
    font-weight: 700;
    color: var(--orna-blue);
    border-top: 2px solid var(--orna-blue-light);
}

/* Les premières lignes se posent à l'ouverture. Au-delà de la douzième, plus
   rien n'est animé : un tableau de deux cents lignes ne doit pas ondoyer. */
@keyframes ligne-apparition {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: none; }
}
.table tbody tr:nth-child(-n+12) { animation: ligne-apparition 300ms ease-out backwards; }
.table tbody tr:nth-child(1)  { animation-delay: 20ms; }
.table tbody tr:nth-child(2)  { animation-delay: 40ms; }
.table tbody tr:nth-child(3)  { animation-delay: 60ms; }
.table tbody tr:nth-child(4)  { animation-delay: 80ms; }
.table tbody tr:nth-child(5)  { animation-delay: 100ms; }
.table tbody tr:nth-child(6)  { animation-delay: 120ms; }
.table tbody tr:nth-child(7)  { animation-delay: 140ms; }
.table tbody tr:nth-child(8)  { animation-delay: 160ms; }
.table tbody tr:nth-child(9)  { animation-delay: 180ms; }
.table tbody tr:nth-child(10) { animation-delay: 200ms; }
.table tbody tr:nth-child(11) { animation-delay: 220ms; }
.table tbody tr:nth-child(12) { animation-delay: 240ms; }
.table--compact th, .table--compact td { padding: 6px var(--sp-3); }
.table__row-actions { display: flex; gap: var(--sp-1); justify-content: flex-end; }

/* Tableau de saisie : ligne éditable en place — §16.3 */
.table--editable td { padding: 4px var(--sp-2); }
/* Un champ de saisie se voit au premier coup d'œil : cadre et fond blanc, même au repos. */
.table--editable .input, .table--editable .select { min-height: 36px; padding: 6px var(--sp-2); border-color: var(--n-300); background-color: var(--n-0); box-shadow: inset 0 1px 2px rgba(13, 13, 61, .06); }
.table--editable .select { padding-right: 30px; }
.table--editable .input:hover, .table--editable .select:hover { border-color: var(--orna-blue-light); }
.table--editable .input:focus, .table--editable .select:focus { border-color: var(--orna-blue-light); background-color: var(--n-0); }
.table--editable .input:disabled, .table--editable .select:disabled { background-color: var(--n-100); box-shadow: none; }
.table--editable tr:focus-within { background: var(--orna-blue-pale); }
.table thead .req { color: var(--orna-rose-text); }

/* Lignes d'opération : colonnes secondaires repliées par défaut. */
.table--lignes:not(.is-details) .col-detail { display: none !important; }
.table--lignes .champ-unite { display: flex; align-items: center; gap: var(--sp-2); }
.table--lignes .champ-unite .input { flex: 1 1 auto; min-width: 0; }
.table--lignes .champ-unite [data-champ="unite"] { flex: 0 0 auto; }
.table--lignes .montant-ligne { font-weight: 600; color: var(--orna-blue); white-space: nowrap; }
[data-details-lignes][aria-pressed="true"] { background: var(--orna-blue-pale); border-color: var(--orna-blue-light); }

/* --------------------------------------------------------------------------
   12. Pastilles de statut — §16.3 et §18
   -------------------------------------------------------------------------- */
.pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 3px 10px;
    border-radius: var(--radius-pill);
    font-size: var(--fs-xs);
    font-weight: 600;
    white-space: nowrap;
    border: 1px solid transparent;
}
.pill__dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: 0 0 auto; }

/* Un décompte d'alertes actives bat doucement : le mouvement signale qu'il y a
   quelque chose à traiter. Le nombre reste écrit à côté — la pulsation ne
   porte aucune information à elle seule (§18). */
@keyframes pastille-battement {
    0%, 100% { transform: scale(1);   opacity: 1; }
    50%      { transform: scale(1.5); opacity: .55; }
}
.pill--rose .pill__dot,
.pill--danger .pill__dot { animation: pastille-battement 2.2s ease-in-out infinite; }
.pill--ok      { background: var(--ok-bg);     color: #1B6B2E; border-color: #BFE5CB; }
.pill--warn    { background: var(--warn-bg);   color: var(--warn-text); border-color: #F3DFA6; }
.pill--danger  { background: var(--danger-bg); color: #A32029; border-color: #F3C3C8; }
.pill--info    { background: var(--info-bg);   color: #10707F; border-color: #B7E2E9; }
.pill--neutral { background: var(--n-100);     color: var(--n-600); border-color: var(--n-300); }
.pill--rose    { background: var(--orna-rose-pale); color: var(--orna-rose-text); border-color: var(--orna-rose-light); }
.pill--gold    { background: var(--orna-gold-pale); color: var(--orna-gold-dark); border-color: #EBD5A0; }

.tag {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 2px 8px;
    border-radius: var(--radius-input);
    background: var(--n-100);
    border: 1px solid var(--n-300);
    font-size: var(--fs-xs);
    color: var(--n-600);
}

/* --------------------------------------------------------------------------
   13. Onglets — §16.3 : soulignement rose, texte bleu principal
   -------------------------------------------------------------------------- */
.tabs {
    display: flex;
    gap: var(--sp-1);
    border-bottom: 1px solid var(--n-300);
    margin-bottom: var(--sp-5);
    overflow-x: auto;
}
.tab {
    position: relative;
    padding: 10px var(--sp-4);
    border: 0;
    background: none;
    font: inherit;
    font-weight: 600;
    color: var(--n-600);
    cursor: pointer;
    white-space: nowrap;
}
.tab:hover { color: var(--orna-blue); }
.tab[aria-selected="true"] { color: var(--orna-blue); }

/* Le soulignement se déplie depuis le centre : présent en permanence, il
   n'apparaît qu'à la sélection ou au survol, sans faire bouger l'onglet. */
.tab::after {
    content: "";
    position: absolute;
    left: var(--sp-3); right: var(--sp-3); bottom: -1px;
    height: 3px;
    border-radius: 3px 3px 0 0;
    background: linear-gradient(90deg, var(--orna-rose) 0%, var(--orna-gold) 100%);
    transform: scaleX(0);
    transition: transform var(--ease);
}
.tab:hover::after { transform: scaleX(.5); }
.tab[aria-selected="true"]::after { transform: scaleX(1); }

/* --------------------------------------------------------------------------
   14. Bandeaux d'avertissement — §15.1
   -------------------------------------------------------------------------- */
.notice {
    display: flex;
    gap: var(--sp-3);
    padding: var(--sp-3) var(--sp-4);
    border: 1px solid;
    border-left-width: 4px;
    border-radius: var(--radius-button);
    font-size: var(--fs-base);
    margin-bottom: var(--sp-5);
}
/* L'icône du bandeau prend la forme d'une pastille pleine, comme partout
   ailleurs : c'est le même vocabulaire visuel qui revient. */
.notice__icon {
    box-sizing: content-box;
    flex: 0 0 auto;
    align-self: flex-start;
    width: 16px; height: 16px;
    padding: 7px;
    border-radius: 9px;
    background: currentColor;
    color: inherit;
}
.notice__icon svg { display: block; width: 16px; height: 16px; color: var(--n-0); }
.notice__title { font-weight: 700; margin-bottom: 2px; }
.notice--gold   { background: linear-gradient(120deg, var(--orna-gold-pale) 0%, #fdf8ec 100%); border-color: var(--orna-gold); color: #6B4E00; }
.notice--info   { background: linear-gradient(120deg, var(--info-bg) 0%, #f2fbfc 100%);   border-color: var(--info);   color: #0C5A66; }
.notice--ok     { background: linear-gradient(120deg, var(--ok-bg) 0%, #f4fcf6 100%);     border-color: var(--ok);     color: #175F28; }
.notice--danger { background: linear-gradient(120deg, var(--danger-bg) 0%, #fef6f7 100%); border-color: var(--danger); color: #8F1C25; }

/* --------------------------------------------------------------------------
   15. États vides — §16.3 et §15.3
   -------------------------------------------------------------------------- */
.empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--sp-3);
    padding: var(--sp-10) var(--sp-5);
    text-align: center;
    color: var(--n-600);
}
.empty__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 58px; height: 58px;
    border-radius: 50%;
    /* Un écran vide n'est pas une panne : la pastille reste aux couleurs de
       la marque plutôt qu'au gris d'un contenu manquant. */
    background: linear-gradient(140deg, var(--orna-blue-pale) 0%, var(--orna-rose-pale) 100%);
    color: var(--orna-blue);
    box-shadow: inset 0 0 0 1px rgba(26, 26, 110, .08);
}
.empty__icon svg { width: 24px; height: 24px; }
.empty__text { font-size: var(--fs-md); }

/* --------------------------------------------------------------------------
   16. Liste d'activité et d'alertes
   -------------------------------------------------------------------------- */
/*
 * Ligne d'activité ou d'alerte. Chaque ligne porte le ton de sa nature — une
 * vente n'a pas la couleur d'un règlement ni d'une alerte de rupture — et
 * réagit au survol : liseré d'accent, léger décalage, chevron qui avance.
 */
.feed__item {
    --feed-ton:       var(--orna-blue);
    --feed-ton-clair: var(--orna-blue-light);
    --feed-voile:     var(--orna-blue-pale);

    position: relative;
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    padding: var(--sp-3) var(--sp-5);
    border-bottom: 1px solid var(--n-200);
    transition: background var(--ease), padding-left var(--ease);
}
.feed__item:last-child { border-bottom: 0; }

/* Liseré révélé au survol : il désigne la ligne visée sans la déplacer
   brutalement ni changer sa hauteur. */
.feed__item::before {
    content: "";
    position: absolute;
    top: 0; bottom: 0; left: 0;
    width: 3px;
    background: linear-gradient(180deg, var(--feed-ton) 0%, var(--feed-ton-clair) 100%);
    transform: scaleY(0);
    transform-origin: center;
    transition: transform var(--ease);
}
.feed__item:hover,
.feed__item:focus-visible {
    background: linear-gradient(90deg, var(--feed-voile) 0%, rgba(255, 255, 255, 0) 65%);
    padding-left: calc(var(--sp-5) + 4px);
}
.feed__item:hover::before,
.feed__item:focus-visible::before { transform: scaleY(1); }

.feed__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px; height: 34px;
    border-radius: 10px;
    background: linear-gradient(140deg, var(--feed-ton) 0%, var(--feed-ton-clair) 100%);
    color: #fff;
    flex: 0 0 auto;
    box-shadow: var(--shadow-sm);
    transition: transform var(--ease);
}
.feed__item:hover .feed__icon { transform: scale(1.07); }

/* Tons disponibles : le ton soutenu reste une couleur de texte validée, la
   pastille étant écrite en blanc dessus. */
.feed__icon--rose   { --feed-ton: var(--orna-rose-text); --feed-ton-clair: var(--orna-rose);  --feed-voile: var(--orna-rose-pale); }
.feed__icon--gold   { --feed-ton: var(--orna-gold-dark); --feed-ton-clair: var(--orna-gold);  --feed-voile: var(--orna-gold-pale); }
.feed__icon--warn   { --feed-ton: var(--warn-text);      --feed-ton-clair: var(--warn);       --feed-voile: var(--warn-bg); }
.feed__icon--danger { --feed-ton: #A81B28;               --feed-ton-clair: var(--danger);     --feed-voile: var(--danger-bg); }
.feed__icon--ok     { --feed-ton: #1E7A34;               --feed-ton-clair: var(--ok);         --feed-voile: var(--ok-bg); }
.feed__icon--info   { --feed-ton: #0F7180;               --feed-ton-clair: var(--info);       --feed-voile: var(--info-bg); }

/* Le ton est porté par la pastille mais colore toute la ligne : on le remonte
   au parent, faute de quoi le liseré et le voile resteraient bleus. */
.feed__item:has(.feed__icon--rose)   { --feed-ton: var(--orna-rose-text); --feed-ton-clair: var(--orna-rose);  --feed-voile: var(--orna-rose-pale); }
.feed__item:has(.feed__icon--gold)   { --feed-ton: var(--orna-gold-dark); --feed-ton-clair: var(--orna-gold);  --feed-voile: var(--orna-gold-pale); }
.feed__item:has(.feed__icon--warn)   { --feed-ton: var(--warn-text);      --feed-ton-clair: var(--warn);       --feed-voile: var(--warn-bg); }
.feed__item:has(.feed__icon--danger) { --feed-ton: #A81B28;               --feed-ton-clair: var(--danger);     --feed-voile: var(--danger-bg); }
.feed__item:has(.feed__icon--ok)     { --feed-ton: #1E7A34;               --feed-ton-clair: var(--ok);         --feed-voile: var(--ok-bg); }
.feed__item:has(.feed__icon--info)   { --feed-ton: #0F7180;               --feed-ton-clair: var(--info);       --feed-voile: var(--info-bg); }

.feed__main { flex: 1; min-width: 0; }
.feed__title { font-weight: 600; color: var(--n-900); }
.feed__meta { font-size: var(--fs-sm); color: var(--n-600); }
.feed__side { text-align: right; white-space: nowrap; }

/* Le chevron de fin de ligne avance vers la destination. */
.feed__item > svg.icon:last-child { transition: transform var(--ease), color var(--ease); }
.feed__item:hover > svg.icon:last-child { transform: translateX(3px); color: var(--feed-ton); }

/* Raccourcis — tuiles d'action. Les tons tournent d'une tuile à l'autre pour
   que la rangée se lise d'un coup d'œil. */
.shortcuts { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: var(--sp-3); }
.shortcut {
    --sc-ton:       var(--orna-blue);
    --sc-ton-clair: var(--orna-blue-light);
    --sc-voile:     var(--orna-blue-pale);

    position: relative;
    overflow: hidden;
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    padding: var(--sp-3);
    border: 1px solid var(--n-300);
    border-radius: var(--radius-button);
    background: linear-gradient(150deg, var(--n-0) 0%, var(--n-0) 55%, var(--sc-voile) 100%);
    color: var(--orna-blue);
    font-weight: 600;
    font-size: var(--fs-sm);
    transition: transform var(--ease), border-color var(--ease), box-shadow var(--ease);
}
.shortcut > svg.icon {
    box-sizing: content-box;
    width: 16px; height: 16px;
    padding: 8px;
    border-radius: 10px;
    background: linear-gradient(140deg, var(--sc-ton) 0%, var(--sc-ton-clair) 100%);
    color: #fff;
    flex: 0 0 auto;
    transition: transform var(--ease);
}
.shortcut:hover {
    transform: translateY(-2px);
    border-color: var(--sc-ton-clair);
    box-shadow: var(--shadow-md);
    text-decoration: none;
}
.shortcut:hover > svg.icon { transform: rotate(-6deg) scale(1.06); }

.shortcut:nth-child(6n+2) { --sc-ton: var(--orna-rose-text); --sc-ton-clair: var(--orna-rose); --sc-voile: var(--orna-rose-pale); }
.shortcut:nth-child(6n+3) { --sc-ton: var(--orna-gold-dark); --sc-ton-clair: var(--orna-gold); --sc-voile: var(--orna-gold-pale); }
.shortcut:nth-child(6n+4) { --sc-ton: #1E7A34;               --sc-ton-clair: var(--ok);        --sc-voile: var(--ok-bg); }
.shortcut:nth-child(6n+5) { --sc-ton: #0F7180;               --sc-ton-clair: var(--info);      --sc-voile: var(--info-bg); }
.shortcut:nth-child(6n)   { --sc-ton: var(--warn-text);      --sc-ton-clair: var(--warn);      --sc-voile: var(--warn-bg); }

/* --------------------------------------------------------------------------
   17. Notifications flottantes — §16.3 : bas à droite, bleu foncé, 3,6 s
   -------------------------------------------------------------------------- */
.toast-stack {
    position: fixed;
    right: var(--sp-5); bottom: var(--sp-5);
    z-index: 200;
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
    max-width: min(360px, calc(100vw - 32px));
}
.toast {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    padding: var(--sp-3) var(--sp-4);
    border-radius: var(--radius-panel);
    background: var(--orna-blue-dark);
    color: #fff;
    box-shadow: var(--shadow-lg);
    font-size: var(--fs-base);
    animation: toast-in 220ms cubic-bezier(.2, .8, .3, 1);
}
.toast.is-leaving { animation: toast-out 220ms ease forwards; }
.toast__icon { color: var(--orna-gold); flex: 0 0 auto; }
.toast__text { flex: 1; }
.toast__close {
    border: 0; background: none; color: rgba(255, 255, 255, .7);
    cursor: pointer; padding: 2px; display: inline-flex;
}
.toast__close:hover { color: #fff; }
.toast--ok .toast__icon { color: #6EE7A0; }
.toast--danger .toast__icon { color: #FF8A94; }

@keyframes toast-in  { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
@keyframes toast-out { to { opacity: 0; transform: translateY(8px); } }

/* --------------------------------------------------------------------------
   18. Modale — §18 : rattachée à son titre, focus piégé, fermeture par Échap
   -------------------------------------------------------------------------- */
.modal-backdrop {
    position: fixed;
    inset: 0;
    z-index: 150;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--sp-5);
    background: rgba(13, 13, 61, .48);
}
.modal-backdrop[hidden] { display: none; }
.modal {
    width: 100%;
    max-width: 520px;
    max-height: 90vh;
    display: flex;
    flex-direction: column;
    background: var(--n-0);
    border-radius: var(--radius-panel);
    box-shadow: var(--shadow-lg);
    overflow: hidden;
}
.modal__head {
    display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sp-3);
    padding: var(--sp-4) var(--sp-5);
    border-bottom: 1px solid var(--n-200);
}
/* Pied de formulaire : reprend les boutons d'action de l'en-tête de page,
   alignés à gauche, dans le fil de lecture du formulaire. */
.form-pied {
    display: flex; flex-wrap: wrap; justify-content: flex-start; align-items: center; gap: var(--sp-2);
    margin-top: var(--sp-5);
    padding-top: var(--sp-5);
    border-top: 1px solid var(--n-200);
    /* Réserve sous les boutons : le bouton flottant « Visite guidée » ne doit
       jamais les recouvrir quand la page est défilée jusqu'en bas. */
    margin-bottom: 64px;
}
/* Le formulaire enveloppe corps et pied : il doit relayer la colonne flex, et
   le corps doit pouvoir rétrécir (min-height: 0) pour que, sur un écran bas,
   le pied et ses boutons restent visibles et le corps défile. */
.modal > form { display: flex; flex-direction: column; min-height: 0; }
.modal__body { padding: var(--sp-5); overflow-y: auto; flex: 1 1 auto; min-height: 0; }
.modal__foot { flex: 0 0 auto; }
.modal__foot {
    display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--sp-2);
    padding: var(--sp-4) var(--sp-5);
    border-top: 1px solid var(--n-200);
    background: var(--n-50);
}

/* --------------------------------------------------------------------------
   18 bis. Gestion commerciale — §5.5
   -------------------------------------------------------------------------- */

/* Choix du groupe d'opération : cartes radio */
.choice-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: var(--sp-3); }
.choice { display: block; cursor: pointer; }
.choice input { position: absolute; opacity: 0; width: 0; height: 0; }
.choice__body {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    padding: var(--sp-3) var(--sp-4);
    border: 1px solid var(--n-300);
    border-radius: var(--radius-button);
    background: var(--n-0);
    transition: border-color var(--ease), background var(--ease);
}
.choice:hover .choice__body { border-color: var(--orna-blue-light); }
.choice input:checked + .choice__body {
    border-color: var(--orna-rose);
    background: var(--orna-rose-pale);
    box-shadow: inset 3px 0 0 var(--orna-rose);
}
.choice input:focus-visible + .choice__body { outline: 2px solid var(--orna-rose); outline-offset: 2px; }
.choice__icon {
    display: inline-flex; align-items: center; justify-content: center;
    width: 34px; height: 34px;
    border-radius: 9px;
    background: var(--orna-blue-pale);
    color: var(--orna-blue);
    flex: 0 0 auto;
}
.choice input:checked + .choice__body .choice__icon { background: var(--n-0); color: var(--orna-rose-text); }
.choice__label { display: block; font-weight: 600; color: var(--orna-blue); }
.choice__hint { display: block; font-size: var(--fs-xs); color: var(--n-600); }

/* Effets à la validation */
.effets { display: flex; flex-direction: column; gap: 4px; font-size: var(--fs-sm); color: var(--n-600); }
.effets li { display: flex; gap: 6px; }
.effets li::before { content: "→"; color: var(--orna-rose-text); flex: 0 0 auto; }

/* Encours du tiers */
.encours {
    padding: var(--sp-2) var(--sp-3);
    border: 1px solid var(--n-300);
    border-radius: var(--radius-input);
    background: var(--n-50);
    font-size: var(--fs-sm);
}
.encours__row { display: flex; justify-content: space-between; gap: var(--sp-3); padding: 2px 0; }
.encours__row .num, .encours__row .mono { font-family: var(--font-mono); }

/* Bandeau de totaux */
.totaux { margin: 0; }
.totaux__row {
    display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3);
    padding: 7px 0;
    border-bottom: 1px solid var(--n-200);
}
.totaux__row dt { color: var(--n-600); }
.totaux__row dd { margin: 0; font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.totaux__row--strong dt, .totaux__row--strong dd { font-weight: 700; color: var(--orna-blue); }
.totaux__row--net {
    border-bottom: 0;
    margin-top: var(--sp-2);
    padding: var(--sp-3);
    border-radius: var(--radius-button);
    background: var(--orna-rose-pale);
}
.totaux__row--net dt { color: var(--orna-rose-text); font-weight: 600; }
.totaux__row--net dd { color: var(--orna-rose-text); font-weight: 700; font-size: var(--fs-lg); }

/* Cycle de vie de l'opération */
.cycle { display: flex; flex-direction: column; gap: var(--sp-3); }
.cycle__step { display: flex; gap: var(--sp-3); align-items: flex-start; }
.cycle__dot {
    width: 11px; height: 11px; margin-top: 4px;
    border-radius: 50%;
    border: 2px solid var(--n-300);
    background: var(--n-0);
    flex: 0 0 auto;
}
.cycle__step.is-current .cycle__dot { border-color: var(--orna-rose); background: var(--orna-rose); }

/* Séparateur d'écriture complémentaire */
.ecriture__sep {
    background: var(--orna-blue-pale);
    font-size: var(--fs-xs);
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--orna-blue);
}

/* --------------------------------------------------------------------------
   Écrans d'authentification — §19.1 et §16

   Deux volets : la scène illustrée à gauche, la carte à droite. Le fond est
   commun — dégradé profond et trois taches de couleur qui dérivent lentement.
   Les mouvements sont tous en CSS ; la règle `prefers-reduced-motion` en fin
   de feuille les ramène à leur état final.
   -------------------------------------------------------------------------- */
body.auth {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    min-height: 100dvh;
    padding: var(--sp-6) var(--sp-4);
    padding-bottom: calc(var(--sp-6) + env(safe-area-inset-bottom, 0px));
    background: #0a0a33;
    background-image:
        radial-gradient(ellipse 80% 60% at 15% 20%, rgba(42, 42, 142, .75) 0%, transparent 60%),
        radial-gradient(ellipse 60% 50% at 90% 90%, rgba(26, 26, 110, .8) 0%, transparent 55%),
        linear-gradient(160deg, #14144f 0%, #0d0d3d 55%, #06061f 100%);
    overflow-x: clip;
}

/* Fond : trois halos en dégradés radiaux — sous tout le reste.
   Volontairement statiques et sans filtre : un flou de 90 px animé sur des
   surfaces de 40 vw se recalcule à chaque image et paralyse un poste sans
   accélération graphique (« la page bloque »). Le dégradé radial rend le même
   halo pour un coût nul. */
.auth-fond { position: fixed; inset: 0; z-index: 0; overflow: hidden; pointer-events: none; }
.auth-fond__tache { position: absolute; border-radius: 50%; }
.auth-fond__tache--rose { width: 70vw; height: 70vw; left: -24vw; top: -26vw; background: radial-gradient(circle, rgba(233, 30, 140, .38) 0%, rgba(233, 30, 140, .14) 38%, rgba(233, 30, 140, 0) 68%); }
.auth-fond__tache--or   { width: 52vw; height: 52vw; right: -20vw; top: 22vh;  background: radial-gradient(circle, rgba(212, 168, 83, .26) 0%, rgba(212, 168, 83, .09) 38%, rgba(212, 168, 83, 0) 68%); }
.auth-fond__tache--bleu { width: 64vw; height: 64vw; left: 20vw; bottom: -34vw; background: radial-gradient(circle, rgba(42, 42, 142, .7) 0%, rgba(42, 42, 142, .3) 38%, rgba(42, 42, 142, 0) 68%); }

.auth-page {
    position: relative;
    z-index: 1;
    display: grid;
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
    align-items: center;
    gap: var(--sp-10);
    width: 100%;
    max-width: 1180px;
}
.auth-page--large { grid-template-columns: minmax(0, .9fr) minmax(0, 1.1fr); }

/* --- Volet illustré ------------------------------------------------------ */
.auth-visuel { display: flex; flex-direction: column; gap: var(--sp-4); min-width: 0; }
.auth-visuel__marque {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    animation: auth-monter .7s cubic-bezier(.2, .7, .2, 1) both;
}
.auth-visuel__logo {
    width: 52px; height: 52px;
    border-radius: 14px;
    background: #fff;
    object-fit: cover;
    box-shadow: 0 8px 24px rgba(233, 30, 140, .28);
}
.auth-visuel__nom { margin: 0; color: #fff; font-size: var(--fs-2xl); letter-spacing: .02em; line-height: 1.1; }
.auth-visuel__baseline { margin: 2px 0 0; color: var(--orna-gold); font-size: var(--fs-sm); }

.auth-visuel__scene {
    position: relative;
    width: 100%;
    /* La scène se réduit avec la hauteur d'écran : sur un portable 768 px de
       haut, elle laisse la place aux atouts sans faire défiler la page. */
    max-width: clamp(340px, calc(100vh - 370px), 560px);
    aspect-ratio: 560 / 520;
    animation: auth-apparaitre 1s .1s ease both;
}
.auth-illu { display: block; width: 100%; height: 100%; overflow: visible; font-family: var(--font-ui); }

/* Textes de la scène */
.illu-texte { fill: #fff; font-size: 12px; font-weight: 600; }
.illu-texte--label { fill: rgba(255, 255, 255, .62); font-size: 10.5px; font-weight: 500; }
.illu-texte--valeur { fill: #fff; font-size: 13px; font-weight: 700; }
.illu-texte--mini { fill: #fff; font-size: 10.5px; font-weight: 600; }
.illu-texte--plus { fill: var(--orna-blue-dark); font-size: 8px; font-weight: 700; }

/* Toute animation de l'illustration est une entrée en scène jouée une fois :
   les boucles perpétuelles (halo, anneaux, ondes, flux, flottement, particules)
   ont été retirées — un SVG animé se redessine à chaque image, et ces boucles
   rendaient l'écran de connexion poussif sur un poste modeste. */
.illu-halo { transform-box: fill-box; transform-origin: center; animation: illu-respirer 1.6s ease-out both; }
@keyframes illu-respirer {
    from { transform: scale(.85); opacity: 0; }
    to   { transform: scale(1);   opacity: .9; }
}

/* Anneaux du noyau : un quart de tour à l'arrivée, puis immobiles */
.illu-anneau { transform-box: fill-box; transform-origin: center; animation: illu-tourner 1.4s cubic-bezier(.2, .7, .2, 1) both; }
.illu-anneau--rapide { animation-direction: reverse; animation-duration: 1.1s; }
@keyframes illu-tourner { from { transform: rotate(-90deg); opacity: 0; } to { transform: rotate(0); opacity: 1; } }

/* Ondes émises par le noyau : deux impulsions, puis plus rien */
.illu-onde {
    transform-box: fill-box;
    transform-origin: center;
    opacity: 0;
    animation: illu-onde 2.4s .6s ease-out both;
}
.illu-onde--2 { animation-delay: 1.4s; }
@keyframes illu-onde {
    0%   { transform: scale(1);   opacity: .7; }
    100% { transform: scale(1.9); opacity: 0; }
}

/* Cartes : entrée en fondu, puis immobiles */
.illu-carte {
    transform-box: fill-box;
    transform-origin: center;
    animation: illu-entrer .8s cubic-bezier(.2, .7, .2, 1) both;
}
.illu-carte--1 { animation-delay: .35s, 1.15s; }
.illu-carte--2 { animation-delay: .5s,  1.3s; animation-duration: .8s, 8s; }
.illu-carte--3 { animation-delay: .65s, 1.45s; animation-duration: .8s, 7.5s; }
.illu-carte--4 { animation-delay: .8s,  1.6s; animation-duration: .8s, 8.5s; }
@keyframes illu-entrer {
    from { opacity: 0; transform: translateY(18px) scale(.96); }
    to   { opacity: 1; transform: none; }
}

/* Histogramme des ventes : chaque barre pousse depuis le sol */
.illu-barres rect {
    transform-box: fill-box;
    transform-origin: bottom;
    animation: illu-pousser .9s cubic-bezier(.2, .7, .2, 1) both;
}
.illu-barres rect:nth-child(1) { animation-delay: 1s; }
.illu-barres rect:nth-child(2) { animation-delay: 1.1s; }
.illu-barres rect:nth-child(3) { animation-delay: 1.2s; }
.illu-barres rect:nth-child(4) { animation-delay: 1.3s; }
.illu-barres rect:nth-child(5) { animation-delay: 1.4s; }
.illu-barres rect:nth-child(6) { animation-delay: 1.5s; }
.illu-barres rect:nth-child(7) { animation-delay: 1.6s; }
@keyframes illu-pousser { from { transform: scaleY(0); } to { transform: scaleY(1); } }

/* Jauge de stock */
.illu-jauge {
    transform-box: fill-box;
    transform-origin: left;
    animation: illu-remplir 1.4s 1.2s cubic-bezier(.2, .7, .2, 1) both;
}
@keyframes illu-remplir { from { transform: scaleX(0); } to { transform: scaleX(.92); } }

/* Coche de validation : le cercle puis la coche se tracent */
.illu-coche-cercle { stroke-dasharray: 110; stroke-dashoffset: 110; animation: illu-tracer 1s 1.4s ease-out forwards; }
.illu-coche { stroke-dasharray: 30; stroke-dashoffset: 30; animation: illu-tracer .5s 2.2s ease-out forwards; }
@keyframes illu-tracer { to { stroke-dashoffset: 0; } }

/* Courbe de paie */
.illu-courbe { stroke-dasharray: 120; stroke-dashoffset: 120; animation: illu-tracer 1.4s 1.6s ease-out forwards; }
.illu-courbe-point {
    transform-box: fill-box;
    transform-origin: center;
    opacity: 0;
    animation: illu-point .6s 2.9s cubic-bezier(.3, 1.4, .5, 1) forwards;
}
@keyframes illu-point { from { opacity: 0; transform: scale(0); } to { opacity: 1; transform: scale(1); } }

/* Équipe : les avatars arrivent un à un */
.illu-equipe circle, .illu-equipe text { transform-box: fill-box; transform-origin: center; animation: illu-point .5s cubic-bezier(.3, 1.4, .5, 1) both; }
.illu-equipe > :nth-child(1) { animation-delay: 1.5s; }
.illu-equipe > :nth-child(2) { animation-delay: 1.65s; }
.illu-equipe > :nth-child(3) { animation-delay: 1.8s; }
.illu-equipe > :nth-child(4), .illu-equipe > :nth-child(5) { animation-delay: 1.95s; }

/* Particules : apparition une fois, immobiles ensuite */
.illu-particule { transform-box: fill-box; transform-origin: center; animation: illu-point .8s 1.8s cubic-bezier(.3, 1.4, .5, 1) both; }
.illu-particule:nth-child(2) { animation-delay: 2s; }
.illu-particule:nth-child(3) { animation-delay: 2.2s; }
.illu-particule:nth-child(4) { animation-delay: 2.4s; }
.illu-particule:nth-child(5) { animation-delay: 2.6s; }
.illu-particule:nth-child(6) { animation-delay: 2.8s; }

/* Atouts sous la scène */
.auth-visuel__atouts { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-3); }
.auth-atout {
    display: flex;
    align-items: flex-start;
    gap: var(--sp-3);
    animation: auth-monter .6s cubic-bezier(.2, .7, .2, 1) both;
    animation-delay: calc(.5s + var(--i, 0) * .12s);
}
.auth-atout__icone {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px; height: 34px;
    border-radius: 10px;
    background: rgba(255, 255, 255, .08);
    border: 1px solid rgba(255, 255, 255, .14);
    color: var(--orna-gold);
}
.auth-atout__titre { display: block; color: #fff; font-size: var(--fs-md); font-weight: 600; }
.auth-atout__texte { display: block; color: rgba(255, 255, 255, .62); font-size: var(--fs-sm); line-height: 1.5; }
.auth-visuel__pied { margin: 0; color: rgba(255, 255, 255, .4); font-size: var(--fs-xs); }

/* --- Volet formulaire ----------------------------------------------------- */
.auth-volet { min-width: 0; width: 100%; max-width: 480px; justify-self: center; }
.auth-page--large .auth-volet { max-width: 640px; }

.auth-carte {
    position: relative;
    padding: var(--sp-8);
    border-radius: 22px;
    background: rgba(255, 255, 255, .96);
    box-shadow:
        0 30px 80px rgba(3, 3, 25, .55),
        0 1px 0 rgba(255, 255, 255, .6) inset;
    animation: auth-surgir .8s cubic-bezier(.2, .7, .2, 1) both;
}
/* Liseré dégradé qui borde la carte — la charte, en un trait. */
.auth-carte::before {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    padding: 1.5px;
    background: linear-gradient(135deg, rgba(233, 30, 140, .8), rgba(212, 168, 83, .8) 50%, rgba(42, 42, 142, .8));
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
    mask-composite: exclude;
    pointer-events: none;
}
.auth-carte > * { animation: auth-monter .55s cubic-bezier(.2, .7, .2, 1) both; }
.auth-carte > :nth-child(1) { animation-delay: .25s; }
.auth-carte > :nth-child(2) { animation-delay: .35s; }
.auth-carte > :nth-child(3) { animation-delay: .45s; }

.auth-carte__marque { display: flex; align-items: center; gap: var(--sp-2); margin-bottom: var(--sp-6); }
.auth-carte__logo { width: 34px; height: 34px; border-radius: 9px; object-fit: cover; box-shadow: var(--shadow-sm); }
.auth-carte__nom { color: var(--orna-blue); font-size: var(--fs-lg); letter-spacing: .02em; }
.auth-carte__tag {
    margin-left: var(--sp-1);
    padding: 2px 8px;
    border-radius: var(--radius-pill);
    background: var(--orna-rose-pale);
    color: var(--orna-rose-text);
    font-size: var(--fs-xs);
    font-weight: 700;
    letter-spacing: .08em;
}
.auth-carte__tete { margin-bottom: var(--sp-6); }
.auth-carte__titre { margin: 0; color: var(--orna-blue); font-size: var(--fs-3xl); line-height: 1.15; }
.auth-carte__sous-titre { margin: var(--sp-2) 0 0; color: var(--n-600); font-size: var(--fs-md); }

/* Champs à icône */
.field__ligne { display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-3); }
.field__ligne .field__label { margin-bottom: 0; }
.field__ligne + .champ-icone { margin-top: var(--sp-2); }
.field__lien { font-size: var(--fs-sm); font-weight: 500; white-space: nowrap; }
.champ-icone { position: relative; display: flex; align-items: center; }
.champ-icone .input { width: 100%; height: 46px; padding-left: 42px; font-size: var(--fs-md); }
.champ-icone .input[type="password"] { letter-spacing: .12em; }
.champ-icone .input::placeholder { color: var(--n-500); letter-spacing: normal; }
.champ-icone__icone {
    position: absolute;
    left: 14px;
    display: inline-flex;
    color: var(--n-500);
    pointer-events: none;
    transition: color var(--ease), transform var(--ease);
}
.champ-icone:focus-within .champ-icone__icone { color: var(--orna-rose); transform: scale(1.08); }
.champ-icone .input[aria-invalid="true"] ~ .champ-icone__icone,
.champ-icone:has(.input[aria-invalid="true"]) .champ-icone__icone { color: var(--danger); }
.champ-icone .input:focus { box-shadow: 0 0 0 4px rgba(233, 30, 140, .14); }
.champ-icone__bascule {
    position: absolute;
    right: 6px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px; height: 36px;
    border: 0;
    border-radius: 8px;
    background: transparent;
    color: var(--n-500);
    cursor: pointer;
    transition: color var(--ease), background var(--ease);
}
.champ-icone__bascule:hover, .champ-icone__bascule:focus-visible { color: var(--orna-blue); background: var(--orna-blue-pale); }
.champ-icone__bascule + .input, .champ-icone:has(.champ-icone__bascule) .input { padding-right: 48px; }
.champ-icone__oeil { display: inline-flex; }
.champ-icone__oeil--ferme { display: none; }
.champ-icone__bascule[aria-pressed="true"] .champ-icone__oeil { display: none; }
.champ-icone__bascule[aria-pressed="true"] .champ-icone__oeil--ferme { display: inline-flex; }

/* Bouton d'entrée : dégradé, lueur et flèche qui file au survol */
.auth-bouton {
    position: relative;
    justify-content: center;
    gap: var(--sp-2);
    height: 50px;
    margin-top: var(--sp-2);
    border-radius: 12px;
    background: linear-gradient(135deg, var(--orna-rose) 0%, #c9127a 100%);
    box-shadow: 0 10px 26px rgba(233, 30, 140, .32);
    overflow: hidden;
    transition: transform var(--ease), box-shadow var(--ease), filter var(--ease);
}
.auth-bouton::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(115deg, transparent 30%, rgba(255, 255, 255, .28) 50%, transparent 70%);
    transform: translateX(-120%);
    transition: transform .7s ease;
}
.auth-bouton:hover:not(:disabled) { background: linear-gradient(135deg, #f0339a 0%, #cf1279 100%); transform: translateY(-2px); box-shadow: 0 14px 32px rgba(233, 30, 140, .42); }
.auth-bouton:hover:not(:disabled)::after { transform: translateX(120%); }
.auth-bouton:active:not(:disabled) { transform: translateY(0); }
.auth-bouton__fleche { transition: transform var(--ease); }
.auth-bouton:hover .auth-bouton__fleche { transform: translateX(4px); }

/* Garanties sous le formulaire */
.auth-garanties {
    list-style: none;
    margin: var(--sp-6) 0 0;
    padding: var(--sp-4) 0 0;
    border-top: 1px solid var(--n-200);
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-2) var(--sp-4);
}
.auth-garanties li { display: inline-flex; align-items: center; gap: 6px; color: var(--n-600); font-size: var(--fs-xs); }
.auth-garanties .icon { color: var(--orna-gold-dark); }

.auth__pied {
    margin: var(--sp-5) 0 0;
    color: rgba(255, 255, 255, .55);
    font-size: var(--fs-xs);
    text-align: center;
    line-height: 1.6;
    animation: auth-apparaitre 1s .6s ease both;
}
.auth__pied a { color: rgba(255, 255, 255, .8); }

@keyframes auth-monter {
    from { opacity: 0; transform: translateY(14px); }
    to   { opacity: 1; transform: none; }
}
@keyframes auth-surgir {
    from { opacity: 0; transform: translateY(28px) scale(.97); }
    to   { opacity: 1; transform: none; }
}
@keyframes auth-apparaitre { from { opacity: 0; } to { opacity: 1; } }

/* Paliers : sous 1024 px, la scène disparaît et la carte prend l'écran. */
@media (max-width: 1023px) {
    .auth-page, .auth-page--large { grid-template-columns: minmax(0, 1fr); gap: 0; }
    .auth-visuel { display: none; }
    .auth-volet { max-width: 520px; }
    .auth-page--large .auth-volet { max-width: 720px; }
}
@media (min-width: 1024px) and (max-width: 1279px) {
    .auth-page { gap: var(--sp-6); }
    .auth-carte { padding: var(--sp-6); }
}

/* Choix de la société à l'entrée (§3.2) */
.societe-choix {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    width: 100%;
    padding: var(--sp-3) var(--sp-4);
    border: 1px solid var(--n-300);
    border-radius: var(--radius-button);
    background: var(--n-0);
    font: inherit;
    text-align: left;
    cursor: pointer;
    transition: border-color var(--ease), background var(--ease);
}
.societe-choix:hover { border-color: var(--orna-rose); background: var(--orna-rose-pale); text-decoration: none; }
.societe-choix__nom { display: block; font-weight: 600; color: var(--orna-blue); }
.societe-choix__meta { display: block; font-size: var(--fs-xs); color: var(--n-600); }

/* --------------------------------------------------------------------------
   Back-office plateforme — application de l'éditeur.
   Même grammaire visuelle, teinte plus sombre : on ne doit jamais confondre
   l'ERP d'une entreprise cliente avec l'administration de l'instance.
   -------------------------------------------------------------------------- */
.app--plateforme .sidebar { background: var(--orna-blue-dark); }
.app--plateforme .nav-link:hover,
.app--plateforme .nav-link:focus-visible { background: #06061f; }
.app--plateforme .nav-link.is-active { background: var(--orna-blue); }
.app--plateforme .nav-link.is-active::before { background: var(--orna-gold); }
.app--plateforme .sidebar__tagline { color: var(--orna-gold); }
.app--plateforme .topbar { border-bottom: 2px solid var(--orna-gold); }

/* Ligne d'inventaire dont l'écart dépasse le seuil : mise en évidence pour
   recomptage — §5.3. La couleur est doublée d'un liseré, jamais seule. */
.table tr.is-hors-seuil { background: var(--danger-bg); box-shadow: inset 3px 0 0 var(--danger); }
.table tr.is-hors-seuil:hover { background: #FBE0E3; }

.icon-button--bare { border-color: transparent; background: transparent; width: 30px; height: 30px; }
.icon-button--bare:hover { border-color: var(--danger); color: var(--danger); background: var(--danger-bg); }

kbd {
    font-family: var(--font-mono);
    font-size: var(--fs-xs);
    padding: 1px 5px;
    border: 1px solid var(--n-300);
    border-bottom-width: 2px;
    border-radius: 4px;
    background: var(--n-50);
}

/* --------------------------------------------------------------------------
   19. Utilitaires
   -------------------------------------------------------------------------- */
.stack > * + * { margin-top: var(--sp-4); }
.row { display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; }
.row--between { justify-content: space-between; }
.row--end { justify-content: flex-end; }
.mt-0 { margin-top: 0; } .mt-2 { margin-top: var(--sp-2); } .mt-4 { margin-top: var(--sp-4); } .mt-5 { margin-top: var(--sp-5); } .mt-6 { margin-top: var(--sp-6); }
.mb-0 { margin-bottom: 0; } .mb-2 { margin-bottom: var(--sp-2); } .mb-4 { margin-bottom: var(--sp-4); } .mb-5 { margin-bottom: var(--sp-5); } .mb-6 { margin-bottom: var(--sp-6); }
.w-full { width: 100%; }
.text-sm { font-size: var(--fs-sm); }
.text-xs { font-size: var(--fs-xs); }
.divider { height: 1px; background: var(--n-200); margin: var(--sp-5) 0; }


/* --------------------------------------------------------------------------
   20. Navigation basse et volet — déclinaison téléphone (§3.1, §16.3, §18)

   En dessous de 768 px, la barre latérale ne peut plus rester une colonne :
   sur un écran de 375 px, sa version réduite confisquerait 18 % de la largeur
   pour des icônes situées hors de portée du pouce. Elle devient donc un volet,
   et les quatre destinations les plus fréquentes descendent dans une barre
   fixée en bas, là où la main tient l'appareil.

   Les deux composants existent dans le document à toutes les tailles ; c'est
   l'affichage qui bascule. Aucune duplication de balisage, donc aucun risque
   de divergence entre la navigation « mobile » et la navigation « bureau ».
   -------------------------------------------------------------------------- */
.bottom-nav {
    display: none;
    position: fixed;
    left: 0; right: 0; bottom: 0;
    z-index: 60;
    /* La barre gestuelle d'iOS et les encoches sont rendues par env() : la
       hauteur utile reste la même, la barre se pose simplement plus haut. */
    padding-bottom: env(safe-area-inset-bottom, 0px);
    background: var(--orna-blue);
    border-top: 1px solid rgba(255, 255, 255, .12);
    box-shadow: 0 -6px 24px rgba(13, 13, 61, .22);
}

.bottom-nav__item {
    flex: 1 1 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    /* 56 px : au-dessus de la cible tactile de 44 px recommandée (§18). */
    min-height: 56px;
    padding: 6px 2px;
    border: 0;
    background: transparent;
    color: rgba(255, 255, 255, .72);
    font: inherit;
    font-size: var(--fs-xs);
    text-decoration: none;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}
.bottom-nav__item:hover { color: #fff; text-decoration: none; }

.bottom-nav__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px; height: 26px;
    border-radius: var(--radius-pill);
    transition: background var(--ease), color var(--ease);
}
.bottom-nav__label {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: 500;
    line-height: 1;
}

/* L'entrée active est signalée par la pastille ET par le libellé en clair :
   jamais par la couleur seule (§18). */
.bottom-nav__item.is-active { color: #fff; font-weight: 600; }
.bottom-nav__item.is-active .bottom-nav__icon { background: var(--orna-rose); color: #fff; }
.bottom-nav__item:focus-visible { outline: 2px solid var(--orna-rose-light); outline-offset: -3px; }

.app--plateforme .bottom-nav { background: var(--orna-blue-dark); }
.app--plateforme .bottom-nav__item.is-active .bottom-nav__icon { background: var(--orna-gold); color: var(--orna-blue-dark); }

/* Voile du volet : il couvre le contenu et intercepte le clic de fermeture. */
.app__scrim {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 45;
    background: rgba(13, 13, 61, .5);
    -webkit-backdrop-filter: blur(2px);
    backdrop-filter: blur(2px);
}
.app__scrim[hidden] { display: none; }

.sidebar__close {
    display: none;
    align-items: center;
    justify-content: center;
    width: 40px; height: 40px;
    margin-left: auto;
    border: 0;
    border-radius: var(--radius-button);
    background: rgba(255, 255, 255, .08);
    color: #fff;
    cursor: pointer;
}
.sidebar__close:hover { background: rgba(255, 255, 255, .16); }

/* Marque et bascule de recherche : réservées au téléphone. */
/* `flex: 0 0 auto` et `max-width: none` sont nécessaires : sans eux, le
   `max-width: 100%` global se résout contre un conteneur flexible de largeur
   nulle, et le logo disparaît. */
.topbar__brand { display: none; align-items: center; flex: 0 0 auto; }
.topbar__brand img { width: 32px; height: 32px; max-width: none; border-radius: 8px; object-fit: cover; }
.topbar__search-toggle { display: none; }
.search__close { display: none; }

/* --------------------------------------------------------------------------
   21. Responsive — échelle complète

   Cinq paliers, du téléphone à l'écran large :
     ≥ 1600  cadre de lecture borné, pour ne pas étirer un tableau sur 2 500 px
     ≤ 1280  les grilles à quatre colonnes passent à deux
     ≤ 1024  la barre latérale se réduit aux icônes (tablette paysage)
     ≤  768  volet + barre basse, une seule colonne (téléphone, tablette portrait)
     ≤  430  compression des espacements et de l'échelle typographique
   -------------------------------------------------------------------------- */

/* Rien ne doit jamais déborder horizontalement : c'est la règle qui rend une
   interface utilisable sur un écran étroit, avant toute autre.

   `clip` et non `hidden` : `overflow-x: hidden` fait de la page un conteneur
   de défilement, et tout ce qui est en `position: sticky` — la barre latérale,
   la barre supérieure, les en-têtes de tableau — cesse alors de tenir à
   l'écran. `clip` coupe le débordement sans créer ce conteneur. */
html, body { max-width: 100%; overflow-x: clip; }
img, svg, video, canvas { max-width: 100%; }

/* Écrans larges : le contenu se centre au lieu de s'étirer indéfiniment. */
@media (min-width: 1600px) {
    .content { max-width: 1680px; margin-inline: auto; width: 100%; }
}

@media (max-width: 1280px) {
    .grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .grid--2-1 { grid-template-columns: minmax(0, 1fr); }
}

/* Palier 1024 px : barre latérale réduite aux icônes — tablette en paysage. */
@media (max-width: 1024px) {
    .app { grid-template-columns: var(--sidebar-w-collapsed) minmax(0, 1fr); }
    .app.is-expanded { grid-template-columns: var(--sidebar-w) minmax(0, 1fr); }

    .grid--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .content { padding: var(--sp-4); }
}

/* Barre latérale réduite : icônes seules, sous-menus en volet flottant. */
.app.is-collapsed .sidebar__brand-text,
.app.is-collapsed .sidebar__footer,
.app.is-collapsed .nav-link__label,
.app.is-collapsed .nav-link__chevron,
.app.is-collapsed .nav-link__tier,
.app.is-collapsed .nav-group__title { display: none; }
.app.is-collapsed .sidebar__brand { justify-content: center; padding: 0; }
.app.is-collapsed .nav-link { justify-content: center; padding: 11px 0; }
.app.is-collapsed .nav-group + .nav-group { margin-top: var(--sp-3); padding-top: var(--sp-3); border-top: 1px solid rgba(255,255,255,.12); }
.app.is-collapsed .nav-sub {
    display: none;
    position: absolute;
    left: 100%; top: 0;
    min-width: 210px;
    padding: var(--sp-2) 0;
    background: var(--orna-blue-dark);
    border-radius: 0 var(--radius-panel) var(--radius-panel) 0;
    box-shadow: var(--shadow-lg);
}
.app.is-collapsed .nav-item:hover > .nav-sub,
.app.is-collapsed .nav-item:focus-within > .nav-sub,
/* Sur écran tactile il n'y a pas de survol : le volet s'ouvre à l'appui,
   l'état `is-open` étant posé par le même bouton qu'au clavier. */
.app.is-collapsed .nav-item.is-open > .nav-sub { display: block; }
.app.is-collapsed .nav-sub__link { padding-left: var(--sp-4); }
.app.is-collapsed .nav-sub__link.is-active::before { margin-left: 0; }

@media (max-width: 1024px) {
    .app:not(.is-expanded) .sidebar__brand-text,
    .app:not(.is-expanded) .sidebar__footer,
    .app:not(.is-expanded) .nav-link__label,
    .app:not(.is-expanded) .nav-link__chevron,
    .app:not(.is-expanded) .nav-link__tier,
    .app:not(.is-expanded) .nav-group__title { display: none; }
    .app:not(.is-expanded) .sidebar__brand { justify-content: center; padding: 0; }
    .app:not(.is-expanded) .nav-link { justify-content: center; padding: 11px 0; }
    .app:not(.is-expanded) .nav-sub {
        display: none;
        position: absolute;
        left: 100%; top: 0;
        min-width: 210px;
        padding: var(--sp-2) 0;
        background: var(--orna-blue-dark);
        border-radius: 0 var(--radius-panel) var(--radius-panel) 0;
        box-shadow: var(--shadow-lg);
    }
    .app:not(.is-expanded) .nav-item:hover > .nav-sub,
    .app:not(.is-expanded) .nav-item:focus-within > .nav-sub,
    .app:not(.is-expanded) .nav-item.is-open > .nav-sub { display: block; }
    .app:not(.is-expanded) .nav-sub__link { padding-left: var(--sp-4); }
}

/* Palier 900 px : la barre supérieure abandonne les libellés de contexte. */
@media (max-width: 900px) {
    .grid--2 { grid-template-columns: minmax(0, 1fr); }
    .span-half, .span-quarter { grid-column: span 1; }
    .context-select__label { display: none; }
    .context-select__value { max-width: 130px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .userbar__text { display: none; }
}

/* ==========================================================================
   Palier 768 px : téléphone et tablette en portrait.
   La colonne de navigation disparaît, la barre basse prend le relais.
   ========================================================================== */
@media (max-width: 768px) {
    /* --- Coquille ---------------------------------------------------- */
    .app,
    .app.is-collapsed,
    .app.is-expanded { grid-template-columns: minmax(0, 1fr); }

    /* 100dvh suit la barre d'adresse mobile, contrairement à 100vh qui
       provoque un débordement au premier défilement. */
    .app { min-height: 100vh; min-height: 100dvh; }
    .app__main { min-height: 0; }

    /* --- La barre latérale devient un volet --------------------------- */
    .sidebar {
        position: fixed;
        top: 0; bottom: 0; left: 0;
        width: min(84vw, 320px);
        height: 100vh; height: 100dvh;
        z-index: 50;
        overflow-y: auto;
        overscroll-behavior: contain;
        transform: translateX(-100%);
        transition: transform var(--ease);
        box-shadow: var(--shadow-lg);
        padding-bottom: env(safe-area-inset-bottom, 0px);
    }
    .app.is-drawer-open .sidebar { transform: none; }
    .app.is-drawer-open .app__scrim { display: block; }

    /* Dans le volet, le menu reprend sa forme complète, quel que soit l'état
       mémorisé de la barre latérale sur grand écran. Les sélecteurs reprennent
       la forme exacte des règles de réduction — même poids, source plus tardive
       — sinon `is-collapsed` continuerait de masquer les libellés. */
    .app.is-collapsed .sidebar__brand-text,
    .app.is-collapsed .sidebar__footer,
    .app.is-collapsed .nav-link__label,
    .app.is-collapsed .nav-link__chevron,
    .app.is-collapsed .nav-link__tier,
    .app.is-collapsed .nav-group__title,
    .app:not(.is-expanded) .sidebar__brand-text,
    .app:not(.is-expanded) .sidebar__footer,
    .app:not(.is-expanded) .nav-link__label,
    .app:not(.is-expanded) .nav-link__chevron,
    .app:not(.is-expanded) .nav-link__tier,
    .app:not(.is-expanded) .nav-group__title { display: revert; }

    .app.is-collapsed .sidebar__brand,
    .app:not(.is-expanded) .sidebar__brand { justify-content: flex-start; padding: 0 var(--sp-4); }

    .app.is-collapsed .nav-link,
    .app:not(.is-expanded) .nav-link {
        justify-content: flex-start;
        padding: 11px var(--sp-4);
        min-height: 44px;
    }

    /* Les sous-menus redeviennent des listes dépliables, jamais des volets
       flottants : il n'y a pas de survol au doigt. */
    .app.is-collapsed .nav-sub,
    .app:not(.is-expanded) .nav-sub {
        position: static;
        display: none;
        min-width: 0;
        padding: 0;
        background: transparent;
        box-shadow: none;
        border-radius: 0;
    }
    .app.is-collapsed .nav-item:hover > .nav-sub,
    .app.is-collapsed .nav-item:focus-within > .nav-sub,
    .app:not(.is-expanded) .nav-item:hover > .nav-sub,
    .app:not(.is-expanded) .nav-item:focus-within > .nav-sub { display: none; }
    .app.is-collapsed .nav-item.is-open > .nav-sub,
    .app:not(.is-expanded) .nav-item.is-open > .nav-sub { display: block; }

    .app.is-collapsed .nav-sub__link,
    .app:not(.is-expanded) .nav-sub__link {
        display: flex;
        align-items: center;
        min-height: 42px;
        padding-left: var(--sp-8);
    }

    .sidebar__close { display: inline-flex; }

    /* --- Barre basse -------------------------------------------------- */
    .bottom-nav { display: flex; }

    /* Le contenu se termine au-dessus de la barre : sans cette réserve, la
       dernière ligne d'un tableau resterait inatteignable. */
    .content {
        padding: var(--sp-4) var(--sp-3);
        padding-bottom: calc(var(--sp-6) + 56px + env(safe-area-inset-bottom, 0px));
    }

    /* --- Barre supérieure --------------------------------------------- */
    .topbar {
        gap: var(--sp-2);
        padding: 0 var(--sp-3);
        padding-top: env(safe-area-inset-top, 0px);
        height: auto;
        min-height: var(--topbar-h);
    }
    .topbar__toggle { display: none; }
    .topbar__brand { display: inline-flex; }
    .topbar__search-toggle { display: inline-flex; }

    /* La recherche se déploie par-dessus la barre plutôt que de la faire
       passer sur deux lignes. */
    /* Seule la recherche globale de la barre supérieure se replie : les
       champs de filtre des écrans portent la même classe et doivent, eux,
       rester visibles et pleine largeur. */
    .topbar .search {
        position: absolute;
        inset: 0 0 auto 0;
        z-index: 5;
        display: none;
        max-width: none;
        padding: var(--sp-2) var(--sp-3);
        background: var(--n-0);
        border-bottom: 1px solid var(--n-300);
    }
    .topbar.is-searching .search { display: block; }
    .topbar .search__icon { left: 22px; }
    .topbar .search__close {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        position: absolute;
        right: 18px; top: 50%;
        transform: translateY(-50%);
        width: 30px; height: 30px;
        border: 0; border-radius: var(--radius-pill);
        background: transparent;
        color: var(--n-600);
        cursor: pointer;
    }

    /* La barre supérieure ne défile pas : chaque élément accepte de rétrécir,
       et le sélecteur d'entreprise absorbe l'espace restant. */
    .topbar > .dropdown { min-width: 0; }
    .topbar__spacer { display: none; }
    .context-select { min-width: 0; padding: 0 var(--sp-2); }
    .context-select__value { max-width: none; }

    /* L'entreprise active garde du texte — c'est le contexte qu'on ne doit
       jamais perdre de vue ; l'exercice se réduit à son icône. Deux libellés
       ne tiennent pas sur 375 px sans repousser la cloche hors de l'écran. */
    .dropdown--societe { flex: 1 1 auto; min-width: 64px; }
    .dropdown--societe .context-select { max-width: 100%; }
    .dropdown--societe .context-select__value { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

    .dropdown--exercice .context-select__text,
    .dropdown--exercice .context-select > .icon:last-child { display: none; }
    .dropdown--exercice .context-select { width: 40px; justify-content: center; padding: 0; }

    /* Le bandeau utilisateur se réduit à son avatar — la règle vaut pour les
       deux applications, l'ERP comme le back-office. */
    .topbar .userbar { padding: 0; gap: 0; border-color: transparent; background: transparent; }
    .topbar .userbar > .icon:last-child { display: none; }

    /* Les menus déroulants se posent en carte pleine largeur, ancrée sous la
       barre : à 375 px, un panneau ancré à droite déborderait. */
    .dropdown__panel {
        position: fixed;
        left: var(--sp-3); right: var(--sp-3);
        top: calc(var(--topbar-h) + env(safe-area-inset-top, 0px) + var(--sp-2));
        min-width: 0 !important;
        max-height: calc(100dvh - var(--topbar-h) - 56px - var(--sp-8));
        overflow-y: auto;
        overscroll-behavior: contain;
    }
    .dropdown__item { min-height: 44px; }

    /* --- En-tête de page --------------------------------------------- */
    .page-head { flex-direction: column; align-items: stretch; gap: var(--sp-3); }
    .page-head__actions { width: 100%; }
    .page-head__actions > .btn,
    .page-head__actions > form,
    .page-head__actions > .search { flex: 1 1 auto; }
    .page-head__actions .btn { justify-content: center; }
    /* Les filtres d'écran portent une largeur maximale en attribut de style :
       sur téléphone, ils prennent toute la ligne. */
    .page-head__actions .search { max-width: none !important; }

    /* --- Pied de formulaire ------------------------------------------ */
    /* Les boutons se partagent la ligne, centrés, à la taille du pouce. */
    .form-pied > .btn { flex: 1 1 auto; justify-content: center; }

    /* --- Grilles et panneaux ----------------------------------------- */
    .grid { gap: var(--sp-4); }
    .grid--4, .grid--3, .grid--2, .grid--2-1 { grid-template-columns: minmax(0, 1fr); }
    .choice-grid { grid-template-columns: minmax(0, 1fr); }
    .panel__body { padding: var(--sp-4); }
    .panel__head { flex-wrap: wrap; gap: var(--sp-2); }
    .panel__actions { flex-wrap: wrap; }

    /* --- Formulaires -------------------------------------------------- */
    .form-row, .form-row--3 { grid-template-columns: minmax(0, 1fr); }
    /* 16 px : en dessous, iOS zoome sur le champ à la mise au point et
       l'utilisateur se retrouve avec une page décalée. */
    .input, .select, .textarea, .search__input, .champ-icone .input { font-size: 16px; min-height: 44px; }
    .btn { min-height: 44px; }

    /* --- Tableaux ------------------------------------------------------
       Les tableaux comptables ne se replient pas en cartes : leur lecture
       repose sur l'alignement des colonnes. Ils défilent horizontalement,
       avec la colonne d'identification figée et une ombre qui signale qu'il
       reste quelque chose à droite. */
    .panel__body--flush .table-wrap,
    .panel > .table-wrap {
        margin-inline: 0;
    }
    .table-wrap {
        -webkit-overflow-scrolling: touch;
        overscroll-behavior-x: contain;
        background:
            linear-gradient(to right, var(--n-0) 30%, rgba(255,255,255,0)) left center / 28px 100% no-repeat,
            linear-gradient(to left,  var(--n-0) 30%, rgba(255,255,255,0)) right center / 28px 100% no-repeat,
            linear-gradient(to right, rgba(13,13,61,.10), rgba(13,13,61,0)) left center / 12px 100% no-repeat,
            linear-gradient(to left,  rgba(13,13,61,.10), rgba(13,13,61,0)) right center / 12px 100% no-repeat;
        background-attachment: local, local, scroll, scroll;
    }
    .table th, .table td { padding: 10px var(--sp-3); }
    .table th[scope="row"] {
        position: sticky;
        left: 0;
        z-index: 1;
        background: var(--n-0);
        box-shadow: 1px 0 0 var(--n-200);
    }
    .table tbody tr:hover th[scope="row"] { background: var(--n-50); }

    /* --- Modale : feuille ancrée en bas, pouce à portée --------------- */
    .modal { align-items: flex-end; padding: 0; }
    .modal__box {
        width: 100%;
        max-width: none;
        max-height: 88dvh;
        border-radius: var(--radius-panel) var(--radius-panel) 0 0;
        padding-bottom: env(safe-area-inset-bottom, 0px);
    }

    /* --- Notifications : au-dessus de la barre basse ------------------ */
    .toast-stack {
        right: var(--sp-3); left: var(--sp-3);
        bottom: calc(56px + env(safe-area-inset-bottom, 0px) + var(--sp-3));
        max-width: none;
    }

    /* --- Onglets : défilement plutôt que retour à la ligne ------------ */
    .tabs {
        flex-wrap: nowrap;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
    }
    .tabs::-webkit-scrollbar { display: none; }
    .tab { white-space: nowrap; }

    /* --- Écrans d'authentification ------------------------------------ */
    body.auth { padding: var(--sp-4) var(--sp-3); padding-bottom: calc(var(--sp-5) + env(safe-area-inset-bottom, 0px)); align-items: flex-start; }
    .auth-volet { max-width: none; }
    .auth-carte { padding: var(--sp-6) var(--sp-5); border-radius: 18px; }
    .auth-carte__titre { font-size: var(--fs-2xl); }

    /* Le choix d'entreprise passe sur deux lignes : à 375 px, la raison
       sociale, le rôle et la pastille d'état ne tiennent pas côte à côte —
       ils se chevauchaient. */
    .societe-choix {
        display: grid;
        grid-template-columns: auto minmax(0, 1fr) auto;
        align-items: center;
        gap: var(--sp-2) var(--sp-3);
    }
    .societe-choix > span:nth-child(2) { grid-column: 2; }
    .societe-choix .tag,
    .societe-choix .pill {
        grid-column: 2 / -1;
        justify-self: start;
        margin: 0;
    }
    .societe-choix .pill { grid-column: 2 / -1; }
    .societe-choix > .icon:last-child { grid-column: 3; grid-row: 1; align-self: center; }
    .societe-choix__nom { overflow-wrap: anywhere; }
}

/* Tablette en portrait : la barre basse est utile, mais la largeur permet
   encore deux colonnes et le libellé de l'exercice. */
@media (min-width: 601px) and (max-width: 768px) {
    .grid--4, .grid--3, .grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .choice-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .form-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }

    .dropdown--exercice .context-select { width: auto; padding: 0 var(--sp-3); }
    .dropdown--exercice .context-select__text { display: flex; }
    .content { padding: var(--sp-5) var(--sp-5); padding-bottom: calc(var(--sp-8) + 56px + env(safe-area-inset-bottom, 0px)); }
}

/* Tableaux repliés en cartes — listes d'enregistrements uniquement.
   Une facture, un client ou un salarié se lisent enregistrement par
   enregistrement ; les intitulés de colonne sont recopiés devant chaque
   valeur par le script, à partir de l'en-tête réel du tableau. */
@media (max-width: 768px) {
    .table--stack thead { display: none; }
    /* `tfoot` doit être déclaré lui aussi : laissé en groupe de tableau dans un
       tableau passé en bloc, il se replierait sur une colonne étroite. */
    .table--stack,
    .table--stack tbody,
    .table--stack tfoot,
    .table--stack tr,
    .table--stack th,
    .table--stack td { display: block; }
    .table--stack tr {
        margin-bottom: var(--sp-3);
        padding: var(--sp-3);
        border: 1px solid var(--n-300);
        border-radius: var(--radius-button);
        background: var(--n-0);
    }
    .table--stack tr:last-child { margin-bottom: 0; }
    .table--stack th, .table--stack td {
        display: flex;
        align-items: baseline;
        justify-content: space-between;
        gap: var(--sp-3);
        padding: 5px 0;
        border: 0;
        text-align: left;
    }
    /* La première cellule de la ligne fait le titre de la carte, qu'elle soit
       un `th` d'en-tête de ligne ou une simple cellule : c'est l'identité de
       l'enregistrement — une référence, un matricule, un nom. */
    .table--stack tbody tr > :first-child {
        position: static;
        box-shadow: none;
        display: block;
        padding: 0 0 var(--sp-2);
        margin-bottom: var(--sp-2);
        border-bottom: 1px solid var(--n-200);
        font-size: var(--fs-md);
        font-weight: 600;
        color: var(--orna-blue);
        text-align: left;
    }
    .table--stack td.num, .table--stack th.num { text-align: right; }
    .table--stack td::before,
    .table--stack th::before {
        content: attr(data-label);
        flex: 0 0 auto;
        font-size: var(--fs-xs);
        font-weight: 600;
        letter-spacing: .06em;
        text-transform: uppercase;
        color: var(--n-600);
    }
    /* Une cellule sans intitulé — titre de carte, actions, pastille seule —
       occupe toute la largeur. */
    .table--stack td[data-label=""]::before,
    .table--stack th[data-label=""]::before,
    .table--stack tbody tr > :first-child::before { content: none; }
    .table--stack .table__row-actions { justify-content: flex-start; }
    .table--stack tbody tr:hover { background: var(--n-0); }

    /* La ligne de totaux devient une carte de synthèse, distincte des
       enregistrements qu'elle résume. */
    .table--stack tfoot tr {
        background: var(--orna-blue-pale);
        border-color: var(--orna-blue-light);
    }
    .table--stack tfoot td { border-top: 0; font-weight: 600; }
    .table--stack tfoot tr > :first-child {
        border-bottom-color: var(--orna-blue-light);
        color: var(--orna-blue);
    }
    /* Le tableau replié ne défile plus : il n'y a plus de colonnes. */
    .table--stack { min-width: 0; }

    /* Tableaux de saisie repliés — lignes d'opération, imputations d'un
       règlement, feuille de comptage. Chaque ligne devient un petit
       formulaire : le champ occupe l'espace restant à droite de son
       intitulé, et retrouve la hauteur de frappe confortable que le mode
       « édition en place » lui retire sur grand écran. */
    .table--editable.table--stack td { padding: 4px 0; }
    .table--editable.table--stack td .input,
    .table--editable.table--stack td .select {
        flex: 1 1 auto;
        min-width: 0;
        min-height: 40px;
        padding: 6px var(--sp-2);
        border-color: var(--n-300);
        background: var(--n-0);
        text-align: right;
    }
    .table--editable.table--stack td .select { text-align: left; }
    .table--editable.table--stack tr:focus-within { background: var(--n-0); box-shadow: 0 0 0 2px var(--orna-blue-pale); }
    /* La colonne de suppression n'a pas d'intitulé : son bouton se pose à
       droite, comme sur une ligne de formulaire. */
    .table--editable.table--stack td:last-child { justify-content: flex-end; }
}

/* Palier 430 px : petits téléphones. */
@media (max-width: 430px) {
    .content { padding: var(--sp-3) var(--sp-3); padding-bottom: calc(var(--sp-6) + 56px + env(safe-area-inset-bottom, 0px)); }
    h1 { font-size: var(--fs-xl); }
    .kpi__value { font-size: clamp(1.125rem, 6vw, 1.5rem); overflow-wrap: anywhere; }
    .panel__body { padding: var(--sp-3); }
    /* Sur les plus petits écrans, la marque cède la place : « Accueil » est
       déjà à portée de pouce dans la barre basse. */
    .topbar__brand { display: none; }
    .bottom-nav__label { font-size: 10px; }
    .page-head__actions { flex-direction: column; align-items: stretch; }
    .page-head__actions .btn { width: 100%; }
    /* Boutons empilés pleine largeur, l'action principale en tête et
       « Annuler » en dernier, loin du pouce. */
    .form-pied { flex-direction: column-reverse; align-items: stretch; }
    .form-pied > .btn { width: 100%; }
}

/* Téléphone en paysage : peu de hauteur, la barre basse se tasse. */
@media (max-height: 460px) and (orientation: landscape) and (max-width: 900px) {
    .bottom-nav__item { min-height: 44px; padding: 4px 2px; }
    .bottom-nav__label { display: none; }
    .content { padding-bottom: calc(var(--sp-4) + 44px + env(safe-area-inset-bottom, 0px)); }
    .toast-stack { bottom: calc(44px + env(safe-area-inset-bottom, 0px) + var(--sp-2)); }
}

/* Pointeur grossier : toute cible interactive atteint 44 px, quelle que soit
   la largeur de l'écran — une tablette tactile large en a autant besoin qu'un
   téléphone (§18). */
@media (pointer: coarse) {
    .icon-button, .topbar__toggle { min-width: 40px; min-height: 40px; }
    .nav-sub__link { min-height: 40px; display: flex; align-items: center; }
    .table__row-actions .btn--sm { min-height: 36px; }
}

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
    .sidebar { transition: none; }
}


/* --------------------------------------------------------------------------
   22. Impression — documents commerciaux, bulletins et états comptables
   -------------------------------------------------------------------------- */
@media print {
    .sidebar, .topbar, .page-head__actions, .toast-stack, .skip-link,
    .bottom-nav, .app__scrim { display: none !important; }
    .app { display: block; }
    .content { padding: 0; max-width: none; }
    /* Un tableau imprimé ne défile pas : il se déplie en entier. */
    .table-wrap { overflow: visible; background: none; }
    .table th[scope="row"] { position: static; box-shadow: none; }
    .table--stack thead { display: table-header-group; }
    .table--stack, .table--stack tbody, .table--stack tr { display: revert; }
    .table--stack th, .table--stack td { display: table-cell; }
    .table--stack td::before, .table--stack th::before { content: none; }
    .panel { border-color: #ccc; box-shadow: none; break-inside: avoid; }
    body { background: #fff; font-size: 11pt; }
}
