/* =====================================================================
   Composants
   ---------------------------------------------------------------------
   Toutes les cibles interactives mesurent au moins 44 px de haut, les
   libellés sont reliés à leurs champs, et chaque erreur est rattachée au
   contrôle concerné par aria-describedby.
   ===================================================================== */

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

.btn {
  --btn-bg: var(--color-cta);
  --btn-fg: #ffffff;
  --btn-border: transparent;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: var(--control-height);
  padding-inline: var(--space-5);
  border: var(--border-width) solid var(--btn-border);
  border-radius: var(--radius-button);
  background: var(--btn-bg);
  color: var(--btn-fg);
  font-family: inherit;
  font-size: var(--size-sm);
  font-weight: 650;
  line-height: 1.2;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--transition-fast), transform var(--transition-fast), box-shadow var(--transition-fast);
}
.btn:hover:not(:disabled) { background: var(--color-cta-dark); color: #fff; }
.btn:active:not(:disabled) { transform: translateY(1px); }
.btn:disabled, .btn[aria-disabled="true"] {
  opacity: 0.55;
  cursor: not-allowed;
  /* Un bouton désactivé explique toujours pourquoi : voir .field__hint. */
}

.btn--secondary {
  --btn-bg: var(--color-surface);
  --btn-fg: var(--color-text);
  --btn-border: var(--color-border);
  box-shadow: var(--shadow-sm);
}
.btn--secondary:hover:not(:disabled) { background: var(--color-primary-soft); color: var(--color-text); }

.btn--ghost { --btn-bg: transparent; --btn-fg: var(--color-primary-dark); --btn-border: transparent; }
.btn--ghost:hover:not(:disabled) { background: var(--color-primary-soft); color: var(--color-primary-dark); }

.btn--danger { --btn-bg: var(--color-danger); }
.btn--danger:hover:not(:disabled) { background: #7d130e; }

/*
 * BOUTON DISCRET — discret ne veut pas dire invisible (v1.9.1).
 *
 * Il portait la couleur du texte secondaire, sans fond ni bordure : posé au
 * bas d'une carte, « Abonnement » se lisait comme une légende, pas comme une
 * commande. On ne clique pas ce qu'on ne prend pas pour un bouton.
 *
 * Il garde son absence de fond — c'est ce qui le rend discret et évite trois
 * boutons pleins dans la même carte — mais il prend la couleur d'action du
 * site. C'est le seul signal qui dit « ceci se clique », et il tient 4,70:1.
 */
.btn--quiet {
  --btn-bg: transparent;
  --btn-fg: var(--color-cta);
  --btn-border: transparent;
  min-height: 36px;
  padding-inline: var(--space-3);
  font-weight: 550;
}
.btn--quiet:hover:not(:disabled) { background: var(--color-primary-soft); color: var(--color-text); }

.btn--lg { min-height: 54px; padding-inline: var(--space-6); font-size: var(--size-md); }
.btn--sm { min-height: 36px; padding-inline: var(--space-3); font-size: var(--size-xs); }
.btn--block { width: 100%; }

.btn--icon {
  padding: 0;
  width: var(--control-height);
  min-height: var(--control-height);
  flex-shrink: 0;
}
.btn--icon.btn--sm { width: 36px; min-height: 36px; }

/*
 * ZONES TACTILES — au doigt, 44 px au minimum (v1.9.1).
 *
 * `btn--sm` mesure 36 px : c'est juste à la souris, où le pointeur est un
 * point. Au doigt, la pulpe couvre environ 10 mm, et une cible de 36 px se
 * rate ou déclenche celle d'à côté — ce qui est bien pire qu'un clic manqué
 * quand les deux boutons voisins sont « Modifier » et « Supprimer ».
 *
 * La règle ne vise PAS « les petits écrans » mais « les pointeurs
 * imprécis » : une tablette de 1024 px se pilote au doigt, un portable de
 * 1280 px à la souris. `pointer: coarse` pose exactement cette question, et
 * laisse l'apparence intacte partout ailleurs.
 */
@media (pointer: coarse) {
  .btn,
  .btn--sm,
  .workspace-nav__item,
  .service-switch__item,
  .site-nav__link {
    min-height: 44px;
  }
  .btn--icon,
  .btn--icon.btn--sm {
    width: 44px;
    min-height: 44px;
  }
}

/* Icônes toujours centrées optiquement, d'un seul système graphique. */
.icon {
  width: 1.15em;
  height: 1.15em;
  flex: 0 0 auto;
  display: block;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.icon--lg { width: 1.5em; height: 1.5em; }

/* ------------------------------- Cartes ------------------------------- */

.card {
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-card);
  padding: var(--card-padding);
  box-shadow: var(--shadow-sm);
}
/*
 * Dans une grille, deux cartes voisines n'ont pas le même volume de texte.
 * Sans cela, leurs boutons se retrouvent à des hauteurs différentes, ce qui
 * se lit comme un défaut d'alignement. La carte devient donc une colonne, et
 * son bloc d'action est poussé en bas.
 */
.grid > .card { display: flex; flex-direction: column; }
.grid > .card > .card__actions { margin-top: auto; padding-top: var(--space-4); }
/* En colonne, un enfant s'étire sur toute la largeur : une étiquette doit
   au contraire épouser son texte. */
.grid > .card > .badge { align-self: flex-start; }

.card--flat { box-shadow: none; }
.card--raised { box-shadow: var(--shadow-md); }
.card--accent { border-color: color-mix(in srgb, var(--color-cta) 35%, var(--color-border)); }
.card--soft { background: var(--color-primary-soft); border-color: transparent; }
/*
 * La carte désignée par l'adresse (/espace/courses/MTM-K4P7R9). Elle est
 * amenée sous les yeux par le défilement ; l'anneau dit laquelle, sans
 * masquer les autres — le transporteur garde le contexte de sa journée.
 */
.card--focus {
  border-color: var(--color-cta);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-cta) 22%, transparent), var(--shadow-md);
  scroll-margin-top: var(--space-6);
}

