:root {
    --encre: #0f172a;
    --encre-douce: #64748b;
    --trait: #e6ebf2;
    --fond: #f7f9fc;
    --surface: #ffffff;
    --accent: #2563eb;
    --accent-clair: #eff5ff;

    /* Trois sémantiques distinctes, et il faut qu'elles le restent : le débit et le crédit disent
       le sens d'une écriture, l'alerte dit qu'il y a quelque chose à faire. Les confondre ferait
       bouger l'un en réglant l'autre — un solde débiteur n'est pas un incident. */
    --debit: #c2410c;
    --credit: #0f8a5f;
    --alerte: #dc2626;

    --rayon: 10px;
    --rayon-carte: 13px;

    /* Deux ombres empilées : la première pose le bord, la seconde donne la profondeur. Une seule
       ombre large sans son filet donne un flou qui décolle la carte du fond. */
    --ombre: 0 1px 2px rgba(15, 23, 42, .04), 0 6px 18px rgba(15, 23, 42, .05);

    /* Fond de l'écran de connexion. Il annonçait la couleur de la barre latérale, désormais
       blanche : il prend donc une teinte de la famille de l'accent, sans quoi la carte de
       connexion flotterait sur du blanc. */
    --fond-connexion: #eef4fb;

    /* Rouge de l'enseigne, distinct d'`--alerte` : il nomme l'entreprise, il n'annonce pas un
       problème. */
    --enseigne: #a3170f;
}

* { box-sizing: border-box; }

html, body {
    margin: 0;
    font-family: "Segoe UI", system-ui, -apple-system, sans-serif;
    font-size: 15px;
    color: var(--encre);
    background: var(--fond);
}

h1 { font-size: 1.5rem; margin: 0; font-weight: 700; }

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

/* Ce qui n'existe que sur le papier. Le pendant de `.sans-impression`, qui vit dans le bloc
   `@media print` : la règle qui l'affiche y est aussi, celle qui le cache doit être ici. Sans cette
   ligne, le mot destiné à l'imprimante s'ajouterait à celui de l'écran. */
.impression-seule { display: none; }

.visuellement-cache {
    position: absolute;
    width: 1px; height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
}

/* ---------- Ossature ---------- */

.page { display: flex; min-height: 100vh; }

/* Blanche, et non plus dans un cyan pâle. Cette teinte datait l'ensemble et n'encodait rien : la
   couleur sert désormais à dire où l'on se trouve, l'écran courant portant seul l'accent. */
.barre-laterale {
    width: 234px;
    flex-shrink: 0;
    background: var(--surface);
    color: var(--encre);
    padding: 1.25rem 0;
    border-right: 1px solid var(--trait);
    /* Colonne pour que le menu occupe la hauteur restante et pousse `.rail-bas` en pied. */
    display: flex;
    flex-direction: column;
}

main { flex: 1; min-width: 0; display: flex; flex-direction: column; }

.barre-haute {
    display: flex;
    justify-content: flex-end;
    align-items: center;
    gap: 1rem;
    height: 56px;
    padding: 0 1.75rem;
    background: var(--surface);
    border-bottom: 1px solid var(--trait);
}

.utilisateur { display: flex; flex-direction: column; line-height: 1.2; text-align: right; }
.utilisateur .nom { font-weight: 600; }
.utilisateur .roles { font-size: .75rem; color: var(--encre-douce); }

.contenu { padding: 1.75rem; }

/* ---------- Navigation ---------- */

.marque { padding: 0 1.25rem 1.5rem; }
.marque a { color: var(--encre); font-size: 1.35rem; font-weight: 800; letter-spacing: .06em; }
.marque a:hover { text-decoration: none; }

/* L'emblème et le nom sur une ligne : l'image ne se laisse pas écraser si la barre rétrécit. */
.logo-marque { display: flex; align-items: center; gap: .5rem; }
.logo-marque img { flex: 0 0 auto; }

.logo-connexion { display: block; margin: 0 auto .75rem; }
/* Une raison sociale peut être longue là où « Suivi des tiers » ne l'était pas : elle est coupée
   plutôt que d'élargir la barre latérale ou de déborder sur le menu. Le titre la donne en entier. */
