/* =============================================================================
   back-office.css — composants du BACK-OFFICE CABINET (charte §5 et §11).

   Extrait de `components.css` le 2026-08-06, qui portait 2 055 lignes : les composants
   partages (boutons, cartes, champs, chips) et ceux du back-office ne se croisent jamais,
   et seuls les seconds continuent de grossir a chaque ecran ajoute.

   Perimetre : tout le prefixe `.bo-*`, plus les composants employes UNIQUEMENT par les
   gabarits de `back_office/templates/` — apercus de signature et de logo, bouton d'ouverture
   d'une ligne, fenetre modale, action de ligne. Le prefixe n'est donc pas le seul critere :
   c'est « qui s'en sert » qui tranche.

   ⚠️ **L'ordre de chargement fait partie du contrat.** Cette feuille est chargee APRES
   `components.css` (cf. `shared/ui/templates/base.html`) et AVANT `utilities.css`, qui garde
   ainsi le dernier mot. Deux regles de meme specificite sont departagees par leur ordre
   d'apparition : charger cette feuille avant `components.css` inverserait des arbitrages qui
   tiennent aujourd'hui a la seule position — sans qu'aucun test ne le signale.

   ⚠️ Aucune regle n'a ete reecrite lors de l'extraction, et leur ordre interne est intact.

   Memes regles de gouvernance que partout : une seule classe par selecteur, ~2 niveaux
   maximum, jamais d'ID, jamais d'`!important`, aucune valeur en dur (tout vient de tokens.css).
   ============================================================================= */

/* --- App-shell du back-office (C7.1) — distillé de la maquette « Dossiers » ------------------

   ⚠️ **Distillation, pas recopie.** La maquette portait des couleurs en dur (#dfe6f1, #c9d3e2,
   #9fb0c9) et cinq tailles hors échelle (10,5 / 11,5 / 12,5 / 15,5 / 16,5 px). Les recopier aurait
   fait échouer les deux gardes de gouvernance — et à raison : ces valeurs ramenaient l'échelle
   typographique au rang d'indication. Tout est ramené aux tokens.

   ⚠️ **Le burger est en CSS pur** (case à cocher + `~`), jamais en JavaScript : la CSP stricte
   (`script-src 'self'`) bloquerait un script en ligne **silencieusement**. La case porte `.vh`
   (visuellement cachée) et non `hidden` : elle doit rester **atteignable au clavier**, sans quoi
   le menu mobile serait inutilisable sans souris.

   ⚠️ **L'ancrage bas ne coûte aucun positionnement absolu** : la grille nommée réserve une rangée
   `1fr` vide entre les liens et l'encart, qui pousse l'abonnement et le compte contre le bas.
   C'est ce qui les garde en place quelle que soit la hauteur du menu. */

.bo-shell {
  display: flex;
  flex-direction: column;
  min-height: 100dvh;
}

.bo-aside {
  background: var(--primary);
  color: var(--on-primary-attenue);
  /* ⚠️ Un ascenseur HORIZONTAL dans un menu est toujours un defaut, jamais un service rendu :
     il n'y a rien a aller voir a droite. On le supprime a la racine plutot que de compter sur
     chaque contenu pour ne jamais deborder — une adresse electronique un peu longue suffisait. */
  overflow-x: hidden;
  /* ⚠️ Réglage **mobile** : le menu est ici un panneau déplié en pleine largeur, pas une colonne
     posée à côté du contenu. L'illusion d'asymétrie qui vaut en desktop (cf. la media query
     900 px) n'a donc pas d'objet, et le retrait reste égal des quatre côtés. */
  padding: var(--e-12);
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  column-gap: var(--e-12);
  /* ⚠️ Le logo prend une **rangée entière au-dessus**, et non une place sur la ligne du nom
     [DÉCIDÉ 2026-08-05]. Partagé avec le nom et le bouton de menu, il comprimait le nom du cabinet
     — qui passait alors sur deux ou trois lignes et faisait grandir le bandeau *par ricochet*,
     sans qu'on voie d'où venait la hauteur. Sur sa propre rangée, il ne dispute la place à
     personne. Rangée **vide et sans hauteur** quand aucun logo n'est déposé. */
  grid-template-areas:
    "logo logo logo"
    "marque marque burger"
    "liens liens liens"
    "compte compte compte"
    "deconnexion deconnexion deconnexion";
}

/* ⚠️ **Bandeau replié : UNE rangée quand un logo existe** [DÉCIDÉ 2026-08-06].
   Logo à gauche, bouton de menu à droite — le nom du cabinet ne figure plus dans le bandeau replié.
   La rangée du logo et celle du nom faisaient double emploi : deux fois la même identité, sur deux
   rangées, en haut d'un écran de téléphone où la hauteur est ce qui manque le plus.

   ⚠️ **Sans logo, rien ne change** : `.bo-marque` reprend cette place, monogramme compris. Un
   bandeau sans logo ET sans nom n'identifierait plus le cabinet — l'anti-confusion (macro §2, B.0)
   veut précisément que l'avocat voie chez qui il travaille.

   ⚠️ **Le lien vers l'accueil n'est pas perdu.** `.bo-marque` pointe vers `bo.dossiers`, qui est
   aussi la première rubrique du menu : replié, on y va par le menu ; déplié, la marque réapparaît
   (voir la règle `:checked` plus bas). C'est ce qui permet de garder le logo NON cliquable, donc de
   ne pas faire annoncer deux fois « accueil » par un lecteur d'écran. */
.bo-aside-logo {
  /* Retrait resserré en haut et en bas : le bandeau à une rangée n'a plus besoin de l'air qui
     séparait les deux d'avant. Les côtés gardent 12 px. */
  padding-block: var(--e-8);
  grid-template-areas:
    "logo logo burger"
    "liens liens liens"
    "compte compte compte"
    "marque marque deconnexion";
}

.bo-aside-logo .bo-marque {
  display: none;
}

/* Le logo cesse d'être centré sur sa propre rangée : il partage la ligne avec le bouton de menu,
   et se colle à gauche comme le nom qu'il remplace. */
.bo-aside-logo .bo-logo {
  justify-self: start;
  margin-left: 0;
}

