/* Composants : cartes, KPI, badges, cartes session, tableaux, graphes, toasts. */

.card {
  background: var(--surface);
  border: 1px solid var(--card-border);
  border-radius: var(--r-m);
  box-shadow: var(--shadow-card);
  padding: var(--s-4);
}

/* ---------------------------------------------------------------- KPI */

.kpi {
  /* Sans min-width, un élément de grille refuse de passer sous la largeur de son
     contenu : une valeur longue (« 3,74 €/100 km ») élargirait la grille et ferait
     défiler la page horizontalement sur mobile. */
  min-width: 0;
}

/* ------------------------------------------------------------- petite note

   Dix-sept règles quasi identiques disaient la même chose — un commentaire
   discret sous une valeur — en oscillant entre 12, 13 et 14 px et entre deux
   gris, sans qu'aucune différence ne soit voulue. Deux niveaux suffisent. */
.note {
  font-size: var(--t-s);
  line-height: 1.45;
  color: var(--text-2);
}

/* Encore plus discret : horodatages, mentions de provenance. */
.note--faible {
  font-size: var(--t-xs);
  color: var(--text-3);
}

/* ------------------------------------------------------------ micro-libellé

   La petite capitale grise qui coiffe un chiffre. Elle était réécrite à
   l'identique dans .kpi__label, .veh-trip__title et .pil-bloc__titre — et
   .kpi__label finissait employé partout, y compris loin de tout KPI, faute
   d'un nom qui dise ce qu'il est. Le voici. */
.microlabel,
.kpi__label {
  font-size: var(--t-s);
  font-weight: var(--w-semi);
  text-transform: uppercase;
  letter-spacing: var(--ap-capitales);
  color: var(--text-2);
}

/* ------------------------------------------------------------- grand chiffre

   Le même geste — chiffre lourd, approche resserrée, coupure autorisée en
   dernier recours — était redéfini ONZE fois, chacune avec sa propre taille :
   .kpi__value, .veh-soc, .veh-panel__value, .veh-trip__value, .pil-bloc__valeur,
   .pil-valeur__txt, .compare-card__total, .fuel-saving, .login__title,
   .offline__title. Une primitive, quatre tailles.

   La coupure en dernier recours n'est pas un détail : les formats français
   emploient l'espace fine insécable, si bien que « 3,74 €/100 km » ne peut pas
   se couper naturellement et faisait défiler la page de côté sur mobile. */
.stat {
  font-size: var(--t-3xl);
  font-weight: var(--w-strong);
  letter-spacing: var(--ap-serree);
  line-height: var(--lh-serre);
  overflow-wrap: anywhere;
  min-width: 0;
}

.stat--heros {
  font-size: var(--t-4xl);
}

.stat--carte {
  font-size: var(--t-2xl);
}

.stat--petit {
  font-size: var(--t-l);
}

/* « On ne sait pas » est une réponse : elle s'écrit en clair, en plus discret. */
.stat--muet {
  font-size: var(--t-l);
  font-weight: var(--w-semi);
  color: var(--text-3);
  letter-spacing: normal;
}

.kpi__value {
  margin-top: var(--s-1);
}

.kpi__sub {
  font-size: var(--t-s);
  color: var(--text-2);
  margin-top: var(--s-1);
}

.kpi--up {
  color: var(--danger-fg);
}

.kpi--down {
  color: var(--accent);
}

.kpi-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s-3);
}

/* 150 px et non 100 : en dessous, « 26,32 kWh » ou « 0,1234 €/kWh » se coupe
   en deux lignes sur un téléphone, et une carte de chiffre qui se replie perd
   ce qui la rend lisible d'un coup d'œil. À 375 px de large, cela donne deux
   colonnes plutôt que trois. */
.kpi-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: var(--s-3);
}