.card__media {
  margin: calc(var(--card-padding) * -1) calc(var(--card-padding) * -1) var(--card-padding);
  border-radius: calc(var(--radius-card) - 1px) calc(var(--radius-card) - 1px) 0 0;
  overflow: hidden;
  height: var(--card-image-height);
  background: var(--color-primary-soft);
}
.card__media img { width: 100%; height: 100%; object-fit: cover; }

.card__title { font-size: var(--size-lg); margin-bottom: var(--space-2); }
.card__meta { font-size: var(--size-sm); color: var(--color-muted); }

.card-link {
  display: block;
  text-decoration: none;
  color: inherit;
  transition: transform var(--transition), box-shadow var(--transition), border-color var(--transition);
}
.card-link:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
  border-color: color-mix(in srgb, var(--color-cta) 30%, var(--color-border));
  color: inherit;
}

/*
 * Compteur d'inscrits, en page d'accueil des deux sites.
 *
 * Il vient sous les boutons du héros, discret : c'est une preuve, pas une
 * promesse. Le chiffre est gros parce qu'il doit se lire d'un coup ; la ligne
 * en dessous dit ce qu'il signifie, sans quoi un nombre nu sur une page
 * d'accueil ressemble à un argument de vente.
 */
.member-counter {
  margin-top: var(--space-5);
  padding-top: var(--space-4);
  border-top: var(--border-width) solid var(--color-border);
}
.member-counter__figure {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  flex-wrap: wrap;
}
.member-counter__value {
  font-size: var(--size-2xl);
  font-weight: 700;
  line-height: 1;
  color: var(--color-primary);
  /* Les chiffres gardent la même largeur : le compteur ne tressaute pas
     quand il passe de 9 à 10 au rechargement. */
  font-variant-numeric: tabular-nums;
}
.member-counter__label { font-size: var(--size-md); font-weight: 600; }
.member-counter__hint {
  margin: var(--space-2) 0 0;
  font-size: var(--size-sm);
  color: var(--color-muted);
  max-width: 42ch;
}