/* Le logo du cabinet, quand il en a déposé un — **il remplace alors le monogramme**, qui n'est
   qu'un substitut : une pastille portant l'initiale, affichée faute de mieux.

   ⚠️ **Sur sa propre rangée, hors du lien vers l'accueil** [DÉCIDÉ 2026-08-05]. Le placer *dans*
   ce lien aurait été possible sur desktop, mais pas sur mobile où il occupe une rangée entière
   au-dessus du nom et du bouton de menu. Plutôt que deux structures divergentes, une seule zone de
   grille sert aux deux formats. Le logo n'est donc **pas cliquable** : en faire un second lien
   vers la même page ferait annoncer deux fois « accueil » par un lecteur d'écran, pour un gain nul
   — le nom du cabinet, juste en dessous, est déjà ce lien. Son `alt` est vide pour la même raison :
   le nom est écrit en toutes lettres à côté, le répéter n'apprendrait rien.

   ⚠️ **Le cartouche blanc n'est pas décoratif.** Un logo est fourni tel quel, souvent en PNG à fond
   transparent : posé directement sur le bleu foncé du menu, un logo aux traits sombres devient
   illisible. Le fond blanc et le retrait qui l'entoure — le « liseré » — garantissent qu'il se
   détache quelles que soient ses couleurs. */
.bo-logo {
  grid-area: logo;
  justify-self: center;
  display: block;
  /* La borne de hauteur n'est décisive que parce que `base.css` laisse `height: auto` à toutes les
     images : une hauteur fixée l'emporterait sur un simple maximum. */
  max-height: var(--l-logo-h);
  /* ⚠️ `max-width: 100%` même sans borne de largeur voulue : c'est le filet contre l'ascenseur
     horizontal que tout ce menu s'emploie à éviter. Une bannière large déborderait sinon l'écran. */
  max-width: 100%;
  /* ⚠️ **Aucune marge sur mobile** [2026-08-06]. Les marges d'avant — 8 px en haut et en bas,
     24 px sur les côtés — servaient à aérer un logo qui occupait **sa propre rangée**, centré
     au-dessus du nom du cabinet. Le bandeau replié n'ayant plus qu'une rangée, le logo partage la
     ligne avec le bouton de menu : le retrait de 12 px du menu suffit, et tout ajout ne fait plus
     que regagner la hauteur qu'on venait précisément d'économiser. */
  /* La règle de dimensionnement : l'image se **réduit** jusqu'à tenir dans les deux bornes, en
     gardant ses proportions [DÉCIDÉ 2026-08-05]. Jamais rognée — une bannière portant le nom du
     cabinet y perdrait son texte, sans que personne ne comprenne pourquoi. */
  object-fit: contain;
  background: var(--surface);
  border-radius: var(--r-md);
  /* Épaisseur du liseré blanc : 8 → 4 → **2 px** [2026-08-05, réglé à l'écran]. Assez pour
     détacher le logo du fond bleu, assez peu pour ne pas se lire comme un cadre autour de lui. */
  padding: var(--e-2);
}

/* Aperçu d'une signature manuscrite — **sur blanc**, parce que c'est le fond de la convention où
   elle sera apposée. Sur le gris d'une carte, un tracé clair ou délavé paraîtrait lisible alors
   qu'il disparaîtrait sur le document ; l'aperçu doit montrer le rendu réel, pas un rendu flatteur.
   La bordure marque les limites de l'image : sans elle, on ne voit pas qu'une signature scannée
   arrive avec un large fond blanc autour du tracé. */
.signature-apercu {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: var(--e-16);
  margin-bottom: var(--e-16);
}

.signature-apercu img {
  max-height: var(--l-signature-h);
  max-width: 100%;
}

/* Aperçu du logo dans les paramètres, **sur le fond du menu** — pas sur le blanc de la carte.
   Un logo aux traits clairs paraîtrait irréprochable sur blanc et disparaîtrait à l'endroit où il
   compte vraiment. L'aperçu doit montrer le rendu réel, pas un rendu flatteur. */
.logo-apercu {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--primary);
  border-radius: var(--r-md);
  padding: var(--e-16);
  margin-bottom: var(--e-16);
}

.bo-marque {
  grid-area: marque;
  display: flex;
  align-items: center;
  gap: var(--e-8);
  min-width: 0;
  text-decoration: none;
  color: inherit;
}

/* Le nom du cabinet a le droit de passer a la ligne — c'est l'identite, la tronquer serait pire.
   `anywhere` ne sert que de garde-fou : un nom d'un seul mot tres long, sinon, elargirait tout. */
.bo-marque-nom {
  display: block;
  font-family: var(--serif);
  font-weight: 600;
  font-size: var(--t-16);
  color: var(--on-primary);
  overflow-wrap: anywhere;
}

/* Sans `min-width: 0`, un enfant de flex refuse de retrecir sous la largeur de son contenu — et
   ni la coupure de mot ni l'ellipsis ne s'appliquent. C'est LA cause de l'ascenseur horizontal. */
.bo-marque-identite,
.bo-compte-identite {
  min-width: 0;
}

.bo-marque-service {
  display: block;
  font-size: var(--t-12);
  color: var(--on-primary-attenue);
}

/* ⚠️ **Absente de la barre du haut sur mobile** [2026-08-04]. Elle y disputait la place au nom du
   cabinet, qui passait sur deux lignes — or c'est LUI qui porte l'anti-confusion (macro §2) : un
   avocat doit voir chez qui il travaille avant de voir son mode commercial. La pastille reste
   accessible, dans le menu deplie. */
.bo-encart {
  grid-area: encart;
  display: none;
}

/* Dernière ligne de l'encart : le lien de contact à gauche, la pastille de mode poussée à droite
   [2026-08-06].

   ⚠️ **Une seule règle pour les deux contextes**, sans média-requête ni variante `:checked`. Elle
   le peut parce que `.bo-encart` est `display: none` partout ailleurs : un enfant d'un bloc masqué
   n'a aucun rendu, donc rien à neutraliser. La disposition interne, elle, est la même en desktop
   et en mobile déplié — c'est le bloc qui change de place, pas son contenu.

   ⚠️ `align-self: stretch` est ce qui fait tout marcher : le parent est `align-items: flex-start`,
   donc cette ligne se serait rétractée sur la largeur de son contenu et `space-between` n'aurait
   rien eu à répartir — la pastille serait restée collée au lien au lieu d'aller au bord. */
.bo-encart-pied {
  align-self: stretch;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--e-8);
}

.bo-burger {
  grid-area: burger;
  /* ⚠️ **`end` et non le défaut** [2026-08-06]. Les colonnes d'une grille sont **globales à toutes
     ses rangées** : depuis que la déconnexion occupe la 3ᵉ colonne sur sa propre rangée, cette
     colonne est dimensionnée sur le bouton « Se déconnecter » (~130 px), pas sur le bouton de menu
     (44 px). Sans cet alignement, le burger se calait à gauche d'une colonne trop large et
     paraissait flotter loin du bord — alors que rien, dans sa propre règle, n'avait changé. */
  justify-self: end;
  display: grid;
  place-items: center;
  width: var(--cible-min);
  height: var(--cible-min);
  border-radius: var(--r-md);
  color: var(--on-primary);
  cursor: pointer;
  border: 1px solid color-mix(in srgb, var(--on-primary) 20%, transparent);
}

