/* ===========================================================================
   COMPOSANTS — Easy Print Center
   ---------------------------------------------------------------------------
   Le vocabulaire unique de l'administration. Un bouton se dessine ici et
   nulle part ailleurs ; un ecran qui a besoin d'une variante l'ajoute ici,
   pas dans sa propre feuille.

   Chaque composant interactif porte ses sept etats : repos, survol, focus,
   actif, desactive, chargement, erreur. Un composant livre avec la moitie de
   ses etats est un composant a refaire.
   =========================================================================== */

/* ===========================================================================
   BOUTONS
   =========================================================================== */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    min-height: 40px;
    padding: 8px 16px;
    border: 1px solid var(--color-line-2);
    border-radius: var(--radius-md);
    background: var(--color-surface);
    color: var(--color-ink);
    font-size: var(--font-size-body);
    font-weight: 550;
    line-height: 1.2;
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
    transition: background-color var(--duree-1) var(--sortie),
                border-color var(--duree-1) var(--sortie),
                color var(--duree-1) var(--sortie),
                transform var(--duree-1) var(--sortie);
}

.btn:hover:not(:disabled):not([aria-disabled='true']) {
    background: var(--color-surface-2);
    color: var(--color-ink);
    text-decoration: none;
}

.btn:active:not(:disabled) { transform: translateY(1px); }

.btn:disabled,
.btn[aria-disabled='true'] {
    opacity: 0.55;
    cursor: not-allowed;
    transform: none;
}

.btn svg {
    width: 17px;
    height: 17px;
    flex: none;
}

/* --- Variantes --------------------------------------------------------- */

/* L'action principale porte le trait d'encre et une ombre franche : elle
   s'enfonce au clic comme un tampon. C'est le seul element de l'outil qui
   prend ce geste, pour qu'il reste un signal. */
.btn--primaire {
    border-color: var(--trait);
    background: var(--color-brand);
    color: var(--color-brand-contraste);
    font-weight: 650;
    box-shadow: var(--ombre-encre);
}

.btn--primaire:hover:not(:disabled):not([aria-disabled='true']) {
    background: var(--color-brand-d);
    color: var(--color-brand-contraste);
}

.btn--primaire:active:not(:disabled) {
    transform: translateY(2px);
    box-shadow: 0 1px 0 var(--trait);
}

.btn--danger {
    border-color: transparent;
    background: var(--color-danger);
    color: #fff;
}

.btn--danger:hover:not(:disabled) {
    background: var(--color-danger-d);
    color: #fff;
}

/* Danger discret : l'action existe, elle ne crie pas depuis une ligne de
   tableau. Elle ne devient rouge pleine qu'au moment de confirmer. */
.btn--danger-doux {
    border-color: transparent;
    background: transparent;
    color: var(--color-danger);
}

.btn--danger-doux:hover:not(:disabled) {
    background: var(--color-danger-tint);
    color: var(--color-danger-d);
}

.btn--fantome {
    border-color: transparent;
    background: transparent;
    color: var(--color-ink-2);
}

.btn--fantome:hover:not(:disabled) {
    background: var(--color-surface-2);
    color: var(--color-ink);
}

/* --- Tailles ----------------------------------------------------------- */

.btn--petit {
    min-height: 32px;
    padding: 5px 10px;
    font-size: var(--font-size-label);
}

.btn--petit svg { width: 15px; height: 15px; }

.btn--grand {
    min-height: 48px;
    padding: 12px 22px;
    font-size: 1rem;
}

.btn--carre {
    width: 36px;
    min-height: 36px;
    padding: 0;
}

.btn--large { width: 100%; }

/* --- Chargement --------------------------------------------------------
   Pose par le controleur Stimulus au moment de la soumission : le bouton
   garde sa largeur, se verrouille, et dit qu'il travaille. */
.btn[data-charge] {
    position: relative;
    color: transparent !important;
    pointer-events: none;
}

.btn[data-charge]::after {
    content: '';
    position: absolute;
    width: 16px;
    height: 16px;
    border: 2px solid color-mix(in oklab, currentColor 30%, transparent);
    border-top-color: var(--color-brand-contraste);
    border-radius: 50%;
    animation: tourne 700ms linear infinite;
}

.btn--primaire[data-charge]::after,
.btn--danger[data-charge]::after { border-top-color: #fff; }

.btn:not(.btn--primaire):not(.btn--danger)[data-charge]::after {
    border-top-color: var(--color-brand);
}

@keyframes tourne { to { transform: rotate(360deg); } }

@media (prefers-reduced-motion: reduce) {
    .btn[data-charge]::after { animation-duration: 1.6s; }
}

/* Groupe d'actions : la principale a droite sur desktop, empilee sur mobile. */
.actions-barre {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
}

/* ===========================================================================
   EN-TETE DE PAGE
   Titre, contexte et actions principales au meme endroit sur tous les ecrans.
   =========================================================================== */

.page-tete {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-3);
    margin-bottom: var(--space-4);
}

.page-tete h1 { margin: 0; }

.page-tete-titres {
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
}

.page-tete-legende {
    margin: 0;
    color: var(--color-ink-3);
    font-size: var(--font-size-label);
}

.fil {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-1);
    margin-bottom: var(--space-2);
    font-size: var(--font-size-label);
    color: var(--color-ink-3);
}

.fil a { color: var(--color-ink-3); text-decoration: none; }
.fil a:hover { color: var(--color-brand); text-decoration: underline; }
.fil-sep { opacity: 0.5; }

/* ===========================================================================
   CARTES ET PANNEAUX
   =========================================================================== */

.panneau {
    padding: var(--space-4);
    border: 1px solid var(--color-line);
    border-radius: var(--radius-lg);
    background: var(--color-surface);
}