@media (min-width: 900px) {
  .kpi-grid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

/* Deux intentions distinctes, longtemps écrasées l'une par l'autre : le même
   nom .btn--danger était défini en contour dans admin.css et en aplat dans
   control.css. control.css se chargeant après, « Supprimer ce contrat »
   s'affichait en rouge plein alors qu'il avait été écrit en contour.

   Contour  : action destructive qu'on ne doit pas avoir envie de toucher.
   Aplat    : confirmation attendue, où le bouton EST l'action demandée. */
.btn--danger {
  color: var(--danger-fg);
  border-color: var(--danger-fg);
}

.btn--danger-plein {
  background: var(--danger-fg);
  border-color: var(--danger-fg);
  color: var(--surface);
}

/* ------------------------------------------------------- champs de saisie

   UNE définition, là où il y en avait quatre à l'identique (.veh-input,
   .pil-input, .field__input, .login__input). Chacune redéclarait en prime son
   propre :focus-visible, qui MASQUAIT celui de base.css avec un décalage
   différent : l'anneau de focus changeait de forme selon la page. Il n'y en a
   plus qu'un, celui du socle. */
.field {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
  min-width: 0;
}

.field__label {
  font-size: var(--t-m);
  font-weight: var(--w-semi);
  color: var(--text-2);
}

.field__input {
  /* 16 px au minimum : en dessous, iOS zoome à la prise de focus. */
  min-height: var(--cible);
  padding: 0 var(--s-3);
  font-size: var(--t-base);
  font-family: inherit;
  color: var(--text);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-s);
  width: 100%;
}

.field__input[disabled] {
  color: var(--text-3);
  background: var(--bg);
  cursor: not-allowed;
}

.field__hint {
  font-size: var(--t-s);
  color: var(--text-3);
}

/* ---------------------------------------------------------------- badges */

.badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 22px;
  padding: 0 var(--s-2);
  border: 1px solid transparent;
  border-radius: var(--r-s);
  font-size: var(--t-xs);
  font-weight: var(--w-semi);
  white-space: nowrap;
}

.badge__dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: currentColor;
  flex: none;
}

.badge--bleu {
  background: var(--tempo-bleu-bg);
  color: var(--tempo-bleu-fg);
}

/* « Blanc » en aplat serait invisible : badge contourné, et le libellé porte l'info. */
.badge--blanc {
  background: var(--tempo-blanc-bg);
  color: var(--tempo-blanc-fg);
  border-color: var(--tempo-blanc-solid);
}

.badge--rouge {
  background: var(--tempo-rouge-bg);
  color: var(--tempo-rouge-fg);
}

/* ------------------------------------------------- tons sémantiques du badge

   Quatre systèmes concurrents se partageaient ce rôle — .badge--charging et
   .badge--anomalie ici, .badge--etat-* dans admin, .pil-cible--* et
   .pil-hist__statut--* dans control — soit dix-neuf règles de teinte pour six
   sens. Il en reste six, et la géométrie n'est plus écrite qu'une fois. */
.badge--ok,
.badge--charging {
  background: var(--succes-bg);
  color: var(--succes-fg);
}

.badge--info {
  background: var(--info-bg);
  color: var(--info-fg);
}

.badge--warn,
.badge--anomalie {
  background: var(--warn-bg);
  color: var(--warn-fg);
}

.badge--danger {
  background: var(--danger-bg);
  color: var(--danger-fg);
}

/* Repoussé à droite d'un en-tête de carte (ancien .pil-cible). */
.badge--pousse {
  margin-left: auto;
}

.badge--muet,
/* Hors Tempo (HP/HC, prix unique, spot) : pas de couleur signifiante à emprunter,
   le libellé porte toute l'information. */
.badge--neutre {
  background: var(--surface-2);
  color: var(--text-2);
}

.badge--creuse {
  background: var(--accent-soft);
  color: var(--accent);
}

.badge--pleine {
  background: var(--accent);
  color: var(--accent-fg);
}