.marque .baseline {
    display: block;
    font-size: .8rem;
    color: var(--enseigne);
    /* L'entreprise n'est plus une baseline décorative : elle dit où l'on travaille. Le gras la pose,
       et l'opacité qui l'estompait disparaît — atténuer ce qu'on vient de mettre en gras reviendrait
       à le reprendre d'une main après l'avoir donné de l'autre. */
    font-weight: 700;
    margin-top: .15rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.menu { display: flex; flex-direction: column; flex: 1; }

/* Liste de définitions en deux colonnes : le libellé étroit, la valeur au large. Une grille plutôt
   qu'un tableau — ce sont des paires clé/valeur, pas des données à trier ou comparer entre lignes,
   et `dl` le dit aux lecteurs d'écran. Elle repasse sur une colonne quand la place manque. */
.paires {
    display: grid;
    grid-template-columns: minmax(7rem, auto) 1fr;
    gap: .4rem 1.2rem;
    margin: 1rem 0 0;
}

.paires dt { color: var(--encre-douce); font-size: .85rem; }
.paires dd { margin: 0; }

@media (max-width: 520px) {
    .paires { grid-template-columns: 1fr; gap: .1rem; }
    .paires dd { margin-bottom: .6rem; }
}

/* ---- Pied du menu ----
   « À propos de nous » et la formule d'abonnement, poussés en bas de la barre. `margin-top: auto`
   plutôt qu'une position absolue : un menu plus haut que l'écran les repousse alors normalement au
   lieu de les faire chevaucher la dernière entrée. */
.rail-bas { margin-top: auto; padding-top: 1rem; }

/* La carte reprend l'allure des cartes du tableau de bord, en plus discret : elle informe, elle
   n'appelle aucune action. */
.carte-abonnement {
    margin: .6rem .7rem 0;
    padding: .6rem .7rem;
    background: var(--accent-clair);
    border: 1px solid #dbe7fb;
    border-radius: var(--rayon);
}

.carte-abonnement .intitule {
    font-size: .66rem;
    font-weight: 700;
    letter-spacing: .09em;
    text-transform: uppercase;
    color: var(--encre-douce);
}

.carte-abonnement .formule {
    margin-top: .15rem;
    font-size: .95rem;
    font-weight: 700;
    color: var(--accent);
}

/* Une pastille plutôt qu'un mot nu : l'état se lit sans être lu. */
.carte-abonnement .etat {
    display: inline-block;
    margin-top: .3rem;
    padding: .05rem .4rem;
    border-radius: 999px;
    background: #e8f6ef;
    color: var(--credit);
    font-size: .68rem;
    font-weight: 600;
}

/* Groupes du menu, dépliables au clic sur leur titre.

   **Un filet fin au-dessus de chaque groupe**, et c'est lui qui porte l'essentiel : il fait lire le
   menu comme quatre blocs distincts plutôt qu'une liste continue où le titre ne serait qu'une ligne
   parmi les autres. La marge horizontale, plus large que celle des entrées hors groupe, ouvre en
   outre la gouttière dans laquelle les entrées viennent s'indenter. */
.groupe-menu {
    display: flex;
    flex-direction: column;
    margin: .55rem .85rem 0;
    padding-top: .55rem;
    border-top: 1px solid var(--trait);
}

/* **Le titre est une étiquette, pas une entrée**, et c'est tout l'enjeu de ce bloc. Il portait
   auparavant la même boîte que `.lien-menu` — même arrondi, même remplissage au survol, même
   indentation — si bien que « TRAITEMENT » et « Factures » se lisaient comme deux éléments de même
   rang, à la casse près.

   **La distinction ne passe pas par l'effacement mais par le contraste** : noir et gras en petites
   capitales espacées, face à des entrées grises en casse normale et en graisse moyenne. Une
   première version atténuait le titre en gris clair ; l'ordre de lecture s'en trouvait inversé,
   l'œil tombant sur les entrées avant de savoir à quel groupe elles appartiennent. Le travail
   structurel est de toute façon fait par le filet au-dessus du groupe et par l'indentation des
   entrées — la couleur n'a plus qu'à désigner la tête de section.

   Il reste un bouton, puisque c'est une commande : le chevron porte l'affordance, et le survol
   agit sur ce chevron plutôt que de poser un fond, lequel redonnerait la boîte qu'on retire. */
.titre-groupe {
    display: flex;
    align-items: center;
    gap: .4rem;
    width: 100%;
    margin: 0 0 .25rem;
    padding: .1rem .1rem .15rem;
    background: none;
    border: 0;
    font-family: inherit;
    font-size: .68rem;
    font-weight: 800;
    letter-spacing: .13em;
    text-transform: uppercase;
    color: var(--encre);
    text-align: left;
    cursor: pointer;
}

.titre-groupe:hover .chevron { color: var(--encre); }

.titre-groupe .chevron {
    font-size: .62rem;
    /* Largeur fixe : sans elle, le titre se décale d'un pixel ou deux entre ▸ et ▾. */
    width: .7rem;
    /* Le chevron reste discret : il indique l'état du groupe, il n'est pas le titre. */
    color: #9aa7b8;
    font-weight: 400;
}

/* **L'indentation dit l'appartenance.** Sans elle, titre et entrées commencent au même endroit et
   rien ne relie les seconds au premier. Elle s'ajoute à la marge du groupe, ce qui creuse aussi
   l'écart avec « Tableau de bord », seule entrée hors groupe. */
.groupe-menu .lien-menu { margin: 1px 0 1px .5rem; }

/* Pastille arrondie plutôt que pleine largeur avec filet à gauche : sur une barre blanche, le
   contraste vient du remplissage et non d'un trait de 3 px. La marge horizontale détache la
   pastille du bord, ce qui la fait lire comme un objet posé plutôt qu'une bande collée. */
.lien-menu {
    display: flex;
    align-items: center;
    gap: .65rem;
    margin: 1px .6rem;
    padding: .5rem .55rem;
    border-radius: 8px;
    color: #334155;
    font-size: .9rem;
    font-weight: 500;
}
.lien-menu:hover { background: #f4f7fb; color: var(--encre); text-decoration: none; }
.lien-menu.active {
    background: var(--accent-clair);
    color: var(--accent);
    font-weight: 600;
}
.puce { font-size: .7rem; opacity: .55; }
.lien-menu.active .puce { opacity: 1; }

/* ---------- Entêtes ---------- */

.entete-page { margin-bottom: 1.25rem; }
.sous-titre { margin: .3rem 0 0; color: var(--encre-douce); font-size: .875rem; }

.fil-ariane { margin-bottom: .75rem; font-size: .85rem; color: var(--encre-douce); }
.fil-ariane span { margin: 0 .35rem; }

.entete-fiche {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 1.5rem;
    flex-wrap: wrap;
    background: var(--surface);
    border: 1px solid var(--trait);
    border-radius: var(--rayon);
    padding: 1.25rem 1.5rem;
    margin-bottom: 1.25rem;
}

.solde-final { text-align: right; }
.solde-final .intitule {
    display: block;
    font-size: .75rem;
    text-transform: uppercase;
    letter-spacing: .05em;
    color: var(--encre-douce);
}
.solde-final .montant {
    display: block;
    font-size: 1.75rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    margin-top: .2rem;
}
.solde-final.debiteur .montant { color: var(--debit); }
.solde-final.crediteur .montant { color: var(--credit); }

/* ---------- Filtres ---------- */

.filtres {
    display: flex;
    align-items: center;
    gap: .75rem 1.25rem;
    flex-wrap: wrap;
    margin-bottom: 1rem;
}

/* Un filtre est un couple libellé + champ, et il ne doit jamais se couper en deux.
   Sans ce groupement, les deux sont frères dans un conteneur `flex-wrap` : rien n'empêche le
   retour à la ligne de tomber entre eux, et le libellé reste seul en fin de ligne précédente
   pendant que son champ passe en dessous. C'était le cas de « Du » sur l'écran des factures.
   L'écart entre groupes est plus large que l'écart interne, pour qu'on lise des blocs et non
   une file de contrôles. */
.filtre {
    display: flex;
    align-items: center;
    gap: .4rem;
    flex: 0 0 auto;
}
.filtre > label {
    white-space: nowrap;
    color: var(--encre-douce);
}

/* Les actions de l'en-tête, groupées sur une même ligne avec un écart serré, et qui passent à la
   ligne ensemble plutôt qu'une à une.

   Ce conteneur ne *corrige* plus rien : `.entete-avec-action` pousse désormais son titre à gauche
   et laisse tout le reste se coller à droite (voir plus bas), quel que soit le nombre d'enfants.
   Il l'a longtemps corrigé, et c'était le défaut : la disposition ne tenait qu'à ce qu'on pense à
   poser ce conteneur, oublié sur `/tiers` — où « + Nouveau tiers » flottait au milieu de la ligne. */
.actions-entete {
    display: flex;
    align-items: center;
    gap: .5rem;
    flex-wrap: wrap;
}

.champ-recherche, .champ-date, .champ {
    padding: .5rem .7rem;
    border: 1px solid var(--trait);
    border-radius: var(--rayon);
    font: inherit;
    background: var(--surface);
}
.champ-recherche { min-width: 280px; }
.champ-recherche:focus, .champ-date:focus, .champ:focus {
    outline: 2px solid var(--accent);
    outline-offset: 1px;
}

.groupe-onglets { display: flex; border: 1px solid var(--trait); border-radius: var(--rayon); overflow: hidden; }
.onglet {
    padding: .5rem .9rem;
    border: 0;
    background: var(--surface);
    font: inherit;
    cursor: pointer;
    color: var(--encre-douce);
}
.onglet:hover { background: var(--accent-clair); }
.onglet.actif { background: var(--accent); color: #fff; }

.case-actifs { display: flex; align-items: center; gap: .4rem; color: var(--encre-douce); }

/* ---------- Tableaux ---------- */

.table-defilante {
    overflow-x: auto;
    background: var(--surface);
    border: 1px solid var(--trait);
    border-radius: var(--rayon-carte);
    box-shadow: var(--ombre);
}

table { width: 100%; border-collapse: collapse; }

th, td { padding: .6rem .9rem; text-align: left; border-bottom: 1px solid #f1f5f9; }

/* En-tête en chasse fixe et en petites capitales : il se distingue des données sans avoir besoin
   d'être plus gros ni plus foncé qu'elles. Ce sont les chiffres qu'on vient lire, pas les titres. */
thead th {
    font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
    font-size: .68rem;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: .09em;
    color: var(--encre-douce);
    background: #fbfcfe;
    border-bottom: 1px solid var(--trait);
    white-space: nowrap;
}

tbody tr:hover { background: #fbfcfe; }
tbody tr:last-child td { border-bottom: 0; }

.nombre { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.solde { font-weight: 600; }

tfoot td {
    border-top: 2px solid var(--trait);
    border-bottom: 0;
    background: #fbfcfd;
    font-weight: 600;
}

.ligne-report td { background: var(--accent-clair); font-style: italic; color: var(--encre-douce); }
.ligne-inactive { opacity: .6; }
.echeance-depassee { color: var(--alerte); font-weight: 600; }

.code-tiers, .numero-piece {
    font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
    font-size: .85rem;
}

.actions { text-align: right; white-space: nowrap; }

/* Deux boutons-liens voisins se touchaient, faute de bordure pour les séparer : « Désactiver » et
   « Supprimer » se lisaient comme un seul mot. L'écart vaut pour toutes les cellules d'action. */
.actions > * + * { margin-left: .6rem; }

/* ---------- Étiquettes ---------- */

.etiquette {
    display: inline-block;
    padding: .12rem .5rem;
    border-radius: 999px;
    font-size: .72rem;
    font-weight: 600;
    margin-left: .35rem;
}
/* Les fonds sont des teintes de leur propre couleur de texte, jamais des gris colorés au hasard :
   une étiquette se lit d'abord comme une tache, et sa teinte doit désigner la même chose que son
   mot. */
/* Client et fournisseur sont deux **catégories**, non deux états : leurs teintes ne viennent donc
   pas des jetons sémantiques. La pastille fournisseur portait `--debit`, dont la valeur convenait
   par coïncidence — régler un jour la couleur du débit pour une raison comptable aurait déplacé
   une étiquette qui n'a rien à voir avec le sens d'une écriture. */
.etiquette.client { background: var(--accent-clair); color: var(--accent); }
.etiquette.fournisseur { background: #fdf1e9; color: #b4530f; }
.etiquette.inactif { background: #eef1f5; color: var(--encre-douce); }
.etiquette.actif { background: #e8f6ef; color: var(--credit); }
.etiquette.alerte { background: #fdeceb; color: var(--alerte); }

/* ---------- Boutons ---------- */

.bouton-principal, .bouton-secondaire {
    display: inline-block;
    padding: .5rem 1rem;
    border-radius: var(--rayon);
    font: inherit;
    font-weight: 500;
    cursor: pointer;
    border: 1px solid transparent;
}
.bouton-principal {
    background: var(--accent);
    color: #fff;
    width: 100%;
    margin-top: 1.25rem;
    font-weight: 600;
    box-shadow: 0 1px 2px rgba(37, 99, 235, .25);
}
.bouton-principal:hover:not(:disabled) { background: #1d4fd0; }
.bouton-principal:disabled { opacity: .6; cursor: default; box-shadow: none; }

.bouton-secondaire {
    background: var(--surface);
    border-color: var(--trait);
    color: #334155;
    box-shadow: 0 1px 1px rgba(15, 23, 42, .03);
}
.bouton-secondaire:hover { background: #f4f7fb; border-color: #cfdbea; color: var(--encre); text-decoration: none; }

.bouton-lien {
    background: none;
    border: 0;
    color: var(--accent);
    cursor: pointer;
    font: inherit;
    font-weight: 500;
    padding: 0;
}
.bouton-lien:hover { text-decoration: underline; }

/* Une action destructrice ne doit pas s'offrir aussi facilement qu'une action ordinaire : elle
   porte sa couleur d'emblée, sans attendre le survol. « Modifier » et « Supprimer » avaient
   jusqu'ici le même poids visuel, alors qu'un seul des deux se rattrape. */
.bouton-lien.danger { color: var(--alerte); }

/* Le même parti pour un bouton bordé : la couleur d'emblée, la bordure comme ses voisins.
   Une ligne d'actions ne doit pas mélanger les familles — deux boutons encadrés suivis d'un
   texte rouge nu se lit comme une note de bas de carte plutôt que comme une commande, et le
   défaut ne saute aux yeux qu'une fois la ligne repliée sur un téléphone. */
.bouton-secondaire.danger { color: var(--alerte); border-color: #f5cdc9; }
.bouton-secondaire.danger:hover {
    background: #fdeceb;
    border-color: var(--alerte);
    color: var(--alerte);
}

/* ---------- États ---------- */

.etat-chargement, .etat-vide {
    padding: 2rem;
    text-align: center;
    color: var(--encre-douce);
    background: var(--surface);
    border: 1px solid var(--trait);
    border-radius: var(--rayon);
}

.message-erreur {
    padding: .75rem 1rem;
    background: #fdeceb;
    border: 1px solid #f4c7c3;
    border-radius: var(--rayon);
    color: var(--alerte);
}

/* Le refus d'un bouton d'action, dit à côté de lui : un bandeau en haut de page serait loin du geste. */
.erreur-en-ligne {
    align-self: center;
    font-size: .82rem;
    color: var(--alerte);
}

.message-succes {
    padding: .75rem 1rem;
    background: #e6f4ec;
    border: 1px solid #b7dfc7;
    border-radius: var(--rayon);
    color: var(--credit);
}

/* Ni erreur ni reussite : un etat de fait, comme une facture qu'on ne peut que consulter. En rouge
   il se lirait comme un echec, en vert comme une confirmation ; ni l'un ni l'autre n'est vrai. */
.message-information {
    padding: .75rem 1rem;
    background: #eef4fb;
    border: 1px solid #c5d9ef;
    border-radius: var(--rayon);
    color: var(--encre);
}

.validation-message { color: var(--alerte); font-size: .8rem; display: block; margin-top: .2rem; }

/* Une liste d'explication dans une carte, la mise a zero du reset laissant sinon les puces
   invisibles et le texte colle a la marge. */
.liste-puces {
    margin: .4rem 0 .8rem 1.1rem;
    padding: 0;
    list-style: disc;
    color: var(--encre-douce);
    font-size: .875rem;
    line-height: 1.7;
}

/* L'apercu d'un message de refus : il doit se lire comme le message lui-meme, pas comme du texte
   d'aide, sans pour autant crier a l'erreur — ce n'en est pas une, c'est un exemple. */
.apercu-refus {
    padding: .75rem 1rem;
    background: var(--accent-clair);
    border-left: 3px solid var(--accent);
    border-radius: var(--rayon);
    color: var(--encre);
}

/* ---------- Connexion ---------- */

.ecran-connexion {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    /* La barre latérale étant devenue blanche, ce fond ne peut plus reprendre sa teinte sans que
       la carte de connexion ne flotte sur du blanc. Il prend donc une nuance de la famille de
       l'accent : l'écran annonce toujours la couleur de l'application. */
    background: var(--fond-connexion);
    padding: 1rem;
}

.carte-connexion {
    width: 100%;
    max-width: 380px;
    background: var(--surface);
    border-radius: 12px;
    padding: 2rem;
    /* Le filet datait du fond blanc, où la carte se confondait avec lui. Il est conservé sur le
       fond cyan : il pose le bord de la carte au lieu de la laisser flotter. */
    border: 1px solid var(--trait);
}
.carte-connexion h1 { text-align: center; font-size: 2rem; letter-spacing: .08em; }
.carte-connexion .sous-titre { text-align: center; margin-bottom: 1.5rem; }
.carte-connexion label { display: block; margin-top: .9rem; margin-bottom: .3rem; font-size: .85rem; }
.carte-connexion .champ { width: 100%; }

/* ---------- Formulaires ---------- */

/* Le titre à gauche, tout le reste à droite — **quel que soit le nombre d'actions**. C'est le
   `margin-right: auto` du premier enfant qui le décide, non un `space-between` : celui-ci répartit
   l'espace entre *tous* les enfants, si bien qu'un en-tête à deux boutons voyait le premier flotter
   au milieu de la ligne. Le défaut existait sur `/tiers` et se réparait jusqu'ici en pensant à
   grouper les boutons dans `.actions-entete` — une parade à reposer à chaque nouvel écran. */
.entete-avec-action {
    display: flex;
    align-items: flex-start;
    gap: 1rem;
    flex-wrap: wrap;
}
.entete-avec-action > *:first-child { margin-right: auto; }

.carte-formulaire {
    background: var(--surface);
    border: 1px solid var(--trait);
    border-radius: var(--rayon);
    padding: 1.25rem 1.5rem;
    margin-bottom: 1.25rem;
}
.carte-formulaire h2 {
    font-size: .8rem;
    text-transform: uppercase;
    letter-spacing: .05em;
    font-weight: 700;
    color: var(--encre-douce);
    margin: 0 0 1rem;
    padding-bottom: .5rem;
    border-bottom: 1px solid var(--trait);
}

.grille-champs {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 1rem;
}

.groupe-champ { display: flex; flex-direction: column; }
.groupe-champ.large { grid-column: 1 / -1; }
.groupe-champ label { font-size: .85rem; margin-bottom: .3rem; font-weight: 500; }
.groupe-champ .champ { width: 100%; }
.groupe-champ .aide { font-size: .75rem; color: var(--encre-douce); margin-top: .25rem; }

select.champ, textarea.champ { font: inherit; }
.champ:disabled { background: #f2f4f6; color: var(--encre-douce); }

table.saisie { width: 100%; table-layout: fixed; }
table.saisie td { padding: .35rem .5rem; }
table.saisie .champ.nombre { text-align: right; }

/* `min-width` sur les champs forçait la largeur du tableau au-delà de son conteneur : chaque
   colonne de saisie réclamait sa place et le tableau débordait horizontalement. Les champs
   s'ajustent désormais à leur colonne, dont la largeur est fixée par le `colgroup`. */
table.saisie .champ { padding: .35rem .5rem; width: 100%; min-width: 0; }

/* Le sélecteur d'article porte « référence — désignation » : plus large que les colonnes de
   nombres, mais borné pour que la désignation garde la place restante. */
/* Le sélecteur d'article était à 14rem : il prenait à la désignation une place dont elle a plus
   besoin que lui. La référence suffit à reconnaître l'article, la désignation complète restant
   lisible dans la liste déroulante déployée. Les colonnes de nombres sont resserrées d'autant. */
table.saisie .col-article { width: 9.5rem; }
table.saisie .col-nombre { width: 5.5rem; }
table.saisie .col-montant { width: 7.5rem; }
table.saisie .col-action { width: 5rem; }

/* <b>Aucun plancher sur la désignation, et ce n'est pas un oubli.</b> Sous `table-layout: fixed`,
   un `min-width` de cellule est ignoré ; posé sur le tableau, il fonctionne — mais fait défiler
   **la page entière** horizontalement dès que la fenêtre descend vers 1024 px, ce que la feuille
   interdit partout ailleurs. Mesuré : 300 px de désignation gagnés contre 200 px de débordement de
   page. `table-layout: auto` avec un `min-width` de cellule donne le même débordement.
   La cause est structurelle et non stylistique : huit colonnes ne tiennent pas dans les ~680 px que
   laisse une fenêtre de 1024. Élargir la désignation passe donc par retirer de la place aux autres,
   ce que font les largeurs ci-dessus — pas par un plancher qui déplacerait le problème sur la page.
   Si la saisie doit rester confortable sous 1150 px, c'est la forme du tableau qu'il faudra revoir
   (deux lignes par article, comme la mise en cartes le fait déjà sur téléphone). */

/* La désignation est la seule colonne élastique : elle absorbe la place restante, et son texte
   se coupe plutôt que d'élargir le tableau. */
table.saisie th, table.saisie td { overflow: hidden; text-overflow: ellipsis; }

/* <b>La bande étroite : entre la mise en cartes (800 px) et l'aisance (1150 px).</b>
   Là, les sept colonnes fixes consommaient toute la place et la désignation tombait à zéro —
   mesuré à 1024 px : un champ de 16 px, inutilisable. Les resserrer lui rend une centaine de
   pixels, ce qui n'est pas confortable mais reste exploitable, et surtout n'entraîne aucun
   défilement de la page. Au-dessus de 1150 px ces valeurs ne s'appliquent pas : la désignation y
   reçoit déjà 245 px à 1280 et 580 px à 1600. */
@media (min-width: 801px) and (max-width: 1150px) {
    table.saisie .col-article { width: 6rem; }
    table.saisie .col-nombre { width: 4.5rem; }
    table.saisie .col-montant { width: 6rem; }
    table.saisie .col-action { width: 4rem; }
}

.recapitulatif {
    margin: 1.25rem 0 0;
    display: flex;
    flex-direction: column;
    gap: .35rem;
    max-width: 320px;
    margin-left: auto;
}
.recapitulatif > div { display: flex; justify-content: space-between; gap: 2rem; }
.recapitulatif dt { color: var(--encre-douce); }
.recapitulatif dd { margin: 0; font-variant-numeric: tabular-nums; }
.recapitulatif .fort {
    border-top: 1px solid var(--trait);
    padding-top: .35rem;
    font-weight: 600;
    font-size: 1.05rem;
}

.barre-actions {
    display: flex;
    justify-content: flex-end;
    gap: .75rem;
    align-items: center;
    margin-top: 1rem;
}
.bouton-principal.compact { width: auto; margin-top: 0; }
.bouton-lien.danger { color: var(--alerte); }

/* Le bouton qui confirme une suppression définitive ne doit pas porter la couleur d'une action
   ordinaire : c'est la dernière occasion de reculer. */
.bouton-principal.danger { background: var(--alerte); border-color: var(--alerte); }

.etiquette.valide { background: #e6f4ec; color: var(--credit); }
.etiquette.brouillon { background: #fdf6e3; color: #8a6d1f; }

/* ---------- Tableau de bord ---------- */

.titre-section {
    font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
    font-size: .7rem;
    text-transform: uppercase;
    letter-spacing: .12em;
    font-weight: 500;
    color: var(--encre-douce);
    margin: 1.75rem 0 .75rem;
}

.grille-indicateurs {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
    gap: 1rem;
}

/* Le filet de 3 px à gauche disparaît : il servait à distinguer les cartes accentuées sur un fond
   plat, mais il coupait le coin arrondi et donnait à toutes les cartes un air de bandeau. La
   distinction passe désormais par la couleur de la valeur et, pour l'alerte, par le fond. */
.carte-indicateur {
    display: flex;
    flex-direction: column;
    gap: .25rem;
    background: var(--surface);
    border: 1px solid var(--trait);
    border-radius: var(--rayon-carte);
    box-shadow: var(--ombre);
    padding: 1rem 1.1rem;
    color: var(--encre);
}
a.carte-indicateur:hover { border-color: #cfdbea; text-decoration: none; }

.carte-indicateur .intitule {
    font-size: .8rem;
    font-weight: 500;
    letter-spacing: 0;
    text-transform: none;
    color: var(--encre-douce);
}
.carte-indicateur .valeur {
    font-size: 1.5rem;
    font-weight: 700;
    letter-spacing: -.025em;
    font-variant-numeric: tabular-nums;
    line-height: 1.15;
}
.carte-indicateur .detail { font-size: .78rem; color: var(--encre-douce); }

.carte-indicateur.accentuee .valeur { color: var(--accent); }

/* L'alerte teinte toute la carte, pas seulement son chiffre : c'est la seule qui doive se repérer
   sans être lue. Les autres se distinguent par la couleur de leur valeur, ce qui suffit. */
.carte-indicateur.alerte {
    background: #fdf5f4;
    border-color: #f5cdc9;
}
.carte-indicateur.alerte .valeur { color: var(--alerte); }

/* ---------- Tableau de bord ---------- */

/* Quatre tuiles sur une ligne au large, deux puis une en descendant. `auto-fit` avec un minimum de
   230 px : en dessous, le montant à sept chiffres se replierait sur deux lignes. */
.tuiles {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
    gap: 1rem;
}

.tuile {
    display: flex;
    flex-direction: column;
    gap: .2rem;
    background: var(--surface);
    border: 1px solid var(--trait);
    border-radius: var(--rayon-carte);
    box-shadow: var(--ombre);
    padding: 1.1rem 1.15rem;
    color: var(--encre);
}
a.tuile:hover { border-color: #cfdbea; text-decoration: none; }

/* Le jeton coloré porte toute la distinction entre les tuiles. C'est ce qui permet de les
   reconnaître du coin de l'œil sans lire les libellés — quatre cartes identiques obligeraient à
   relire à chaque passage. Il précède le libellé plutôt que de flotter à droite : l'œil descend la
   colonne de gauche. */
.tuile .jeton {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    margin-bottom: .45rem;
    border-radius: 9px;
    font-size: 1rem;
    line-height: 1;
}
.tuile .jeton.ambre { background: #fdf3e3; color: #b45309; }
.tuile .jeton.vert { background: #e8f6ef; color: var(--credit); }
.tuile .jeton.rouge { background: #fdeceb; color: var(--alerte); }
.tuile .jeton.bleu { background: var(--accent-clair); color: var(--accent); }

.tuile .lib { font-size: .8rem; color: var(--encre-douce); }
.tuile .val {
    font-size: 1.55rem;
    font-weight: 700;
    letter-spacing: -.025em;
    font-variant-numeric: tabular-nums;
    line-height: 1.15;
    color: var(--accent);
}
.tuile .det { font-size: .78rem; color: var(--encre-douce); }
.tuile .det b { color: var(--encre); font-weight: 600; }

/* **Le montant des factures échues est rouge en permanence**, y compris à zéro. Il ne l'était
   qu'au-delà, ce qui paraissait cohérent — le rouge signale un problème, et zéro facture en retard
   n'en est pas un — mais rendait la tuile méconnaissable les jours où tout va bien : on la
   cherchait parmi les trois autres au lieu de la reconnaître. Ici le rouge dit « c'est la tuile des
   retards », pas « il y a un retard », et le chiffre dit le reste. */
.tuile.echues .val { color: var(--alerte); }

/* Le fond teinté, lui, reste conditionnel : c'est lui qui alerte. Une tuile rose un jour sans
   aucun retard crierait au feu dans une maison vide. */
.tuile.alerte { background: #fdf5f4; border-color: #f5cdc9; }

/* Trois panneaux au large. Le premier passe seul sur une ligne dès qu'on rétrécit : `minmax`
   plutôt qu'un nombre fixe de colonnes, pour que la bascule vienne de la place disponible. */
.rangee-panneaux {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(310px, 1fr));
    gap: 1rem;
    margin-top: 1.25rem;
}

.panneau {
    background: var(--surface);
    border: 1px solid var(--trait);
    border-radius: var(--rayon-carte);
    box-shadow: var(--ombre);
    padding: .35rem .35rem .5rem;
    min-width: 0;
}

.panneau-tete {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: .75rem;
    padding: .85rem .9rem .6rem;
}
.panneau-tete h2 { font-size: .95rem; font-weight: 700; margin: 0; }
.panneau-tete a { font-size: .78rem; font-weight: 500; }

.panneau-vide {
    margin: 0;
    padding: .4rem .9rem 1rem;
    color: var(--encre-douce);
    font-size: .85rem;
}

/* ---- Activité du jour ---- */
/* Trois colonnes : libellé, compte, montant. Le compte est ce qu'on lit en premier, d'où sa taille ;
   le montant vient ensuite, aligné à droite en chiffres tabulaires pour se comparer d'une ligne à
   l'autre. */
.lignes-activite { display: flex; flex-direction: column; }

.ligne-activite {
    display: grid;
    grid-template-columns: 1fr auto minmax(6.5rem, auto);
    align-items: baseline;
    gap: .75rem;
    padding: .55rem .9rem;
    border-radius: 9px;
    color: var(--encre);
}
.ligne-activite:hover { background: #f4f7fb; text-decoration: none; }
.ligne-activite .l { font-size: .87rem; }
.ligne-activite .v { font-size: 1.05rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.ligne-activite .m {
    text-align: right;
    font-size: .8rem;
    color: var(--encre-douce);
    font-variant-numeric: tabular-nums;
}

/* ---- Principaux comptes ---- */
.classement { list-style: none; margin: 0; padding: 0; }

/* La première colonne porte un code de caisse (« COFFRE », « AG-YDE »), non un rang à un chiffre :
   à 1,4 rem, les codes débordaient sur le libellé ou passaient sur deux lignes. */
.classement a {
    display: grid;
    grid-template-columns: minmax(3.2rem, max-content) 1fr minmax(6.5rem, auto);
    align-items: center;
    gap: .6rem;
    padding: .5rem .9rem;
    border-radius: 9px;
    color: var(--encre);
}
.classement a:hover { background: #f4f7fb; text-decoration: none; }

.classement .rang {
    white-space: nowrap;
    font-size: .75rem;
    font-weight: 700;
    color: var(--encre-douce);
    font-variant-numeric: tabular-nums;
}
.classement .nom {
    min-width: 0;
    font-size: .87rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.classement .montant {
    text-align: right;
    font-size: .85rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--debit);
}

/* La barre dit la part de chacun par rapport au plus lourd. Lire cinq nombres et les comparer de
   tête est exactement ce qu'elle évite. */
.classement .barre {
    display: block;
    height: 3px;
    margin-top: .3rem;
    border-radius: 2px;
    background: #eef2f7;
}
.classement .barre span {
    display: block;
    height: 100%;
    border-radius: 2px;
    background: var(--accent);
}

/* ---- À traiter ---- */
.alertes { display: flex; flex-direction: column; }

.alerte-ligne {
    display: grid;
    grid-template-columns: 26px 1fr;
    align-items: start;
    gap: .65rem;
    padding: .55rem .9rem;
    border-radius: 9px;
    color: var(--encre);
}
.alerte-ligne:hover { background: #f4f7fb; text-decoration: none; }

.alerte-ligne .ic {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border-radius: 7px;
    font-size: .85rem;
    line-height: 1;
}
.alerte-ligne .ic.rouge { background: #fdeceb; color: var(--alerte); }
.alerte-ligne .ic.ambre { background: #fdf3e3; color: #b45309; }
.alerte-ligne .ic.bleu { background: var(--accent-clair); color: var(--accent); }

.alerte-ligne b { display: block; font-size: .85rem; font-weight: 600; }
.alerte-ligne .d {
    display: block;
    margin-top: .1rem;
    font-size: .78rem;
    color: var(--encre-douce);
    line-height: 1.35;
}

/* ---------- Document imprimable (facture remise au client) ----------
   Une feuille, pas un écran. Les mesures sont en points et en millimètres : ce document est fait
   pour du papier, et le voir à l'écran n'est qu'un aperçu. */

.barre-document {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
    margin-bottom: 1rem;
}
.barre-document p { margin: 0; color: var(--encre-douce); font-size: .875rem; }
.barre-document > div { display: flex; gap: .5rem; }

/* La largeur d'une page A4 moins ses marges : ce qu'on voit à l'écran est ce qui sortira. */
.document {
    max-width: 170mm;
    margin: 0 auto;
    padding: 12mm 14mm;
    background: var(--surface);
    border: 1px solid var(--trait);
    border-radius: var(--rayon-carte);
    box-shadow: var(--ombre);
    color: var(--encre);
    font-size: 10.5pt;
    line-height: 1.45;
}

.document p { margin: 0; }

.document-tete {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 2rem;
    padding-bottom: 1.2rem;
    border-bottom: 2px solid var(--encre);
}

.document .raison { font-size: 1.15rem; font-weight: 700; margin-bottom: .2rem; }
.document .emetteur p { color: var(--encre-douce); font-size: 9.5pt; }
.document .emetteur .raison { color: var(--encre); font-size: 1.15rem; }

.document .piece { text-align: right; flex: none; }
.document .piece .intitule {
    text-transform: uppercase;
    letter-spacing: .16em;
    font-size: .68rem;
    font-weight: 700;
    color: var(--encre-douce);
}
.document .piece .numero {
    font-size: 1.35rem;
    font-weight: 700;
    letter-spacing: -.01em;
    margin-bottom: .35rem;
}
.document .piece dl { display: grid; gap: .1rem; margin: 0; }
.document .piece dl > div { display: flex; justify-content: flex-end; gap: .5rem; }
.document .piece dt { color: var(--encre-douce); font-size: 9.5pt; }
.document .piece dd { margin: 0; font-size: 9.5pt; font-variant-numeric: tabular-nums; }

/* Le destinataire à droite, l'émetteur restant à gauche : c'est la disposition d'usage sur une
   facture, et celle qui place l'adresse en regard d'une fenêtre d'enveloppe.

   Le bloc est poussé à droite, mais **son texte reste aligné à gauche** : une adresse en drapeau
   droit se recopie mal, et le nom du client doit commencer au même endroit que sa rue. */
.destinataire {
    margin: 1.4rem 0 1.2rem auto;
    width: 62%;
    max-width: 85mm;
}
.destinataire .intitule {
    text-transform: uppercase;
    letter-spacing: .16em;
    font-size: .68rem;
    font-weight: 700;
    color: var(--encre-douce);
    margin-bottom: .2rem;
}
.destinataire p:not(.raison):not(.intitule) { color: var(--encre-douce); font-size: 9.5pt; }

.document-lignes { width: 100%; border-collapse: collapse; margin-top: .6rem; }

.document-lignes th {
    text-align: left;
    font-size: .68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .1em;
    color: var(--encre-douce);
    padding: .4rem .5rem;
    border-bottom: 1px solid var(--encre);
}

.document-lignes td {
    padding: .45rem .5rem;
    border-bottom: 1px solid var(--trait);
    vertical-align: top;
}

/* Le point qui motivait tout ce travail : du texte se replie, un champ de saisie non. */
.document-lignes td:first-child { overflow-wrap: anywhere; }

.document-lignes .nombre {
    text-align: right;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.document-totaux { display: flex; justify-content: flex-end; margin-top: 1rem; }
.document-totaux dl { display: grid; gap: .25rem; margin: 0; min-width: 62mm; }
.document-totaux dl > div { display: flex; justify-content: space-between; gap: 2rem; }
.document-totaux dt { color: var(--encre-douce); }
.document-totaux dd { margin: 0; font-variant-numeric: tabular-nums; }

.document-totaux .fort {
    border-top: 1px solid var(--encre);
    margin-top: .2rem;
    padding-top: .35rem;
    font-weight: 700;
}
.document-totaux .fort dt { color: var(--encre); }

.document-note { margin-top: 1.4rem; }
.document-note .intitule {
    text-transform: uppercase;
    letter-spacing: .16em;
    font-size: .68rem;
    font-weight: 700;
    color: var(--encre-douce);
}

.document-pied {
    margin-top: 2rem;
    padding-top: .8rem;
    border-top: 1px solid var(--trait);
    color: var(--encre-douce);
    font-size: 9pt;
}
.document-pied p + p { margin-top: .2rem; }

/* ---------- Recu de paiement ---------- */

/* La somme est ce qu'on vient lire sur un recu : elle est encadree et detachee du reste, la ou une
   facture etale ses lignes. Le cadre survit a l'impression — c'est lui qui empeche de confondre le
   montant avec le reste du texte. */
.recu-somme {
    margin-top: 1.4rem;
    border: 1.5px solid var(--encre);
    border-radius: var(--rayon);
    padding: .9rem 1.1rem;
}

.recu-chiffre { display: flex; align-items: baseline; justify-content: space-between; gap: 1.5rem; }

.recu-chiffre .intitule {
    text-transform: uppercase;
    letter-spacing: .16em;
    font-size: .68rem;
    font-weight: 700;
    color: var(--encre-douce);
}

.recu-chiffre .valeur {
    font-size: 1.45rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

/* La mention en toutes lettres : en italique et sur toute la largeur, comme sur une quittance. */
.recu-lettres {
    margin-top: .5rem;
    padding-top: .5rem;
    border-top: 1px dashed var(--trait);
    font-style: italic;
    font-size: 9.5pt;
}

/* Deux colonnes en pied de piece : le lieu et la date a gauche, la signature a droite. */
.recu-signature {
    margin-top: 2rem;
    display: flex;
    justify-content: space-between;
    gap: 2rem;
    flex-wrap: wrap;
}

.recu-signature .intitule {
    text-transform: uppercase;
    letter-spacing: .16em;
    font-size: .68rem;
    font-weight: 700;
    color: var(--encre-douce);
}

/* Un trait a signer, pas une bordure decorative : il lui faut une largeur reelle et de la place
   au-dessus, sinon la signature deborde sur la ligne precedente. */
.trait-signature {
    margin-top: 3rem;
    width: 55mm;
    border-bottom: 1px solid var(--encre);
}

/* ---------- Le reçu au format d'un carnet (A5, A6) ----------
   Une quittance n'est pas une facture. Elle se détache, se remet en main propre et se range dans
   une pochette : sortie sur une A4, elle occupe le tiers haut de la feuille et laisse deux tiers de
   blanc — du papier gâché à chaque encaissement, et un document qui ne ressemble à aucun reçu.

   **C'est le remplissage qui porte le blanc de la feuille, pas la marge de `@page`** — laquelle
   vaut zéro. Le navigateur dessine en effet l'adresse de la page et son numéro *dans* cette marge :
   lui en laisser une, c'est retrouver « https://…/recu » et « 1/1 » en bas d'une quittance. Sans
   marge, il n'a plus où les écrire. Ce remplissage doit donc **survivre à l'impression**, à rebours
   de `.document`, qui le remet à zéro (voir le bloc `@media print`).

   La largeur déclarée ici est celle du papier entier, remplissage compris : ce qu'on voit à l'écran
   est exactement ce qui sortira. A5 : 148 − 2×10 = 128 mm de texte ; A6 : 105 − 2×7 = 91 mm ;
   A4 : 210 − 2×14 = 182 mm.

   **Tout ce qui est dimensionné en `rem` doit repasser en `em`.** Une raison sociale à 1,15 rem
   garde ses 18 px sur une largeur deux fois moindre : sur une A6 elle mange la ligne entière. */
.document.format-a4 { max-width: 210mm; padding: 14mm; }
.document.format-a5 { max-width: 148mm; padding: 10mm; font-size: 9pt; }
.document.format-a6 { max-width: 105mm; padding: 7mm; font-size: 7.5pt; line-height: 1.3; }

.document:is(.format-a5, .format-a6) .raison,
.document:is(.format-a5, .format-a6) .emetteur .raison { font-size: 1.25em; }

.document:is(.format-a5, .format-a6) .piece .numero { font-size: 1.15em; }

.document:is(.format-a5, .format-a6) .emetteur p,
.document:is(.format-a5, .format-a6) .piece dt,
.document:is(.format-a5, .format-a6) .piece dd,
.document:is(.format-a5, .format-a6) .destinataire p:not(.raison):not(.intitule),
.document:is(.format-a5, .format-a6) .recu-lettres,
.document:is(.format-a5, .format-a6) .document-pied { font-size: .92em; }

.document:is(.format-a5, .format-a6) .intitule { font-size: .72em; letter-spacing: .1em; }
.document:is(.format-a5, .format-a6) .recu-chiffre .valeur { font-size: 1.7em; }

/* Les écarts se resserrent avec la feuille : les 2 rem de respiration d'une A4 laisseraient un reçu
   A6 vide en haut et coupé en bas. */
.document:is(.format-a5, .format-a6) .destinataire { margin: .9rem 0 .8rem auto; width: 70%; }
.document:is(.format-a5, .format-a6) .recu-somme { margin-top: .9rem; padding: .6rem .7rem; }
.document:is(.format-a5, .format-a6) .document-note { margin-top: .9rem; }
.document:is(.format-a5, .format-a6) .recu-signature { margin-top: 1.2rem; gap: 1rem; }
.document:is(.format-a5, .format-a6) .trait-signature { margin-top: 1.6rem; width: 40mm; }
.document.format-a6 .trait-signature { margin-top: 1.1rem; width: 32mm; }

/* ---------- Trois signatures : bon de décaissement, bordereau de transfert ----------
   **Une grille, pas le repli du flex.** Trois traits de 40 mm tiennent de justesse sur une A5 et pas
   sur une A6 : laissés au flex, le troisième passerait seul à la ligne, et le réceptionnaire
   signerait sous l'émetteur. La grille partage la largeur en trois quelle que soit la feuille, et
   ses traits suivent la colonne. Plus spécifique que la règle d'impression de `.recu-signature`,
   elle l'emporte aussi sur le papier. */
.document .recu-signature.trois {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 1.2rem;
}
.document .recu-signature.trois .trait-signature { width: 100%; }

/* D'une caisse à l'autre : le trajet des fonds se lit de gauche à droite. */
.document .bordereau-trajet {
    display: flex;
    align-items: center;
    gap: 1rem;
    margin-top: 1.4rem;
}
.document .bordereau-trajet > div { flex: 1; min-width: 0; }
.document .bordereau-trajet > div:last-child { text-align: right; }
.document .bordereau-trajet .intitule {
    text-transform: uppercase;
    letter-spacing: .16em;
    font-size: .68rem;
    font-weight: 700;
    color: var(--encre-douce);
}
.document .bordereau-trajet .fleche { font-size: 1.6em; color: var(--encre-douce); }
.document:is(.format-a5, .format-a6) .bordereau-trajet { margin-top: .9rem; }
.document:is(.format-a5, .format-a6) .bordereau-trajet .intitule { font-size: .72em; letter-spacing: .1em; }

/* Le groupe d'onglets porte son propre assemblage — bordure unique, coins arrondis, pas d'écart.
   `.barre-document > div` est **plus spécifique** que `.groupe-onglets` (une classe et un élément
   contre une classe) et lui imposait un écart d'un demi-rem : les trois formats se détachaient en
   trois boutons séparés au lieu d'un segment. */
.barre-document .groupe-onglets { gap: 0; }

/* ---------- Modale ---------- */

.fond-modale {
    position: fixed;
    inset: 0;
    background: rgba(22, 32, 44, .55);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    z-index: 100;
}
.modale {
    background: var(--surface);
    border-radius: var(--rayon);
    padding: 1.5rem;
    width: 100%;
    max-width: 460px;
}
.modale h2 { margin-top: 0; font-size: 1.15rem; }
.modale label { display: block; margin: .75rem 0 .3rem; font-size: .85rem; font-weight: 500; }
.modale .champ { width: 100%; }

/* ---------- États ---------- */

.carte-etat {
    display: flex;
    flex-direction: column;
    gap: .35rem;
    background: var(--surface);
    border: 1px solid var(--trait);
    border-radius: var(--rayon);
    padding: 1.1rem 1.25rem;
    color: var(--encre);
}
.carte-etat:hover { border-color: var(--accent); text-decoration: none; }
.carte-etat .titre { font-weight: 600; color: var(--accent); }
.carte-etat .detail { font-size: .82rem; color: var(--encre-douce); line-height: 1.4; }

.aide.avertissement {
    background: #fdf6e3;
    border: 1px solid #e8d9a8;
    border-radius: var(--rayon);
    padding: .6rem .9rem;
    color: #8a6d1f;
    margin-bottom: .75rem;
}


/* ---------- Onglets de page (Utilisateurs / Profils / Permissions) ---------- */

/* Nommés `onglet-page` et non `onglet` : ce dernier existe déjà plus haut, pour les filtres
   segmentés des listes, avec un fond accent sur l'élément retenu. Les deux se ressemblent de nom
   sans faire le même métier — l'un filtre une liste, l'autre change le contenu de la page — et la
   collision avait rendu le libellé de l'onglet courant invisible : texte accent sur fond accent. */
.onglets {
    display: flex;
    gap: .25rem;
    border-bottom: 1px solid var(--trait);
    margin-bottom: 1.25rem;
}

.onglet-page {
    background: none;
    border: 0;
    /* Le filet du bas porte l'état courant : réservé dès le départ pour que la bascule ne décale
       pas le contenu de deux pixels. */
    border-bottom: 3px solid transparent;
    padding: .6rem 1rem;
    font: inherit;
    color: var(--encre-douce);
    cursor: pointer;
}

.onglet-page:hover { color: var(--encre); }

.onglet-page.courant {
    color: var(--accent);
    border-bottom-color: var(--accent);
    font-weight: 600;
}

/* ---------- Profils ---------- */

.grille-profils {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: 1rem;
}

.carte-profil {
    background: var(--surface);
    border: 1px solid var(--trait);
    border-radius: var(--rayon);
    padding: 1rem;
}

.carte-profil h2 { font-size: 1.05rem; margin: 0 0 .25rem; }
.carte-profil .actions { margin-top: .75rem; }

.compte-permissions {
    color: var(--accent);
    font-size: .8rem;
    font-weight: 600;
    letter-spacing: .04em;
    margin: 0 0 .4rem;
}

/* Sur la ligne d'un utilisateur, le décompte passe sous le nom du profil plutôt qu'à côté :
   accolés, les deux se lisaient comme un seul libellé. */
td .compte-permissions { display: block; font-weight: 400; letter-spacing: 0; }
.profil-nom { font-weight: 600; }

/* ---------- Catalogue et composition des permissions ---------- */

.entete-permissions {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    margin-top: 1.5rem;
}

.entete-permissions h3 { margin: 0; font-size: 1rem; }

.groupe-permissions {
    border: 1px solid var(--trait);
    border-radius: var(--rayon);
    padding: .75rem 1rem 1rem;
    margin: .75rem 0 0;
}

.groupe-permissions legend,
.groupe-permissions h2 {
    font-weight: 600;
    font-size: .95rem;
    padding: 0 .4rem;
    display: flex;
    align-items: baseline;
    gap: .75rem;
}

.ligne-permission {
    display: grid;
    /* Deux colonnes : la case, puis le libellé. La troisième portait le code technique, retiré de
       l'affichage — il n'apprenait rien à qui compose un profil. */
    grid-template-columns: auto 1fr;
    align-items: center;
    gap: .6rem;
    padding: .3rem 0;
}

.ligne-permission input[disabled] + span { color: var(--encre-douce); }

.aide.avertissement {
    color: var(--debit);
    border-left: 3px solid var(--debit);
    padding-left: .6rem;
}

/* ---------- Erreurs Blazor ---------- */

#blazor-error-ui {
    background: #fff3cd;
    bottom: 0;
    display: none;
    left: 0;
    padding: .6rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
    box-shadow: 0 -1px 2px rgba(0,0,0,.2);
}
#blazor-error-ui .dismiss { cursor: pointer; position: absolute; right: .75rem; top: .5rem; }

/* Le bouton du menu n'existe que sur petit écran : au-dessus, la barre latérale est permanente et
   un bouton pour la dérouler n'aurait rien à ouvrir. */
.bouton-menu { display: none; }

@media (max-width: 800px) {
    /* Repère de positionnement pour la barre haute et pour le menu déroulé, tous deux sortis du
       flux plus bas. */
    .page { flex-direction: column; position: relative; }

    .barre-laterale {
        width: 100%;
        padding: 0;
        /* Empilée, la barre est au-dessus du contenu : le filet passe en bas. */
        border-right: 0;
        border-bottom: 1px solid var(--trait);
        position: relative;
    }

    /* ---- Bandeau ----
       Le compte et la déconnexion viennent occuper le coin haut droit, à hauteur de l'enseigne :
       ils formaient sinon une seconde bande sous la première, pour deux mots. Sortis du flux, ils
       ne repoussent rien. */
    .barre-haute {
        position: absolute;
        top: 0;
        right: 0;
        z-index: 20;
        height: auto;
        min-height: 0;
        padding: .55rem 1rem;
        border: 0;
        background: none;
        gap: .75rem;
    }

    .barre-haute .utilisateur { text-align: right; }

    /* ---- Menu hamburger ----
       Le bouton passe **sous** l'enseigne, à gauche : la place à sa droite revient au compte. */
    .marque { display: block; padding: .6rem 1rem .5rem; }
    .marque-texte { display: block; }

    .bouton-menu {
        display: block;
        margin-top: .35rem;
        background: none;
        border: 0;
        font-size: 1.5rem;
        line-height: 1;
        color: var(--encre);
        cursor: pointer;
        /* 44 px : la cible tactile minimale confortable. Un chevron de 24 px se rate une fois sur
           trois, et rater le menu est la première chose qu'on fait sur un téléphone. */
        min-width: 44px;
        min-height: 44px;
        padding: 0;
        text-align: left;
    }

    .menu { display: none; }

    /* Déroulé **par-dessus** le contenu et non au-dessus de lui : inséré dans le flux, il
       repoussait le formulaire de six cents pixels, et refermer le menu ramenait l'écran ailleurs
       qu'où on l'avait laissé. */
    .menu.deploye {
        display: flex;
        flex-direction: column;
        position: absolute;
        top: 100%;
        left: 0;
        right: 0;
        z-index: 30;
        background: var(--surface);
        border-top: 1px solid var(--trait);
        box-shadow: 0 8px 16px rgba(0, 0, 0, .18);
        padding-bottom: .5rem;
        /* Onze entrées dépassent un petit écran : le menu défile en lui-même plutôt que de sortir
           de l'écran par le bas. */
        max-height: calc(100vh - 100%);
        overflow-y: auto;
    }

    /* Le liseré passe à gauche comme sur ordinateur : la liste est verticale des deux côtés, donc
       le repère de la page courante n'a aucune raison de changer de bord. */
    .lien-menu { padding: .8rem 1rem; }

    .contenu { padding: 1rem; }

    /* ---- Filtres ----
       Le groupe « Du … Au … » mesure 359 px pour 345 disponibles : `flex: 0 0 auto`, qui ailleurs
       tient le libellé contre son champ, lui interdit ici de se réduire, et le second champ venait
       affleurer le bord de l'écran. On lui rend donc le droit de rétrécir et ses deux champs de
       date se partagent la place. `min-width: 0` des deux côtés est indispensable : la largeur
       intrinsèque d'un champ de date natif — qui porte son gabarit et son icône de calendrier —
       sert autrement de plancher et rien ne cède. */
    .filtre { flex: 1 1 auto; min-width: 0; }
    .champ-date { flex: 1 1 0; min-width: 0; }

    /* ---- Formulaires ----
       Deux colonnes de 220 px ne tiennent pas dans 375 : la grille passe à une colonne pleine,
       au lieu de laisser `auto-fit` produire des champs comprimés. */
    .grille-champs { grid-template-columns: 1fr; }

    .barre-actions { flex-wrap: wrap; }
    .barre-actions > * { flex: 1 1 auto; }

    /* ---- Tableaux : chaque ligne devient une carte ----
       De six à dix colonnes, aucun de ces tableaux ne tient dans 375 px. Les faire défiler
       latéralement obligeait à balayer l'écran pour lire une seule ligne, et à retenir de tête la
       colonne où l'on était. Empilée, la ligne se lit d'un coup : le nom de colonne passe devant
       sa valeur, porté par `data-libelle`, et l'en-tête disparaît puisqu'elle se répéterait. */
    .table-defilante { overflow-x: visible; border: 0; }

    table.liste { display: block; table-layout: auto; width: 100%; }
    table.liste thead { display: none; }
    table.liste tbody, table.liste tr, table.liste td { display: block; width: auto; }

    table.liste tr {
        border: 1px solid var(--trait);
        border-radius: var(--rayon);
        padding: .6rem .75rem;
        margin-bottom: .75rem;
        background: var(--surface);
    }

    table.liste td {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: .75rem;
        padding: .3rem 0;
        border: 0;
        text-align: left;
    }

    table.liste td::before {
        content: attr(data-libelle);
        flex: 0 0 42%;
        font-size: .8rem;
        color: var(--encre-douce);
    }

    /* Une cellule sans libellé — la colonne d'actions — prend toute la largeur. */
    table.liste td:not([data-libelle])::before { content: none; }

    /* Les actions passent en bas de la carte, séparées par un filet : ce sont des boutons, pas
       une donnée de plus à lire. */
    table.liste td.actions {
        flex-wrap: wrap;
        justify-content: flex-start;
        gap: .5rem;
        margin-top: .5rem;
        padding-top: .6rem;
        border-top: 1px solid var(--trait);
    }

    /* **L'écart vient du `gap`, plus de la marge**, et c'est ce qui manquait. `.actions > * + *`
       pose un `margin-left` pour séparer les actions sur ordinateur, où la cellule n'est pas un
       conteneur flex. Ici les deux s'additionnaient — et surtout, la marge suit l'élément quand il
       passe à la ligne : « Supprimer », replié sous ses voisins, s'y retrouvait décalé de neuf
       pixels vers la droite, aligné sur rien. Mesuré sur un téléphone à 360 px. */
    table.liste td.actions > * + * { margin-left: 0; }

    /* Les montants restent alignés à droite, comme sur ordinateur : c'est ce qui les rend
       comparables d'une carte à l'autre. */
    table.liste td.nombre, table.liste td.solde { justify-content: space-between; }

    /* Une cellule à deux valeurs — le profil et son nombre de permissions — les empile plutôt que
       de les serrer côte à côte : « 39 permissions » se coupait en deux lignes et venait buter
       contre le nom du profil. */
    table.liste td { flex-wrap: wrap; }
    table.liste td .compte-permissions { flex: 1 0 100%; text-align: right; margin: 0; }

    /* ---- Saisie de lignes ----
       Même empilement, mais la valeur est un champ : il prend la place restante. */
    table.saisie .champ { flex: 1 1 auto; width: auto; }
    table.saisie .champ.nombre { text-align: left; }
    table.saisie td { justify-content: flex-start; }
    table.saisie td::before { flex: 0 0 40%; }
    table.saisie td.actions { justify-content: flex-end; }

}

/* ---------- Formulaire en lecture seule ----------
   `fieldset[disabled]` neutralise d'un coup tous les champs imbriques, y compris ceux qu'on
   ajoutera plus tard : c'est ce qui evite d'avoir a poser `disabled` sur vingt controles et d'en
   oublier un au prochain ajout. Le fieldset n'est la que pour cela, d'ou le retrait de sa bordure
   et de ses marges par defaut, qui dessineraient un cadre que personne n'a demande. */
fieldset.sans-cadre {
    border: 0;
    padding: 0;
    margin: 0;
    min-width: 0;
}

/* Un champ desactive doit se lire, pas seulement se distinguer : le gris pale que les navigateurs
   appliquent par defaut rend une facture consultee difficile a dechiffrer, alors que la consulter
   est justement le but. */
fieldset.sans-cadre[disabled] .champ,
fieldset.sans-cadre[disabled] input,
fieldset.sans-cadre[disabled] textarea,
fieldset.sans-cadre[disabled] select {
    background: #f4f7fb;
    color: var(--encre);
    opacity: 1;
    cursor: default;
}

/* ---------- Caisses ----------
   Le sens d'un montant se dit par la couleur à l'écran et par le signe sur le papier : une
   impression en noir et blanc garde « − » et « + », jamais le rouge ni le vert. Les deux couleurs
   reprennent débit et crédit, et non l'alerte : une sortie de caisse n'est pas un incident. */

.montant-negatif { color: var(--debit); }
.montant-positif { color: var(--credit); }

.valeur-forte {
    margin: .15rem 0 .25rem;
    font-size: 1.35rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

/* Le comptage se saisit dans un tableau étroit : des champs de quantité à droite, pas la grille
   à sept colonnes des lignes de facture dont `table.saisie` fixe les largeurs. */
table.comptage { width: 100%; }
table.comptage .champ { width: 100%; min-width: 0; padding: .35rem .5rem; }
table.comptage .champ.nombre { text-align: right; max-width: 9rem; margin-left: auto; display: block; }
table.comptage tfoot td { font-weight: 600; }

.aide.avertissement { color: var(--debit); }

/* Les deux signatures du procès-verbal de contrôle, sur le papier seulement. */
.zone-signatures {
    gap: 3rem;
    margin-top: 2.5rem;
    break-inside: avoid;
}
.zone-signatures > div { flex: 1; }
@media print { .zone-signatures.impression-seule { display: flex; } }
.zone-signatures p { margin: 0 0 3rem; color: var(--encre-douce); font-size: .9rem; }

/* ---------- Graphiques du tableau de bord ----------
   Couleurs de la palette validée (contrôle daltonien et contraste passés sur le fond blanc des
   panneaux) : bleu et orange pour les deux courbes, bleu et rouge pour la polarité entrées / sorties.
   Aucun texte ne porte la couleur d'une série — la clé colorée est à côté du texte, qui reste à l'encre.
   Traits de 2 px, colonnes fines arrondies à leur extrémité, grille en filet qu'on devine à peine. */

.rangee-graphiques {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 420px), 1fr));
    gap: 1rem;
    margin-top: 1.25rem;
}

.periode-graphique { font-size: .76rem; color: var(--encre-douce); }

/* Le défilement horizontal est celui du graphique seul, jamais de la page : sur un téléphone, les
   graduations resteraient lisibles plutôt que de rétrécir à quelques pixels. */
.graphique {
    position: relative;
    overflow-x: auto;
    padding: 0 .5rem .35rem;
}

.graphique svg { display: block; width: 100%; min-width: 440px; height: auto; }

.graphique .grille { stroke: #eef1f5; stroke-width: 1; }
.graphique .axe { stroke: #c3c2b7; stroke-width: 1; }
.graphique .graduation { font-size: 11px; fill: var(--encre-douce); font-variant-numeric: tabular-nums; }
.graphique .etiquette-fin { font-size: 11px; font-weight: 600; fill: var(--encre); }

.graphique .trace { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.graphique .trace.serie-especes { stroke: #2a78d6; }
.graphique .trace.serie-depots { stroke: #eb6834; }

/* L'anneau blanc garde le point lisible là où il croise l'autre courbe. */
.graphique .point { stroke: var(--surface); stroke-width: 2; }
.graphique .point.serie-especes { fill: #2a78d6; }
.graphique .point.serie-depots { fill: #eb6834; }

.graphique .barre.serie-entrees { fill: #2a78d6; }
.graphique .barre.serie-sorties { fill: #e34948; }

.graphique .zone { fill: transparent; cursor: crosshair; outline: none; }
.graphique .zone.active { fill: rgba(15, 23, 42, .045); }
.graphique .zone:focus-visible { stroke: var(--accent); stroke-width: 1; }
.graphique .curseur { stroke: #94a3b8; stroke-width: 1; }

.legende-graphique {
    list-style: none;
    display: flex;
    flex-wrap: wrap;
    gap: .35rem 1.1rem;
    margin: 0;
    padding: 0 .9rem .5rem;
    font-size: .78rem;
    color: var(--encre-douce);
}
.legende-graphique li { display: flex; align-items: center; gap: .4rem; }

.cle-ligne { display: inline-block; width: 16px; height: 2px; border-radius: 1px; }
.cle-barre { display: inline-block; width: 10px; height: 10px; border-radius: 2px; }
.cle-ligne.serie-especes, .cle-barre.serie-especes { background: #2a78d6; }
.cle-ligne.serie-depots, .cle-barre.serie-depots { background: #eb6834; }
.cle-ligne.serie-entrees, .cle-barre.serie-entrees { background: #2a78d6; }
.cle-ligne.serie-sorties, .cle-barre.serie-sorties { background: #e34948; }
.cle-ligne.sans-serie { visibility: hidden; }

/* La valeur d'abord, le nom ensuite : dans la bulle, on connaît la série et on cherche le chiffre. */
.infobulle {
    position: absolute;
    z-index: 2;
    min-width: 13rem;
    padding: .5rem .65rem;
    background: var(--surface);
    border: 1px solid var(--trait);
    border-radius: 9px;
    box-shadow: var(--ombre);
    font-size: .78rem;
    pointer-events: none;
}
.infobulle .titre { margin-bottom: .3rem; color: var(--encre-douce); }
.infobulle .titre::first-letter { text-transform: uppercase; }
.infobulle .rangee { display: grid; grid-template-columns: 16px auto 1fr; align-items: center; gap: .5rem; padding: .1rem 0; }
.infobulle strong { font-variant-numeric: tabular-nums; text-align: right; color: var(--encre); }
.infobulle .libelle { color: var(--encre-douce); }

.donnees-graphiques { margin-top: .75rem; }
.donnees-graphiques summary { cursor: pointer; font-size: .82rem; color: var(--accent); }
.donnees-graphiques .table-defilante { margin-top: .5rem; }

/* Les règles de la reprise d'un registre : trois phrases qu'on lit avant de choisir le fichier. */
.liste-regles {
    margin: 1rem 0 0;
    padding-left: 1.2rem;
    display: grid;
    gap: .35rem;
    font-size: .85rem;
    color: var(--encre-douce);
}
.liste-regles b { color: var(--encre); font-weight: 600; }

/* ---------- Impression ----------
   En dernier, et c'est essentiel : sur un telephone, ce bloc et celui des petits ecrans
   s'appliquent tous les deux. A specificite egale, le dernier l'emporte. Place avant, il se
   faisait ecraser par la mise en cartes et la balance sortait en cartes sur la feuille au lieu
   du tableau attendu. L'impression est un autre media, pas un ecran plus etroit : elle tranche
   en dernier. */
@media print {
    .barre-laterale,
    .barre-haute,
    .sans-impression,
    #blazor-error-ui { display: none !important; }

    body { background: #fff; font-size: 11pt; }
    .contenu { padding: 0; }
    .page { display: block; }

    /* Le conteneur défilant tronquerait le tableau à la largeur de l'écran. */
    .table-defilante { overflow: visible; border: 0; }
    table { font-size: 10pt; }
    tr { break-inside: avoid; }

    /* ---- Annulation de la mise en cartes ----
       Sur un téléphone, le bloc des petits écrans s'applique aussi à l'impression, et ses
       sélecteurs `table.liste …` sont **plus spécifiques** que `thead` ou `table` : les remettre en
       dernier dans la feuille ne suffisait pas, la spécificité primant sur l'ordre. La balance
       sortait donc en cartes là où on attend un tableau — une carte par compte se lit à l'écran,
       jamais sur une feuille où l'on compare des colonnes de chiffres.
       Une feuille de papier n'est pas un petit écran : le tableau y reprend sa forme. */
    table.liste, table.saisie { display: table; table-layout: auto; }
    table.liste thead, table.saisie thead { display: table-header-group; }
    table.liste tbody, table.saisie tbody { display: table-row-group; }

    table.liste tr, table.saisie tr {
        display: table-row;
        border: 0;
        border-radius: 0;
        padding: 0;
        margin: 0;
        background: none;
    }

    table.liste td, table.saisie td {
        display: table-cell;
        border-bottom: 1px solid var(--trait);
        border-top: 0;
        padding: .4rem .6rem;
        margin: 0;
    }

    /* Le libellé de colonne revient dans l'en-tête : le répéter devant chaque valeur doublerait
       toute la feuille. */
    table.liste td::before, table.saisie td::before { content: none; }

    table.liste td.nombre, table.liste td.solde { text-align: right; }
    table.liste td .compte-permissions { display: block; text-align: left; }

    a { color: inherit; text-decoration: none; }
    .etiquette { border: 1px solid #999; background: none !important; color: inherit !important; }

    /* ---- Un formulaire imprimé doit se lire comme un document ----
       Imprimer une facture telle qu'elle s'affiche donnerait une feuille de cases : chaque valeur
       enfermée dans un rectangle gris, avec des flèches de liste déroulante et des icônes de
       calendrier. Le papier n'a pas de champs, il a du texte.

       Les bordures et les fonds tombent donc, et les contrôles reprennent la largeur de leur
       contenu au lieu de s'étirer sur toute la colonne — un numéro de facture suivi de huit
       centimètres de vide se lit comme une erreur d'impression. */
    .carte-formulaire {
        border: 0;
        box-shadow: none;
        padding: 0;
        margin-bottom: 1.2rem;
        break-inside: avoid;
    }

    .champ, .champ-date, .champ-recherche, select.champ, textarea.champ {
        border: 0 !important;
        background: none !important;
        padding: 0 !important;
        box-shadow: none !important;
        color: inherit !important;
        font-weight: 600;
        /* `auto` sur un input ne suffit pas : sa largeur vient de l'attribut `size`, pas du
           contenu. `min-content` le laisse se réduire, et `max-width: 100%` l'empêche de déborder
           d'une cellule étroite du tableau des lignes. */
        width: auto;
        min-width: 0;
        max-width: 100%;
    }

    /* Le fond gris d'un champ désactivé n'a plus d'objet sur le papier : rien n'y est modifiable. */
    .champ:disabled, .champ-date:disabled, select.champ:disabled, textarea.champ:disabled {
        background: none !important;
        color: inherit !important;
    }

    /* Chrome et Firefox dessinent la flèche du `select` et l'icône du calendrier même sans bordure,
       et elles n'ont aucun sens sur une feuille. */
    select.champ { appearance: none; -webkit-appearance: none; }
    input[type="date"]::-webkit-calendar-picker-indicator { display: none; }

    /* Le libellé reste, en plus discret : c'est lui qui dit ce que la valeur signifie. */
    .groupe-champ > label { color: #555; font-weight: 400; }

    /* Un champ numérique reste aligné à droite dans sa colonne d'origine : privé de sa bordure, sa
       valeur se retrouvait à plusieurs centimètres de son libellé, sans rien entre les deux. Sur le
       papier, la valeur suit l'étiquette. */
    .champ.nombre, input[type="number"].champ { text-align: left !important; }

    /* Une zone de texte vide laissait un grand blanc et sa poignée de redimensionnement. Elle
       reprend la hauteur de son contenu et perd la poignée, qui ne veut rien dire sur une feuille. */
    textarea.champ { resize: none; height: auto; min-height: 0; }

    /* Textes d'aide et pied de formulaire : utiles à l'écran, muets sur le papier — « Enregistrer »
       et « Annuler » n'ont rien à faire sur une feuille.

       `case-actifs` porte les bascules de saisie (« Détailler en lignes », « Actifs seulement ») :
       une case à cocher désactivée n'informe personne sur du papier. `message-information` porte
       les consignes d'écran, du même ordre. `fil-ariane` est un chemin de navigation : sur une
       feuille, il n'y a nulle part où remonter. */
    .aide, .barre-actions, .case-actifs, .message-information, .fil-ariane { display: none; }

    /* L'inverse de `sans-impression` : ce qui ne paraît qu'une fois imprimé. */
    .impression-seule { display: inline; }

    /* ---- Le document de facture prend la feuille ----
       À l'écran il s'affiche comme une page posée sur un fond : bordure, ombre, coins arrondis,
       largeur limitée. Sur du papier, tout cela n'a plus d'objet — la feuille *est* la page. Les
       marges viennent de l'imprimante, pas du document, sans quoi elles s'additionneraient. */
    .document {
        max-width: none;
        margin: 0;
        padding: 0;
        border: 0;
        border-radius: 0;
        box-shadow: none;
    }

    /* ---- Le reçu, lui, garde son remplissage ----
       **C'est l'exception à la règle ci-dessus, et elle est délibérée.** La marge de son `@page`
       vaut zéro — seul moyen d'empêcher le navigateur d'écrire l'adresse de la page et « 1/1 » en
       bas de la quittance, ce pied étant dessiné *dans* la marge et hors d'atteinte du document.
       Le blanc de la feuille doit donc venir d'ailleurs : c'est ce remplissage, repris ici à
       l'identique de l'aperçu.

       Il n'y a rien à faire pour que ces trois règles l'emportent — `.document.format-a5` compte
       deux classes contre une —, mais tout à faire pour ne pas les oublier : sans elles, le reçu
       s'imprimerait collé aux quatre bords du papier, et une imprimante rognerait le premier
       centimètre. La largeur, elle, se relâche : la feuille *est* la page. */
    .document.format-a4 { max-width: none; padding: 14mm; }
    .document.format-a5 { max-width: none; padding: 10mm; }
    .document.format-a6 { max-width: none; padding: 7mm; }

    /* Une facture longue se poursuit page suivante : l'en-tête du tableau se répète, et aucune
       ligne n'est coupée en deux. */
    .document-lignes thead { display: table-header-group; }
    .document-lignes tr { break-inside: avoid; }

    /* Les totaux et le pied restent solidaires : un « Total TTC » seul en haut d'une page, séparé
       de ses lignes, se lit mal et se conteste. */
    .document-totaux, .document-pied { break-inside: avoid; }

    /* Dans le tableau des lignes, ces jumeaux remplacent des champs numériques : ils reprennent
       l'alignement à droite qui permet de comparer des colonnes de chiffres d'une ligne à l'autre,
       et que la cellule ne porte pas — c'est l'input qui l'avait. */
    table.saisie .impression-seule {
        display: block;
        text-align: right;
        font-variant-numeric: tabular-nums;
    }

    /* L'astérisque marque un champ obligatoire à la saisie. Sur le papier, plus rien ne se saisit ;
       il ne reste qu'un signe que le lecteur prend pour un renvoi de note. */
    .groupe-champ > label .obligatoire,
    table.saisie th .obligatoire { display: none; }

    /* ---- La grille de champs ne se replie pas sur une colonne ----
       **Une feuille A4 fait 794 px de large à 96 ppp, donc sous le seuil de 800 px** : le bloc des
       petits écrans s'applique à l'impression et forçait `grid-template-columns: 1fr`. Numéro, date
       et échéance descendaient alors chacun sur sa ligne, mangeant un tiers de page pour trois
       valeurs de dix caractères. Même piège que celui déjà corrigé sur la balance — une feuille de
       papier n'est pas un petit écran. */
    .grille-champs { grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }

    /* ---- Le tableau des lignes tient dans la page ----
       Huit colonnes à la taille de l'écran débordaient de la feuille : la dernière était coupée au
       bord droit, et le trop-plein poussait une seconde page vide. Le corps réduit et les marges
       resserrées y suffisent. */
    /* **Sans `table-layout: fixed`, et c'est délibéré.** Il y avait été mis pour contenir le tableau
       dans la page ; il ne servait à rien — le corps réduit et les marges resserrées y suffisent —
       et il faisait *ignorer* les largeurs déclarées plus bas : les colonnes se partageaient la
       feuille à parts égales, la désignation devenait aussi étroite que « TVA % » et se lisait
       « RIZ… ». En disposition automatique, les mêmes pourcentages sont honorés à l'unité près et
       une désignation longue ne se fait plus couper. Mesuré : 238 px pour 30 % déclarés. */
    table.saisie {
        width: 100%;
        font-size: 8.5pt;
    }

    table.saisie th, table.saisie td {
        padding: .25rem .3rem;
        overflow-wrap: anywhere;
    }

    /* **Les largeurs doivent être déclarées, sinon la mise en page fixe les répartit à parts
       égales.** La désignation se retrouvait alors aussi étroite que « TVA % » et se lisait
       « RIZ… » ; les colonnes de chiffres, elles, avaient trois fois la place qu'il leur faut.
       La désignation prend donc le tiers, les pourcentages le minimum. */
    table.saisie th:nth-child(1), table.saisie td:nth-child(1) { width: 12%; }  /* Article */
    table.saisie th:nth-child(2), table.saisie td:nth-child(2) { width: 30%; }  /* Désignation */
    table.saisie th:nth-child(3), table.saisie td:nth-child(3) { width: 9%; }   /* Quantité */
    table.saisie th:nth-child(4), table.saisie td:nth-child(4) { width: 14%; }  /* Prix unitaire */
    table.saisie th:nth-child(5), table.saisie td:nth-child(5) { width: 9%; }   /* Remise % */
    table.saisie th:nth-child(6), table.saisie td:nth-child(6) { width: 9%; }   /* TVA % */
    table.saisie th:nth-child(7), table.saisie td:nth-child(7) { width: 17%; }  /* Montant HT */

    /* Un `input` tire sa largeur de son attribut `size`, pas de sa cellule : privé de bordure il
       gardait sa largeur propre, et une désignation plus longue défilait à l'intérieur au lieu de
       s'afficher. Sur le papier il n'y a rien à faire défiler. */
    table.saisie .champ { width: 100%; }

    /* **Le lieu à gauche, la signature à droite — imposé, jamais laissé au repli.** Une feuille A4
       fait 794 px à 96 ppp, c'est-à-dire juste sous le point de rupture des petits écrans : le
       couple se repliait donc l'un sous l'autre à l'impression, en gaspillant la hauteur et en
       éloignant le trait de son intitulé. C'est le même piège que la mise en cartes des tableaux,
       et il se corrige de la même façon : en déclarant ce qu'on veut au lieu d'espérer. */
    .recu-signature { display: flex; flex-wrap: nowrap; justify-content: space-between; }
    .recu-signature > div { flex: 0 1 auto; }

    /* Un reçu tient sur une feuille : rien ne doit le couper en deux, et surtout pas entre la somme
       et sa mention en toutes lettres, qui ne valent que lues ensemble. */
    .recu-somme, .recu-signature { break-inside: avoid; page-break-inside: avoid; }
}