.panneau + .panneau { margin-top: var(--space-4); }

.panneau-tete {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    margin-bottom: var(--space-3);
}

.panneau-tete h2,
.panneau-tete h3 { margin: 0; }

/* Panneau qui contient un tableau : le tableau touche les bords. */
.panneau--serre { padding: 0; overflow: hidden; }
.panneau--serre .panneau-tete { padding: var(--space-3) var(--space-4) 0; }

/* Grille de panneaux sans point de rupture. */
.grille {
    align-items: start;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: var(--space-3);
}

.grille--large { grid-template-columns: repeat(auto-fit, minmax(340px, 1fr)); }

/* ===========================================================================
   CHIFFRES
   Pas la carte-metrique geante : une valeur, son intitule, et le lien vers ce
   qu'elle compte. Cliquable quand il y a quelque chose a voir derriere.
   =========================================================================== */

.chiffres-rangee {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    gap: var(--space-3);
}

.chiffre {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: var(--space-3);
    border: 1px solid var(--color-line);
    border-radius: var(--radius-lg);
    background: var(--color-surface);
    color: inherit;
    text-decoration: none;
    transition: border-color var(--duree-1) var(--sortie),
                background-color var(--duree-1) var(--sortie);
}

a.chiffre:hover {
    border-color: color-mix(in oklab, var(--color-brand) 45%, var(--color-line));
    background: var(--color-surface-2);
    text-decoration: none;
}

.chiffre-intitule {
    font-size: var(--font-size-label);
    font-weight: 550;
    color: var(--color-ink-3);
}

.chiffre-valeur {
    font-size: 1.625rem;
    font-weight: 650;
    line-height: 1.15;
    letter-spacing: -0.02em;
    font-variant-numeric: tabular-nums;
    color: var(--color-ink);
}

.chiffre-note {
    font-size: var(--font-size-small);
    color: var(--color-ink-3);
}

.chiffre--alerte { border-color: color-mix(in oklab, var(--color-danger) 40%, var(--color-line)); }
.chiffre--alerte .chiffre-valeur { color: var(--color-danger); }

/* ===========================================================================
   PASTILLES D'ETAT
   Jamais la couleur seule : un point, un mot, et le mot suffit en noir et
   blanc comme pour un daltonien.
   =========================================================================== */

.pastille {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 3px 9px;
    border: 1px solid transparent;
    border-radius: var(--radius-rond);
    background: var(--color-surface-2);
    color: var(--color-ink-2);
    font-size: var(--font-size-small);
    font-weight: 600;
    line-height: 1.4;
    white-space: nowrap;
}

.pastille::before {
    content: '';
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: currentColor;
    flex: none;
}

.pastille--sans-point::before { display: none; }

.pastille--ok { background: var(--color-ok-tint); color: var(--color-ok); }
.pastille--attente { background: var(--color-warn-tint); color: var(--color-warn); }
.pastille--danger { background: var(--color-danger-tint); color: var(--color-danger); }
.pastille--info { background: var(--color-info-tint); color: var(--color-info); }
.pastille--marque { background: var(--color-brand-tint); color: var(--color-brand); }
.pastille--neutre { background: var(--color-surface-2); color: var(--color-ink-2); }

/* Etiquette de service ou de module : pas un etat, une appartenance. */
.etiquette {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 2px 8px;
    border: 1px solid var(--color-line);
    border-radius: var(--radius-sm);
    background: var(--color-surface);
    color: var(--color-ink-2);
    font-size: var(--font-size-small);
    font-weight: 550;
    white-space: nowrap;
}

.etiquettes {
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
}

/* ===========================================================================
   MESSAGES
   =========================================================================== */

.message {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    padding: var(--space-3);
    border: 1px solid var(--color-line);
    border-radius: var(--radius-md);
    background: var(--color-surface-2);
    color: var(--color-ink);
}

.message svg { width: 18px; height: 18px; flex: none; margin-top: 1px; }
.message p { margin: 0; }
.message-corps { min-width: 0; }
.message-titre { font-weight: 650; }

.message--ok { border-color: color-mix(in oklab, var(--color-ok) 35%, var(--color-line)); background: var(--color-ok-tint); }
.message--ok svg { color: var(--color-ok); }
.message--danger { border-color: color-mix(in oklab, var(--color-danger) 35%, var(--color-line)); background: var(--color-danger-tint); }
.message--danger svg { color: var(--color-danger); }
.message--attention { border-color: color-mix(in oklab, var(--color-warn) 40%, var(--color-line)); background: var(--color-warn-tint); }
.message--attention svg { color: var(--color-warn); }
.message--info { border-color: color-mix(in oklab, var(--color-info) 30%, var(--color-line)); background: var(--color-info-tint); }
.message--info svg { color: var(--color-info); }

/* ===========================================================================
   NOTIFICATIONS EPHEMERES
   =========================================================================== */

.toasts {
    position: fixed;
    right: var(--space-3);
    bottom: var(--space-3);
    z-index: var(--z-toast);
    display: flex;
    flex-direction: column-reverse;
    gap: var(--space-2);
    max-width: min(380px, calc(100vw - 2 * var(--space-3)));
    pointer-events: none;
}

.toast {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    padding: 12px var(--space-3);
    border: 1px solid var(--color-line);
    border-radius: var(--radius-md);
    background: var(--color-surface);
    box-shadow: var(--shadow-3);
    pointer-events: auto;
    animation: toast-entre var(--duree-3) var(--sortie);
}

.toast svg { width: 18px; height: 18px; flex: none; margin-top: 1px; }
.toast--ok svg { color: var(--color-ok); }
.toast--danger svg { color: var(--color-danger); }
.toast--attention svg { color: var(--color-warn); }
.toast-corps { min-width: 0; flex: 1; }
.toast-titre { font-weight: 600; }
.toast-detail { font-size: var(--font-size-label); color: var(--color-ink-3); }