/*
 * Jours de la semaine d'un transport répétitif.
 *
 * Sept cases à cocher en colonne prendraient la moitié de l'écran et se
 * liraient mal : on cherche ici une forme de calendrier, où l'œil embrasse la
 * semaine d'un coup. La case reste une vraie case à cocher — accessible au
 * clavier, annoncée par un lecteur d'écran — simplement habillée.
 */
.weekday-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 3.4rem;
  padding: var(--space-2) var(--space-3);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-button);
  background: var(--color-surface);
  font-size: var(--size-sm);
  font-weight: 600;
  cursor: pointer;
  user-select: none;
  transition: background var(--transition), border-color var(--transition), color var(--transition);
}
/*
 * La case reste PRÉSENTE, simplement masquée à l'œil.
 *
 * Corrigé en v1.9.1 : elle était réduite à `width: 0; height: 0`. Une case de
 * taille nulle n'est plus considérée comme visible — ni par un outil
 * d'automatisation, ni par certaines technologies d'assistance qui s'appuient
 * sur la boîte de l'élément pour le restituer. Le motif retenu ici est celui
 * recommandé : un point d'un pixel, découpé, qui garde à l'élément une boîte
 * réelle sans qu'il se voie.
 */
.weekday-toggle input {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
.weekday-toggle:hover { border-color: color-mix(in srgb, var(--color-cta) 40%, var(--color-border)); }
.weekday-toggle:has(input:checked) {
  background: var(--color-cta);
  border-color: var(--color-cta);
  /* Même blanc que le bouton principal : ce sont les deux seules surfaces
     pleines de la couleur d'action. */
  color: #ffffff;
}
/* Le focus clavier doit se voir : la case elle-même est invisible. */
.weekday-toggle:has(input:focus-visible) {
  outline: 2px solid var(--color-cta);
  outline-offset: 2px;
}

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

.form { max-width: var(--form-max-width); }

.field { display: block; margin-bottom: var(--space-4); }
.field__label {
  display: block;
  font-size: var(--size-sm);
  font-weight: 600;
  margin-bottom: var(--space-2);
  color: var(--color-text);
}
.field__required { color: var(--color-danger); margin-inline-start: 2px; }
.field__optional { color: var(--color-muted); font-weight: 450; margin-inline-start: 4px; }

.input, .select, .textarea {
  width: 100%;
  min-height: var(--control-height);
  padding: 11px var(--space-3);
  font-family: inherit;
  font-size: var(--size-md);
  color: var(--color-text);
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-input);
  transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}
.input:hover, .select:hover, .textarea:hover { border-color: color-mix(in srgb, var(--color-primary) 40%, var(--color-border)); }
.input::placeholder, .textarea::placeholder { color: color-mix(in srgb, var(--color-muted) 75%, transparent); }
.textarea { min-height: 120px; resize: vertical; line-height: 1.55; }

.select {
  appearance: none;
  padding-inline-end: 40px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='%23546b7b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
}

.input[aria-invalid="true"], .select[aria-invalid="true"], .textarea[aria-invalid="true"] {
  border-color: var(--color-danger);
  background: var(--color-danger-soft);
}

.field__hint { display: block; font-size: var(--size-sm); color: var(--color-muted); margin-top: var(--space-2); }
.field__error {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  font-size: var(--size-sm);
  color: var(--color-danger);
  font-weight: 550;
  margin-top: var(--space-2);
}

.field-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr));
  gap: var(--space-4);
}