/* Recharge hors domicile : ni Tempo ni tarif maison, un ton à part. */
.badge--itinerance {
  background: var(--warn-bg);
  color: var(--warn-fg);
}

.pulse {
  animation: pulse 2s ease-out infinite;
}

@keyframes pulse {
  0% {
    box-shadow: 0 0 0 0 currentColor;
    opacity: 1;
  }
  70% {
    box-shadow: 0 0 0 7px transparent;
    opacity: 0.85;
  }
  100% {
    box-shadow: 0 0 0 0 transparent;
    opacity: 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  .pulse {
    animation: none;
  }
}

/* ---------------------------------------------------------------- carte session */

.session-card {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  padding: var(--s-3) var(--s-4);
}

.session-card__head {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  flex-wrap: wrap;
}

.session-card__time {
  font-size: var(--t-base);
  font-weight: var(--w-semi);
}

.session-card__eur {
  margin-left: auto;
  font-size: var(--t-l);
  font-weight: var(--w-strong);
}

.session-card__meta {
  display: flex;
  gap: var(--s-3);
  font-size: var(--t-m);
  color: var(--text-2);
}

.session-card__warn {
  color: var(--warn-fg);
}

/* Recharge hors domicile dans la liste : même gabarit que les sessions, liseré
   pour qu'on la distingue d'un coup d'œil sans lire l'étiquette. */
.session-card--away {
  background: var(--surface-2);
  border-left: 3px solid var(--warn-fg);
}

.session-card__split {
  width: 100%;
  height: 6px;
  border-radius: 3px;
  overflow: hidden;
  display: block;
}

/* Segments de ventilation : HP en aplat, HC en version atténuée du même solide. */
.split__seg--BLEU_HP,
.split__seg--BLEU {
  fill: var(--tempo-bleu-solid);
}

.split__seg--BLEU_HC {
  fill: color-mix(in srgb, var(--tempo-bleu-solid) 60%, transparent);
}

.split__seg--BLANC_HP,
.split__seg--BLANC {
  fill: var(--tempo-blanc-solid);
}

.split__seg--BLANC_HC {
  fill: color-mix(in srgb, var(--tempo-blanc-solid) 60%, transparent);
}

.split__seg--ROUGE_HP,
.split__seg--ROUGE {
  fill: var(--tempo-rouge-solid);
}

.split__seg--ROUGE_HC {
  fill: color-mix(in srgb, var(--tempo-rouge-solid) 60%, transparent);
}

.split__seg--HP,
.split__seg--UNIQUE,
.split__seg--DYN {
  fill: var(--accent);
}

.split__seg--HC {
  fill: color-mix(in srgb, var(--accent) 60%, transparent);
}

.split__seg--UNKNOWN {
  fill: var(--text-3);
}

.day-group {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
}

.day-group__head {
  position: sticky;
  top: 0;
  z-index: 5;
  padding: var(--s-2) var(--s-1);
  background: var(--bg);
  font-size: var(--t-s);
  font-weight: var(--w-semi);
  color: var(--text-2);
}

/* ---------------------------------------------------------------- session en cours */

.card--live {
  border: 1px solid var(--accent);
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
}

.card--live__head {
  display: flex;
  align-items: center;
  gap: var(--s-2);
}

.card--live__head h2 {
  font-size: var(--t-l);
  font-weight: var(--w-strong);
}

/* ---------------------------------------------------------------- bandeau Tempo */

.tempo-banner {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  flex-wrap: wrap;
  padding: var(--s-3) var(--s-4);
}

.tempo-banner__label {
  font-size: var(--t-m);
  color: var(--text-2);
}

.tempo-banner--alerte {
  background: var(--tempo-rouge-bg);
  border-color: var(--tempo-rouge-solid);
}

.tempo-banner__conseil {
  width: 100%;
  font-size: var(--t-m);
  font-weight: var(--w-semi);
  color: var(--tempo-rouge-fg);
}

/* ---------------------------------------------------------------- filtres */

.filters {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  padding: var(--s-2) 0;
  background: var(--bg);
}

.filters__row {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  flex-wrap: wrap;
}

.month-nav {
  display: flex;
  align-items: center;
  gap: var(--s-2);
}

.month-nav__label {
  font-size: var(--t-base);
  font-weight: var(--w-strong);
  min-width: 8em;
  text-align: center;
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 32px;
  padding: 0 var(--s-3);
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  font-size: var(--t-m);
  color: var(--text-2);
}

.chip.is-on {
  border-color: var(--accent);
  background: var(--accent-soft);
  color: var(--accent);
  font-weight: var(--w-semi);
}

/* Chips de période : teintées quand la période a une couleur (Tempo), neutres sinon. */
.chip--bleu.is-on {
  border-color: var(--tempo-bleu-solid);
  background: var(--tempo-bleu-bg);
  color: var(--tempo-bleu-fg);
}

.chip--blanc.is-on {
  border-color: var(--tempo-blanc-solid);
  background: var(--tempo-blanc-bg);
  color: var(--tempo-blanc-fg);
}

.chip--rouge.is-on {
  border-color: var(--tempo-rouge-solid);
  background: var(--tempo-rouge-bg);
  color: var(--tempo-rouge-fg);
}

.btn-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border: 1px solid var(--border);
  border-radius: var(--r-s);
  background: var(--surface);
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  min-height: 44px;
  padding: 0 var(--s-4);
  border: 1px solid var(--border);
  border-radius: var(--r-s);
  background: var(--surface);
  font-size: var(--t-base);
  font-weight: var(--w-semi);
}