.toast-fermer {
    min-height: 0;
    padding: 2px;
    border: 0;
    background: none;
    color: var(--color-ink-3);
    line-height: 1;
}

.toast-fermer:hover { background: none; color: var(--color-ink); }

.toast[data-sort] { animation: toast-sort var(--duree-2) var(--sortie) forwards; }

@keyframes toast-entre {
    from { opacity: 0; transform: translateY(10px) scale(0.98); }
    to { opacity: 1; transform: none; }
}

@keyframes toast-sort {
    to { opacity: 0; transform: translateY(6px); }
}

@media (prefers-reduced-motion: reduce) {
    .toast { animation: toast-fond var(--duree-2) linear; }
    @keyframes toast-fond { from { opacity: 0; } to { opacity: 1; } }
}

/* Sur telephone, la notification passe en haut : le bas de l'ecran est occupe
   par la barre d'actions et par le pouce. */
@media (max-width: 700px) {
    .toasts {
        top: calc(var(--space-2) + env(safe-area-inset-top));
        bottom: auto;
        left: var(--space-2);
        right: var(--space-2);
        max-width: none;
        flex-direction: column;
    }
}

/* ===========================================================================
   TABLEAU DE DONNEES
   =========================================================================== */

.tableau {
    width: 100%;
    border-collapse: collapse;
}

.tableau thead th {
    position: sticky;
    top: 0;
    z-index: var(--z-colle);
    padding: 10px var(--space-3);
    border-bottom: 1px solid var(--color-line);
    background: var(--color-surface);
    color: var(--color-ink-3);
    font-size: var(--font-size-label);
    font-weight: 600;
    text-align: left;
    white-space: nowrap;
}

.tableau tbody td {
    padding: 11px var(--space-3);
    border-bottom: 1px solid var(--color-line);
    vertical-align: middle;
}

.tableau tbody tr { transition: background-color var(--duree-1) var(--sortie); }
.tableau tbody tr:hover { background: var(--color-surface-2); }
.tableau tbody tr[data-choisie] { background: var(--color-brand-tint); }
.tableau tbody tr:last-child td { border-bottom: 0; }

.tableau .services { color: var(--color-ink-2); white-space: nowrap; }
.tableau .principal { font-weight: 600; min-width: 190px; }
.tableau .principal a { color: var(--color-ink); text-decoration: none; }
.tableau .principal a:hover { color: var(--color-brand); text-decoration: underline; }
.tableau .secondaire { color: var(--color-ink-3); font-size: var(--font-size-label); }
.tableau .droite { text-align: right; }
.tableau .montant { text-align: right; font-variant-numeric: tabular-nums; }
.tableau .fin { width: 1%; white-space: nowrap; text-align: right; }

/* En-tete triable : le bouton porte l'ordre, la colonne active le montre. */
.tri {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    min-height: 0;
    padding: 0;
    border: 0;
    background: none;
    color: inherit;
    font: inherit;
    font-weight: 600;
    cursor: pointer;
}

.tri:hover { background: none; color: var(--color-ink); }
.tri-fleche { opacity: 0; transition: opacity var(--duree-1) var(--sortie); }
.tri:hover .tri-fleche { opacity: 0.45; }
[aria-sort] .tri { color: var(--color-ink); }
[aria-sort] .tri-fleche { opacity: 1; }
[aria-sort='descending'] .tri-fleche { transform: rotate(180deg); }

/* Les actions d'une ligne restent visibles, en retrait.
   Les faire apparaitre au survol donne une liste plus calme et une action
   qu'on ne trouve pas : il faut deja savoir qu'elle est la pour aller la
   chercher, et au doigt le survol n'existe pas. Elles sont donc toujours la,
   discretes, et le survol de la ligne les affirme. */
.ligne-actions {
    display: flex;
    justify-content: flex-end;
    gap: var(--space-1);
}

@media (hover: hover) and (pointer: fine) {
    .ligne-actions .btn {
        border-color: transparent;
        background: transparent;
        color: var(--color-ink-3);
        transition: color var(--duree-1) var(--sortie),
                    background-color var(--duree-1) var(--sortie),
                    border-color var(--duree-1) var(--sortie);
    }

    tr:hover .ligne-actions .btn,
    .ligne-actions:focus-within .btn {
        border-color: var(--color-line-2);
        background: var(--color-surface);
        color: var(--color-ink);
    }
}

/* --- Le tableau devient des cartes sous 860px -----------------------------
   Pas de defilement lateral a l'aveugle : chaque ligne devient une fiche, et
   l'intitule de colonne passe en etiquette via data-col. */
@media (max-width: 860px) {
    .tableau--cartes thead { display: none; }

    .tableau--cartes tbody tr {
        display: grid;
        grid-template-columns: auto 1fr;
        gap: 2px var(--space-3);
        padding: var(--space-3);
        border: 1px solid var(--color-line);
        border-radius: var(--radius-md);
        background: var(--color-surface);
    }

    .tableau--cartes tbody tr + tr { margin-top: var(--space-2); }

    .tableau--cartes tbody td {
        display: contents;
        border: 0;
        padding: 0;
    }

    .tableau--cartes tbody td::before {
        content: attr(data-col);
        color: var(--color-ink-3);
        font-size: var(--font-size-small);
        font-weight: 550;
        padding: 3px 0;
    }

    /* justify-self : avec display:contents sur la cellule, ses enfants
       deviennent des cases de la grille et une pastille s'etirerait sur toute
       la colonne. */
    .tableau--cartes tbody td > * { padding: 3px 0; justify-self: start; }

    /* La cellule principale occupe la ligne entiere, en tete de carte. */
    .tableau--cartes tbody td.principal,
    .tableau--cartes tbody td.fin {
        display: block;
        grid-column: 1 / -1;
    }

    .tableau--cartes tbody td.principal::before,
    .tableau--cartes tbody td.fin::before { content: none; }

    .tableau--cartes tbody td.principal {
        font-size: 1rem;
        margin-bottom: var(--space-1);
    }

    .tableau--cartes tbody td.fin {
        margin-top: var(--space-2);
        padding-top: var(--space-2);
        border-top: 1px solid var(--color-line);
        text-align: left;
    }

    .tableau--cartes .ligne-actions { justify-content: flex-start; opacity: 1; }
    .tableau--cartes .montant { text-align: left; }
}