.checkbox, .radio {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-3);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-input);
  cursor: pointer;
  background: var(--color-surface);
  transition: border-color var(--transition-fast), background var(--transition-fast);
}
.checkbox:hover, .radio:hover { border-color: var(--color-primary); background: var(--color-primary-soft); }
.checkbox input, .radio input {
  width: 20px; height: 20px;
  margin: 1px 0 0;
  flex-shrink: 0;
  accent-color: var(--color-cta);
  cursor: pointer;
}
.checkbox:has(input:checked), .radio:has(input:checked) {
  border-color: var(--color-cta);
  background: var(--color-cta-soft);
}
.checkbox__text { font-size: var(--size-sm); line-height: 1.5; }
.checkbox__title { display: block; font-weight: 600; }
.checkbox__hint { display: block; color: var(--color-muted); margin-top: 2px; }

fieldset { border: 0; margin: 0 0 var(--space-5); padding: 0; }
legend {
  font-size: var(--size-md);
  font-weight: 650;
  padding: 0;
  margin-bottom: var(--space-3);
}

/* ------------------------------ Étapes -------------------------------- */

.steps {
  display: flex;
  gap: var(--space-2);
  margin-bottom: var(--space-6);
  list-style: none;
  padding: 0;
  flex-wrap: wrap;
}
.steps__item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: 8px 14px;
  border-radius: var(--radius-pill);
  font-size: var(--size-sm);
  font-weight: 600;
  color: var(--color-muted);
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-border);
  margin: 0;
}
.steps__item[aria-current="step"] {
  color: #fff;
  background: var(--color-cta);
  border-color: var(--color-cta);
}
.steps__item[data-done="true"] { color: var(--color-success); border-color: var(--color-success); background: var(--color-success-soft); }
.steps__number {
  display: grid;
  place-items: center;
  width: 22px; height: 22px;
  border-radius: 50%;
  background: currentColor;
  color: var(--color-surface);
  font-size: var(--size-xs);
  font-weight: 700;
}
.steps__item[aria-current="step"] .steps__number { background: #fff; color: var(--color-cta); }

/* ------------------------------ Statuts ------------------------------- */

.badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 11px;
  border-radius: var(--radius-pill);
  font-size: var(--size-xs);
  font-weight: 650;
  letter-spacing: 0.015em;
  background: var(--color-primary-soft);
  color: var(--color-primary-dark);
  white-space: nowrap;
}
.badge--success { background: var(--color-success-soft); color: var(--color-success); }
.badge--warning { background: var(--color-warning-soft); color: var(--color-warning); }
.badge--danger { background: var(--color-danger-soft); color: var(--color-danger); }
.badge--info { background: var(--color-info-soft); color: var(--color-info); }
.badge--neutral { background: color-mix(in srgb, var(--color-border) 45%, transparent); color: var(--color-muted); }
.badge--accent { background: var(--color-accent-soft); color: var(--color-accent); }
.badge__dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; flex-shrink: 0; }

/* ------------------------------ Messages ------------------------------ */

.notice {
  display: flex;
  gap: var(--space-3);
  padding: var(--space-4);
  border-radius: var(--radius-input);
  border-inline-start: 4px solid var(--color-info);
  background: var(--color-info-soft);
  font-size: var(--size-sm);
  line-height: 1.55;
}
.notice--success { border-color: var(--color-success); background: var(--color-success-soft); }
.notice--warning { border-color: var(--color-warning); background: var(--color-warning-soft); }
.notice--danger { border-color: var(--color-danger); background: var(--color-danger-soft); }
.notice--neutral { border-color: var(--color-border); background: var(--color-surface); }
.notice__title { font-weight: 700; display: block; margin-bottom: 3px; }
.notice__body { min-width: 0; }
.notice .icon { margin-top: 2px; }

.banner {
  padding: var(--space-3) 0;
  font-size: var(--size-sm);
  background: var(--color-info-soft);
  border-bottom: var(--border-width) solid color-mix(in srgb, var(--color-info) 25%, transparent);
  color: var(--color-text);
}
.banner--warning { background: var(--color-warning-soft); border-color: color-mix(in srgb, var(--color-warning) 30%, transparent); }
.banner--critical { background: var(--color-danger-soft); border-color: color-mix(in srgb, var(--color-danger) 30%, transparent); }