/* Le remplissage prend l'encre cuivre, pas le cuivre de marque : sur fond
   clair, celui-ci ne tient que 3,3 contre du texte clair — insuffisant. */
.btn--primary {
  background: var(--accent-ink);
  border-color: var(--accent-ink);
  color: var(--accent-fg);
}

.btn--block {
  width: 100%;
}

/* ---------------------------------------------------------------- tableaux */

.table-wrap {
  overflow-x: auto;
  border-radius: var(--r-m);
  border: 1px solid var(--border);
  background: var(--surface);
}

table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--t-m);
}

th,
td {
  padding: var(--s-2) var(--s-3);
  text-align: right;
  white-space: nowrap;
  border-bottom: 1px solid var(--border);
}

th:first-child,
td:first-child {
  position: sticky;
  left: 0;
  text-align: left;
  background: var(--surface);
}

thead th {
  font-size: var(--t-xs);
  text-transform: uppercase;
  letter-spacing: var(--ap-capitales);
  color: var(--text-2);
}

tbody tr:last-child td {
  border-bottom: 0;
}

/* ---------------------------------------------------------------- graphes */

.chart {
  position: relative;
  height: 200px;
}

@media (min-width: 900px) {
  .chart {
    height: 280px;
  }
}

.legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  margin-top: var(--s-3);
}

.legend__item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--t-s);
  color: var(--text-2);
}

.legend__swatch {
  width: 10px;
  height: 10px;
  border-radius: 3px;
  flex: none;
}

/* ---------------------------------------------------------------- divers */

.empty__message {
  color: var(--text-2);
}

/* Une action proposée sous le message : elle se détache, sans crier. */
.empty__action {
  margin-top: var(--s-3);
}

.empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-6) var(--s-4);
  color: var(--text-2);
  text-align: center;
}

/* ------------------------------------------------------------------ messages

   Quatre familles rivales se partageaient ce rôle : .notice--warn ici,
   .notice--succes/--erreur dans admin, .fuel-notice-ok dans fuel, et
   .pil-indispo/.pil-erreur dans control. Pire, le .notice de base n'avait NI
   fond NI couleur : utilisé nu, il rendait une boîte presque invisible.

   Il n'en reste qu'une, à quatre tons, avec un ton neutre par défaut. */