/* Repli pour les tableaux non convertis : defilement encadre et annonce. */
.table-defile {
    overflow-x: auto;
    overscroll-behavior-x: contain;
}

/* ===========================================================================
   BARRE DE FILTRES
   Des onglets rapides plutot qu'un pave de champs, et les filtres actifs
   affiches en jetons qu'on retire d'un clic.
   =========================================================================== */

.barre-outils {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
    margin-bottom: var(--space-3);
}

.barre-outils .recherche { flex: 1 1 260px; min-width: 200px; }

.recherche {
    position: relative;
    display: flex;
    align-items: center;
}

.recherche svg {
    position: absolute;
    left: 12px;
    width: 17px;
    height: 17px;
    color: var(--color-ink-3);
    pointer-events: none;
}

.recherche input { padding-left: 37px; }

/* Onglets de filtre : Toutes / Actives / Impayees ... */
.segments {
    display: inline-flex;
    padding: 3px;
    border: 1px solid var(--color-line);
    border-radius: var(--radius-md);
    background: var(--color-surface-2);
    gap: 2px;
}

.segments a,
.segments button {
    min-height: 32px;
    padding: 5px 12px;
    border: 0;
    border-radius: 7px;
    background: transparent;
    color: var(--color-ink-2);
    font-size: var(--font-size-label);
    font-weight: 550;
    text-decoration: none;
    white-space: nowrap;
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.segments a:hover,
.segments button:hover:not(:disabled) {
    background: color-mix(in oklab, var(--color-surface) 70%, transparent);
    color: var(--color-ink);
}

.segments [aria-current],
.segments [aria-pressed='true'] {
    background: var(--color-surface);
    color: var(--color-ink);
    box-shadow: var(--shadow-1);
}

.segments .compte {
    padding: 0 5px;
    border-radius: var(--radius-rond);
    background: var(--color-surface-3);
    font-size: var(--font-size-small);
    font-variant-numeric: tabular-nums;
}

/* Jetons de filtre actif */
.jetons {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
    margin-bottom: var(--space-3);
}

.jeton {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-height: 30px;
    padding: 3px 6px 3px 11px;
    border: 1px solid var(--color-line-2);
    border-radius: var(--radius-rond);
    background: var(--color-surface);
    color: var(--color-ink-2);
    font-size: var(--font-size-label);
    text-decoration: none;
}

.jeton b { color: var(--color-ink); font-weight: 600; }

.jeton-retirer {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    min-height: 0;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: var(--color-surface-2);
    color: var(--color-ink-3);
    line-height: 1;
}

.jeton-retirer:hover {
    background: var(--color-danger-tint);
    color: var(--color-danger);
}

/* ===========================================================================
   MENU CONTEXTUEL  (popover natif : rien a positionner a la main, et il
   echappe a tout conteneur en overflow hidden)
   =========================================================================== */

.menu-pop {
    position: absolute;
    min-width: 200px;
    margin: 0;
    padding: 5px;
    border: 1px solid var(--color-line);
    border-radius: var(--radius-md);
    background: var(--color-surface);
    box-shadow: var(--shadow-3);
    inset: auto;
}

.menu-pop:popover-open {
    animation: menu-entre var(--duree-2) var(--sortie);
}

@keyframes menu-entre {
    from { opacity: 0; transform: translateY(-4px); }
    to { opacity: 1; transform: none; }
}

.menu-pop a,
.menu-pop button {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    width: 100%;
    min-height: 36px;
    padding: 7px 10px;
    border: 0;
    border-radius: var(--radius-sm);
    background: none;
    color: var(--color-ink);
    font-size: var(--font-size-body);
    font-weight: 500;
    text-align: left;
    text-decoration: none;
    justify-content: flex-start;
}

.menu-pop a:hover,
.menu-pop button:hover:not(:disabled) {
    background: var(--color-surface-2);
    color: var(--color-ink);
}

.menu-pop svg { width: 16px; height: 16px; flex: none; color: var(--color-ink-3); }
.menu-pop .danger { color: var(--color-danger); }
.menu-pop .danger:hover { background: var(--color-danger-tint); color: var(--color-danger-d); }
.menu-pop hr { margin: 5px 0; }
.menu-pop-titre {
    padding: 6px 10px 4px;
    color: var(--color-ink-3);
    font-size: var(--font-size-small);
    font-weight: 600;
}

/* ===========================================================================
   MODALE ET PANNEAU LATERAL  (element dialog natif)
   =========================================================================== */

.modale,
.tiroir {
    padding: 0;
    border: 0;
    background: var(--color-surface);
    color: var(--color-ink);
    box-shadow: var(--shadow-3);
}

.modale::backdrop,
.tiroir::backdrop {
    background: light-dark(oklch(0.22 0.016 168 / 0.35), oklch(0 0 0 / 0.6));
    backdrop-filter: blur(2px);
}

.modale {
    width: min(520px, calc(100vw - 2 * var(--space-3)));
    max-height: calc(100vh - 2 * var(--space-4));
    margin: auto;
    border-radius: var(--radius-lg);
}

.modale[open] { animation: modale-entre var(--duree-3) var(--sortie); }
.modale::backdrop { animation: voile-entre var(--duree-2) var(--sortie); }

@keyframes modale-entre {
    from { opacity: 0; transform: translateY(12px) scale(0.985); }
    to { opacity: 1; transform: none; }
}

@keyframes voile-entre { from { opacity: 0; } to { opacity: 1; } }

/* Le tiroir : modifier sans quitter la liste. */
.tiroir {
    width: min(560px, 100vw);
    max-width: 100vw;
    height: 100vh;
    max-height: 100vh;
    margin: 0 0 0 auto;
    border-radius: 0;
}

.tiroir[open] { animation: tiroir-entre var(--duree-3) var(--sortie); }

@keyframes tiroir-entre {
    from { transform: translateX(24px); opacity: 0; }
    to { transform: none; opacity: 1; }
}

/* Sur telephone, le tiroir devient une feuille qui monte du bas : le pouce
   atteint le haut d'une feuille, pas le coin d'une fenetre. */
@media (max-width: 700px) {
    .tiroir {
        width: 100vw;
        height: auto;
        max-height: 88vh;
        margin: auto 0 0;
        border-radius: var(--radius-xl) var(--radius-xl) 0 0;
    }

    .tiroir[open] { animation: feuille-entre var(--duree-3) var(--sortie); }

    @keyframes feuille-entre {
        from { transform: translateY(100%); }
        to { transform: none; }
    }

    /* La poignee : elle dit que ca vient du bas et que ca s'y renvoie. */
    .tiroir .dialogue-tete::before {
        content: '';
        position: absolute;
        top: 7px;
        left: 50%;
        width: 36px;
        height: 4px;
        border-radius: var(--radius-rond);
        background: var(--color-line-2);
        transform: translateX(-50%);
    }

    .tiroir .dialogue-tete { padding-top: var(--space-4); }
}

.dialogue-tete {
    position: sticky;
    top: 0;
    z-index: 1;
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-4);
    border-bottom: 1px solid var(--color-line);
    background: var(--color-surface);
}