.bo-burger:hover {
  background: color-mix(in srgb, var(--on-primary) 8%, transparent);
}

/* Le focus se voit sur le BURGER alors qu'il vit sur la case : sans cela, naviguer au clavier
   ferait disparaître l'indication de focus au moment précis où elle sert. */
.bo-bascule:focus-visible ~ .bo-shell .bo-burger {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.bo-liens {
  grid-area: liens;
  display: none;
  flex-direction: column;
  gap: var(--e-4);
  margin-top: var(--e-8);
  padding-top: var(--e-8);
  border-top: 1px solid color-mix(in srgb, var(--on-primary) 14%, transparent);
}

/* Employée par des `<a>` ET par le bouton de déconnexion — d'où la remise à zéro des styles
   natifs du bouton : sans elle, il porterait le fond gris et la bordure du navigateur. */
.bo-lien {
  display: flex;
  align-items: center;
  gap: var(--e-8);
  width: 100%;
  min-height: var(--cible-min);
  padding: 0 var(--e-12);
  border: 0;
  border-radius: var(--r-md);
  background: none;
  font-family: inherit;
  font-size: var(--t-14);
  font-weight: 500;
  color: var(--on-primary-attenue);
  text-align: left;
  text-decoration: none;
  cursor: pointer;
}

.bo-lien:hover {
  background: color-mix(in srgb, var(--on-primary) 7%, transparent);
  color: var(--on-primary);
}

/* ⚠️ La rubrique courante est marquée par `aria-current`, pas par une classe : l'attribut est
   requis pour les lecteurs d'écran de toute façon, et deux marqueurs finiraient par diverger. */
.bo-lien[aria-current] {
  background: color-mix(in srgb, var(--on-primary) 12%, transparent);
  color: var(--on-primary);
}

/* ⚠️ **Écart assumé avec la maquette : elle n'a aucune déconnexion.** Un back-office de cabinet
   tourne sur des postes partagés — ne pas pouvoir en sortir n'est pas un oubli d'affichage, c'est
   un défaut de sécurité. D'où ce pied qui regroupe le compte ET la sortie. */
.bo-pied {
  grid-area: compte;
  display: none;
  flex-direction: column;
  margin-top: var(--e-8);
  border-top: 1px solid color-mix(in srgb, var(--on-primary) 14%, transparent);
}

/* La déconnexion a quitté `.bo-pied` pour devenir un élément de grille à part entière : c'est ce
   qui lui permet de partager sa ligne avec la marque (voir `base_bo.html`). Masquée avec le reste
   du menu tant qu'il est replié. */
.bo-deconnexion {
  grid-area: deconnexion;
  display: none;
  justify-self: end;
}

/* ⚠️ **Un liseré, pas un aplat** [2026-08-06]. La déconnexion doit se distinguer des rubriques sans
   se donner l'importance d'une action principale : elle partage sa ligne avec la marque, et un
   bouton plein y ferait le poids d'un « Valider ». `currentColor` reprend exactement la couleur du
   texte — un liseré d'une autre teinte aurait demandé un jeton de plus pour un gain nul. */
.bo-lien-sortie {
  width: auto;
  border: 1px solid currentColor;
}

.bo-compte {
  display: flex;
  align-items: center;
  gap: var(--e-12);
  padding: var(--e-12);
  text-decoration: none;
}

.bo-compte:hover {
  background: color-mix(in srgb, var(--on-primary) 7%, transparent);
}

.bo-avatar {
  width: var(--e-32);
  height: var(--e-32);
  border-radius: 50%;
  background: var(--accent);
  color: var(--on-accent);
  display: grid;
  place-items: center;
  font-weight: 700;
  font-size: var(--t-13);
  flex: none;
}

/* ⚠️ Tronquee, contrairement au nom du cabinet : tant que prenom et nom ne sont pas renseignes,
   ce libelle est une ADRESSE ELECTRONIQUE. La laisser passer a la ligne donnait deux lignes
   illisibles ; la laisser deborder creait l'ascenseur. L'integrale reste au survol (`title`). */
.bo-compte-nom {
  display: block;
  font-size: var(--t-13);
  color: var(--on-primary);
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.bo-compte-role {
  display: block;
  font-size: var(--t-12);
  color: var(--on-primary-attenue);
}

/* ⚠️ **Écart assumé avec la maquette.** Elle masquait ces deux liens sur mobile, ce qui rendait
   « Contactez-nous » **inatteignable au téléphone** — or B.2.8 l'ouvre à *tous* les comptes, et
   c'est le seul canal de support du cabinet. Ils réapparaissent donc quand le menu est déplié,
   l'encart prenant alors sa propre rangée sous les rubriques. Repli fermé : seule la pastille de
   mode reste visible, comme dans la maquette. */
.bo-sous-lien {
  display: none;
}

.bo-bascule:checked ~ .bo-shell .bo-liens,
.bo-bascule:checked ~ .bo-shell .bo-pied,
.bo-bascule:checked ~ .bo-shell .bo-deconnexion {
  display: flex;
}

.bo-bascule:checked ~ .bo-shell .bo-aside {
  grid-template-areas:
    "logo logo logo"
    "marque marque burger"
    "liens liens liens"
    "encart encart encart"
    "compte compte compte"
    "deconnexion deconnexion deconnexion";
}

/* ⚠️ **Le bandeau du haut ne bouge pas quand le menu s'ouvre** [DÉCIDÉ 2026-08-06]. Déplier est
   déjà un changement suffisant : voir en plus la rangée du haut se réorganiser — le logo se
   recentrer, un nom apparaître — donne l'impression que la page a changé, pas qu'un panneau s'est
   ouvert. Logo et bouton de menu restent donc exactement où ils étaient.

   La marque réapparaît en revanche **en bas**, sur la ligne de la déconnexion : c'est ce qui rend
   acceptable son absence du bandeau replié, puisque le lien vers l'accueil redevient atteignable
   dès l'ouverture. */
.bo-bascule:checked ~ .bo-shell .bo-aside-logo {
  grid-template-areas:
    "logo logo burger"
    "liens liens liens"
    "encart encart encart"
    "compte compte compte"
    "marque marque deconnexion";
}

.bo-bascule:checked ~ .bo-shell .bo-aside-logo .bo-marque {
  display: flex;
  justify-self: start;
  padding: var(--e-8) var(--e-12);
}

.bo-bascule:checked ~ .bo-shell .bo-encart {
  justify-self: stretch;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--e-8);
  margin-top: var(--e-8);
  padding-top: var(--e-8);
  border-top: 1px solid color-mix(in srgb, var(--on-primary) 14%, transparent);
}

.bo-bascule:checked ~ .bo-shell .bo-sous-lien {
  display: inline-flex;
  font-size: var(--t-13);
  font-weight: 600;
  color: var(--on-primary);
  text-decoration: none;
}

/* ⚠️ `min-width: 0` n'est pas une precaution : une piste `1fr` prend par defaut la largeur de son
   CONTENU s'il deborde (`min-width: auto`). Un tableau large, une URL non coupee, et la grille
   entiere s'elargit — d'ou l'ascenseur horizontal qui traversait toute la page. */
.bo-principal {
  flex: 1;
  min-width: 0;
  padding-block: var(--e-24);
}

/* ⚠️ **Pas de `margin: auto`**, contrairement a `.container`. Sur un ecran large, le centrage
   decollait le titre du menu et laissait un vide a gauche — alors qu'un back-office se lit en
   partant du menu. Le contenu reste donc ancre a gauche ; c'est aussi ce que reclame le tableau
   de dossiers, qui veut toute la largeur disponible. */
.bo-contenu {
  min-width: 0;
  padding-inline: clamp(var(--e-16), 3vw, var(--e-32));
}

@media (min-width: 900px) {
  .bo-shell {
    display: grid;
    grid-template-columns: var(--l-menu-bo) 1fr;
  }

  /* ⚠️ `sticky` + `100dvh` : le menu reste **collé à la fenêtre** pendant que la liste défile.
     Sans cela, le bloc « abonnement + compte » descendrait avec la page et quitterait l'écran —
     or c'est précisément un bloc qu'on veut atteindre à tout moment. */
  .bo-aside {
    position: sticky;
    top: 0;
    height: 100dvh;
    /* ⚠️ **Filet, pas comportement attendu.** Le menu est dimensionne pour tenir sans defilement
       (voir les compactions ci-dessous) ; `auto` ne se declenche donc que sur une fenetre
       anormalement basse — ou il vaut mieux un ascenseur que de perdre la deconnexion. */
    overflow-y: auto;
    grid-template-columns: 1fr;
    grid-template-rows: auto auto auto 1fr auto auto auto;
    grid-template-areas:
      "logo"
      "marque"
      "liens"
      "vide"
      "encart"
      "compte"
      "deconnexion";
    align-items: stretch;
    /* Retrait resserré [2026-08-04] : 8 px au lieu de 12.
       ⚠️ **Symétrique — troisième et dernier état** [2026-08-05]. L'histoire vaut d'être gardée :
       symétrique, puis asymétrique (8 à gauche, 12 à droite) au motif que le fond de la rubrique
       courante venait toucher la frontière avec le contenu clair, puis symétrique à nouveau après
       arbitrage à l'écran. La leçon n'est pas la valeur retenue, c'est que **cet écart-là se juge
       sur l'écran et non dans le raisonnement** : les deux argumentations étaient correctes, seul
       le rendu a tranché.
       ⚠️ Ces deux lignes écrasent le `padding` de la règle de base : c'est ici, et non là-bas, que
       se règle l'apparence du menu sur un écran de bureau. */
    padding-block: var(--e-16);
    padding-inline: var(--e-8);
    row-gap: var(--e-4);
  }

  /* ⚠️ La borne de **largeur** ne s'applique qu'ici. Sur mobile le menu occupe toute la largeur de
     l'écran : la brider à 220 px y réduirait le logo sans raison. Sur desktop, la colonne fait
     238 px — sans cette borne, un logo large viendrait toucher ses deux bords. */
  .bo-logo {
    max-height: var(--l-logo-h-large);
    max-width: var(--l-logo-l);
    margin-bottom: var(--e-8);
  }

  .bo-marque {
    padding: 0 var(--e-8) var(--e-12);
    border-bottom: 1px solid color-mix(in srgb, var(--on-primary) 12%, transparent);
  }

  /* ⚠️ **Le bandeau à une rangée est un réglage MOBILE, et il faut le dire ici** [2026-08-06].
     `.bo-aside-logo .bo-marque` porte deux classes : sans ces contre-règles de même spécificité,
     il masquerait aussi le nom du cabinet **sur desktop**, où la colonne est dépliée en permanence
     et où logo et nom ne se disputent aucune hauteur. Le piège est classique — une règle écrite
     pour un format qui déborde sur l'autre parce qu'elle pèse plus lourd. */
  .bo-aside-logo .bo-marque {
    display: flex;
    justify-self: stretch;
  }

  .bo-aside-logo .bo-logo {
    justify-self: center;
  }

  /* Le menu est déplié en permanence : la déconnexion est toujours visible, et reprend la pleine
     largeur sous le compte — la ligne partagée avec la marque n'a de sens que sur mobile, où la
     hauteur est comptée. */
  .bo-deconnexion {
    display: flex;
    justify-self: stretch;
  }

  .bo-lien-sortie {
    width: 100%;
  }

  /* Le retrait resserré du bandeau mobile ne vaut pas ici : la colonne garde ses 16 px. */
  .bo-aside-logo {
    padding-block: var(--e-16);
  }

  /* Plus de burger : le panneau est déplié en permanence. */
  .bo-burger {
    display: none;
  }

  .bo-liens,
  .bo-pied {
    display: flex;
  }

  .bo-liens {
    margin-top: var(--e-8);
    padding-top: 0;
    border-top: 0;
  }

  /* ⚠️ 44 px est une **cible tactile** : au doigt, sur mobile. A la souris, elle ne sert a rien et
     ne fait qu'ajouter 30 px de hauteur au menu — de quoi declencher l'ascenseur que ces reglages
     existent pour eviter. */
  .bo-lien {
    min-height: var(--e-40);
  }

  .bo-lien[aria-current] {
    box-shadow: inset 3px 0 0 var(--accent);
  }

  .bo-compte {
    padding: var(--e-8) var(--e-12);
  }

  .bo-encart {
    justify-self: stretch;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--e-8);
    background: color-mix(in srgb, var(--on-primary) 7%, transparent);
    border: 1px solid color-mix(in srgb, var(--on-primary) 14%, transparent);
    border-radius: var(--r-md);
    padding: var(--e-8) var(--e-12);
    margin-bottom: var(--e-8);
  }

  .bo-sous-lien {
    display: inline-flex;
    font-size: var(--t-13);
    font-weight: 600;
    color: var(--on-primary);
    text-decoration: none;
  }

  .bo-sous-lien:hover {
    color: var(--accent);
  }
}