.notice {
  display: flex;
  align-items: flex-start;
  gap: var(--s-2);
  padding: var(--s-3) var(--s-4);
  border-radius: var(--r-m);
  font-size: var(--t-m);
  line-height: var(--lh-court);
  background: var(--surface-2);
  color: var(--text-2);
}

.notice .icon {
  flex: none;
  margin-top: 2px;
}

.notice--info {
  background: var(--info-bg);
  color: var(--info-fg);
}

.notice--succes {
  background: var(--succes-bg);
  color: var(--succes-fg);
  font-weight: var(--w-semi);
}

.notice--warn {
  background: var(--warn-bg);
  color: var(--warn-fg);
}

.notice--erreur {
  background: var(--danger-bg);
  color: var(--danger-fg);
}

/* Variante compacte, pour les messages logés dans une carte de commande. */
.notice--compact {
  padding: var(--s-2) var(--s-3);
  border-radius: var(--r-s);
  font-size: var(--t-s);
}

.meta-list {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--s-2) var(--s-4);
  font-size: var(--t-m);
  margin-top: var(--s-3);
}

.meta-list dt {
  color: var(--text-2);
}

.meta-list dd {
  margin: 0;
  text-align: right;
}

details > summary {
  cursor: pointer;
  font-size: var(--t-m);
  font-weight: var(--w-semi);
  color: var(--text-2);
}

@media (prefers-reduced-motion: reduce) {
  .skeleton {
    animation: none;
  }
}

.toasts {
  position: fixed;
  left: 50%;
  bottom: calc(var(--nav-h) + var(--s-4) + env(safe-area-inset-bottom));
  z-index: 40;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  width: min(92vw, 420px);
}

.toast {
  padding: var(--s-3) var(--s-4);
  border-radius: var(--r-m);
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-pop);
  font-size: var(--t-m);
}

.toast--error {
  background: var(--danger-bg);
  color: var(--danger-fg);
  border-color: var(--danger-fg);
}

/* ---------------------------------------------------------------- onglets internes

   Défilables horizontalement : à quatre libellés français, ils ne tiennent pas
   toujours sur la largeur d'un téléphone, et une barre qui se replie sur deux
   lignes se lit mal. */
.onglets {
  display: flex;
  gap: var(--s-1);
  overflow-x: auto;
  scrollbar-width: none;
  padding-bottom: var(--s-1);
  margin-inline: calc(var(--s-4) * -1);
  padding-inline: var(--s-4);
  scroll-snap-type: x proximity;
}

.onglets::-webkit-scrollbar {
  display: none;
}

.onglet {
  flex: none;
  scroll-snap-align: start;
  display: inline-flex;
  align-items: center;
  min-height: 36px;
  padding: 0 var(--s-3);
  border-radius: var(--r-pilule);
  font-size: var(--t-m);
  font-weight: var(--w-semi);
  color: var(--text-2);
  text-decoration: none;
  white-space: nowrap;
  border: 1px solid transparent;
}

.onglet.is-actif {
  background: var(--accent-soft);
  color: var(--accent-ink);
  border-color: color-mix(in srgb, var(--accent) 35%, transparent);
}

/* ---------------------------------------------------------------- carte voiture

   L'objet héros de l'accueil. La photo n'est pas un ornement : c'est ce qui
   permet de reconnaître l'écran d'un coup d'œil, comme dans les applications
   constructeur. Elle est détourée, donc elle prend la couleur du fond quel que
   soit le thème — aucun rectangle blanc en mode sombre. */

.photo-voiture {
  display: block;
  width: 100%;
  height: auto;
  max-width: 100%;
}

.carte-voiture {
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  overflow: hidden;
}

.carte-voiture__tete {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-2);
}

/* Les chiffres à gauche, la voiture à droite. Elle déborde volontairement de la
   carte : une photo tronquée par le bord se lit comme un objet posé là, une
   photo entièrement contenue se lit comme une vignette de catalogue. */