.dialogue-tete h2 { margin: 0; font-size: var(--font-size-h2); }
.dialogue-legende { margin: 2px 0 0; color: var(--color-ink-3); font-size: var(--font-size-label); }

.dialogue-corps {
    padding: var(--space-4);
    overflow-y: auto;
    max-height: calc(100vh - 150px);
}

.dialogue-pied {
    position: sticky;
    bottom: 0;
    display: flex;
    justify-content: flex-end;
    gap: var(--space-2);
    padding: var(--space-3) var(--space-4);
    border-top: 1px solid var(--color-line);
    background: var(--color-surface);
    padding-bottom: max(var(--space-3), env(safe-area-inset-bottom));
}

@media (max-width: 560px) {
    .dialogue-pied { flex-direction: column-reverse; }
    .dialogue-pied .btn { width: 100%; }
}

/* ===========================================================================
   ETAT VIDE
   Il enseigne l'ecran : ce que c'est, et le geste suivant.
   =========================================================================== */

.vide-etat {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-6) var(--space-4);
    text-align: center;
}

.vide-etat svg {
    width: 34px;
    height: 34px;
    color: var(--color-ink-3);
    opacity: 0.7;
}

.vide-etat h3 { margin: var(--space-1) 0 0; font-size: var(--font-size-h3); }

.vide-etat p {
    margin: 0;
    max-width: 46ch;
    color: var(--color-ink-3);
    text-wrap: pretty;
}

.vide-etat .btn { margin-top: var(--space-2); }

/* ===========================================================================
   SQUELETTES DE CHARGEMENT
   =========================================================================== */

.squelette {
    border-radius: var(--radius-sm);
    background: linear-gradient(
        90deg,
        var(--color-surface-2) 25%,
        var(--color-surface-3) 37%,
        var(--color-surface-2) 63%
    );
    background-size: 400% 100%;
    animation: squelette-glisse 1.4s ease-in-out infinite;
    color: transparent;
    user-select: none;
}

.squelette--ligne { height: 1em; }
.squelette--titre { height: 1.6em; width: 42%; }

@keyframes squelette-glisse {
    from { background-position: 100% 50%; }
    to { background-position: 0 50%; }
}

@media (prefers-reduced-motion: reduce) {
    .squelette { animation: none; background: var(--color-surface-2); }
}

/* ===========================================================================
   FORMULAIRES
   =========================================================================== */

.champ {
    display: flex;
    flex-direction: column;
    gap: 5px;
    margin-bottom: var(--space-3);
}

.champ > label {
    display: flex;
    align-items: center;
    gap: 5px;
}

.champ .requis { color: var(--color-danger); }

.champ-aide {
    margin: 0;
    color: var(--color-ink-3);
    font-size: var(--font-size-small);
    text-wrap: pretty;
}

.champ-erreurs {
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin: 0;
    padding: 0;
    list-style: none;
    color: var(--color-danger);
    font-size: var(--font-size-label);
    font-weight: 550;
}

/* Le verdict d'un controle en direct (TVA, email, domaine). */
.champ-verdict {
    display: flex;
    align-items: center;
    gap: 5px;
    font-size: var(--font-size-label);
    font-weight: 550;
}

.champ-verdict svg { width: 15px; height: 15px; flex: none; }
.champ-verdict--ok { color: var(--color-ok); }
.champ-verdict--ko { color: var(--color-danger); }
.champ-verdict--attente { color: var(--color-ink-3); }

/* Deux colonnes qui se replient d'elles-memes. */
.champs-paire {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 0 var(--space-3);
}

.champs-trio {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: 0 var(--space-3);
}

/* Section de formulaire : un titre, une explication, ses champs. */
.section-form {
    padding: var(--space-4) 0;
    border-top: 1px solid var(--color-line);
}