/* --- Back-office : liste de dossiers (C7.2) — distillée de la maquette « Dossiers » ----------

   ⚠️ **Un seul balisage, deux rendus.** Mobile : chaque ligne est une carte empilée. Desktop : la
   même ligne devient une rangée de grille, et les libellés de champ (`.bo-cl`) s'effacent parce
   que l'en-tête de colonnes les remplace. Deux balisages auraient divergé au premier champ
   ajouté — et c'est le mobile, moins regardé, qui aurait décroché.

   ⚠️ `minmax(0, …fr)` et non `…fr` : une piste `1fr` vaut `min-width: auto`, donc refuse de
   descendre sous la largeur de son contenu. Un nom de client un peu long élargirait alors le
   tableau entier — la même faute que celle corrigée sur le menu. */

.bo-filtres {
  display: flex;
  align-items: center;
  gap: var(--e-8);
  flex-wrap: wrap;
  margin-bottom: var(--e-12);
}

.bo-filtre {
  width: auto;
  max-width: 100%;
  min-height: var(--e-40);
  padding: var(--e-8) var(--e-12);
  font-size: var(--t-14);
}

.bo-tri {
  margin: 0;
}

.bo-recherche {
  margin-bottom: var(--e-12);
}

/* Le tableau desktop ne se comprime pas indéfiniment : sous sa largeur utile, on défile
   HORIZONTALEMENT DANS LE TABLEAU plutôt que de tasser sept colonnes en bouillie. */