.carte-voiture__corps {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
  align-items: center;
  gap: var(--s-2);
}

.carte-voiture__chiffres {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  min-width: 0;
}

.carte-voiture__autonomie {
  font-size: var(--t-m);
  color: var(--text-2);
}

.carte-voiture__photo {
  /* Le halo cuivré sous la voiture remplace l'ombre portée du studio, retirée
     au détourage : sans lui, le véhicule flotte. Il suit le thème. */
  background: radial-gradient(
    ellipse 62% 42% at 50% 78%,
    color-mix(in srgb, var(--accent) 22%, transparent),
    transparent 70%
  );
  margin-right: calc(var(--s-4) * -1);
  min-width: 0;
}

.carte-voiture__badges {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
}

.carte-voiture__lieu {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  padding-top: var(--s-3);
  border-top: 1px solid var(--border);
}

.carte-voiture__adresse {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  font-size: var(--t-m);
  line-height: var(--lh-court);
  color: var(--text);
}

.carte-voiture__itineraires {
  display: flex;
  gap: var(--s-2);
  flex-wrap: wrap;
}

.carte-voiture__itineraires .btn {
  gap: var(--s-2);
}

/* La rangée d'actions colle au bas de la carte, sans bordure au-dessus : elle
   appartient à la voiture, ce n'est pas une section séparée. */
.carte-voiture .actions-rapides {
  margin: 0 calc(var(--s-4) * -1) calc(var(--s-2) * -1);
  padding: var(--s-2) var(--s-4);
}

/* ---------------------------------------------------------------- volets

   Un <details> qui range ce qui étaye une réponse déjà donnée. Le résumé doit
   se voir comme un bouton, sinon personne ne l'ouvre. */

.stats-volet,
.fuel-details {
  margin: var(--s-4) 0;
}

.stats-volet > summary,
.fuel-details > summary {
  cursor: pointer;
  list-style: none;
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  min-height: var(--cible);
  padding: 0 var(--s-4);
  border: 1px solid var(--border);
  border-radius: var(--r-pilule);
  background: var(--surface);
  font-size: var(--t-m);
  font-weight: var(--w-semi);
  color: var(--text-2);
}

.stats-volet > summary::-webkit-details-marker,
.fuel-details > summary::-webkit-details-marker {
  display: none;
}

.stats-volet > summary::after,
.fuel-details > summary::after {
  content: "▾";
  font-size: var(--t-s);
}

.stats-volet[open] > summary::after,
.fuel-details[open] > summary::after {
  content: "▴";
}

/* ---------------------------------------------------------------- modale

   <dialog> natif : la CSP interdit tout script en ligne, et ce projet n'a ni
   React ni étape de build. Le navigateur fournit déjà le piégeage du focus, la
   fermeture par Échap et le fond inerte — il n'y a rien à réécrire. */

.modale {
  width: min(32rem, calc(100vw - 2 * var(--s-4)));
  padding: var(--s-5);
  border: 1px solid var(--card-border);
  border-radius: var(--r-l);
  background: var(--surface);
  color: var(--text);
  box-shadow: var(--shadow-pop);
}

.modale::backdrop {
  background: rgb(0 0 0 / 0.45);
}

.modale__tete {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-3);
  margin-bottom: var(--s-3);
}

.modale__titre {
  font-size: var(--t-l);
  font-weight: var(--w-strong);
}

.modale__corps {
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
}

.modale__actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--s-2);
  flex-wrap: wrap;
}

/* Enveloppe d'un fragment htmx : présente dans le DOM pour servir de cible,
   absente de la mise en page. Sans cela, un fragment vide — pas de couleur
   Tempo connue, aucune charge en cours — laissait malgré tout sa gouttière
   dans la colonne, soit deux trous de 24 px en haut de l'accueil. */
.enveloppe {
  display: contents;
}