.section-form:first-of-type { border-top: 0; padding-top: 0; }
.section-form > h2 { margin-bottom: var(--space-1); font-size: var(--font-size-h3); }

.section-form-legende {
    margin: 0 0 var(--space-3);
    color: var(--color-ink-3);
    font-size: var(--font-size-label);
    max-width: 60ch;
}

/* Champ avec prefixe ou suffixe collés : €, %, BE, /mois. */
.champ-groupe {
    display: flex;
    align-items: stretch;
    border: 1px solid var(--color-line-2);
    border-radius: var(--radius-md);
    background: var(--color-surface);
    overflow: hidden;
    transition: border-color var(--duree-1) var(--sortie), box-shadow var(--duree-1) var(--sortie);
}

.champ-groupe:focus-within {
    border-color: var(--color-brand);
    box-shadow: 0 0 0 3px color-mix(in oklab, var(--color-brand) 22%, transparent);
}

.champ-groupe input,
.champ-groupe select {
    border: 0;
    border-radius: 0;
    background: none;
}

.champ-groupe input:focus-visible,
.champ-groupe select:focus-visible { box-shadow: none; }

.champ-fixe {
    display: flex;
    align-items: center;
    padding: 0 11px;
    background: var(--color-surface-2);
    color: var(--color-ink-3);
    font-size: var(--font-size-label);
    font-weight: 600;
    white-space: nowrap;
}

.champ-fixe:first-child { border-right: 1px solid var(--color-line); }
.champ-fixe:last-child { border-left: 1px solid var(--color-line); }