.bo-tscroll {
  overflow-x: auto;
}

.bo-rows {
  /* Client · Affaire · Traitant · Reçu le · Statut · action.
     ⚠️ Le STATUT est en dernier avant l'action [2026-08-04] : c'est lui qui commande le geste
     suivant, et le lire juste avant le bouton évite l'aller-retour de l'œil d'un bout à l'autre
     de la ligne. « Expire le » a été retiré — l'échéance se lit au détail, pas en balayage. */
  --bo-cols: minmax(0, 1.6fr) minmax(0, 1fr) minmax(0, 0.9fr) minmax(0, 0.75fr)
    minmax(0, 1.35fr) 150px;
  display: flex;
  flex-direction: column;
  gap: var(--e-8);
}

/* Variante « comptes » (B.2.4) : **mêmes rangées**, colonnes propres à cet écran.
   Nom · Adresse · Profil · Dernière connexion · Dossiers · actions.
   ⚠️ Une variante d'une classe de largeur, pas un second composant : le tableau desktop, les
   tuiles mobiles et le défilement horizontal restent ceux de la liste des dossiers. */
/* Même composant, colonnes propres aux comptes.
   ⚠️ **Toute la largeur va aux données** [2026-08-05]. La colonne d'actions réservait 260 px pour
   trois boutons empilés ; il n'en reste qu'un, et ces 110 px de vide se payaient en troncatures
   dans toutes les autres colonnes — « Me Bastien Gala… », « Avocat · ad… », « 05/08/2026 à 1… ».
   Elle est ramenée à la largeur du bouton (150 px) et le reste est redistribué : nom et adresse
   d'abord, puis profil et date, qui doivent tenir « Avocat · administrateur » et une date horodatée
   en entier. `minmax(0, …)` sur chacune, sans quoi une valeur longue refuserait de se réduire et
   déborderait la grille au lieu de s'abréger. */
.bo-rows-comptes {
  --bo-cols: minmax(0, 1.5fr) minmax(0, 1.7fr) minmax(0, 1.1fr) minmax(0, 1.1fr)
    minmax(0, 0.9fr) 150px;
}

/* --- Page « Guide » (C6.8) --------------------------------------------------------------------

   ⚠️ **Le titre d'une ligne se replie au lieu d'être coupé.** `.bo-who` tronque à l'ellipse, ce qui
   convient à un nom de client dans une liste qu'on balaie — pas à l'intitulé d'un message dans une
   page d'aide, où « Convention envoyée pour sig… » oblige à survoler pour lire ce que la colonne est
   censée dire. Variante, pas exception : les autres listes gardent l'ellipse. */
.bo-who-long {
  white-space: normal;
  overflow: visible;
  text-overflow: clip;
}

/* Le cycle de vie d'un dossier — une suite d'étapes, chacune portant les messages qui en partent.
   ⚠️ Le filet vertical n'est pas décoratif : c'est lui qui dit « puis », et qui distingue une suite
   d'étapes d'une liste d'options. */
.guide-cycle {
  list-style: none;
  margin: 0;
  padding: 0 0 0 var(--e-16);
  border-inline-start: 2px solid var(--line);
}

.guide-etape {
  position: relative;
  padding-block: var(--e-8);
  max-width: none;
}

.guide-etape + .guide-etape {
  margin-block-start: var(--e-16);
}

/* Une fin de parcours qui n'envoie rien : atténuée, pour qu'elle se distingue du chemin nominal
   sans disparaître — c'est justement l'absence de message qu'on vient y lire. */
.guide-etape-muette .label {
  color: var(--muted);
}

/* L'aperçu d'un message : du texte d'e-mail, tel qu'il part.
   ⚠️ `pre-wrap` et non `pre` : un corps d'e-mail porte des lignes longues, et un ascenseur
   horizontal dans une fenêtre modale est toujours un défaut. */
.guide-apercu {
  white-space: pre-wrap;
  font-family: var(--sans);
  font-size: var(--t-13);
  background: var(--ground);
  border-radius: var(--r-md);
  padding: var(--e-16);
  margin: 0 0 var(--e-16);
  max-height: 50vh;
  overflow-y: auto;
}

/* Variantes de la page « Guide » (C6.8) : **mêmes rangées**, colonnes propres à ces deux tableaux.
   ⚠️ Le premier a cinq colonnes — c'est le plus large du produit — parce qu'il répond à cinq
   questions qu'on se pose ensemble : quel message, à qui, quand, avec quel lien, et copié ou non.
   Les séparer en deux tableaux obligerait à croiser du regard, ce qui est exactement la difficulté
   que cette page existe pour supprimer. La colonne « Quand » est la plus large : elle porte une
   phrase, pas un mot. */
.bo-rows-guide {
  --bo-cols: minmax(0, 1.2fr) minmax(0, 0.7fr) minmax(0, 1.8fr) minmax(0, 0.9fr)
    minmax(0, 0.8fr) 110px;
}

.bo-rows-reglages {
  --bo-cols: minmax(0, 1.6fr) minmax(0, 1fr);
}

/* Les documents légaux : le titre — cliquable quand le document est en ligne — et ce qu'il dit.
   ⚠️ La seconde colonne est la plus large : c'est une phrase, et c'est elle qu'on lit pour
   savoir lequel des documents on cherche. */
.bo-rows-documents {
  --bo-cols: minmax(0, 1fr) minmax(0, 1.8fr);
}

/* Variante « journal des envois » (C6.4) : **mêmes rangées**, quatre colonnes.
   ⚠️ La dernière est la plus large de toutes, ce qui n'est le cas d'aucune autre liste — elle porte
   l'état, la cause d'un échec en toutes lettres et le bouton de reprise, empilés. La rétrécir
   couperait précisément le message d'erreur, c'est-à-dire la seule information qui dise s'il faut
   réessayer ou corriger l'adresse. */