/* ------------------------------- Tables ------------------------------- */

.table-wrap { overflow-x: auto; border-radius: var(--radius-card); border: var(--border-width) solid var(--color-border); }
.table { width: 100%; border-collapse: collapse; font-size: var(--size-sm); background: var(--color-surface); }
.table th, .table td { padding: 12px var(--space-4); text-align: start; border-bottom: var(--border-width) solid var(--color-border); }
.table th { font-weight: 650; color: var(--color-muted); background: var(--color-bg); white-space: nowrap; font-size: var(--size-xs); text-transform: uppercase; letter-spacing: 0.05em; }
.table tr:last-child td { border-bottom: 0; }
.table tbody tr:hover { background: var(--color-primary-soft); }
.table td[data-numeric], .table th[data-numeric] { text-align: end; font-variant-numeric: tabular-nums; }

/* ----------------------------- Fenêtres ------------------------------- */

.dialog {
  border: 0;
  padding: 0;
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-lg);
  max-width: min(var(--modal-max-width), calc(100vw - var(--space-6)));
  width: 100%;
  background: var(--color-surface);
  color: var(--color-text);
}
.dialog::backdrop { background: rgba(13, 36, 54, 0.5); backdrop-filter: blur(2px); }
.dialog__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--card-padding) var(--card-padding) var(--space-3);
}
.dialog__title { margin: 0; font-size: var(--size-xl); }
.dialog__body { padding: 0 var(--card-padding); max-height: min(60vh, 560px); overflow-y: auto; }

/*
 * Lecture obligatoire des documents légaux.
 *
 * UN SEUL ASCENSEUR. Le corps de fenêtre défile déjà ; y imbriquer une zone
 * qui défile aussi donnerait deux ascenseurs côte à côte, et c'est le mauvais
 * — l'extérieur — qui recevrait la molette. La zone de lecture est donc
 * dimensionnée pour rester à l'intérieur du corps, et c'est elle qui défile.
 * Là où le navigateur connaît « :has », on neutralise l'ascenseur extérieur
 * pour de bon.
 */
.legal-consent__scroll {
  max-height: min(46vh, 400px);
  overflow-y: auto;
  padding: var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  /* Le défilement s'arrête net au bout du texte au lieu d'entraîner la page
     entière derrière la fenêtre. */
  overscroll-behavior: contain;
}

.legal-consent__scroll:focus-visible {
  outline: 2px solid var(--color-focus, currentColor);
  outline-offset: 2px;
}

.dialog__body:has(.legal-consent__scroll) { max-height: none; overflow: visible; }
.dialog__foot {
  display: flex;
  gap: var(--space-3);
  justify-content: flex-end;
  flex-wrap: wrap;
  padding: var(--space-4) var(--card-padding) var(--card-padding);
}

/* -------------------------- Détail secondaire ------------------------- */
/* Le contenu contextuel se révèle au survol, au focus clavier ET au
   toucher. Rien de nécessaire à une décision n'y est jamais placé. */

.detail { position: relative; display: inline-flex; }
.detail__trigger {
  border: 0;
  background: none;
  padding: 0 2px;
  cursor: help;
  color: var(--color-muted);
  display: inline-flex;
  align-items: center;
  font: inherit;
}
.detail__content {
  position: absolute;
  bottom: calc(100% + 8px);
  inset-inline-start: 50%;
  transform: translateX(-50%);
  width: max-content;
  max-width: min(300px, 80vw);
  padding: var(--space-3);
  background: var(--color-deep);
  color: #eef4f7;
  font-size: var(--size-xs);
  line-height: 1.5;
  border-radius: 10px;
  box-shadow: var(--shadow-lg);
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--transition-fast), visibility var(--transition-fast);
  z-index: 70;
  text-align: start;
  font-weight: 450;
}
.detail:hover .detail__content,
.detail__trigger:focus-visible + .detail__content,
.detail[data-open="true"] .detail__content { opacity: 1; visibility: visible; }