/* Champ monetaire : le montant se lit aligne a droite comme sur une facture. */
.champ-groupe input[data-montant] {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* --- Interrupteur ------------------------------------------------------- */

.bascule {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: 11px var(--space-3);
    border: 1px solid var(--color-line);
    border-radius: var(--radius-md);
    background: var(--color-surface);
    cursor: pointer;
}

.bascule:hover { border-color: var(--color-line-2); }
.bascule-corps { flex: 1; min-width: 0; }
.bascule-nom { font-weight: 600; color: var(--color-ink); }
.bascule-note { font-size: var(--font-size-label); color: var(--color-ink-3); }

.bascule input {
    appearance: none;
    position: relative;
    width: 42px;
    height: 24px;
    min-height: 0;
    flex: none;
    margin: 0;
    padding: 0;
    border: 0;
    border-radius: var(--radius-rond);
    background: var(--color-line-2);
    cursor: pointer;
    transition: background-color var(--duree-2) var(--sortie);
}

.bascule input::after {
    content: '';
    position: absolute;
    top: 3px;
    left: 3px;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: #fff;
    box-shadow: var(--shadow-1);
    transition: transform var(--duree-2) var(--sortie);
}

.bascule input:checked { background: var(--color-brand); }
.bascule input:checked::after { transform: translateX(18px); }
.bascule input:disabled { opacity: 0.5; cursor: not-allowed; }

/* --- Choix segmente : deux a quatre options exclusives, sans select ------ */

.choix-segments {
    display: flex;
    flex-wrap: wrap;
    padding: 3px;
    border: 1px solid var(--color-line-2);
    border-radius: var(--radius-md);
    background: var(--color-surface-2);
    gap: 2px;
}

.choix-segments label {
    flex: 1 1 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    min-height: 34px;
    padding: 5px 12px;
    border-radius: 7px;
    color: var(--color-ink-2);
    font-size: var(--font-size-label);
    font-weight: 550;
    text-align: center;
    cursor: pointer;
    transition: background-color var(--duree-1) var(--sortie), color var(--duree-1) var(--sortie);
}

.choix-segments input {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
}

.choix-segments label:hover { color: var(--color-ink); }

.choix-segments input:checked + span,
.choix-segments label:has(input:checked) {
    background: var(--color-surface);
    color: var(--color-ink);
    box-shadow: var(--shadow-1);
}

.choix-segments label:has(input:focus-visible) {
    outline: 2px solid var(--color-brand-l);
    outline-offset: 1px;
}

/* --- Compteur : quantite au doigt, sans viser une fleche de 8 pixels ----- */

.compteur {
    display: inline-flex;
    align-items: stretch;
    border: 1px solid var(--color-line-2);
    border-radius: var(--radius-md);
    overflow: hidden;
    background: var(--color-surface);
}

.compteur:focus-within {
    border-color: var(--color-brand);
    box-shadow: 0 0 0 3px color-mix(in oklab, var(--color-brand) 22%, transparent);
}

.compteur button {
    width: 40px;
    min-height: 40px;
    padding: 0;
    border: 0;
    border-radius: 0;
    background: var(--color-surface-2);
    color: var(--color-ink-2);
    font-size: 1.1rem;
    font-weight: 600;
}

.compteur button:hover:not(:disabled) { background: var(--color-surface-3); color: var(--color-ink); }

.compteur input {
    width: 64px;
    min-height: 40px;
    border: 0;
    border-radius: 0;
    text-align: center;
    font-variant-numeric: tabular-nums;
    -moz-appearance: textfield;
}

.compteur input::-webkit-outer-spin-button,
.compteur input::-webkit-inner-spin-button { appearance: none; margin: 0; }
.compteur input:focus-visible { box-shadow: none; }

/* --- Liste de suggestions (autocompletion) ------------------------------ */

.suggere { position: relative; }

.suggere-liste {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    z-index: var(--z-menu);
    max-height: 280px;
    margin: 0;
    padding: 4px;
    overflow-y: auto;
    list-style: none;
    border: 1px solid var(--color-line);
    border-radius: var(--radius-md);
    background: var(--color-surface);
    box-shadow: var(--shadow-3);
}

.suggere-liste li {
    padding: 8px 10px;
    border-radius: var(--radius-sm);
    cursor: pointer;
}

.suggere-liste li:hover,
.suggere-liste li[aria-selected='true'] { background: var(--color-surface-2); }
.suggere-liste .sug-nom { font-weight: 550; }
.suggere-liste .sug-note { font-size: var(--font-size-small); color: var(--color-ink-3); }
.suggere-liste mark { background: var(--color-brand-tint); color: inherit; border-radius: 3px; }

/* --- Barre d'enregistrement collante ------------------------------------
   Elle n'apparait qu'apres une modification : un formulaire au repos ne
   reclame rien. */
.barre-garde {
    position: sticky;
    bottom: 0;
    z-index: var(--z-colle);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    margin: var(--space-4) calc(-1 * var(--space-4)) calc(-1 * var(--space-4));
    padding: var(--space-3) var(--space-4);
    padding-bottom: max(var(--space-3), env(safe-area-inset-bottom));
    border-top: 1px solid var(--color-line);
    border-radius: 0 0 var(--radius-lg) var(--radius-lg);
    background: color-mix(in oklab, var(--color-surface) 92%, transparent);
    backdrop-filter: blur(8px);
}

.barre-garde-etat {
    display: flex;
    align-items: center;
    gap: 6px;
    color: var(--color-ink-3);
    font-size: var(--font-size-label);
}

.barre-garde-etat > * { display: none; }
.barre-garde[data-modifie] .barre-garde-etat { color: var(--color-warn); font-weight: 550; }
.barre-garde[data-modifie] .barre-garde-etat > * { display: inline; }

/* L'asterisque du champ obligatoire ne colle pas au libelle. */
.requis { margin-left: 3px; color: var(--color-danger); }

@media (max-width: 560px) {
    .barre-garde { flex-direction: column; align-items: stretch; }
    .barre-garde .btn { width: 100%; }
}

/* --- Divulgation progressive -------------------------------------------
   Les reglages d'une option n'existent qu'une fois l'option activee. */
.revele {
    display: grid;
    grid-template-rows: 0fr;
    transition: grid-template-rows var(--duree-3) var(--sortie);
}

.revele > * { overflow: hidden; min-height: 0; }
.revele[data-ouvert] { grid-template-rows: 1fr; }

@media (prefers-reduced-motion: reduce) {
    .revele { transition: none; }
}

/* ===========================================================================
   ONGLETS
   =========================================================================== */

.onglets {
    display: flex;
    gap: var(--space-1);
    margin-bottom: var(--space-4);
    border-bottom: 1px solid var(--color-line);
    overflow-x: auto;
    scrollbar-width: none;
}

.onglets::-webkit-scrollbar { display: none; }

.onglets a,
.onglets button {
    position: relative;
    min-height: 40px;
    padding: 9px 14px;
    border: 0;
    border-radius: 0;
    background: none;
    color: var(--color-ink-3);
    font-size: var(--font-size-body);
    font-weight: 550;
    white-space: nowrap;
    text-decoration: none;
}

.onglets a:hover,
.onglets button:hover { background: none; color: var(--color-ink); }

.onglets [aria-current],
.onglets [aria-selected='true'] { color: var(--color-ink); }

.onglets [aria-current]::after,
.onglets [aria-selected='true']::after {
    content: '';
    position: absolute;
    inset: auto 8px -1px;
    height: 2px;
    border-radius: 2px 2px 0 0;
    background: var(--color-brand);
}

/* ===========================================================================
   PAGINATION
   =========================================================================== */

.pages {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    padding: var(--space-3) 0 0;
    color: var(--color-ink-3);
    font-size: var(--font-size-label);
}

.pages-liens { display: flex; align-items: center; gap: var(--space-2); }

/* ===========================================================================
   UTILITAIRES
   =========================================================================== */

.pile { display: flex; flex-direction: column; gap: var(--space-3); }
.pile--serree { gap: var(--space-2); }
.rangee { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.rangee--bout { justify-content: space-between; }
.pousse { margin-left: auto; }
.discret { color: var(--color-ink-3); }
.gras { font-weight: 600; }

/* Reserve au lecteur d'ecran : les intitules que l'oeil deduit de la mise en
   page et que la voix, elle, ne deduit pas. */
.lecture-seule-ecran {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* ===========================================================================
   DEPLIANT
   Un panneau qui se replie, sur le <details> natif : le pli, le clavier et
   l'etat ouvert sont deja ecrits dans le navigateur.
   =========================================================================== */

.depliant { padding: 0; overflow: hidden; }

.depliant > summary {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-3) var(--space-4);
    font-weight: 600;
    cursor: pointer;
    list-style: none;
}

.depliant > summary::-webkit-details-marker { display: none; }
.depliant > summary:hover { background: var(--color-surface-2); }
.depliant > summary svg { flex: none; color: var(--color-ink-3); }
.depliant > summary svg:last-child { margin-left: auto; transition: transform var(--duree-2) var(--sortie); }
.depliant[open] > summary svg:last-child { transform: rotate(180deg); }
.depliant[open] > summary { border-bottom: 1px solid var(--color-line); }
.depliant-corps { padding: var(--space-4); }

.carte-europe {
    height: 420px;
    border-radius: var(--radius-md);
    overflow: hidden;
    background: var(--color-surface-2);
}

.legende-point {
    display: inline-block;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--color-brand);
}

.legende-point--client { background: var(--color-accent); }

/* ===========================================================================
   SEMAINE DE LIVRAISONS
   =========================================================================== */

.semaine {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: var(--space-2);
}

.jour {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    padding: var(--space-2);
    border: 1px solid var(--color-line);
    border-radius: var(--radius-md);
    background: var(--color-surface);
}

/* Aujourd'hui se distingue par un fond, pas par un filet colore sur un bord. */
.jour--aujourdhui {
    border-color: color-mix(in oklab, var(--color-brand) 45%, var(--color-line));
    background: var(--color-brand-tint);
}

.jour-tete {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-2);
    font-size: var(--font-size-label);
    font-weight: 650;
}