.bo-rows-envois {
  --bo-cols: minmax(0, 1.3fr) minmax(0, 1.4fr) minmax(0, 0.9fr) minmax(0, 1.6fr);
}

/* Sur mobile, l'en-tête de colonnes n'a pas de sens : il n'y a pas de colonnes. */
.bo-rhead {
  display: none;
}

.bo-row {
  display: flex;
  flex-direction: column;
  gap: var(--e-8);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: var(--e-12) var(--e-16);
  /* Repère pour le lien étendu de `.btn-ouvrir` — voir ce composant. */
  position: relative;
}

/* ⚠️ **Une seule ligne, tronquée** [2026-08-04]. Toutes les rangées doivent avoir la MÊME
   hauteur : un nom qui passe à la ligne — « Menuiseries du Languedoc et de la Vallée de
   l'Hérault » — ferait une rangée deux fois plus haute que ses voisines, et un tableau qui
   ondule se balaie mal. Le nom entier reste au survol (`title`). */
.bo-who {
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.bo-fld {
  font-size: var(--t-13);
  color: var(--muted);
  /* Chiffres à chasse fixe : sans cela, une colonne de dates ne s'aligne pas verticalement. */
  font-variant-numeric: tabular-nums;
}

.bo-cl {
  color: var(--muted);
  font-weight: 600;
  margin-right: var(--e-4);
}

.bo-act {
  margin-top: var(--e-4);
}

/* Bouton d'ouverture d'une rangée — **blanc au repos, plein au survol**.
   Au repos il se pose sur la surface blanche de la rangée : discret, il ne dispute pas la lecture
   des données. Au survol de la rangée il s'inverse en bleu plein — c'est ce qui désigne la rangée
   survolée comme la cible du prochain clic, là où l'ancien lien souligné disparaissait dans le
   lavis de survol (fond de survol et fond de bouton fantôme partagent le même jeton). */
.btn-ouvrir {
  display: inline-flex;
  align-items: center;
  gap: var(--e-8);
  padding: var(--e-8) var(--e-12);
  background: var(--surface);
  color: var(--primary);
  border: 1.5px solid var(--line);
  border-radius: var(--r-md);
  font-family: var(--sans);
  font-size: var(--t-13);
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
}

.bo-row:hover .btn-ouvrir,
.btn-ouvrir:hover,
.btn-ouvrir:focus-visible {
  background: var(--primary);
  color: var(--on-primary);
  border-color: var(--primary);
}

/* ⚠️ **Toute la rangée est cliquable** [DÉCIDÉ 2026-08-05] — par ce pseudo-élément, qui étire la
   zone cliquable du lien à la rangée entière. **Pas de JavaScript** : la CSP stricte interdit les
   gestionnaires en ligne, et un `onclick` externe perdrait ce qu'un vrai lien donne gratuitement —
   clic droit, ouverture en nouvel onglet, aperçu de l'URL, tabulation au clavier, lecteur d'écran.
   Contrepartie assumée : le texte de la rangée n'est plus sélectionnable à la souris, le
   pseudo-élément le recouvrant. C'est le compromis habituel des listes cliquables ; les valeurs à
   recopier se prennent sur la page de détail. */
.btn-ouvrir::after {
  content: "";
  position: absolute;
  inset: 0;
}

@media (min-width: 900px) {
  .bo-rows {
    display: block;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    overflow: hidden;
    min-width: 860px;
  }

  .bo-rhead {
    display: grid;
    grid-template-columns: var(--bo-cols);
    gap: var(--e-12);
    align-items: center;
    padding: var(--e-12) var(--e-16);
    background: var(--ground);
    border-bottom: 1px solid var(--line);
    font-size: var(--t-12);
    font-weight: 700;
    color: var(--muted);
  }

  .bo-row {
    display: grid;
    grid-template-columns: var(--bo-cols);
    gap: var(--e-12);
    align-items: center;
    padding: var(--e-12) var(--e-16);
    border: 0;
    border-top: 1px solid var(--line);
    border-radius: 0;
  }

  /* ⚠️ Le complément de `.bo-who` : sur desktop, AUCUNE cellule ne passe à la ligne, sinon la
     rangée s'étire et l'alignement des colonnes se perd d'une ligne à l'autre. */
  .bo-row .bo-fld {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .bo-row:first-of-type {
    border-top: 0;
  }

  .bo-row:hover {
    background: var(--primary-wash);
  }

  /* Les en-têtes de colonnes remplacent les libellés de champ. */
  .bo-cl {
    display: none;
  }

  .bo-act {
    margin-top: 0;
    text-align: right;
  }
}

/* --- Back-office : détail d'un dossier (C7.3) ------------------------------------------------
   2 classes. Le reste réutilise `.card`, `.badge-*`, `.btn-danger`, `.cluster`, `.eyebrow`. */

.bo-entete {
  display: flex;
  align-items: center;
  gap: var(--e-12);
  flex-wrap: wrap;
}

/* Libellé / valeur en deux colonnes sur large, empilés sur mobile.
   ⚠️ Une vraie `<dl>` : ces paires SONT des définitions, et un lecteur d'écran annonce alors le
   libellé avec sa valeur. Deux `<span>` auraient le même rendu et ne diraient rien. */
.bo-paires {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--e-8) var(--e-16);
  margin: 0;
}

.bo-paires dt {
  color: var(--muted);
  font-size: var(--t-13);
}

.bo-paires dd {
  margin: 0 0 var(--e-8);
  font-size: var(--t-13);
  /* Une adresse ou une raison sociale longue se coupe plutôt que d'élargir sa colonne. */
  overflow-wrap: anywhere;
}

@media (min-width: 680px) {
  .bo-paires {
    grid-template-columns: minmax(0, 13rem) minmax(0, 1fr);
  }

  .bo-paires dd {
    margin-bottom: 0;
  }
}

/* ⚠️ **Deux paires par ligne** à partir du desktop : une fiche de client compte une douzaine de
   champs, et sur un large écran une seule colonne les étire sur toute la largeur — l'œil parcourt
   alors une ligne entière pour relier « Profession » à sa valeur.

   ⚠️ Remplissage **ligne par ligne**, contrairement à la V1 qui remplit colonne par colonne. Un
   `columns: 2` aurait donné son ordre exact, mais il peut couper un libellé de sa valeur en bas de
   colonne — un défaut qui n'apparaît qu'à certaines hauteurs de fenêtre, donc jamais au moment où
   on le cherche. Quatre pistes de grille rendent la paire indissociable par construction. */
@media (min-width: 900px) {
  .bo-paires {
    grid-template-columns:
      minmax(0, 11rem) minmax(0, 1fr)
      minmax(0, 11rem) minmax(0, 1fr);
    column-gap: var(--e-24);
  }
}

/* --- Back-office : barre d'actions et onglets d'un dossier (V1) ------------------------------
   4 classes. Le reste réutilise `.btn-*`, `.badge-*`, `.card`, `.bo-paires`. */

/* Sur mobile la barre s'empile ; à partir de 680 px elle tient sur une ligne, actions à droite. */
/* ⚠️ **Le titre d'un écran de back-office ne s'affiche QUE sur mobile** [DÉCIDÉ 2026-08-05].
   Sur desktop, le menu latéral affiche en permanence l'écran actif : le titre le répétait mot pour
   mot, à quelques centimètres de distance. Sur mobile ce menu se replie en bandeau — le titre
   redevient alors la seule indication de l'endroit où l'on se trouve.

   ⚠️ **Classe distincte de `.etat-titre`, et ce n'est pas un doublon.** `.etat-titre` sert aussi
   aux pages 404 et 500, à la façade publique et aux écrans de connexion : masquer *cette* classe
   sur desktop aurait effacé le titre d'une page d'erreur, où il est le seul texte utile.

   ⚠️ **ÉCART D'ACCESSIBILITÉ ASSUMÉ — blanc sur accent à 16 px : 3,53 pour 1.**
   Le seuil est de 4,5 pour du texte courant ; celui de 3, plus permissif, ne vaut qu'à partir de
   18,66 px en gras. À 20 px ce bandeau était conforme ; à 16 px il ne l'est plus.
   **Signalé et arbitré le 2026-08-05 : la teinte et la taille sont maintenues en l'état.** Ce n'est
   donc pas une dette à traiter mais un choix, à ne rouvrir que si une revue d'accessibilité est
   menée. Le correctif serait alors immédiat et ne changerait pas la teinte perçue : `--accent-h`
   (#8f6d30), déjà dans les jetons comme état de survol de l'accent, donne **4,77 pour 1**. */
.bo-titre {
  background: var(--accent);
  color: var(--on-primary);
  font-size: var(--t-16);
  font-weight: 700;
  text-align: center;
  padding: var(--e-12) var(--e-16);
  /* Arrondi **en bas seulement** : le haut reste droit pour se souder au menu qui le précède. */
  border-radius: 0 0 var(--r-lg) var(--r-lg);
  /* Le bandeau **déborde** les retraits de ses parents pour toucher les deux bords de l'écran et
     venir se coller au menu : en haut le retrait vertical de `.bo-principal`, sur les côtés le
     retrait horizontal de `.bo-contenu`. Les reprendre en marge négative est ce qui évite de
     déplacer ces retraits vers chaque écran — ils profitent à tout le reste du contenu. */
  margin: calc(-1 * var(--e-24)) calc(-1 * clamp(var(--e-16), 3vw, var(--e-32))) var(--e-24);
}

/* Le menu latéral reprend son rôle : le titre s'efface. Il reste dans le document — un écran sans
   `<h1>` perd sa structure pour un lecteur d'écran, qui ne lit pas le menu à sa place. */
@media (min-width: 900px) {
  .bo-titre {
    display: none;
  }
}

.bo-barre {
  display: flex;
  align-items: center;
  gap: var(--e-12);
  flex-wrap: wrap;
  margin-bottom: var(--e-16);
}

.bo-barre-titre {
  font-size: var(--t-24);
  margin: 0;
}

.bo-barre-actions {
  display: flex;
  align-items: center;
  gap: var(--e-8);
  flex-wrap: wrap;
  margin-left: auto;
}

/* ⚠️ Onglets DÉFILANTS horizontalement sur mobile plutôt que repliés : cinq onglets courts se
   parcourent au pouce, alors qu'un menu déroulant cacherait la structure — or c'est justement
   elle qu'on veut lire d'un coup d'œil en arrivant sur un dossier. */
.bo-onglets {
  display: flex;
  gap: var(--e-4);
  overflow-x: auto;
  border-bottom: 1px solid var(--line);
  margin-bottom: var(--e-20);
}

.bo-onglet {
  display: inline-flex;
  align-items: center;
  min-height: var(--cible-min);
  padding: 0 var(--e-12);
  font-size: var(--t-14);
  font-weight: 600;
  color: var(--muted);
  text-decoration: none;
  white-space: nowrap;
  border-bottom: 2px solid transparent;
}

.bo-onglet:hover {
  color: var(--ink);
}

/* Même parti pris que le menu de gauche : `aria-current` porte l'état, pas une classe de plus. */
.bo-onglet[aria-current] {
  color: var(--primary);
  border-bottom-color: var(--primary);
}

/* ⚠️ **Bandeau gris, comme en V1**, et ce n'est pas décoratif : il sépare l'ENTÊTE de la zone de
   son CONTENU. Sans lui, le titre et le bouton « Modifier » flottent au-dessus des données et l'œil
   ne sait plus où commence le bloc — un écran de sept cartes devient une bouillie.
   Les marges négatives compensent le padding de `.card` : le bandeau doit toucher les bords. */
.bo-carte-entete {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--e-12);
  margin: calc(-1 * var(--e-20)) calc(-1 * var(--e-20)) var(--e-20);
  padding: var(--e-12) var(--e-20);
  background: var(--ground);
  border-bottom: 1px solid var(--line);
  border-radius: var(--r-lg) var(--r-lg) 0 0;
}