/* Densité compacte : les précisions secondaires sont repliées. */
:root[data-density="COMPACT"] .secondary-detail { display: none; }
:root[data-density="COMFORTABLE"] .card { padding: calc(var(--card-padding) * 1.25); }

/* ------------------------------ Divers -------------------------------- */

.muted { color: var(--color-muted); }
.small { font-size: var(--size-sm); }
.tiny { font-size: var(--size-xs); }
.strong { font-weight: 650; }
.center { text-align: center; }
.nowrap { white-space: nowrap; }
.numeric { font-variant-numeric: tabular-nums; }

.price { font-size: var(--size-3xl); font-weight: 700; line-height: 1; letter-spacing: -0.02em; }
.price__unit { font-size: var(--size-sm); font-weight: 550; color: var(--color-muted); }

.divider { height: var(--border-width); background: var(--color-border); margin-block: var(--space-5); border: 0; }

.empty-state {
  text-align: center;
  padding: var(--space-8) var(--space-4);
  color: var(--color-muted);
}
.empty-state .icon { width: 40px; height: 40px; margin: 0 auto var(--space-4); opacity: 0.4; }

.spinner {
  width: 18px; height: 18px;
  border: 2px solid color-mix(in srgb, currentColor 25%, transparent);
  border-top-color: currentColor;
  border-radius: 50%;
  animation: spin 700ms linear infinite;
  flex-shrink: 0;
}
@keyframes spin { to { transform: rotate(360deg); } }

.skeleton {
  background: linear-gradient(90deg, var(--color-border) 25%, color-mix(in srgb, var(--color-border) 40%, transparent) 37%, var(--color-border) 63%);
  background-size: 400% 100%;
  animation: shimmer 1.4s ease infinite;
  border-radius: var(--radius-input);
  min-height: 1em;
}
@keyframes shimmer { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }

/* Zone d'annonce pour les technologies d'assistance. */
.live-region { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }

.toast-stack {
  position: fixed;
  inset-block-end: var(--space-5);
  inset-inline-end: var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  z-index: 120;
  max-width: min(400px, calc(100vw - var(--space-6)));
}
.toast {
  display: flex;
  gap: var(--space-3);
  padding: var(--space-4);
  border-radius: var(--radius-card);
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-border);
  border-inline-start: 4px solid var(--color-info);
  box-shadow: var(--shadow-lg);
  font-size: var(--size-sm);
  animation: toast-in var(--transition) both;
}
.toast--success { border-inline-start-color: var(--color-success); }
.toast--danger { border-inline-start-color: var(--color-danger); }
@keyframes toast-in { from { opacity: 0; transform: translateY(8px); } }

/* --------------------------- Zoom navigateur -------------------------- */
/* À 200 % de zoom, la mise en page reste utilisable sans défilement
   horizontal : toutes les grilles retombent en colonne unique. */