.jour-tete .num { color: var(--color-ink-3); font-weight: 500; }

.jour-entree {
    padding: var(--space-2);
    border-radius: var(--radius-sm);
    background: var(--color-surface-2);
    font-size: var(--font-size-label);
}

.jour-entree .secondaire { color: var(--color-ink-3); font-size: var(--font-size-small); }
.jour-vide { color: var(--color-ink-3); font-size: var(--font-size-small); font-style: italic; }

/* Une etiquette peut etre un lien : elle en prend alors le comportement. */
a.etiquette { text-decoration: none; }
a.etiquette:hover {
    border-color: var(--color-brand);
    background: var(--color-brand-tint);
    color: var(--color-brand);
}

/* Tout tableau non encore converti en cartes defile dans sa propre boite
   plutot que de pousser la page entiere.

   display:block sur un <table> le sort du mode tableau pour la boite, mais
   ses lignes gardent leur disposition : c'est ce qui permet de contenir le
   debordement des quarante-quatre tableaux du projet sans toucher un seul
   gabarit. Les tableaux passes au systeme portent .tableau--cartes et ne sont
   pas concernes : eux se replient vraiment. */
@media (max-width: 860px) {
    table:not(.tableau--cartes) {
        display: block;
        overflow-x: auto;
        overscroll-behavior-x: contain;
    }
}

/* Un menu qui contient un petit formulaire plutot qu'une liste d'actions :
   encaisser demande un moyen et une communication, ce qui ne tient pas dans
   une cellule de tableau mais ne justifie pas de quitter la page. */
.menu-pop--large { min-width: 300px; }
.menu-pop--large .champ { margin-bottom: var(--space-2); }
.menu-pop--large .champ-aide { padding: 0 2px; }

/* ===========================================================================
   OFFRES ET DEFINITIONS
   =========================================================================== */

.offres {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: var(--space-2);
    margin-bottom: var(--space-3);
}

.offre {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    padding: var(--space-3);
    border: 1px solid var(--color-line);
    border-radius: var(--radius-md);
    background: var(--color-surface);
    cursor: pointer;
    transition: border-color var(--duree-1) var(--sortie), background-color var(--duree-1) var(--sortie);
}

.offre:hover { border-color: var(--color-line-2); }

/* La carte entiere montre qu'elle est prise, pas seulement sa case. */
.offre:has(input:checked) {
    border-color: var(--color-brand);
    background: var(--color-brand-tint);
}

.offre:has(input:focus-visible) { outline: 2px solid var(--color-brand-l); outline-offset: 2px; }
.offre input { margin-top: 2px; flex: none; }
.offre-corps { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.offre-tete { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.offre-nom { font-weight: 650; }
.offre-prix { color: var(--color-ink-2); font-size: var(--font-size-label); }

/* Liste de definitions : intitule a gauche, valeur a droite, alignes. */
.paires {
    display: grid;
    grid-template-columns: minmax(120px, auto) 1fr;
    gap: 6px var(--space-3);
    margin: 0 0 var(--space-3);
}

.paires dt { color: var(--color-ink-3); font-size: var(--font-size-label); }
.paires dd { margin: 0; }

@media (max-width: 560px) {
    .paires { grid-template-columns: 1fr; gap: 0 0; }
    .paires dd { margin-bottom: var(--space-2); }
}

/* ===========================================================================
   ETATS VIDES AVEC PURINTA (identite du 11/10/2026)
   La version calme de l'identite dans l'outil : la mascotte n'apparait que
   la ou il n'y a rien d'autre a regarder. Purinta somnole au-dessus du
   message. Les petits tableaux de detail (moins de six colonnes : lignes d'un
   devis, reglements d'un ticket) gardent leur simple ligne de texte.
   =========================================================================== */

.vide-etat svg { display: none; }

.vide-etat::before,
td.empty:is([colspan='6'], [colspan='7'], [colspan='8'])::before {
    content: '';
    display: block;
    width: 108px;
    height: 108px;
    margin: 0 auto var(--space-2);
    background: url('/images/purinta/purinta-vide.webp') center / contain no-repeat;
}

td.empty:is([colspan='6'], [colspan='7'], [colspan='8']) {
    padding-top: var(--space-5);
    padding-bottom: var(--space-5);
    color: var(--color-ink-3);
    text-align: center;
}

/* ===========================================================================
   IMPRESSION
   Un ticket, une facture ou une liste s'impriment sans le menu, la barre
   haute ni les boutons : seul le contenu sort, en noir sur blanc.
   =========================================================================== */

@media print {
    @page { margin: 12mm; }

    :root { color-scheme: light; }

    body {
        background: #fff !important;
        color: #000 !important;
        font-size: 10.5pt;
    }

    .nav,
    .barre-haute,
    .saut-contenu,
    .toasts,
    dialog,
    form,
    button,
    .btn,
    .ligne-actions,
    .ne-pas-imprimer { display: none !important; }

    .coque,
    .zone,
    .contenu {
        display: block !important;
        margin: 0 !important;
        padding: 0 !important;
        max-width: none !important;
    }

    .form-card,
    .panneau,
    .carte,
    .chiffre {
        border: 1px solid #999 !important;
        background: #fff !important;
        box-shadow: none !important;
        break-inside: avoid;
    }

    .table-scroll { overflow: visible !important; }

    a { color: #000 !important; text-decoration: none !important; }

    h1, h2, h3 { color: #000 !important; }
}