/* ⚠️ Le rythme entre blocs, décidé une fois ici : sept cartes collées se lisent comme un seul pavé.
   Sur la marge du bas plutôt que le `gap` d'un conteneur — les cartes sont rendues par des branches
   `{% if %}` distinctes, elles n'ont pas de parent commun sur lequel poser un `gap`. */
.bo-carte {
  margin-bottom: var(--e-16);
}

/* ⚠️ **Une carte qui suit un formulaire respire davantage.** Elle se retrouve sinon collée aux
   boutons « Enregistrer / Annuler », et se lit comme faisant partie de ce qu'ils valident — alors
   qu'elle porte au contraire une action **autonome**, avec son propre bouton. L'écart dit qu'on
   change de sujet. Le cas se reproduit partout où un dépôt de fichier suit des champs de texte
   (logo, signature), d'où une règle plutôt qu'une marge posée écran par écran. */
form + .bo-carte {
  margin-top: var(--e-32);
}

/* --- pied d'un formulaire de parties -----------------------------------------------------------
   Deux groupes d'actions **qui n'ont pas la même conséquence**, donc deux ancrages : à gauche ce
   qui clôt la saisie (Enregistrer, Annuler), à droite ce qui la prolonge (Ajouter une partie).

   ⚠️ Ce n'est pas une préférence esthétique. Dans une grappe unique, « + Ajouter un client » se
   trouvait collé à « Enregistrer » : deux boutons voisins dont l'un valide et l'autre rallonge le
   formulaire. Les séparer aux deux extrémités rend la confusion impossible au clic comme à l'œil.

   Le `<span></span>` vide du gabarit en lecture occupe la place de gauche : `space-between` a
   besoin de deux enfants pour pousser le second à droite.

   Mobile d'abord : empilé sous 560 px, où deux groupes côte à côte deviendraient illisibles. */