@media (max-width: 640px) {
  :root { --section-spacing: 48px; --card-padding: 18px; --page-gutter: 16px; }
  .page-head { flex-direction: column; align-items: stretch; }

  /*
   * SUR TÉLÉPHONE, UNE FENÊTRE DEVIENT UN PANNEAU (v1.9.1).
   *
   * Une boîte centrée de 620 px est une forme d'écran de bureau. Sur un
   * téléphone elle occupait presque toute la largeur sans en avoir l'air,
   * son corps était plafonné à 60 % de la hauteur — soit une lucarne de
   * 500 px pour un formulaire de six champs — et les boutons d'action se
   * retrouvaient parfois hors de vue, au-delà du clavier virtuel.
   *
   * Le panneau s'ancre en bas, là où le pouce arrive, monte jusqu'à 92 % de
   * la hauteur utile et pas davantage. Le TITRE et les ACTIONS restent
   * collés en haut et en bas ; seul le contenu défile entre les deux. On sait
   * donc toujours dans quelle fenêtre on est, et comment en sortir.
   *
   * `dvh` et non `vh` : sur mobile, la barre d'adresse se rétracte au
   * défilement et `vh` se fige sur la hauteur la PLUS GRANDE — le bas du
   * panneau passait alors sous le bord de l'écran. `dvh` suit la hauteur
   * réellement visible.
   */
  .dialog {
    max-width: 100vw;
    width: 100vw;
    margin: 0;
    margin-block-start: auto;
    max-height: 92dvh;
    display: flex;
    flex-direction: column;
    border-start-start-radius: var(--radius-card);
    border-start-end-radius: var(--radius-card);
    border-end-start-radius: 0;
    border-end-end-radius: 0;
  }
  .dialog__head {
    flex: 0 0 auto;
    position: sticky;
    top: 0;
    z-index: 1;
    background: var(--color-surface);
    border-bottom: var(--border-width) solid var(--color-border);
  }
  .dialog__body {
    flex: 1 1 auto;
    max-height: none;
    padding-block: var(--space-3);
  }
  .dialog__foot {
    flex: 0 0 auto;
    position: sticky;
    bottom: 0;
    background: var(--color-surface);
    border-top: var(--border-width) solid var(--color-border);
    /* Sur iPhone, la barre de gestes recouvre le bas de l'écran. */
    padding-bottom: max(var(--card-padding), env(safe-area-inset-bottom));
  }
  /* Les actions s'étirent : deux boutons côte à côte pleine largeur se
     visent mieux au pouce que deux pastilles serrées à droite. */
  .dialog__foot .btn { flex: 1 1 auto; justify-content: center; }

  /* La zone de lecture obligatoire suit la hauteur du panneau au lieu de
     rester bloquée sur une fraction de l'écran. */
  .legal-consent__scroll { max-height: 58dvh; }
  .toast-stack { inset-inline: var(--space-3); inset-block-end: var(--space-3); max-width: none; }
}

/* ------------------------- Installer l'application ---------------------- */

/*
 * Page « Installer l'application ». Les instructions sont des <details> :
 * celles de l'appareil détecté sont ouvertes, les autres restent à portée
 * de clic sans encombrer.
 */
.install-mark {
  width: 96px;
  height: 96px;
  margin-inline: auto;
  display: grid;
  place-items: center;
  border-radius: var(--radius-card);
  background: var(--color-primary-soft);
}
.install-mark img { width: 72px; height: 72px; }

.install-platform + .install-platform { margin-top: var(--space-3); }
.install-platform summary {
  cursor: pointer;
  font-size: var(--size-lg);
  list-style: none;
}
.install-platform summary::-webkit-details-marker { display: none; }
.install-platform summary::after {
  content: '';
  float: inline-end;
  width: 10px;
  height: 10px;
  margin-top: 8px;
  border-right: 2px solid var(--color-muted);
  border-bottom: 2px solid var(--color-muted);
  transform: rotate(45deg);
  transition: transform 120ms ease;
}
.install-platform[open] summary::after { transform: rotate(-135deg); }
.install-platform summary:focus-visible {
  outline: 3px solid var(--color-focus);
  outline-offset: 3px;
  border-radius: var(--radius-input);
}

.install-steps {
  list-style: none;
  margin: var(--space-4) 0 0;
  padding: 0;
}
.install-step {
  display: flex;
  gap: var(--space-3);
  align-items: flex-start;
  padding-block: var(--space-2);
}
.install-step + .install-step { border-top: 1px solid var(--color-border); }
.install-step__number {
  flex: 0 0 auto;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: var(--color-primary);
  color: #fff;
  font-size: var(--size-sm);
  font-weight: 650;
}