.bo-actions-formulaire {
  display: flex;
  flex-direction: column;
  gap: var(--e-12);
}

@media (min-width: 560px) {
  .bo-actions-formulaire {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
  }
}

/* --- Pop-up de refus (CSS pur) ---------------------------------------------------------------
   ⚠️ `<dialog>` aurait été plus juste sémantiquement, mais son ouverture passe par `showModal()`,
   donc par du JavaScript — que la CSP stricte bloquerait SANS RIEN DIRE. Une case à cocher pilote
   donc l'affichage, comme le burger du menu. */
.bo-modale {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 10;
  background: color-mix(in srgb, var(--ink) 55%, transparent);
  padding: var(--e-16);
  overflow-y: auto;
}

/* ⚠️ **`+` et non `~`** [corrigé le 2026-08-28]. Le combinateur de frères **généraux** désigne
   *tous* les frères suivants : avec une seule fenêtre par page — le cas du dossier — la différence
   était invisible, et la règle a vécu ainsi. La page « Guide » en aligne **quinze** en enfilade, et
   cocher la première ouvrait la première **et les quatorze suivantes**, empilées.

   Le combinateur **adjacent** ne désigne que le frère immédiat. Les trois usages du produit
   respectent déjà cette forme — bascule, puis fenêtre — et c'est désormais ce que la règle exige au
   lieu de le supposer. */
.bo-bascule-modale:checked + .bo-modale {
  display: grid;
  place-items: center;
}

.bo-modale-boite {
  width: 100%;
  max-width: var(--l-formulaire);
  background: var(--surface);
  border-radius: var(--r-lg);
  padding: var(--e-24);
}

/* Intitulé d'un sous-groupe de champs dans une fiche de dossier (C7.3).
   ⚠️ Discret à dessein : il structure la lecture sans concurrencer le titre de la carte. Le premier
   n'a pas de marge haute — il touche déjà le bandeau d'entête. */
.bo-groupe {
  font-size: var(--t-12);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  margin: var(--e-20) 0 var(--e-8);
}

.bo-groupe:first-of-type {
  margin-top: 0;
}

/* --- grille à deux colonnes (réglages courts) --------------------------------
   ⚠️ Réservée aux champs **brefs** — quatre nombres, ici. Sur des textes longs, deux colonnes
   couperaient la lecture en deux et rallongeraient chaque ligne au lieu de la raccourcir.
   Une seule colonne sous 680 px : à cette largeur, deux champs côte à côte ne tiennent pas. */
.bo-grille-2 {
  display: grid;
  /* ⚠️ **Les deux gouttières, pas seulement l'horizontale.** Un `gap: 0 …` laissait les lignes se
     toucher : la note d'un champ collait au libellé du suivant, et l'on ne savait plus à qui elle
     se rapportait. */
  gap: var(--e-24);
}

@media (min-width: 680px) {
  .bo-grille-2 {
    grid-template-columns: 1fr 1fr;
  }
}

/* --- fenêtre modale (back-office) --------------------------------------------
   Confirmation d'une action conséquente : elle **dit ce qui va se passer** avant de le faire.

   ⚠️ **Un `<dialog>` natif**, et c'est ce qui la rend accessible sans effort : fermeture par Échap,
   focus piégé à l'intérieur puis restitué au bouton d'origine, inertie du reste de la page. Une
   boîte maison n'obtient chacun de ces points qu'au prix d'un travail réel — et les oublie
   silencieusement.

   ⚠️ **Centrée sur la ZONE DE CONTENU, pas sur l'écran.** Un back-office se lit à droite du menu ;
   une fenêtre centrée sur la fenêtre du navigateur paraît décalée à gauche, chevauchant le menu
   qu'elle recouvre à moitié. D'où le décalage de `--l-menu-bo`, la largeur de ce menu. */
.modale {
  --modale-largeur: min(33vw, 560px);

  width: max(var(--modale-largeur), 320px);
  max-width: calc(100vw - var(--e-32));
  padding: 0;
  border: 0;
  border-radius: var(--r-lg);
  background: var(--surface);
  box-shadow: var(--ombre-carte);
  color: var(--ink);
  /* Le dialogue natif se centre déjà dans la fenêtre ; on ne corrige que l'axe horizontal, et
     seulement quand le menu est présent (voir la media query plus bas). */
  margin: auto;
}

.modale::backdrop {
  background: color-mix(in srgb, var(--ink) 45%, transparent);
}

/* ⚠️ **Bandeau marine, comme le menu** : la fenêtre appartient visiblement à l'outil de travail,
   pas à la page qu'elle recouvre. Même couleur, même police que `.bo-aside`. */
.modale-entete {
  padding: var(--e-16) var(--e-20);
  background: var(--primary);
  border-radius: var(--r-lg) var(--r-lg) 0 0;
}

.modale-titre {
  margin: 0;
  font-family: var(--sans);
  font-size: var(--t-16);
  font-weight: 600;
  color: var(--on-primary);
}

.modale-corps {
  padding: var(--e-20);
  font-size: var(--t-15);
  line-height: 1.5;
}

.modale-corps p {
  margin: 0;
  max-width: none;
}

.modale-actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--e-8);
  padding: 0 var(--e-20) var(--e-20);
}

@media (min-width: 900px) {
  .modale {
    /* Centrage sur la zone de contenu : on saute le menu, puis on centre dans ce qui reste. */
    margin-inline-start: calc(
      var(--l-menu-bo) + (100vw - var(--l-menu-bo) - max(var(--modale-largeur), 320px)) / 2
    );
    margin-inline-end: 0;
  }
}

/* --- action dans une ligne de tableau ----------------------------------------
   ⚠️ **Jamais de fond.** `.bo-row:hover` teinte la ligne avec `--primary-wash` — exactement le fond
   de `.btn-ghost` : au survol, le bouton et la ligne devenaient la même couleur, et le bouton
   disparaissait purement et simplement. Une action de ligne se distingue donc par la **couleur du
   texte**, jamais par un aplat qui entrera toujours en concurrence avec le fond de la ligne. */
.action-ligne {
  background: none;
  border: 0;
  padding: 0;
  font-family: var(--sans);
  font-size: var(--t-14);
  font-weight: 600;
  color: var(--primary);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}

.action-ligne:hover {
  color: var(--primary-h);
}

/* Action destructrice : le rouge dit ce que le libellé seul ne dit pas assez fort. */
.action-ligne-danger {
  color: var(--danger);
}

.action-ligne-danger:hover {
  color: var(--danger);
  text-decoration-thickness: 2px;
}
