/* ==========================================================================
   Docteur High Tech — feuille de style unique
   Direction : clinique technique. Bleu profond (marine) + blanc bleuté,
   monospace pour toute la donnée, ordonnance d'admission comme signature.
   Identité de marque : BLEU ET BLANC. Le vert, l'ambre et le rouge ne
   servent qu'aux états (validé, en atelier, incident), jamais à la marque.
   ========================================================================== */

/* --- Jetons ------------------------------------------------------------- */
:root {
  --ink: #061a33;
  --petrol: #0d2a4d;
  --petrol-2: #123c6b;
  --petrol-3: #1d5fa6;
  --sterile: #f3f7fc;
  --sterile-2: #e2ebf7;
  --paper: #ffffff;
  --line: #cfdfee;
  --line-strong: #a6c0dc;
  --text: #0a1f38;

  /* `--muted` assombri de #5a7290 à #4f6a8c : l'ancien ton tombait à 4,43:1
     sur `--sterile` (sous le seuil AA de 4,5:1). Même famille de teinte. */
  --muted: #4f6a8c;

  /* Accents « signal » : la teinte de marque est celle du logo du porteur,
     `#1E73BE` (mesurée dans le fichier : 30, 115, 190). Les variantes `-ink`
     servent au **texte** et aux traits fins, où le seuil AA est plus dur à
     tenir : c'est le même bleu assombri (même teinte, 208°), #185C98, qui porte
     le texte à 6,95:1 sur blanc et 6,46:1 sur `--sterile`. Le bleu de marque
     tel quel donne 4,94:1 avec du blanc (boutons pleins, pastilles) et 4,59:1
     en texte sur `--sterile` — conforme AA, mais sans marge : d'où la variante
     pour tout ce qui se lit. Aucune de ces deux teintes n'est une couleur
     d'état : le vert, l'ambre et le rouge restent réservés aux statuts. */
  --signal: #1E73BE;
  --signal-dark: #185C98;
  --signal-ink: #185C98;
  --vital: #0b7a58;
  --vital-ink: #0b7d61;
  --amber: #a86800;
  --amber-ink: #8a5500;
  --info: #1d5fa6;
  --alert-ink: #b3261e;

  /* Cible tactile confortable (doigt) — utilisée par le menu mobile, les
     pastilles-boutons et les zones de commande du back-office. */
  --tap: 44px;

  --radius: 14px;
  --radius-sm: 9px;
  --shadow: 0 1px 2px rgba(6, 26, 51, 0.05), 0 8px 24px -14px rgba(6, 26, 51, 0.28);
  --shadow-lg: 0 2px 4px rgba(6, 26, 51, 0.06), 0 26px 60px -28px rgba(6, 26, 51, 0.45);

  --display: "Bricolage Grotesque", "Archivo", system-ui, sans-serif;
  --body: "Instrument Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, "SFMono-Regular", Menlo, monospace;

  --wrap: 1180px;
  --gutter: clamp(18px, 4vw, 40px);
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--sterile);
  color: var(--text);
  font-family: var(--body);
  font-size: 17px;
  line-height: 1.6;
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  /* Une adresse e-mail ou un numéro de suivi long ne doit jamais élargir la
     page : on autorise la coupure des mots insécables à l'intérieur des blocs
     de texte. */
  overflow-wrap: break-word;
}

img {
  max-width: 100%;
  display: block;
}

a {
  color: inherit;
  text-decoration-color: var(--line-strong);
  text-underline-offset: 3px;
  overflow-wrap: break-word;
}

a:hover {
  text-decoration-color: currentColor;
}

:focus-visible {
  outline: 2.5px solid var(--signal);
  outline-offset: 2px;
  border-radius: 4px;
}

/* --- Typographie -------------------------------------------------------- */
h1,
h2,
h3,
h4 {
  font-family: var(--display);
  font-weight: 800;
  line-height: 1.04;
  letter-spacing: -0.022em;
  margin: 0 0 0.5em;
  text-wrap: balance;
}

h1 {
  font-size: clamp(2.3rem, 5.4vw, 4rem);
}

h2 {
  font-size: clamp(1.75rem, 3.4vw, 2.6rem);
}

h3 {
  font-size: clamp(1.15rem, 1.6vw, 1.4rem);
  letter-spacing: -0.01em;
}

h4 {
  font-size: 1.03rem;
  font-weight: 600;
}

/* Titre de niveau 2 ou 3 dont on veut garder la taille « h3 » réelle
   (ex. titres de cartes, de panneaux, de colonnes de pied de page) :
   la hiérarchie du document reste correcte sans changer le dessin. */
.h3 {
  font-size: clamp(1.15rem, 1.6vw, 1.4rem);
  letter-spacing: -0.01em;
}

.h4 {
  font-size: 1.03rem;
  font-weight: 600;
}

p {
  margin: 0 0 1em;
}

p:last-child {
  margin-bottom: 0;
}

.lead {
  font-size: clamp(1.06rem, 1.5vw, 1.24rem);
  color: var(--muted);
  max-width: 62ch;
}

.mono {
  font-family: var(--mono);
  font-size: 0.78rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.eyebrow {
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--petrol-3);
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 16px;
}

.eyebrow::before {
  content: "";
  width: 26px;
  height: 2px;
  background: var(--signal);
  flex: none;
}

.eyebrow.on-dark {
  color: #93c0f5;
}

/* Intertitre posé sur un bloc sombre (carte t_12ec3dcb). Deux blocs de l'accueil
   (« Installer l'application », « Une boutique… ») gardaient `--petrol-3`, la
   teinte des fonds CLAIRS : 2,69:1 sur le marine, sous le seuil AA de 4,5:1. La
   couleur d'un intertitre dépend de son fond, pas de la mémoire du gabarit —
   la déclarer ici couvre les blocs présents et les suivants. `#93c0f5` est
   l'accent bleu ciel déjà éprouvé sur le marine par `tests/contraste.js`. */
.band--ink .eyebrow,
.card--ink .eyebrow {
  color: #93c0f5;
}

.small {
  font-size: 0.9rem;
  color: var(--muted);
}

.tiny {
  font-size: 0.8rem;
  color: var(--muted);
}

.num {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
}

strong {
  font-weight: 600;
}

/* --- Mise en page ------------------------------------------------------- */
.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin: 0 auto;
  padding: 0 var(--gutter);
}

.band {
  padding: clamp(52px, 8vw, 104px) 0;
}

.band--tight {
  padding: clamp(34px, 5vw, 58px) 0;
}

.band--paper {
  background: var(--paper);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}

.band--ink {
  background: var(--ink);
  color: #e9f1fb;
}

.band--ink h2,
.band--ink h1,
.band--ink h3 {
  color: #fff;
}

.band--ink .lead,
.band--ink .small,
.band--ink .tiny {
  color: #9fb8d6;
}

.head {
  max-width: 66ch;
  margin-bottom: clamp(28px, 4vw, 48px);
}

.head--center {
  margin-left: auto;
  margin-right: auto;
  text-align: center;
}

.head--center .eyebrow {
  justify-content: center;
}

.grid {
  display: grid;
  gap: clamp(16px, 2vw, 24px);
}

.grid--3 {
  grid-template-columns: repeat(auto-fit, minmax(268px, 1fr));
}

.grid--2 {
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
}

.grid--4 {
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
}

.split {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  gap: clamp(30px, 5vw, 70px);
  align-items: center;
}

/* Formulaire principal + colonne d'information : la proportion est
   asymétrique, mais elle s'empile comme les autres blocs `.split` sous
   880 px (l'ancien style en ligne l'emportait sur la media query et
   provoquait un débordement de 28 px en 360 px). */
.split--form {
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 0.75fr);
  align-items: start;
}

@media (max-width: 880px) {
  .split {
    grid-template-columns: 1fr;
  }
}

.stack > * + * {
  margin-top: 14px;
}

.rule {
  height: 1px;
  background: var(--line);
  border: 0;
  margin: 0;
}

/* --- Icônes ------------------------------------------------------------- */
.ico {
  width: 1.1em;
  height: 1.1em;
  flex: none;
  vertical-align: -0.16em;
}

.btn .ico {
  width: 1.05em;
  height: 1.05em;
}

.card__icon .ico {
  width: 24px;
  height: 24px;
}

.admin-nav a .ico {
  width: 19px;
  height: 19px;
  opacity: 0.9;
}

/* --- Boutons ------------------------------------------------------------ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  font-family: var(--body);
  font-weight: 600;
  font-size: 0.97rem;
  line-height: 1;
  padding: 14px 20px;
  border-radius: 999px;
  border: 1px solid transparent;
  cursor: pointer;
  text-decoration: none;
  transition: transform 0.16s ease, background 0.16s ease, box-shadow 0.16s ease, color 0.16s ease;
}

.btn:hover {
  transform: translateY(-1px);
}

.btn:active {
  transform: translateY(0);
}

.btn--primary {
  /* Le bleu de la marque, tel quel : blanc sur #1E73BE donne 4,94:1, au-dessus
     du seuil AA de 4,5:1 — inutile d'assombrir le fond du bouton. Le survol
     assombrit d'un cran (même teinte), au lieu du rouge #a8281a qu'on y
     trouvait : le rouge est une couleur d'état dans cette charte, il n'a rien à
     faire sous le curseur du bouton d'action principal. */
  background: var(--signal);
  color: #fff;
  box-shadow: 0 10px 24px -14px rgba(30, 115, 190, 0.9);
}

.btn--primary:hover {
  background: var(--signal-dark);
}

.btn--dark {
  background: var(--petrol);
  color: #fff;
}

.btn--dark:hover {
  background: var(--petrol-2);
}

.btn--ghost {
  background: transparent;
  border-color: var(--line-strong);
  color: var(--text);
}

.btn--ghost:hover {
  border-color: var(--petrol-3);
  background: rgba(18, 60, 107, 0.05);
}

.btn--onink {
  background: transparent;
  border-color: rgba(234, 241, 251, 0.4);
  color: #fff;
}

.btn--onink:hover {
  background: rgba(234, 241, 251, 0.12);
}

.btn--sm {
  padding: 9px 14px;
  font-size: 0.86rem;
  min-height: 36px;
}

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

.btn--danger {
  background: transparent;
  border-color: rgba(30, 115, 190, 0.45);
  color: var(--signal-dark);
}

.btn--danger:hover {
  background: rgba(30, 115, 190, 0.08);
}

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
}

/* --- Cartes ------------------------------------------------------------- */
.card {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: clamp(20px, 2.4vw, 28px);
  box-shadow: var(--shadow);
}

.card--flat {
  box-shadow: none;
}

.card--ink {
  background: var(--petrol);
  border-color: var(--petrol-2);
  color: #e9f1fb;
}

.card--ink h2,
.card--ink h3,
.card--ink h4 {
  color: #fff;
}

.card--link {
  display: flex;
  flex-direction: column;
  gap: 10px;
  text-decoration: none;
  transition: transform 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease;
}

.card--link:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-lg);
  border-color: var(--line-strong);
}

.card__icon {
  width: 44px;
  height: 44px;
  border-radius: 10px;
  display: grid;
  place-items: center;
  background: var(--sterile-2);
  color: var(--petrol-2);
  flex: none;
}

.card__icon svg {
  width: 24px;
  height: 24px;
}

.card__foot {
  margin-top: auto;
  font-family: var(--mono);
  font-size: 0.74rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--petrol-3);
  display: flex;
  align-items: center;
  gap: 8px;
}

/* --- Badges / pastilles ------------------------------------------------- */
/* Une seule grammaire pour tous les statuts : même hauteur, même bordure
   1px, même point de couleur, même graisse. Seule la teinte change — et
   jamais seule : le libellé texte reste lisible et suffisant. */
.pill {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-family: var(--mono);
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 6px 11px;
  border-radius: 999px;
  border: 1px solid var(--line-strong);
  background: var(--paper);
  color: var(--petrol-2);
  white-space: nowrap;
  max-width: 100%;
  min-height: 26px;
}

.pill::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: currentColor;
  flex: none;
}

.pill--info {
  color: var(--info);
  border-color: rgba(29, 95, 166, 0.4);
  background: rgba(29, 95, 166, 0.07);
}

.pill--work {
  color: var(--amber-ink);
  border-color: rgba(168, 104, 0, 0.42);
  background: rgba(168, 104, 0, 0.09);
}

/* « Devis envoyé — votre accord est attendu » : aplat plein, volontairement le
   seul aplat bleu de la liste. C'est le dossier qui bloque l'atelier, il doit
   se repérer instantanément dans un tableau où tout le reste est en contour. */
.pill--action {
  color: #ffffff;
  border-color: var(--signal);
  background: var(--signal);
}

.pill--action::before {
  background: #ffffff;
}

.pill--good {
  color: var(--vital-ink);
  border-color: rgba(11, 122, 88, 0.42);
  background: rgba(11, 122, 88, 0.09);
}

.pill--alert {
  color: var(--alert-ink);
  border-color: rgba(179, 38, 30, 0.4);
  background: rgba(179, 38, 30, 0.08);
}

.pill--muted {
  color: var(--muted);
}

.tag {
  display: inline-block;
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  border-bottom: 1px solid var(--line-strong);
  padding-bottom: 2px;
}

/* --- En-tête du site ---------------------------------------------------- */
.topbar {
  background: var(--ink);
  color: #b7cbe4;
  font-family: var(--mono);
  font-size: 0.74rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.topbar .wrap {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 22px;
  align-items: center;
  justify-content: space-between;
  padding-top: 9px;
  padding-bottom: 9px;
}

.topbar a {
  text-decoration: none;
  color: #dfeafb;
}

.topbar a:hover {
  color: #fff;
}

.topbar__dot {
  color: #93c0f5;
}

.site-header {
  position: sticky;
  top: 0;
  z-index: 40;
  background: rgba(241, 246, 243, 0.94);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
}

.site-header .wrap {
  display: flex;
  align-items: center;
  gap: 22px;
  padding-top: 14px;
  padding-bottom: 14px;
}

.logo {
  display: flex;
  align-items: center;
  gap: 11px;
  text-decoration: none;
  flex: none;
}

/* Le lien de marque garde une cible tactile confortable : l'image ne mesure que
   34 px de haut, et sans ce plancher le lien d'accueil deviendrait la plus
   petite cible de la barre (44 px est la cible de la maison, `--tap`). */
.site-header .logo {
  min-height: var(--tap);
}

/* Marque du porteur : image bitmap, JAMAIS déformée — la hauteur est fixée, la
   largeur suit les proportions du fichier. Étaient définis ici `.logo__mark`,
   `.logo__text`, `.logo__name` et `.logo__sub` : le sceau vectoriel de la maison
   et sa signature « Atelier de réparation ». Les quatre gabarits qui les
   portaient (en-tête, pied de page, barre latérale et connexion du back-office)
   affichent maintenant le logo du porteur, qui porte lui-même la signature
   « Services Informatiques » : ces règles n'avaient plus aucun porteur. */
.logo__image {
  display: block;
  height: 34px;
  width: auto;
  flex: none;
}

/* Dans les colonnes étroites — pied de page, barre latérale du back-office — la
   marque est plafonnée à la largeur de la colonne (mesurée : 204 px en fenêtre
   étroite, 238 px au large, 222 px dans la barre latérale) : `width: 100%` avec
   `height: auto` la réduit sans jamais la déformer ni la faire sortir de sa
   colonne. Un débordement y serait coûteux : la barre latérale défile
   verticalement, donc horizontalement aussi. */
.site-footer .logo__image,
.admin-side .logo__image {
  width: 100%;
  max-width: 213px;
  height: auto;
}

/* Espacement des entrées du menu. La valeur de la maison était 20 px ; elle a
   été ramenée à 14 px parce que la marque du porteur est plus large que l'ancien
   sceau : à 34 px de haut, le logo mesure 241 px là où la marque maison en
   faisait 210. Mesuré à 1280 px de fenêtre (1100 px utiles) : la rangée
   logo + menu + boutons demandait 1101 px, soit 1 px de trop — le menu se
   répartissait donc sur deux lignes pour chaque entrée longue. À 14 px, la
   rangée demande 1071 px et respire de 29 px. L'air autour du logo, lui, n'a
   pas bougé. */
.nav {
  display: flex;
  gap: 14px;
  margin-left: auto;
  align-items: center;
}

.nav a {
  text-decoration: none;
  font-size: 0.94rem;
  font-weight: 500;
  color: var(--petrol-2);
  padding: 4px 0;
  border-bottom: 2px solid transparent;
}

.nav a:hover,
.nav a[aria-current="page"] {
  border-bottom-color: var(--signal);
}

/* Alignement de la colonne de deux appels à l'action (« Envoyer mon appareil »,
   « L'application ») : il est décrit ICI et jamais par un attribut `style` en
   ligne dans views/partials/header.ejs. Un attribut de style l'emporte sur la
   feuille de style et neutraliserait la règle responsive qui masque l'ensemble
   sous 1020 px (media query ci-dessous) : la colonne resterait alors rendue sur
   téléphone et élargirait les pages.
   Même raison pour la règle `.site-header.open .header-cta` du menu mobile,
   qui reprend ces trois déclarations : elles restent surchargeables. */
.header-cta {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 8px;
  flex: none;
}

.burger {
  display: none;
  background: var(--paper);
  border: 1px solid var(--line-strong);
  border-radius: 10px;
  padding: 9px 11px;
  min-width: var(--tap);
  min-height: var(--tap);
  align-items: center;
  justify-content: center;
  cursor: pointer;
  margin-left: auto;
  color: var(--petrol-2);
}

.burger:hover {
  border-color: var(--petrol-3);
}

.burger__close {
  display: none;
}

/* Le bouton montre une croix quand le panneau est ouvert : l'état « ouvert »
   ne repose pas seulement sur aria-expanded. */
.site-header.open .burger__open {
  display: none;
}

.site-header.open .burger__close {
  display: block;
}

@media (max-width: 1020px) {
  .nav,
  .header-cta {
    display: none;
  }
  .burger {
    display: inline-flex;
  }
  .site-header.open {
    box-shadow: var(--shadow);
  }
  .site-header.open .wrap {
    flex-wrap: wrap;
  }
  .site-header.open .nav {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    width: 100%;
    gap: 0;
    padding: 4px 0 2px;
    border-top: 1px solid var(--line);
    margin-top: 10px;
  }
  /* Chaque entrée est une ligne pleine largeur, séparée par un filet :
     cible tactile de 44 px minimum, lisible au doigt. */
  .site-header.open .nav a {
    display: flex;
    align-items: center;
    width: 100%;
    min-height: var(--tap);
    padding: 10px 12px;
    border-bottom: 1px solid var(--line);
    border-radius: 0;
    font-size: 1rem;
  }
  .site-header.open .nav a:last-child {
    border-bottom: 0;
  }
  /* L'onglet courant se marque par un trait vertical, pas par le filet
     séparateur (qui ne doit pas être confondu avec un état sélectionné). */
  .site-header.open .nav a[aria-current="page"] {
    color: var(--signal-ink);
    font-weight: 600;
    box-shadow: inset 3px 0 0 var(--signal);
  }
  .site-header.open .header-cta {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    width: 100%;
    gap: 8px;
    padding: 10px 0 16px;
  }
  .site-header.open .header-cta .btn {
    min-height: var(--tap);
  }
}

/* Bande « bureaux compacts » (1021 – 1180 px) : la rangée manque de place. Le
   logo du porteur (241 px à 34 px de haut) a mangé l'air qui restait, et entre
   1021 et 1180 px de fenêtre la rangée logo + menu + boutons ne tenait plus sur
   une ligne. Mesuré : sans cette règle le menu se coupe en deux lignes jusqu'à
   1160 px de fenêtre. On resserre donc l'espacement et on baisse d'un demi-point
   la taille des entrées — sur la bande seulement, là où la place manque. Rien
   ne change au-dessus de 1180 px. */
@media (min-width: 1021px) and (max-width: 1180px) {
  .nav {
    gap: 8px;
  }
  .nav a {
    font-size: 0.9rem;
  }
}

@media (max-width: 420px) {
  .header-cta .btn,
  .topbar__contact {
    font-size: 0.9rem;
  }
  .topbar .wrap {
    gap: 4px 16px;
  }
}

/* --- Héros -------------------------------------------------------------- */
.hero {
  background: var(--ink);
  color: #eaf1fb;
  padding: clamp(48px, 7vw, 92px) 0 0;
  position: relative;
  overflow: hidden;
}

.hero::after {
  content: "";
  position: absolute;
  inset: auto -10% -40% 40%;
  height: 70%;
  background: radial-gradient(60% 70% at 50% 50%, rgba(11, 122, 88, 0.22), transparent 70%);
  pointer-events: none;
}

.hero .split {
  align-items: start;
}

.hero h1 {
  color: #fff;
}

.hero h1 em {
  font-style: normal;
  color: #93c0f5;
}

.hero p.lead {
  color: #a9c4e0;
}

.hero__facts {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 26px;
  margin: 26px 0 0;
  padding: 18px 0 0;
  border-top: 1px solid rgba(234, 241, 251, 0.16);
  list-style: none;
}

.hero__facts li {
  font-family: var(--mono);
  font-size: 0.74rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #b7cbe4;
  display: flex;
  align-items: center;
  gap: 8px;
}

.hero__facts b {
  color: #fff;
  font-weight: 500;
}

/* Trace de monitoring : la seule animation assumée du site. */
.trace {
  display: block;
  width: 100%;
  height: 58px;
  margin-top: clamp(38px, 5vw, 66px);
  margin-bottom: -1px;
  color: rgba(147, 192, 245, 0.75);
}

.trace path {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-dasharray: 2400;
  stroke-dashoffset: 2400;
  animation: trace 3.4s ease-out 0.25s forwards;
}

@keyframes trace {
  to {
    stroke-dashoffset: 0;
  }
}

/* --- Ordonnance (signature) -------------------------------------------- */
.ordo {
  position: relative;
  background:
    repeating-linear-gradient(180deg, transparent 0 27px, rgba(18, 60, 107, 0.06) 27px 28px),
    var(--paper);
  color: var(--text);
  border-radius: 4px;
  box-shadow: var(--shadow-lg);
  padding: 26px 24px 20px 30px;
  transform: rotate(-1.4deg);
  max-width: 460px;
  margin-left: auto;
  font-family: var(--mono);
  font-size: 0.82rem;
}

.ordo::before {
  content: "";
  position: absolute;
  left: 10px;
  top: 14px;
  bottom: 14px;
  width: 1px;
  background: repeating-linear-gradient(180deg, var(--line-strong) 0 7px, transparent 7px 13px);
}

.ordo__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 14px;
  padding-bottom: 12px;
  border-bottom: 1.5px solid var(--petrol);
}

.ordo__title {
  font-family: var(--display);
  font-weight: 800;
  font-size: 1.16rem;
  letter-spacing: -0.02em;
  line-height: 1.05;
}

.ordo__kicker {
  font-size: 0.66rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--muted);
}

.ordo__no {
  text-align: right;
  font-size: 0.78rem;
  color: var(--signal-ink);
  font-weight: 500;
  white-space: nowrap;
}

.ordo__rows {
  margin: 14px 0 0;
  display: grid;
  gap: 7px;
}

.ordo__row {
  display: flex;
  gap: 10px;
  align-items: baseline;
  border-bottom: 1px dotted var(--line-strong);
  padding-bottom: 5px;
}

.ordo__row span:first-child {
  color: var(--muted);
  font-size: 0.68rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  flex: none;
  width: 96px;
}

.ordo__check {
  display: flex;
  gap: 9px;
  align-items: flex-start;
  font-size: 0.78rem;
  margin-top: 4px;
}

.box {
  width: 14px;
  height: 14px;
  border: 1.5px solid var(--petrol-2);
  border-radius: 3px;
  flex: none;
  margin-top: 2px;
  position: relative;
}

.box--done::after {
  content: "";
  position: absolute;
  inset: 1px 1px 1px 1px;
  background: var(--petrol-2);
  border-radius: 1px;
}

.ordo__barcode {
  margin-top: 16px;
  height: 44px;
  background-image: repeating-linear-gradient(
    90deg,
    var(--petrol) 0 2px,
    transparent 2px 4px,
    var(--petrol) 4px 5px,
    transparent 5px 9px,
    var(--petrol) 9px 12px,
    transparent 12px 14px
  );
  opacity: 0.85;
}

/* Le pied de la fiche : la référence ne doit JAMAIS se couper (carte
   t_e5d85206). Mesuré avant : à 0,14 em de lettrage la ligne remplissait la
   largeur imprimable à 1,7 pt près, si bien que le pied basculait d'un chiffre
   à l'autre — DHT-26-0001 sur une ligne, DHT-26-0002 sur deux, sa référence
   coupée au trait d'union (« DHT-26- » puis « 0002 »). Deux corrections :
   le lettrage passe à 0,10 em (mesuré : ~39 px de marge au lieu de 1,5 px,
   les deux dossiers tiennent alors sur une ligne) et les deux fragments sont
   insécables — le pied se replie ENTRE eux, jamais dedans. */
.ordo__foot {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  row-gap: 3px;
  font-size: 0.64rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  margin-top: 8px;
}

/* Chaque fragment du pied reste d'un seul tenant : sans cette règle, un manque
   de place d'un dixième de pixel suffisait à couper « DHT-26-0002 » en
   « DHT-26- » puis « 0002 », le trait d'union étant une occasion de coupure. */
.ordo__foot > span {
  white-space: nowrap;
}

@media (max-width: 880px) {
  .ordo {
    transform: none;
    margin: 30px auto 0;
  }
}

/* --- Étapes ------------------------------------------------------------- */
.steps {
  counter-reset: step;
  display: grid;
  gap: clamp(18px, 3vw, 30px);
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
}

.step {
  position: relative;
  padding-top: 26px;
  border-top: 2px solid var(--line-strong);
}

.step__n {
  position: absolute;
  top: -15px;
  left: 0;
  font-family: var(--mono);
  font-size: 0.82rem;
  letter-spacing: 0.08em;
  background: var(--sterile);
  padding-right: 10px;
  color: var(--signal-ink);
}

.band--paper .step__n {
  background: var(--paper);
}

.band--ink .step {
  border-top-color: rgba(234, 241, 251, 0.3);
}

.band--ink .step__n {
  background: var(--ink);
  color: #93c0f5;
}

.step h3,
.step .h3 {
  font-size: 1.12rem;
  margin-bottom: 8px;
}

.step p {
  font-size: 0.95rem;
  color: var(--muted);
}

.band--ink .step p {
  color: #a9c4e0;
}

/* --- Bande tarifaire ---------------------------------------------------- */
.price-band {
  display: grid;
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
  gap: clamp(22px, 4vw, 54px);
  align-items: center;
  background: var(--paper);
  border: 1px solid var(--line);
  border-left: 5px solid var(--signal);
  border-radius: var(--radius);
  padding: clamp(22px, 3vw, 40px);
  box-shadow: var(--shadow);
}

.price-band__amount {
  font-family: var(--mono);
  font-size: clamp(2.6rem, 6vw, 3.9rem);
  font-weight: 500;
  line-height: 1;
  letter-spacing: -0.03em;
  color: var(--ink);
}

.price-band__amount small {
  font-size: 0.9rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  display: block;
  margin-top: 10px;
}

@media (max-width: 780px) {
  .price-band {
    grid-template-columns: 1fr;
  }
}

.facture {
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: var(--paper);
}

.facture__row {
  display: flex;
  gap: 16px;
  justify-content: space-between;
  align-items: baseline;
  padding: 13px 16px;
  border-bottom: 1px dashed var(--line);
  font-size: 0.95rem;
}

.facture__row:last-child {
  border-bottom: 0;
}

.facture__row--total {
  background: var(--sterile);
  font-weight: 600;
}

.facture__label {
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.76rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

/* --- Listes ------------------------------------------------------------- */
.ticks {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: 11px;
}

.ticks li {
  position: relative;
  padding-left: 26px;
  font-size: 0.98rem;
}

.ticks li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.42em;
  width: 12px;
  height: 7px;
  border-left: 2px solid var(--vital);
  border-bottom: 2px solid var(--vital);
  transform: rotate(-45deg);
}

.band--ink .ticks li::before {
  border-color: #93c0f5;
}

.crosses {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: 10px;
}

.crosses li {
  position: relative;
  padding-left: 24px;
  font-size: 0.95rem;
  color: var(--muted);
}

.crosses li::before {
  content: "×";
  position: absolute;
  left: 4px;
  top: -0.1em;
  font-size: 1.2rem;
  color: var(--signal);
  line-height: 1.4;
}

/* --- FAQ ---------------------------------------------------------------- */
.faq {
  display: grid;
  gap: 10px;
}

.faq details {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 4px 18px;
}

.faq details[open] {
  border-color: var(--line-strong);
  box-shadow: var(--shadow);
}

.faq summary {
  cursor: pointer;
  padding: 15px 0;
  font-weight: 600;
  font-size: 1.02rem;
  list-style: none;
  display: flex;
  gap: 14px;
  align-items: flex-start;
}

.faq summary::-webkit-details-marker {
  display: none;
}

.faq summary::after {
  content: "+";
  margin-left: auto;
  font-family: var(--mono);
  color: var(--petrol-3);
  font-size: 1.2rem;
  line-height: 1;
}

.faq details[open] summary::after {
  content: "–";
}

.faq .faq__body {
  padding: 0 0 18px;
  color: var(--muted);
  font-size: 0.97rem;
  max-width: 78ch;
}

/* --- Formulaires -------------------------------------------------------- */
.field {
  display: block;
  margin-bottom: 16px;
}

.field__label {
  display: block;
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--petrol-3);
  margin-bottom: 7px;
}

.field__hint {
  display: block;
  font-size: 0.82rem;
  color: var(--muted);
  margin-top: 5px;
  text-transform: none;
  letter-spacing: 0;
  font-family: var(--body);
}

input[type="text"],
input[type="email"],
input[type="tel"],
input[type="password"],
input[type="number"],
input[type="search"],
select,
textarea {
  width: 100%;
  font-family: var(--body);
  font-size: 1rem;
  color: var(--text);
  background: var(--paper);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  padding: 12px 14px;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

textarea {
  min-height: 130px;
  resize: vertical;
  line-height: 1.55;
}

input:focus,
select:focus,
textarea:focus {
  border-color: var(--petrol-3);
  box-shadow: 0 0 0 3px rgba(29, 95, 166, 0.14);
}

/* Le contour de focus clavier n'est retiré qu'au focus souris : au clavier,
   le contour rouge global reste visible (WCAG 2.4.7). */
input:focus:not(:focus-visible),
select:focus:not(:focus-visible),
textarea:focus:not(:focus-visible) {
  outline: none;
}

input[aria-invalid="true"],
textarea[aria-invalid="true"],
select[aria-invalid="true"] {
  border-color: var(--signal-ink);
  background: #fff7f5;
}

.field__error {
  display: block;
  margin-top: 6px;
  color: var(--signal-dark);
  font-size: 0.85rem;
  font-weight: 500;
}

/* Message d'erreur relié au champ : on garde la même forme que le reste. */
.field__error::before {
  content: "! ";
  font-family: var(--mono);
  font-weight: 500;
}

.field-row {
  display: grid;
  gap: 16px;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}

.check {
  display: flex;
  gap: 11px;
  align-items: flex-start;
  font-size: 0.9rem;
  color: var(--muted);
}

.check input {
  margin-top: 4px;
  width: 17px;
  height: 17px;
  accent-color: var(--petrol-2);
  flex: none;
}

.form-card {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: clamp(22px, 3vw, 34px);
  box-shadow: var(--shadow);
}

fieldset {
  border: 0;
  padding: 0;
  margin: 0 0 26px;
}

legend {
  font-family: var(--mono);
  font-size: 0.74rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--petrol-3);
  padding: 0 0 12px;
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  border-bottom: 1px solid var(--line);
  margin-bottom: 18px;
}

/* --- Encarts ------------------------------------------------------------ */
/* Grammaire unique : filet gauche 4 px + fond teinté léger + pastille de
   ton devant le titre. Une seule échelle (ok / avertissement / alerte /
   action) pour tout le produit. */
.notice {
  border: 1px solid var(--line-strong);
  border-left: 4px solid var(--info);
  background: var(--paper);
  border-radius: var(--radius-sm);
  padding: 14px 18px;
  font-size: 0.93rem;
  margin: 0 0 18px;
  /* Un message d'état porte souvent un CHEMIN ABSOLU (les deux fichiers de
     configuration : carte t_ea28ca92) ou la réponse brute d'un serveur. Un tel
     jeton n'a aucune espace où se couper : sans cette règle, il déborde de la
     page sur un écran de 360 px (mesuré : +249 px). */
  overflow-wrap: anywhere;
}

.notice:last-child {
  margin-bottom: 0;
}

.notice--ok {
  border-left-color: var(--vital-ink);
  background: rgba(11, 122, 88, 0.07);
}

.notice--warn {
  border-left-color: var(--amber-ink);
  background: rgba(168, 104, 0, 0.08);
}

.notice--alert {
  border-left-color: var(--signal-ink);
  background: rgba(30, 115, 190, 0.07);
}

.notice--action {
  border-left-color: var(--signal-ink);
  background: #fff;
  box-shadow: var(--shadow);
}

.notice strong {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-bottom: 3px;
}

/* Pastille de ton : même forme que celle des badges de statut, pour que
   « ça s'est bien passé » / « attention » / « action attendue » se
   reconnaisse d'un écran à l'autre. */
.notice strong::before {
  content: "";
  width: 9px;
  height: 9px;
  border-radius: 2px;
  background: var(--info);
  flex: none;
}

.notice--ok strong::before {
  background: var(--vital-ink);
}

.notice--warn strong::before {
  background: var(--amber-ink);
}

.notice--alert strong::before,
.notice--action strong::before {
  background: var(--signal-ink);
}

/* --- Frise de suivi ----------------------------------------------------- */
.progress {
  height: 6px;
  border-radius: 99px;
  background: var(--sterile-2);
  overflow: hidden;
}

.progress__bar {
  height: 100%;
  border-radius: 99px;
  background: linear-gradient(90deg, var(--petrol-3), var(--vital));
  transition: width 0.5s ease;
}

.timeline {
  list-style: none;
  margin: 0;
  padding: 0;
  position: relative;
}

.timeline li {
  position: relative;
  padding: 0 0 26px 34px;
  border-left: 2px solid var(--line);
}

.timeline li:last-child {
  border-left-color: transparent;
  padding-bottom: 0;
}

.timeline li::before {
  content: "";
  position: absolute;
  left: -8px;
  top: 3px;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--paper);
  border: 2px solid var(--line-strong);
}

.timeline li.is-done {
  border-left-color: var(--vital);
}

.timeline li.is-done::before {
  background: var(--vital);
  border-color: var(--vital);
}

.timeline li.is-current::before {
  border-color: var(--signal);
  box-shadow: 0 0 0 4px rgba(30, 115, 190, 0.16);
}

.timeline li.is-current {
  border-left-color: var(--signal);
}

.timeline__title {
  font-weight: 600;
  display: flex;
  gap: 10px;
  align-items: center;
  flex-wrap: wrap;
}

.timeline__desc {
  color: var(--muted);
  font-size: 0.92rem;
  margin-top: 4px;
}

.timeline__time {
  font-family: var(--mono);
  font-size: 0.72rem;
  color: var(--muted);
  letter-spacing: 0.06em;
}

/* --- Journal (fils de messages) ---------------------------------------- */
.thread {
  display: grid;
  gap: 14px;
}

.msg {
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--paper);
  padding: 14px 16px;
}

.msg--client {
  background: var(--sterile);
  border-left: 4px solid var(--petrol-3);
}

.msg--note {
  background: #fffbe9;
  border-left: 4px solid var(--amber);
}

.msg--system {
  background: var(--sterile);
  border-left: 4px solid var(--line-strong);
}

.msg__meta {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  font-family: var(--mono);
  font-size: 0.7rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 6px;
}

.msg__body {
  font-size: 0.96rem;
  white-space: pre-line;
}

/* --- Tableaux ----------------------------------------------------------- */
.table-wrap {
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--paper);
  /* Zone de défilement atteignable au clavier (tabindex ajouté dans les vues) */
  scrollbar-width: thin;
}

table.data {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.93rem;
  min-width: 720px;
}

table.data th {
  text-align: left;
  font-family: var(--mono);
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 500;
  padding: 12px 14px;
  border-bottom: 1px solid var(--line);
  background: var(--sterile);
  white-space: nowrap;
}

table.data td {
  padding: 12px 14px;
  border-bottom: 1px solid var(--line);
  vertical-align: middle;
}

/* La première colonne porte la référence ou le destinataire : elle reste
   collée à gauche pendant le défilement horizontal, pour ne jamais perdre
   la ligne qu'on est en train de lire. */
table.data th:first-child,
table.data td:first-child {
  position: sticky;
  left: 0;
  z-index: 2;
  background: var(--paper);
  box-shadow: 1px 0 0 var(--line);
}

table.data th:first-child {
  background: var(--sterile);
  z-index: 3;
}

table.data tr:last-child td {
  border-bottom: 0;
}

table.data tr:hover td {
  background: rgba(18, 60, 107, 0.03);
}

table.data tr:hover td:first-child {
  background: #f3f7fc;
}

table.data a {
  color: var(--petrol-2);
  font-weight: 500;
}

/* --- Tableaux des pages ciblées (fiches du lot 2) ---------------------- */
/* La page « Communes desservies » est la première page publique à porter des
   tableaux de données. Deux écarts avec les tableaux du back-office :
   — la première colonne y est un EN-TÊTE DE LIGNE (`th scope="row"`) : elle
     reprend la typographie du texte courant, sinon un nom de commune se
     lirait en petites capitales à chasse fixe ;
   — le plancher de largeur est plus bas (640 px) : le tableau des trois
     colonnes n'a pas besoin des 720 px prévus pour les listes à neuf
     colonnes, et le laisser défiler pour rien sur une tablette serait un
     défaut visible.
   Le défilement horizontal, lui, reste celui de `.table-wrap` (zone
   atteignable au clavier, `role="region"` posé par le gabarit). */
.table-wrap--page {
  margin: 20px 0 4px;
}

table.data--page {
  min-width: 640px;
}

table.data--page th[scope='row'] {
  font-family: inherit;
  font-size: inherit;
  letter-spacing: 0;
  text-transform: none;
  font-weight: 600;
  color: var(--ink);
}

/* Les libellés se replient : « à privilégier même de loin : aucune
   manutention » est une phrase, pas une référence — elle ne doit pas élargir
   le tableau au-delà de ce qui se lit. Et les cellules s'alignent par le
   haut, sinon trois lignes de texte se centrent face à un mot seul. */
table.data--page th,
table.data--page td {
  white-space: normal;
  vertical-align: top;
}

/* --- Tableau des communes desservies (carte t_405cfe36) -------------------
   Quatre colonnes courtes : commune, code postal, population, distance. Le
   plancher de 640 px de `data--page` a été posé pour les tableaux de PHRASES
   du lot 2 ; ici il oblige à faire défiler la zone horizontalement sur
   téléphone, et aucune ligne n'est alors lisible d'un coup — mesuré à 360 px :
   zone de 322 px pour un tableau de 640 px, 0 ligne entièrement visible sur
   les 52. Le plancher tombe donc pour ce seul tableau : les quatre colonnes
   tiennent dans la largeur, le nom de commune se replie au lieu de pousser la
   ligne, et les trois colonnes chiffrées restent d'un bloc. La zone garde son
   `role="region"` et son `tabindex="0"` : sur un écran plus large que la
   page elle-même (zoom, texte agrandi), le défilement reste possible. */
table.data--communes {
  min-width: 0;
}

table.data--communes th,
table.data--communes td {
  padding: 10px 12px;
}

/* La première colonne ne défile plus : elle n'a rien à retenir à gauche, et
   la barre verticale du `sticky` soulignerait une colonne immobile. */
table.data--communes th:first-child,
table.data--communes td:first-child {
  position: static;
  box-shadow: none;
}

/* Le nom se replie (aux traits d'union, et au besoin ailleurs) : c'est lui qui
   absorbe la largeur disponible, pas les chiffres. */
table.data--communes th[scope='row'] {
  overflow-wrap: anywhere;
}

/* Les trois colonnes chiffrées tiennent sur une ligne chacune : un code postal
   ou une distance coupés en deux se liraient mal. */
table.data--communes td {
  white-space: nowrap;
}

@media (max-width: 640px) {
  table.data--communes {
    font-size: 0.88rem;
  }
  table.data--communes th,
  table.data--communes td {
    padding: 8px 7px;
  }
  table.data--communes th {
    font-size: 0.6rem;
    letter-spacing: 0.02em;
  }
}

.ref {
  font-family: var(--mono);
  font-size: 0.84rem;
  color: var(--ink);
}

/* --- Valeur d'identité en attente (carte t_da1d4cd4) -------------------- */
/* Les informations d'entreprise que le porteur n'a pas encore (SIRET, statut,
   hébergeur, médiateur) s'affichent dans les mentions légales, les CGV et la
   politique de confidentialité. Un emplacement vide et SIGNALÉ vaut mieux
   qu'une valeur inventée : le libellé seul ne suffisait pas — « À compléter »
   posé comme du texte courant se lit comme une valeur renseignée. Encadré
   pointillé ambré, même famille de tons que `.notice--warn`, sans en prendre
   la structure (une seule ligne, dans un `<dd>` ou au milieu d'une phrase).
   `display: inline-block` + `max-width: 100%` : la boîte peut passer à la
   ligne dans une colonne étroite, elle ne déborde jamais du bloc parent. */
.attente {
  display: inline-block;
  max-width: 100%;
  border: 1px dashed var(--amber-ink);
  border-radius: var(--radius-sm);
  background: rgba(168, 104, 0, 0.08);
  color: var(--ink);
  padding: 1px 7px;
  font-size: 0.86rem;
  line-height: 1.45;
  overflow-wrap: break-word;
}

/* --- Pied de page ------------------------------------------------------- */
/* 0,875 rem (14 px) plutôt que 0,93 rem : à cinq colonnes de 206 px, les
   libellés longs (« Réparation à Brive-la-Gaillarde », 215 px à 0,93 rem,
   « Réparation MacBook par envoi », 211 px) passaient sur deux lignes dans
   trois colonnes différentes — et une colonne de deux lignes de plus que sa
   voisine, c'est précisément le déséquilibre à corriger. Mesuré à 0,875 rem :
   le plus long libellé du pied fait 202 px, il tient sur une ligne. */
.site-footer {
  background: var(--ink);
  color: #a9c4e0;
  padding: clamp(40px, 6vw, 64px) 0 26px;
  font-size: 0.875rem;
}

.site-footer .footer__title {
  color: #fff;
  font-family: var(--mono);
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  line-height: 1.4;
  margin: 0 0 14px;
}

.site-footer a {
  color: #cfe0f2;
  text-decoration: none;
}

.site-footer a:hover {
  color: #fff;
  text-decoration: underline;
}

.site-footer ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 9px;
}

/* Cinq colonnes de largeur ÉGALE, alignées en haut. Le nombre de colonnes est
   fixé, il n'est plus déduit du contenu : `repeat(auto-fit, minmax(190px, 1fr))`
   plaçait quatre blocs sur la première rangée et le cinquième seul sur la
   seconde (mesuré à 1280 px : 4 × 237,5 px puis une colonne de 237,5 px à
   gauche, et 3 + 1 orpheline à 768 px). Gouttière serrée (18 px) : à 1280 px,
   les cinq colonnes font 206 px, de quoi tenir le plus long libellé sur une
   seule ligne (202 px). */
.footer-grid {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 26px 18px;
  align-items: start;
}

/* Un élément de grille garde par défaut la largeur de son contenu insécable
   (`min-width: auto`), et une grille sans colonne déclarée s'élargit de même à
   sa liste. L'adresse e-mail de l'atelier (203 px) débordait donc de sa colonne
   — et de la page entière (30 px mesurés à 360 px, quinze pages). `min-width: 0`
   et `minmax(0, 1fr)` rendent la main à `overflow-wrap`, qui replie le texte.
   La règle vaut à toutes les largeurs : les colonnes du pied sont étroites
   partout, pas seulement sous 620 px. */
.footer-grid > div {
  min-width: 0;
}

.site-footer li a {
  overflow-wrap: anywhere;
}

/* Sous 1020 px, deux colonnes larges valent mieux que cinq colonnes de 130 px.
   La marque prend toute la largeur : les quatre autres blocs se répartissent en
   deux rangées de deux, sans colonne orpheline en bas. */
@media (max-width: 1020px) {
  .footer-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 24px 20px;
  }
  .footer-grid > div:first-child {
    grid-column: 1 / -1;
  }
}

/* Coordonnées de l'atelier, en pleine largeur sous les colonnes : leur contenu
   (adresse sur deux lignes, e-mail) ne se compare à aucune colonne de liens.
   `<address>` est en italique par défaut. */
.footer-contact {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 26px;
  margin-top: clamp(24px, 3.4vw, 36px);
  font-style: normal;
}

.footer-bottom {
  margin-top: clamp(28px, 4vw, 44px);
  padding-top: 18px;
  border-top: 1px solid rgba(234, 241, 251, 0.16);
  display: flex;
  flex-wrap: wrap;
  gap: 10px 24px;
  justify-content: space-between;
  font-family: var(--mono);
  font-size: 0.7rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* --- Fil d'Ariane ------------------------------------------------------- */
.crumbs {
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  display: flex;
  gap: 9px;
  flex-wrap: wrap;
  padding-top: 20px;
}

.crumbs a {
  text-decoration: none;
  color: var(--petrol-2);
}

/* --- Bandeau d'appel ---------------------------------------------------- */
.cta-band {
  background: var(--petrol);
  color: #eaf1fb;
  border-radius: var(--radius);
  padding: clamp(26px, 4vw, 46px);
  display: flex;
  flex-wrap: wrap;
  gap: 22px;
  align-items: center;
  justify-content: space-between;
}

.cta-band h2 {
  color: #fff;
  margin-bottom: 6px;
}

.cta-band p {
  color: #a9c4e0;
  margin: 0;
  max-width: 52ch;
}

/* ==========================================================================
   BACK-OFFICE
   ========================================================================== */
.admin-shell {
  min-height: 100vh;
  display: grid;
  grid-template-columns: 258px minmax(0, 1fr);
  background: var(--sterile);
}

.admin-side {
  background: var(--ink);
  color: #cfe0f2;
  padding: 22px 18px;
  display: flex;
  flex-direction: column;
  gap: 22px;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
}

.admin-nav {
  display: grid;
  gap: 4px;
}

.admin-nav a {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  text-decoration: none;
  color: #cfe0f2;
  font-size: 0.94rem;
}

.admin-nav a:hover {
  background: rgba(234, 241, 251, 0.08);
  color: #fff;
}

.admin-nav a[aria-current="page"] {
  background: var(--petrol-2);
  color: #fff;
}

.admin-nav .badge {
  margin-left: auto;
  font-family: var(--mono);
  font-size: 0.7rem;
  background: var(--signal);
  color: #fff;
  border-radius: 999px;
  padding: 2px 8px;
}

.admin-side__foot {
  margin-top: auto;
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #7fa39b;
  display: grid;
  gap: 8px;
}

.admin-side__foot .btn {
  width: 100%;
}

.admin-main {
  padding: clamp(20px, 3vw, 38px);
  min-width: 0;
}

.admin-top {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 24px;
}

/* Les libellés de statut du back-office peuvent être longs
   (« Devis envoyé — votre accord est attendu ») : ils passent à la ligne
   plutôt que d'élargir la page sur mobile. */
.admin-top .pill {
  white-space: normal;
  text-align: left;
}

.admin-title {
  font-family: var(--display);
  font-size: clamp(1.5rem, 3vw, 2.1rem);
  font-weight: 800;
  letter-spacing: -0.02em;
  margin: 0;
  overflow-wrap: anywhere;
}

.kpis {
  display: grid;
  gap: 14px;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  margin-bottom: 26px;
}

.kpi {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 16px 18px;
}

.kpi__label {
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
}

.kpi__value {
  font-family: var(--mono);
  font-size: 1.9rem;
  font-weight: 500;
  letter-spacing: -0.03em;
  line-height: 1.2;
  margin-top: 6px;
}

.kpi__hint {
  font-size: 0.82rem;
  color: var(--muted);
}

.filters {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
  margin-bottom: 16px;
}

.filters input,
.filters select {
  width: auto;
  min-width: 160px;
  padding: 9px 12px;
  font-size: 0.92rem;
}

.panel {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 20px;
  margin-bottom: 18px;
}

.panel > h3,
.panel > h2 {
  font-size: 1.05rem;
  margin-bottom: 14px;
}

.panel--quiet {
  background: var(--sterile);
}

/* --- Liste de gestion des dossiers (carte t_14d8914f) ------------------- */

/* Barre de vues : l'état des dossiers, cliquable, avec le compte. Les comptes
   portent sur le périmètre courant (recherche, appareil, période). */
.vues {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0 0 14px;
}

.vue {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: 36px;
  padding: 6px 13px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--paper);
  color: var(--petrol-2);
  font-size: 0.9rem;
  text-decoration: none;
}

.vue:hover {
  border-color: var(--line-strong);
  background: var(--sterile);
}

.vue__n {
  font-family: var(--mono);
  font-size: 0.76rem;
  color: var(--muted);
}

.vue--active {
  background: var(--petrol-2);
  border-color: var(--petrol-2);
  color: #fff;
}

.vue--active .vue__n {
  color: #cfe0f2;
}

/* Les deux situations qui coûtent de l'argent quand elles traînent : leur
   compteur se lit avant les autres. La couleur seule ne dit rien à un
   lecteur d'écran — le libellé, lui, est explicite. */
.vue--alerte:not(.vue--active) .vue__n {
  color: var(--alert-ink);
}

/* Recherche et filtres : deux rangées sur grand écran, empilées au besoin. */
.filters--gestion {
  align-items: flex-start;
}

.filters__groupe {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
}

.filters__groupe--principal {
  flex: 1 1 380px;
}

.filters--gestion input[type='search'] {
  flex: 1 1 320px;
  min-width: 240px;
}

.filters__dates {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.filters__dates input {
  min-width: 150px;
}

.filters__tiret {
  color: var(--muted);
}

.filters--gestion > .btn {
  align-self: center;
}

/* Barre d'actions groupées. Elle est HORS du tableau (des formulaires
   imbriqués sont interdits) : les cases le rejoignent par `form="…"`. */
.bulk {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
  padding: 12px 14px;
  margin: 0 0 12px;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.bulk__compte {
  margin: 0 auto 0 0;
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}

.bulk select {
  width: auto;
  min-width: 170px;
  padding: 8px 11px;
  font-size: 0.9rem;
}

.bulk select[hidden] {
  display: none;
}

/* Le cadre défilant doit être le bloc conteneur de ce qu'il contient : un
   `overflow` ne coupe que les descendants dont il EST le bloc conteneur. Sans
   cette ligne, le `.sr-only` absolu du dernier en-tête (« Ouvrir la fiche »)
   et la légende du tableau s'échappaient du cadre et étiraient le document
   entier : mesuré à 1100 px de fenêtre, 40 px de défilement latéral de PAGE
   pour un texte invisible d'un pixel. Le texte lu par les lecteurs d'écran
   reste en place — seule sa position, invisible, change. */
.table-wrap--gestion {
  position: relative;
}

/* Plancher de largeur du tableau : en dessous, mieux vaut le laisser défiler
   dans son cadre (`role="region"`, déjà prévu pour cela) que de comprimer
   neuf colonnes. Le vrai plancher est de toute façon la largeur MIN-CONTENT
   du contenu (~927 px mesurés) : un plancher plus haut ne protégeait rien,
   il forçait seulement un défilement inutile là où la place existe. Mesuré à
   1280 px de fenêtre : 1000 px de tableau pour 944 px de colonne de contenu,
   soit 56 px à faire défiler pour rien — la fin de la colonne « Ouvrir »
   seule. `width: 100%` le fait en outre occuper toute la largeur offerte au
   lieu de laisser un vide à droite. */
table.data--gestion {
  min-width: 900px;
  width: 100%;
}

/* La référence d'un dossier ne se coupe pas : coupée en deux (« DHT-26- » /
   « 0034 »), elle ne se relit plus. La largeur de la colonne s'y ajuste. */
table.data--gestion td.cellule-ref,
table.data--gestion td[data-label='Client'] .tiny a,
table.data--gestion .montant {
  white-space: nowrap;
}

/* Le montant sur sa ligne, l'état du devis en dessous (comme avant, sans
   ` <br>` dans le gabarit). */
table.data--gestion .montant {
  display: block;
}

/* La case de sélection d'une ligne, et son en-tête. */
.col-selection {
  width: 44px;
  text-align: center;
}

/* Neuf colonnes dans la largeur d'un écran de bureau : les marges internes
   de la liste sont resserrées (10 px au lieu de 14) pour que le tableau
   tienne sans défilement horizontal — mesuré, cela rend 72 px. */
table.data--gestion th,
table.data--gestion td {
  padding: 10px;
}

.col-selection input[type='checkbox'] {
  width: 18px;
  height: 18px;
  accent-color: var(--signal);
}

/* La pastille de statut peut porter un libellé long (« Devis envoyé — votre
   accord est attendu ») : dans la liste, elle passe à la ligne au lieu de
   déborder de sa cellule — mesuré à 360 px : 20 px de contenu en trop, dont
   6 px hors de la page. Même règle que la pastille de l'en-tête du dossier. */
table.data--gestion .pill {
  white-space: normal;
}

/* Colonnes triables : le titre est le lien, l'ordre actif est dit à l'œil
   (flèche + graisse) ET aux lecteurs d'écran (`aria-sort` sur le `th`). */
table.data th a.tri {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 2px 0;
  border-bottom: 1px dotted var(--line-strong);
  color: inherit;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  text-decoration: none;
  white-space: nowrap;
}

/* Les intitulés de colonne peuvent passer à la ligne : « Dernier mouvement »
   tient sur deux lignes au lieu d'élargir sa colonne de 58 px — c'est ce qui
   fait tenir les neuf colonnes dans un écran de bureau. */
table.data--gestion th,
table.data--gestion th a.tri {
  white-space: normal;
}

table.data th a.tri:hover {
  color: var(--petrol-2);
  border-bottom-color: var(--petrol-2);
}

table.data th a.tri--actif {
  color: var(--ink);
  border-bottom-style: solid;
}

.tri__fleche {
  font-size: 0.7rem;
}

/* Édition rapide du statut, dans la ligne. */
.rapide {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
  margin-top: 8px;
}

/* 170 px, et non 240 : la largeur intrinsèque d'un `select` est celle de son
   option la plus longue (« Devis envoyé — votre accord est attendu »), et
   c'est elle qui impose la largeur de toute la colonne Statut — donc celle du
   tableau. Mesuré à 1280 px : 240 px de `select` donnent une colonne de
   260 px et un tableau de 997 px pour 944 px de place (56 px de défilement) ;
   à 170 px, la colonne fait 190 px et le tableau 927 px, qui tient. Le
   libellé complet n'est jamais perdu : la pastille de statut, juste au-dessus
   dans la même cellule, le porte en entier. */
.rapide select {
  width: auto;
  max-width: 170px;
  padding: 5px 9px;
  font-size: 0.82rem;
}

.rapide .btn {
  min-height: 32px;
  padding: 4px 11px;
  font-size: 0.8rem;
}

/* Jours depuis le dernier mouvement : le repère qui révèle un dossier
   oublié. Le rouge ne porte pas seul l'information — le `sr-only` de la vue
   nomme le retard, et le nombre de jours est écrit. */
.delai {
  display: block;
  font-family: var(--mono);
  font-size: 0.86rem;
}

.delai--alerte {
  color: var(--alert-ink);
  font-weight: 500;
}

/* Pagination et compteur. */
.pagination {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 18px;
  align-items: center;
  justify-content: space-between;
  margin-top: 14px;
}

.pagination__compte {
  margin: 0;
  font-size: 0.92rem;
  color: var(--muted);
}

.pagination__compte .tiny {
  margin-left: 6px;
}

.pagination__liens {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
}

.pagination__page {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 36px;
  min-height: 36px;
  padding: 0 9px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--paper);
  color: var(--petrol-2);
  font-family: var(--mono);
  font-size: 0.82rem;
  text-decoration: none;
}

.pagination__page:hover {
  border-color: var(--line-strong);
  background: var(--sterile);
}

.pagination__page--active {
  background: var(--petrol-2);
  border-color: var(--petrol-2);
  color: #fff;
}

.pagination__vide {
  color: var(--muted);
  padding: 0 2px;
}

/* État vide : jamais un tableau vide, toujours une phrase et une porte de
   sortie (base vierge ou recherche sans résultat). */
.vide {
  text-align: left;
}

.vide h2 {
  margin-top: 0;
}

/* La phrase qui dit ce que le changement de statut n'a PAS fait (devis non
   envoyé, décision non enregistrée, retour sans numéro de suivi) : sur sa
   propre ligne, dans l'encadré, jamais noyée dans le reste. */
.notice__suite {
  display: block;
  margin-top: 6px;
}

/* --- Liste des clients (carte t_e4b09119) ------------------------------
   Huit colonnes au lieu de neuf (la ville est passée sous le nom, dans la
   cellule Client) : le plancher de largeur suit. Mesuré à 1 280 px, neuf
   colonnes donnaient un tableau de 1 076 px pour 946 px de place — 132 px de
   défilement interne pour rien.

   Une adresse e-mail est un mot SANS espace : le navigateur n'a rien à y
   couper, donc la colonne prenait la largeur de la plus longue adresse du
   carnet (245 px mesurés). `overflow-wrap: anywhere` (et pas `break-word`)
   change la largeur MINIMALE de la colonne : l'adresse passe sur deux lignes
   au lieu d'élargir le tableau, et le plancher redevient la somme des
   colonnes courtes. La fiche client réutilise la même classe. */
table.data--clients {
  min-width: 700px;
}

/* `table.data--gestion td.cellule-ref { white-space: nowrap }` protège une
   RÉFÉRENCE de dossier (courte) — mais la cellule du nom, ici, porte aussi la
   ville : « Saint-Yrieix-la-Perche 87500 » insécable élargissait la colonne à
   290 px et le tableau à 1 083 px (mesuré). On rend la coupure possible. */
table.data--clients td.cellule-ref {
  white-space: normal;
}

table.data--clients td[data-label='E-mail'] {
  overflow-wrap: anywhere;
}

/* Coordonnées de la fiche client. Une adresse e-mail est insécable (le
   navigateur ne coupe ni à « @ » ni au point) : mesurée à 176 px, elle
   débordait de sa colonne de valeurs (174 px, mesuré : 360 px de panneau,
   moins 40 px de marges, 132 px de libellés et 14 px de gouttière) et, en
   dessous de 480 px, faisait déborder la PAGE de 2 px. Deux réponses, chacune
   mesurée : la colonne des libellés passe de 132 à 108 px (« CLIENT DEPUIS »
   en mono 0,7 rem en demande 84 — mesuré), ce qui rend la place à l'adresse ;
   sous 480 px, les libellés passent AU-DESSUS des valeurs, où la colonne fixe
   n'a plus de sens, et une valeur insécable peut se couper plutôt que
   d'élargir la page. */
dl.dl--client {
  grid-template-columns: 108px minmax(0, 1fr);
}

@media (max-width: 480px) {
  dl.dl--client {
    grid-template-columns: 1fr;
    gap: 2px;
  }
  dl.dl--client dt {
    padding-top: 8px;
  }
  dl.dl--client dd {
    overflow-wrap: anywhere;
  }

  /* La ligne d'en-tête d'un message est une rangée `space-between` : ses deux
     moitiés ne se coupent pas, et leur SOMME (une adresse e-mail insécable
     plus une date) décidait de la largeur minimale du panneau. Mesuré sur la
     fiche client à 360 px : 348 px de minimum pour 332 px de place, d'où 2 px
     de débordement de page — corrigés ici. La même ligne existe sur la page
     « Messages du site » (mêmes classes) : elle en bénéficie, mais son
     débordement d'avant n'a pas été mesuré, il n'est donc pas affirmé. */
  .msg__meta {
    flex-wrap: wrap;
  }
}

/* Sous 820 px, une liste de gestion à neuf colonnes est illisible : chaque
   dossier devient une carte. Le tableau RESTE un tableau dans le document
   (les lecteurs d'écran gardent la structure et les liens d'en-tête), seule
   sa mise en page change. Les libellés de colonne sont repris devant chaque
   valeur (`data-label`), l'en-tête part hors du champ visuel sans être
   retiré aux technologies d'assistance. */
@media (max-width: 820px) {
  .table-wrap--gestion {
    overflow: visible;
    border: 0;
    background: transparent;
  }
  table.data--gestion {
    display: block;
    min-width: 0;
  }
  table.data--gestion thead {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
  }
  table.data--gestion tbody,
  table.data--gestion tr,
  table.data--gestion th,
  table.data--gestion td {
    display: block;
    width: auto;
  }
  table.data--gestion tr {
    position: relative;
    padding: 14px 16px 12px;
    margin-bottom: 12px;
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: var(--radius);
  }
  table.data--gestion td {
    padding: 5px 0;
    border: 0;
  }
  /* La case de sélection part en haut à droite de la carte, sous le pouce. */
  table.data--gestion td.col-selection,
  table.data--gestion td.col-selection:first-child {
    position: absolute;
    top: 12px;
    right: 14px;
    left: auto;
    width: auto;
    padding: 0;
    background: transparent;
    box-shadow: none;
  }
  table.data--gestion td.col-selection input[type='checkbox'] {
    width: 22px;
    height: 22px;
  }
  table.data--gestion td[data-label]::before {
    content: attr(data-label);
    display: block;
    margin-bottom: 2px;
    font-family: var(--mono);
    font-size: 0.66rem;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--muted);
  }
  /* La référence est le titre de la carte : pas d'étiquette au-dessus. */
  table.data--gestion td.cellule-ref {
    padding: 0 34px 6px 0;
  }
  table.data--gestion td.cellule-ref::before {
    display: none;
  }
  table.data--gestion td.cellule-ref .ref {
    font-size: 1.05rem;
  }
  table.data--gestion td.col-action {
    padding-top: 10px;
  }
  table.data--gestion td.col-action .btn {
    width: 100%;
  }
  table.data--gestion .rapide {
    margin-top: 6px;
  }
  table.data--gestion .rapide select {
    flex: 1 1 auto;
    max-width: none;
    min-height: var(--tap);
  }
  table.data--gestion .rapide .btn {
    min-height: var(--tap);
  }
  .bulk {
    align-items: stretch;
  }
  .bulk__compte {
    flex: 1 1 100%;
    margin: 0;
  }
  .bulk select,
  .bulk .btn {
    flex: 1 1 160px;
    min-height: var(--tap);
  }
  .filters--gestion input[type='search'],
  .filters--gestion select,
  .filters__dates,
  .filters__dates input {
    flex: 1 1 100%;
    width: 100%;
    min-width: 0;
  }
  .filters__dates {
    display: flex;
  }
  .filters__tiret {
    display: none;
  }
}

.dossier-grid {
  display: grid;
  gap: 18px;
  grid-template-columns: minmax(0, 1.42fr) minmax(0, 1fr);
  align-items: start;
}

@media (max-width: 1080px) {
  .dossier-grid {
    grid-template-columns: 1fr;
  }
  .admin-shell {
    grid-template-columns: 1fr;
  }
  /* Barre latérale -> barre haute compacte : le logo et les comptes restent
     accessibles, la navigation devient une rangée qui défile si la place
     manque (jamais d'écrasement des libellés). */
  .admin-side {
    position: static;
    height: auto;
    flex-direction: column;
    align-items: stretch;
    gap: 12px;
    padding: 14px 16px;
  }
  .admin-nav {
    display: flex;
    flex-wrap: nowrap;
    gap: 6px;
    overflow-x: auto;
    scrollbar-width: thin;
    margin: 0 -16px;
    padding: 2px 16px 6px;
  }
  .admin-nav a {
    flex: 0 0 auto;
    min-height: var(--tap);
    padding: 10px 14px;
    border: 1px solid rgba(234, 241, 251, 0.16);
  }
  .admin-nav a[aria-current="page"] {
    border-color: transparent;
  }
  .admin-nav a .ico {
    width: 18px;
    height: 18px;
  }
  /* Le pied de barre (dont la déconnexion) était masqué : plus aucun moyen
     de fermer sa session sur tablette et mobile. Il redevient une rangée. */
  .admin-side__foot {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 14px;
    margin-top: 0;
  }
  .admin-side__foot .btn {
    width: auto;
    min-height: 36px;
  }
  .admin-side__foot form {
    margin-left: auto !important;
  }
}

.dl {
  display: grid;
  grid-template-columns: 132px minmax(0, 1fr);
  gap: 8px 14px;
  font-size: 0.94rem;
  margin: 0;
}

.dl dt {
  font-family: var(--mono);
  font-size: 0.7rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  padding-top: 3px;
}

.dl dd {
  margin: 0;
}

.item-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 84px 110px 40px;
  gap: 8px;
  margin-bottom: 8px;
}

.item-row input {
  padding: 9px 11px;
  font-size: 0.92rem;
}

.item-row .remove {
  border: 1px solid var(--line-strong);
  background: var(--paper);
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-size: 1rem;
  color: var(--signal-dark);
}

@media (max-width: 620px) {
  /* Éditeur de lignes de devis : une ligne = désignation pleine largeur,
     puis quantité / prix / suppression sur une rangée de commande. Les
     champs restent utilisables au doigt (44 px) sans écraser les libellés. */
  .item-row {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) var(--tap);
    grid-template-areas:
      "designation designation designation"
      "qty price remove";
    gap: 8px 10px;
    padding-bottom: 12px;
    margin-bottom: 12px;
    border-bottom: 1px dashed var(--line);
  }
  .item-row > :nth-child(1) {
    grid-area: designation;
  }
  .item-row > :nth-child(2) {
    grid-area: qty;
  }
  .item-row > :nth-child(3) {
    grid-area: price;
  }
  .item-row > :nth-child(4) {
    grid-area: remove;
  }
  /* La ligne d'en-têtes visuels devient inutile quand les champs se
     répartissent sur deux rangées : chaque champ porte son propre nom
     accessible (`aria-label`). */
  .item-row--head {
    display: none;
  }
  .item-row .remove {
    min-height: var(--tap);
    font-size: 1.2rem;
  }
}

.login-shell {
  min-height: 100vh;
  display: grid;
  place-items: center;
  background: var(--ink);
  padding: 24px;
}

.login-card {
  width: 100%;
  max-width: 420px;
  background: var(--paper);
  border-radius: var(--radius);
  padding: 30px;
  box-shadow: var(--shadow-lg);
}

/* ==========================================================================
   PASSE RESPONSIVE — COMPACTION MOBILE
   Objectif : la page d'accueil faisait ~8 700 px de haut en 390 px de large.
   On resserre les rythmes verticaux et on bascule les listes de cartes en
   lignes compactes. Aucun contenu n'est retiré, aucune section supprimée.
   ========================================================================== */
@media (max-width: 620px) {
  /* 1. Rythme vertical des sections */
  .band {
    padding: clamp(34px, 8vw, 104px) 0;
  }
  .band--tight {
    padding: clamp(24px, 5vw, 58px) 0;
  }
  .head {
    margin-bottom: 20px;
  }
  .grid {
    gap: 12px;
  }
  .stack > * + * {
    margin-top: 12px;
  }

  /* 2. Cartes : moins de gras, listes en lignes */
  .card {
    padding: 16px;
    border-radius: 12px;
  }
  .card__icon {
    width: 34px;
    height: 34px;
    border-radius: 9px;
  }
  .card__icon svg {
    width: 19px;
    height: 19px;
  }
  /* Les cartes-liste (5 familles d'appareils, 4 engagements) passent en
     ligne : icône à gauche, titre à droite, texte dessous. */
  .card--link,
  .card--row {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 8px 12px;
  }
  .card--link h2,
  .card--link h3,
  .card--row h2,
  .card--row h3 {
    flex: 1 1 140px;
    min-width: 0;
    margin: 6px 0 0;
  }
  .card--link p,
  .card--row p {
    flex: 1 1 100%;
    margin: 0;
  }
  .card--link .card__foot,
  .card--row .card__foot {
    flex: 1 1 100%;
    margin-top: 2px;
  }
  .card--row h2.h3,
  .card--row h3,
  .card--link h2.h3,
  .card--link h3 {
    font-size: 1.08rem;
  }

  /* 3. Étapes : filet plus court, texte plus compact */
  .steps {
    gap: 18px;
  }
  .step {
    padding-top: 22px;
  }
  .step h3,
  .step .h3 {
    font-size: 1.05rem;
    margin-bottom: 6px;
  }
  .step p {
    font-size: 0.92rem;
  }

  /* 4. Bandes tarifaires et factures */
  .price-band {
    padding: 18px;
    gap: 18px;
  }
  .price-band__amount small {
    margin-top: 6px;
  }
  .facture__row {
    padding: 10px 12px;
    font-size: 0.92rem;
  }

  /* 5. FAQ */
  .faq {
    gap: 8px;
  }
  .faq summary {
    padding: 13px 0;
    font-size: 0.99rem;
    gap: 10px;
  }
  .faq .faq__body {
    padding-bottom: 14px;
    font-size: 0.94rem;
  }

  /* 6. Bandeau d'appel */
  .cta-band {
    padding: 22px;
    gap: 16px;
  }

  /* 7. Pied de page : deux colonnes — la marque en pleine largeur, puis quatre
     blocs en deux rangées de deux (mêmes règles qu'entre 621 et 1020 px, voir
     `.footer-grid`). Ici, seuls les espacements et la cible tactile changent. */
  .site-footer {
    padding-top: 32px;
    font-size: 0.9rem;
  }
  .footer-grid {
    gap: 22px 18px;
  }
  .site-footer ul {
    gap: 2px;
  }
  /* Un lien devenu `inline-flex` ne peut plus se replier de lui-même : sa
     largeur minimale est celle de son contenu insécable. C'est là que
     `overflow-wrap: anywhere` (règle de base) devient indispensable. */
  .site-footer li a {
    display: inline-flex;
    align-items: center;
    min-height: 30px;
    padding: 4px 0;
  }
  .footer-bottom {
    margin-top: 22px;
    gap: 8px 16px;
  }

  /* 8. Définitions : libellé au-dessus de la valeur (fini les colonnes de
     132 px qui écrasent les adresses e-mail et les numéros de série) */
  .dl {
    grid-template-columns: minmax(0, 1fr);
    gap: 2px;
    font-size: 0.92rem;
  }
  .dl dt {
    padding-top: 10px;
  }
  .dl dt:first-child {
    padding-top: 0;
  }
  .dl dd {
    overflow-wrap: anywhere;
  }

  /* 9. Héros : moins de vide, ordonnance plus serrée */
  .hero {
    padding: clamp(30px, 7vw, 92px) 0 0;
  }
  .hero__facts {
    margin-top: 20px;
    padding-top: 14px;
    gap: 8px 18px;
  }
  .hero .btn-row {
    gap: 10px;
  }
  .trace {
    height: 44px;
    margin-top: 24px;
  }
  .ordo {
    padding: 20px 18px 16px 26px;
    font-size: 0.78rem;
    margin-top: 24px;
  }
  .ordo__rows {
    gap: 6px;
    margin-top: 12px;
  }
  .ordo__row span:first-child {
    width: 84px;
  }
  .ordo__barcode {
    height: 34px;
    margin-top: 12px;
  }

  /* 10. Panneaux du back-office */
  .panel {
    padding: 16px;
  }
  .kpis {
    gap: 10px;
    margin-bottom: 18px;
  }
  .admin-main {
    padding: 16px 14px 28px;
  }
  .admin-top {
    gap: 10px;
    margin-bottom: 18px;
  }
  .dossier-grid {
    gap: 14px;
  }
  .filters input,
  .filters select {
    min-width: 0;
    width: 100%;
  }
}

/* Tablette étroite : le héros reste lisible sans occuper tout l'écran */
@media (min-width: 621px) and (max-width: 880px) {
  .band {
    padding: clamp(44px, 6vw, 80px) 0;
  }
  .ordo {
    max-width: 420px;
  }
}

/* --- Coquilles d'écriture (bons, bordereaux) --------------------------- */
.write-box {
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius-sm);
  height: 170px;
}

.write-box--sm {
  height: 120px;
}

.sign-box {
  border-bottom: 1px solid var(--ink);
  height: 70px;
}

/* --- Impression --------------------------------------------------------- */
.print-sheet {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: clamp(22px, 4vw, 44px);
  max-width: 860px;
  margin: 26px auto;
}

.print-sheet__head {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  justify-content: space-between;
  align-items: flex-start;
  border-bottom: 2px solid var(--ink);
  padding-bottom: 16px;
  margin-bottom: 22px;
}

.print-sheet__title {
  font-family: var(--display);
  font-weight: 800;
  font-size: 1.6rem;
  letter-spacing: -0.02em;
  margin: 0;
}

.instructions {
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius-sm);
  padding: 16px 18px;
  background: var(--sterile);
  font-size: 0.94rem;
}

@media print {
  .no-print,
  .site-header,
  .topbar,
  .site-footer,
  .admin-side,
  .admin-top form,
  .crumbs,
  .burger,
  .admin-top .btn-row {
    display: none !important;
  }
  html,
  body {
    background: #fff;
    color: #000;
    font-size: 10.5pt;
    line-height: 1.45;
  }
  .wrap {
    max-width: none;
    padding: 0;
  }
  .print-sheet {
    border: 0;
    border-radius: 0;
    box-shadow: none;
    padding: 0;
    margin: 0;
    max-width: none;
  }
  .print-sheet__head {
    border-bottom-width: 1.5px;
    margin-bottom: 14px;
    padding-bottom: 10px;
  }
  .print-sheet__title {
    font-size: 1.35rem;
  }
  .eyebrow {
    margin-bottom: 8px;
  }
  .lead {
    font-size: 10.5pt;
  }
  .grid {
    gap: 16px !important;
    margin-top: 0 !important;
  }
  .dl {
    grid-template-columns: 96px minmax(0, 1fr);
    gap: 3px 10px;
    font-size: 9.5pt;
  }
  .rule {
    margin: 14px 0 !important;
  }
  .facture__row {
    padding: 6px 10px;
    font-size: 9.5pt;
  }
  .instructions {
    background: none;
    padding: 12px 14px;
  }
  .ordo__check {
    font-size: 9pt;
    margin-top: 0;
  }
  .ordo__barcode {
    height: 30px;
    margin-top: 12px;
  }
  .write-box {
    height: 84px;
  }
  .write-box--sm {
    height: 62px;
  }
  .sign-box {
    height: 44px;
  }
  .card,
  .panel,
  .facture,
  .instructions,
  .msg,
  .ordo__check,
  tr,
  .timeline li {
    break-inside: avoid;
  }
  h1,
  h2,
  h3 {
    break-after: avoid;
  }
  /* Impression d'une page du back-office : on ne garde que le contenu. */
  .admin-shell {
    display: block;
  }
  .admin-main {
    padding: 0;
  }
  a[href]::after {
    content: "";
  }
}

@page {
  size: A4;
  margin: 12mm 14mm;
}

/* --- Avis clients (recopiés depuis Google, voir src/avis.js) ------------- */
/* Convention de la charte : bleu et blanc pour l'identité, et les couleurs
   vives réservées aux états. Les étoiles font exception : une note EST une
   donnée, pas une décoration de marque, et un client attend une étoile dorée.
   Le reste — cartes, texte, encadrés — reste strictement bleu et blanc. */
/* Disposition pensée pour SIX avis : trois cartes par ligne sur ordinateur
   (deux lignes pleines), deux sur tablette, une sur téléphone. Le nombre de
   cartes affichées reste celui de `src/avis.js` — rien n'est codé en dur.
   Tant qu'il y en a cinq, la dernière ligne est CENTRÉE au lieu de pendre à
   gauche, et le jour où le sixième avis arrive la grille est déjà juste.

   `flex` et non `grid` : avec `justify-content: center`, une dernière ligne
   incomplète se centre d'elle-même, ce que `auto-fit` ne sait pas faire.
   Défaut mesuré avant : à 768 px, 5 cartes se répartissaient en 2+2+1, la
   cinquième seule et collée à gauche ; à 1280 px, 3+2 laissait un trou à
   droite (372 px). */
.grimoire {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 18px;
  margin-top: 24px;
}

.avis {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin: 0;
  padding: 20px 22px;
  background: #fff;
  border: 1px solid rgba(18, 60, 107, 0.14);
  border-radius: 14px;
  box-shadow: 0 1px 0 rgba(6, 26, 51, 0.04);
  /* Téléphone : une carte par ligne, toute la largeur disponible. */
  flex: 1 1 100%;
  min-width: 0;
  max-width: 100%;
}

.avis__note {
  display: flex;
  align-items: center;
  gap: 3px;
}

.avis__etoile {
  width: 17px;
  height: 17px;
  fill: #c5d5e8; /* étoile vide : bleu très clair, jamais un gris sale */
}

.avis__etoile--pleine {
  fill: #d98d1f; /* état « note » : réservé aux icônes, jamais du texte */
}

.avis__note .tiny {
  margin-left: 6px;
}

.avis__texte {
  margin: 0;
  font-size: 1rem;
  line-height: 1.65;
}

.avis__auteur {
  margin-top: auto;
  padding-top: 4px;
  display: flex;
  align-items: baseline;
  gap: 4px;
  flex-wrap: wrap;
}

/* Deux cartes par ligne dès que deux cartes de 300 px et leur gouttière
   tiennent (2 × 300 + 18 = 618 px de contenu, soit ~672 px de fenêtre) ;
   en dessous, la carte occupe seule toute la largeur.
   La base est un POURCENTAGE et non `300px` : avec une base en pixels, trois
   cartes « hypothétiques » de 300 px tiennent dans un conteneur de 940 px
   avant que la limite des deux colonnes ne s'applique — mesuré à 1019 px :
   3 cartes de 301 px puis 2 de 460 px, largeurs inégales. Avec 40 %, trois
   bases ne tiennent jamais sur une ligne, et la limite ci-dessus fait la
   largeur. Le demi-pixel évite qu'un arrondi bascule la deuxième carte. */
@media (min-width: 672px) {
  .avis {
    flex-basis: 40%;
    max-width: calc((100% - 18px) / 2 - 0.5px);
  }
}

/* Trois cartes par ligne — la grille vise 3 × 2 pour six avis. La dernière
   ligne incomplète reste centrée par le `justify-content` du conteneur. */
@media (min-width: 1020px) {
  .avis {
    max-width: calc((100% - 36px) / 3 - 0.5px);
  }
}

/* Pied du bloc d'avis : le lien vers la fiche Google. Une classe, et non un
   attribut `style` — un attribut l'emporte sur toute la feuille de style et
   neutralise les requêtes média (défaut déjà payé sur `.header-cta`). */
.grimoire__pied {
  margin-top: 18px;
}

/* Bouton large : réservé aux appels à l'action qu'on ne doit pas manquer —
   l'installation de l'application, par exemple. */
.btn--lg {
  font-size: 1.06rem;
  padding: 16px 28px;
}

/* --- Récupération de données (accueil) ---------------------------------- */
/* Bandeau CLAIR, carte marquée — et surtout pas d'aplat bleu plein : la charte
   réserve l'aplat à un seul usage (la pastille « devis en attente » du suivi),
   et le site est bleu et blanc. Le bloc emprunte donc la grammaire de la carte
   tarifaire (`.price-band`) : fond blanc, filet gauche de 5 px en bleu de
   marque `--signal`, ombre légère. Le filet et les numéros d'étape sont des
   traits, jamais un aplat ; aucune couleur d'état (vert, ambre, rouge) n'entre
   ici — elle ne dirait pas la même chose que la marque. */
.recup {
  background: var(--paper);
  border: 1px solid var(--line);
  border-left: 5px solid var(--signal);
  border-radius: var(--radius);
  padding: clamp(22px, 3vw, 40px);
  box-shadow: var(--shadow);
}

.recup__grille {
  display: grid;
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
  gap: clamp(22px, 4vw, 54px);
  align-items: start;
}

/* Le montant : même échelle et même fonte de donnée que `.price-band__amount`
   (IBM Plex Mono, chiffres tabulaires par nature). */
.recup__montant {
  font-family: var(--mono);
  font-size: clamp(2.6rem, 6vw, 3.9rem);
  font-weight: 500;
  line-height: 1;
  letter-spacing: -0.03em;
  color: var(--ink);
  margin: 0 0 14px;
}

.recup__montant small {
  font-size: 0.9rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  display: block;
  margin-top: 10px;
}

/* Avis cité dans le bloc. Volontairement SANS la grammaire des cartes d'avis
   (`blockquote.avis`, en bas de page) : un simple filet pointillé au-dessus de
   la citation suffit à l'attribuer, et le bloc ne ressemble pas à une
   deuxième section d'avis. */
.recup__avis {
  margin: 22px 0 0;
  padding: 16px 0 0;
  border-top: 1px dashed var(--line-strong);
}

.recup__avis p {
  margin: 0 0 6px;
  font-size: 0.95rem;
  line-height: 1.6;
}

/* Les quatre étapes : une liste ORDONNÉE (le déroulé a un ordre), les numéros
   étant posés en mono par le compteur CSS. */
.recup__etapes {
  counter-reset: recup;
  list-style: none;
  margin: 16px 0 0;
  padding: 0;
  display: grid;
  gap: 14px;
}

.recup__etapes li {
  position: relative;
  padding-left: 46px;
  font-size: 0.97rem;
}

.recup__etapes li::before {
  counter-increment: recup;
  content: counter(recup, decimal-leading-zero);
  position: absolute;
  left: 0;
  top: 0.1em;
  font-family: var(--mono);
  font-size: 0.8rem;
  letter-spacing: 0.08em;
  color: var(--signal-ink);
  border-bottom: 2px solid var(--signal);
  padding-bottom: 1px;
}

/* La réserve d'honnêteté garde la grammaire des encarts du site (`.notice`),
   en ton neutre : ce n'est ni une alerte, ni une attente, ni une validation. */
.recup__reserve {
  margin: 18px 0 0;
}

.recup__actes {
  margin-top: clamp(20px, 3vw, 30px);
}

/* Sous 780 px, la même bascule que la carte tarifaire : une seule colonne. */
@media (max-width: 780px) {
  .recup__grille {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 620px) {
  .recup {
    padding: 14px;
  }
  .recup__grille {
    gap: 14px;
  }
  .recup__etapes li {
    padding-left: 40px;
  }
  .recup__avis {
    margin-top: 16px;
    padding-top: 12px;
  }
}

/* --- Mouvement réduit --------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  .trace path {
    stroke-dashoffset: 0;
  }
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.skip {
  position: absolute;
  left: -999px;
  top: 0;
  background: var(--signal);
  color: #fff;
  padding: 10px 16px;
  z-index: 100;
}

.skip:focus {
  left: 8px;
  top: 8px;
}

/* ==========================================================================
   PASSE 2 — DENSIFICATION MOBILE (<= 620 px)
   La page d'accueil mesurait 7 522 px de haut en 390 px (7 951 px en 360 px).
   On resserre encore les rythmes verticaux et les blocs décoratifs. Aucun
   contenu n'est retiré : seuls les espacements et les hauteurs de décoration
   changent. Les valeurs restent >= 10 px pour ne pas coller les blocs.
   ========================================================================== */
@media (max-width: 620px) {
  /* Rythme des sections */
  .band {
    padding: 26px 0;
  }
  .band--tight {
    padding: 20px 0;
  }
  .head {
    margin-bottom: 14px;
  }
  .grid {
    gap: 10px;
  }
  .stack > * + * {
    margin-top: 10px;
  }
  .rule {
    margin: 14px 0 !important;
  }
  .btn-row {
    gap: 8px;
  }

  /* Héros : marge haute et liste de garanties */
  .hero {
    padding-top: 26px;
  }
  .hero__facts {
    gap: 8px 18px;
    margin-top: 16px;
    padding-top: 12px;
  }
  .trace {
    height: 34px;
    margin-top: 20px;
  }

  /* Faux bordereau (décoratif) : on garde l'objet, on réduit son encombrement */
  .ordo {
    margin: 20px auto 0;
    padding-bottom: 16px;
  }
  .ordo__rows {
    margin-top: 10px;
    gap: 5px;
  }
  .ordo__row {
    padding-bottom: 3px;
  }
  .ordo__row span:first-child {
    width: 78px;
  }
  .ordo__check {
    margin-top: 3px;
  }
  .ordo__barcode {
    height: 28px;
    margin-top: 10px;
  }

  /* Cartes et étapes : on densifie le texte, pas le nombre d'items */
  .card {
    padding: 13px 14px;
  }
  .card--link,
  .card--row {
    gap: 6px 10px;
  }
  .card--link p,
  .card--row p,
  .card__foot {
    font-size: 0.9rem;
  }
  .steps {
    gap: 12px;
  }
  .step {
    padding-top: 18px;
  }
  .step h3,
  .step .h3 {
    margin-bottom: 4px;
  }

  /* Bandes tarifaires, factures, FAQ, appel */
  .price-band {
    padding: 14px;
    gap: 14px;
  }
  .facture__row {
    padding: 8px 10px;
  }
  .faq {
    gap: 6px;
  }
  .faq summary {
    padding: 11px 0;
  }
  .faq .faq__body {
    padding-bottom: 10px;
  }
  .cta-band {
    padding: 18px;
    gap: 12px;
  }
  .notice,
  .instructions {
    padding: 12px 14px;
  }

  /* Cibles tactiles : les liens de la barre haute mesuraient 19 px de haut.
     On leur donne une zone d'au moins 44 px sans changer leur apparence. */
  .topbar a {
    display: inline-flex;
    align-items: center;
    min-height: var(--tap);
  }
  .topbar__contact {
    gap: 4px 14px;
  }

  /* Pied de page */
  .site-footer {
    padding-top: 24px;
  }
  .footer-grid {
    gap: 16px 14px;
  }
}

/* Tablettes et petites fenêtres : on garde un rythme intermédiaire */
@media (min-width: 621px) and (max-width: 880px) {
  .head {
    margin-bottom: 24px;
  }
  .grid {
    gap: 14px;
  }
  .trace {
    height: 44px;
    margin-top: 32px;
  }
}

/* Cibles tactiles de la navigation en mode bureau large : la zone cliquable
   dépasse 24 px (seuil AA 2.5.8) et s'approche des 44 px recommandés. */
.nav a {
  padding: 12px 0;
}

/* ==========================================================================
   PASSE 3 — TYPOGRAPHIE ET BLOCS ETROITS (<= 620 px)
   Sur un écran de 390 px, 17 px / 1.6 rendent chaque paragraphe très haut.
   On passe à 16.5 px / 1.5 (au-dessus du minimum lisible de 16 px) et on
   resserre les marges de paragraphe. Aucun texte n'est modifié ou coupé.
   ========================================================================== */
@media (max-width: 620px) {
  body {
    font-size: 16.5px;
    line-height: 1.5;
  }
  p {
    margin-bottom: 0.75em;
  }
  .lead {
    font-size: 1.02rem;
    line-height: 1.5;
  }
  h1 {
    font-size: clamp(1.85rem, 7.5vw, 2.3rem);
  }
  h2 {
    font-size: clamp(1.5rem, 6vw, 1.9rem);
  }
  h3,
  .h3 {
    font-size: 1.08rem;
  }

  /* Barre haute : le texte d'adresse tient sur moins de lignes */
  .topbar {
    font-size: 0.82rem;
    line-height: 1.35;
  }
  .topbar .wrap {
    padding-top: 4px;
    padding-bottom: 4px;
  }

  /* Boutons : même zone tactile, moins de hauteur perdue */
  .btn {
    padding: 13px 18px;
  }

  /* Faux bordereau : les rangées d'information se resserrent */
  .ordo__head {
    padding: 12px 14px;
  }
  .ordo__row {
    font-size: 0.85rem;
  }

  /* Grilles de cartes : deux colonnes seulement quand la place existe */
  .grid--3,
  .grid--4 {
    grid-template-columns: 1fr;
  }
  .grid--2 {
    grid-template-columns: 1fr;
  }

  /* Pied de page */
  .footer-grid h3,
  .footer-grid .h3 {
    font-size: 0.95rem;
    margin-bottom: 6px;
  }
  .footer-grid li + li {
    margin-top: 6px;
  }
}

/* --- Tableau de bord du matin (carte t_572c9a29) --------------------------
   Ce que le porteur ouvre en arrivant. Composition en deux colonnes, comme
   les widgets du tableau de bord de WordPress : ce qui attend une décision à
   gauche, ce qui se mesure et ce qui vient de se passer à droite.

   Deux pièges de mise en page évités ici, tous les deux mesurés ailleurs dans
   ce dépôt : une colonne de grille `1fr` a pour MINIMUM le min-contenu de ses
   items (un montant ou une adresse qui ne se coupe pas élargit la colonne
   au-delà du conteneur — d'où `minmax(0, 1fr)`, qui autorise la colonne à
   tomber sous son min-contenu), et une grille qui change de nombre de colonnes
   doit le faire sur un seuil LARGE (1020 px), pas au milieu du texte. */

.tablo {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 18px;
  align-items: start;
  margin: 0 0 26px;
}

.tablo__colonne {
  min-width: 0;
}

.tablo__colonne > .panel:last-child {
  margin-bottom: 0;
}

/* La phrase qui dit le PÉRIMÈTRE des chiffres du tableau de bord. Sans elle,
   les nombres d'ici et ceux de la barre de vues de la liste (qui, elle, suit
   la recherche et la période) paraîtraient se contredire. */
.tablo__regle {
  margin: -12px 0 18px;
  font-size: 0.82rem;
  color: var(--muted);
}

.tablo__note {
  margin: 10px 0 0;
  font-size: 0.82rem;
  color: var(--muted);
}

.tablo__note--alerte {
  color: var(--alert-ink);
}

/* Quatre chiffres d'ouverture, dont les deux qui coûtent de l'argent quand ça
   traîne. */
.kpis--matin {
  margin-bottom: 10px;
}

.kpi__lien {
  margin-left: 6px;
  white-space: nowrap;
}

/* Encaissé : les trois périodes du porteur, côte à côte. */
.periodes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 12px;
}

.periode {
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 12px 14px;
  background: var(--sterile);
}

.periode__quand {
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0;
}

/* Deux lignes, et non une : « MOIS PRÉCÉDENT · AOÛT 2026 » sur une seule ligne
   de 133 px se coupait au milieu du mot (mesuré sur la capture de 1 280 px).
   Le mois passe donc sous son étiquette, et les trois cartes s'alignent. */
.periode__quand-rel {
  display: block;
  color: var(--petrol-2);
}

.periode__montant {
  font-family: var(--mono);
  font-size: 1.2rem;
  font-weight: 500;
  line-height: 1.3;
  margin: 6px 0 0;
  font-variant-numeric: tabular-nums;
}

.periode__quoi {
  margin: 2px 0 0;
  font-size: 0.78rem;
  color: var(--muted);
}

/* Mesures en liste de définitions : le libellé, la valeur, et sous la valeur
   son DÉNOMINATEUR (« sur 12 devis décidés ») — un taux sans sa population ne
   veut rien dire. */
.mesures {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 8px 16px;
  margin: 16px 0 0;
  font-size: 0.94rem;
}

.mesures dt {
  font-family: var(--mono);
  font-size: 0.7rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  padding-top: 4px;
}

.mesures dd {
  margin: 0;
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
}

.mesures dd .tiny {
  display: block;
  font-family: var(--body);
  line-height: 1.45;
}

/* Les trois délais : la valeur en gros à droite, sa population dessous. */
.delais {
  margin: 0;
}

.delais__ligne {
  display: flex;
  flex-wrap: wrap;
  gap: 2px 14px;
  align-items: baseline;
  justify-content: space-between;
  padding: 10px 0;
  border-top: 1px solid var(--line);
}

.delais__ligne:first-child {
  border-top: 0;
  padding-top: 0;
}

.delais dt {
  font-size: 0.92rem;
}

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

.delais__valeur {
  display: block;
  font-family: var(--mono);
  font-size: 1.15rem;
  font-variant-numeric: tabular-nums;
}

/* Fil d'activité : les derniers mouvements, du plus récent au plus ancien.
   Chaque ligne est un LIEN vers le dossier — la cible tactile fait toute la
   largeur, et l'ordre des éléments du lien donne sa phrase à un lecteur
   d'écran (« DHT-26-0012 Jérôme Pêcheur Statut : Réparation en cours,
   17/09 08:12 »).
   Une seule ligne par mouvement, et pas de hauteur maximale : mesuré à 1 280 px
   avec quatre lignes par mouvement (client, corps du message…), le fil pesait
   2 900 px et laissait la colonne de gauche 1 900 px plus haut que lui. Le
   corps du message n'est pas repris ici — il se lit sur la fiche, à un clic. */
.fil {
  list-style: none;
  margin: 10px 0 0;
  padding: 0;
}

.fil__item + .fil__item {
  border-top: 1px solid var(--line);
}

.fil__lien {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 2px 12px;
  align-items: baseline;
  padding: 8px;
  border-radius: var(--radius-sm);
  color: var(--text);
  text-decoration: none;
}

.fil__lien:hover {
  background: var(--sterile);
}

.fil__lien:focus-visible {
  outline: 3px solid var(--signal-ink);
  outline-offset: -3px;
}

.fil__ref {
  font-family: var(--mono);
  font-size: 0.86rem;
  font-weight: 500;
  white-space: nowrap;
}

.fil__quand {
  font-family: var(--mono);
  font-size: 0.76rem;
  color: var(--muted);
  text-align: right;
  white-space: nowrap;
}

/* Deux lignes par mouvement, et c'est tout : la référence et sa date en haut,
   le client et ce qui s'est passé en dessous. Mesuré à 1 280 px dans une
   colonne de 464 px, une ligne unique à quatre colonnes ne laissait que 18 px
   au libellé du mouvement (le `1fr` se réduisait à rien) et chaque ligne
   s'étirait sur 376 px. */
.fil__details {
  grid-column: 1 / -1;
  font-size: 0.84rem;
  color: var(--muted);
  overflow-wrap: anywhere;
}

.fil__client {
  color: var(--text);
}

.fil__interne {
  display: inline-block;
  margin-left: 6px;
  padding: 0 6px;
  border: 1px solid var(--line);
  border-radius: 999px;
  font-family: var(--mono);
  font-size: 0.66rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
}

/* Sous 1020 px, une seule colonne : deux colonnes de 460 px à 1020 px
   laisseraient 210 px par widget, où « Mois précédent · août 2026 » se coupe
   au milieu du mot. */
@media (max-width: 1020px) {
  .tablo {
    grid-template-columns: minmax(0, 1fr);
  }
  .delais dd {
    text-align: left;
  }
}

/* Sous 480 px, la grille des mesures s'empile : le libellé au-dessus de sa
   valeur, sinon « Forfait diagnostic » laisse 120 px à un texte qui en demande
   300 et la colonne des valeurs devient illisible. */
@media (max-width: 480px) {
  .mesures {
    grid-template-columns: minmax(0, 1fr);
    gap: 4px 0;
  }
  .mesures dt {
    padding-top: 8px;
  }
  .periodes {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ── Textes du site (carte t_5fa5ba22) ────────────────────────────────────
   L'écran d'édition des textes : des onglets, un champ par texte, l'historique
   replié sous chaque champ (élément natif : clavier et lecteur d'écran
   compris, sans un octet de JavaScript), et le panneau de lecture seule des
   documents juridiques. Les textes longs se lisent au `pre-wrap` : les
   retours à la ligne du porteur sont conservés, exactement comme il les a
   saisis — la page les rend en HTML, l'aperçu de l'historique aussi. */

.onglets {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 18px 0 0;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--line);
}

.onglet {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 38px;
  padding: 7px 14px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--paper);
  color: var(--petrol);
  font-size: 0.92rem;
  font-weight: 500;
  text-decoration: none;
}

.onglet:hover {
  border-color: var(--line-strong);
  background: var(--sterile);
}

.onglet[aria-current="page"] {
  border-color: var(--signal);
  background: var(--signal);
  color: #fff;
  font-weight: 600;
}

.onglet__n {
  font-family: var(--mono);
  font-size: 0.72rem;
  opacity: 0.75;
}

.onglets__resume {
  margin: 12px 0 20px;
  color: var(--muted);
}

.texte {
  margin-bottom: 18px;
  padding: 16px 18px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--paper);
  box-shadow: var(--shadow);
}

/* Intertitre d'une entrée éditée (une question de FAQ, un engagement…) : sans
   lui, « Question 3 » et « Réponse 3 » se suivraient sans qu'on sache ce
   qu'ils portent. Le titre affiché est le texte EN COURS, pas une copie : il
   suit la saisie dès qu'elle est enregistrée. */
.texte__groupe {
  margin: 26px 0 10px;
  font-family: var(--display);
  font-size: 0.98rem;
  font-weight: 600;
  color: var(--petrol);
}

.texte__groupe-n {
  display: inline-block;
  margin-right: 8px;
  padding: 2px 9px;
  border-radius: 999px;
  background: var(--sterile-2);
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.66rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

/* Le champ qu'une saisie refusée visait : encadré d'alerte, et l'erreur est
   annoncée en haut de page (`role="alert"`). */
.texte--fautif {
  border-color: var(--alert-ink);
  box-shadow: 0 0 0 2px rgba(179, 38, 30, 0.12);
}

.texte__tete {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px 14px;
  margin-bottom: 10px;
}

.texte__titre {
  margin: 0;
  font-family: var(--display);
  font-size: 1.06rem;
}

.texte__etat {
  margin: 0;
  color: var(--muted);
  font-size: 0.84rem;
}

.pastille {
  display: inline-block;
  padding: 2px 9px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--sterile);
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.pastille--saisi {
  border-color: var(--signal);
  background: rgba(30, 115, 190, 0.1);
  color: var(--signal-ink);
}

.field--texte {
  display: block;
}

.field--texte textarea {
  width: 100%;
  min-height: 3.4rem;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--paper);
  color: var(--text);
  font-family: var(--body);
  font-size: 0.95rem;
  line-height: 1.55;
  resize: vertical;
}

.texte__pied {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 18px;
  margin-top: 10px;
}

.texte__ou {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 10px;
  font-size: 0.86rem;
}

.texte__oulabel {
  font-family: var(--mono);
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
}

.texte__pied .tiny {
  margin: 0;
  flex: 1 1 240px;
  color: var(--muted);
}

.histo {
  margin-top: 14px;
  border-top: 1px dashed var(--line);
  padding-top: 10px;
}

.histo summary {
  cursor: pointer;
  color: var(--signal-ink);
  font-size: 0.88rem;
  font-weight: 500;
}

.histo__liste {
  margin: 12px 0 0;
  padding: 0;
  list-style: none;
}

.histo__item {
  padding: 10px 12px;
  margin-bottom: 8px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--sterile);
}

.histo__entete {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 12px;
  margin-bottom: 6px;
}

.histo__date {
  font-family: var(--mono);
  font-size: 0.78rem;
  color: var(--petrol);
}

/* La valeur remplacée, telle qu'elle était publiée : les retours à la ligne
   sont ceux de la saisie. */
.histo__valeur {
  margin: 0 0 10px;
  padding: 8px 10px;
  border-left: 3px solid var(--line-strong);
  background: var(--paper);
  color: var(--text);
  font-size: 0.88rem;
  line-height: 1.5;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* ── Panneau de lecture seule (mentions légales et CGV) ─────────────────── */

.lecture {
  margin-bottom: 22px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--paper);
  box-shadow: var(--shadow);
  overflow: hidden;
}

.lecture__bandeau {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 16px;
  padding: 12px 18px;
  border-bottom: 1px solid var(--line);
  background: var(--sterile);
}

.lecture__bandeau h2 {
  margin: 0;
  font-size: 1.05rem;
}

.lecture__etat {
  margin: 0;
  flex: 1 1 120px;
}

.lecture__sceau {
  display: inline-block;
  padding: 2px 10px;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: var(--paper);
  color: var(--petrol);
  font-family: var(--mono);
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

/* Le texte publié est repris tel quel : on neutralise seulement les bandes
   de la page publique (fond et gouttières) pour qu'il se lise dans le
   panneau, sans réécrire une ligne de ce qui est publié. */
.lecture__texte {
  padding: 4px 18px 14px;
  overflow-wrap: anywhere;
}

.lecture__texte .band,
.lecture__texte .wrap {
  padding: 0;
  margin: 0;
  background: transparent;
  border: 0;
  max-width: none;
}

.lecture__texte .card {
  box-shadow: none;
}

.lecture__texte .crumbs,
.lecture__texte .head h1 {
  display: none;
}

.regles ul {
  margin: 10px 0 0;
  padding-left: 20px;
}

.regles li {
  margin-bottom: 8px;
}

/* Sous 620 px, le pied d'un champ s'empile : « Apparaît sur » au-dessus des
   liens, le bouton en dernier — un bouton à droite d'un texte de 240 px
   laisserait 12 px au texte. */
@media (max-width: 620px) {
  .texte {
    padding: 14px;
  }
  .texte__pied {
    flex-direction: column;
    align-items: flex-start;
  }
  .texte__pied .btn {
    align-self: stretch;
    text-align: center;
  }
  .lecture__bandeau {
    align-items: flex-start;
  }
}

/* ==========================================================================
   IMAGES — la bibliothèque du site (carte t_8e210101)
   --------------------------------------------------------------------------
   Un bloc par emplacement d'image : aperçu, chiffres réels, pages où elle
   apparaît, et les trois gestes (remplacer, revenir en arrière, supprimer).

   Deux précautions de mise en page, mesurées :
     — `minmax(min(320px, 100%), 1fr)` : une colonne de grille a pour minimum le
       MIN-CONTENU de ses items ; un nom d'emplacement sans espace
       (« appareil-ordinateur-pc ») élargirait la colonne au-delà du conteneur à
       360 px. Le plancher `min(320px, 100%)` l'en empêche ;
     — `overflow-wrap: anywhere` sur les identifiants : un identifiant long se
       coupe au lieu de déborder.
   ========================================================================== */
.images {
  display: grid;
  gap: 18px;
  grid-template-columns: repeat(auto-fill, minmax(min(320px, 100%), 1fr));
  margin-bottom: 26px;
}

.images__titre {
  font-family: var(--display);
  font-size: clamp(1.15rem, 2vw, 1.45rem);
  font-weight: 800;
  letter-spacing: -0.01em;
  margin: 30px 0 6px;
  display: flex;
  align-items: center;
  gap: 10px;
  overflow-wrap: anywhere;
}

.img-card {
  display: flex;
  flex-direction: column;
  min-width: 0;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}

.img-card--lourde {
  border-color: var(--amber);
}

.img-card__apercu {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 132px;
  padding: 12px;
  background: repeating-conic-gradient(var(--sterile) 0% 25%, var(--sterile-2) 0% 50%) 50% / 18px 18px;
  border-bottom: 1px solid var(--line);
}

.img-card__apercu img {
  max-width: 100%;
  max-height: 190px;
  width: auto;
  height: auto;
  display: block;
  border-radius: var(--radius-sm);
  background: var(--paper);
}

.img-card__vide {
  margin: 0;
  text-align: center;
  color: var(--muted);
  font-size: 0.85rem;
  display: grid;
  gap: 8px;
  justify-items: center;
}

.img-card__corps {
  padding: 14px 15px 16px;
  display: grid;
  gap: 10px;
  min-width: 0;
}

.img-card__titre {
  margin: 0;
  font-family: var(--mono);
  font-size: 0.95rem;
  font-weight: 600;
  overflow-wrap: anywhere;
}

.img-card__chiffres {
  margin: 0;
  font-size: 0.85rem;
  color: var(--muted);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  overflow-wrap: anywhere;
}

.img-card__alerte {
  margin: 0;
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  font-size: 0.82rem;
  background: rgba(168, 104, 0, 0.09);
  border-left: 3px solid var(--amber);
  overflow-wrap: anywhere;
}

.img-card__alerte--forte {
  background: rgba(179, 38, 30, 0.08);
  border-left-color: var(--alert-ink);
}

.img-card__alerte strong {
  display: block;
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--amber-ink);
}

.img-card__alerte--forte strong {
  color: var(--alert-ink);
}

.img-card__pages h4 {
  margin: 0 0 6px;
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

.img-card__vues {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 6px;
}

.img-card__vues li {
  font-size: 0.85rem;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px;
  overflow-wrap: anywhere;
}

.img-card__vues a {
  color: var(--signal-ink);
}

.img-card__form {
  display: grid;
  gap: 8px;
  padding-top: 12px;
  border-top: 1px solid var(--line);
}

.field__fichier {
  width: 100%;
  font-size: 0.85rem;
  padding: 8px;
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--sterile);
  color: var(--text);
}

.field__fichier:focus-visible {
  outline: 3px solid var(--signal);
  outline-offset: 2px;
}

.methode details {
  margin-top: 8px;
}

.methode summary {
  cursor: pointer;
  font-size: 0.85rem;
  color: var(--signal-ink);
}

.images__poids,
.images__marque {
  margin-top: 12px;
}

.images__marque td,
.images__marque th {
  vertical-align: top;
  white-space: normal;
  overflow-wrap: anywhere;
}

.histo--danger summary {
  color: var(--alert-ink);
  font-weight: 600;
}

@media (max-width: 620px) {
  .img-card__apercu img {
    max-height: 150px;
  }
  .images {
    gap: 14px;
  }
}

/* ==========================================================================
   Carte « nous ne vous traçons pas » (carte t_34947d22)
   --------------------------------------------------------------------------
   Le porteur a demandé « un pop up » ; l'arbitrage est une CARTE, jamais un
   interstitiel : Google sanctionne les fenêtres qui recouvrent la page sur
   téléphone, et le référencement local a coûté des heures.

   LA CARTE NE RECOUVRE RIEN, À AUCUNE LARGEUR. Elle est posée DANS le flux,
   en fin de pied de page — sur téléphone comme sur ordinateur. Le coin
   bas-droit de la PAGE, pas celui de la fenêtre.

   Ce n'est pas un choix de confort, c'est une mesure. Une variante « carte
   flottante dans le coin bas-droit, position fixe, à partir de 1021 px » a
   été construite puis MESURÉE page par page (Chromium, fenêtre 1280 × 800 —
   relevés reproductibles par la sonde de la carte, voir tests/confidentialite.js) :

     · /envoi   : 25 198 px² de texte informatif recouverts ;
     · /tarifs  :  2 323 px² ;
     · /faq     : 3 éléments INTERACTIFS sous la carte (des liens qu'on ne
                  peut plus cliquer tant qu'on n'a pas fermé la carte) ;
     · /reparations : 1, /suivi : 2 ;
     · accueil  : rien d'informatif, mais une étiquette décorative
                  (`aria-hidden`) recouverte, et 8,27 % de la fenêtre occupés.

   Or la règle de la carte est écrite noir sur blanc : « la page reste
   entièrement lisible et utilisable sans fermer la carte », « elle ne
   recouvre jamais le contenu ». Un lien recouvert n'est plus cliquable : la
   variante flottante ne tenait pas cette promesse autrement qu'en la
   chiffrant. Elle est donc écartée, et la question est posée au porteur :
   garder la carte dans le flux (zéro recouvrement, visible en bas de page)
   ou accepter un recouvrement de coin au-delà de 1020 px.

   Trois propriétés, dans l'ordre :

     1. SANS JavaScript — la carte est un bloc ORDINAIRE, en fin de pied de
        page. Elle ne recouvre rien, ne se ferme pas, et n'a pas besoin de se
        fermer : le message se lit, la page reste entièrement utilisable.
     2. AVEC JavaScript — `public/js/confidentialite.js` pose
        `.carte-prive--js`, qui fait apparaître le bouton « Fermer » : une
        commande qui ne peut pas agir ne s'affiche pas.
     3. Au-delà de 1020 px, la carte se cale dans le coin bas-droit de la
        PAGE (`margin-left: auto` dans le `.wrap` du pied) : même place que la
        carte flottante, sans rien recouvrir.

   Couleurs : `--text` sur `--paper` (16,59:1 mesuré) et `--signal-ink` pour
   le lien et le bouton (6,95:1), toutes deux déjà portées par
   `tests/contraste.js`. Le bleu de marque `--signal` n'est pas employé en
   texte : il ne tient que 4,94:1 sur blanc, sans marge.
   ========================================================================== */
.carte-prive {
  margin: 22px 0 0;
  padding: 14px 16px;
  max-width: 62ch;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--paper);
  color: var(--text);
  font-size: 0.9rem;
  line-height: 1.5;
}

.carte-prive__texte {
  margin: 0;
}

.carte-prive__texte a {
  color: var(--signal-ink);
}

/* Le bouton « Fermer » ne s'affiche que lorsqu'il peut agir : sans
   JavaScript, il serait une commande morte. C'est le script qui pose
   `.carte-prive--js` — et lui seul. */
.carte-prive__fermer {
  display: none;
}

.carte-prive--js .carte-prive__fermer {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  margin-top: 10px;
  padding: 8px 16px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--paper);
  color: var(--signal-ink);
  font: inherit;
  font-size: 0.85rem;
  cursor: pointer;
}

.carte-prive--js .carte-prive__fermer:hover {
  border-color: var(--signal);
}

@media (min-width: 1021px) {
  .carte-prive {
    margin-left: auto;
    max-width: 420px;
    box-shadow: var(--shadow);
  }
}

/* --- Liste d'activation du paiement (carte t_0659a16a) ------------------
   Sept étapes numérotées, chacune avec l'état CONSTATÉ par le serveur et,
   pour les deux étapes que le site ne peut pas mesurer (l'immatriculation et
   l'ouverture du compte Stripe), une case que le porteur coche lui-même.
   La numérotation est portée par le titre (« 1. », « 2. »…) et non par un
   marqueur de liste : à 360 px, la ligne passe sur deux lignes et un marqueur
   `list-style` se détacherait du texte. */
.etapes {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 12px;
}

.etape {
  background: var(--paper);
  border: 1px solid var(--line);
  border-left: 4px solid var(--line-strong);
  border-radius: var(--radius-sm);
  padding: 12px 16px;
}

.etape--faite {
  border-left-color: var(--vital-ink);
  background: rgba(11, 122, 88, 0.05);
}

.etape__titre {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin: 0;
}

/* Les noms d'événements Stripe (« checkout.session.async_payment_succeeded »,
   « charge.refunded »…) ne contiennent AUCUN point de coupure : dans une
   colonne étroite, un tel mot impose son min-content, la piste de grille
   s'élargit au-delà du panneau et la page déborde (mesuré à 360 px : carte de
   341 px pour 298 px de place, 12 px de débordement de page). `overflow-wrap:
   anywhere` change le min-content — `break-word` ne le fait pas. La règle est
   portée par la carte elle-même : aucun texte de la liste d'activation ne peut
   plus élargir le panneau, quelle que soit la longueur d'un jeton. */
.etape {
  overflow-wrap: anywhere;
}

.etape .ref {
  overflow-wrap: anywhere;
}

/* Le paragraphe qui liste les quatre événements à cocher chez Stripe porte les
   mêmes jetons ; il vit hors de la liste d'activation, d'où sa propre règle
   (classe posée par views/admin/paiement.ejs). */
.paiement-jetons .ref {
  overflow-wrap: anywhere;
}

/* ==========================================================================
   MESSAGE D'INFORMATION — BANDE FIXE, ZONE DE LECTURE RÉSERVÉE
   (carte t_d0b8a8fd ; complète la carte t_34947d22 sans la refaire)
   ==========================================================================
   Le porteur a demandé que le message « nous ne vous traçons pas » SUIVE
   L'ÉCRAN jusqu'à ce qu'il le ferme, et la carte pose une limite non
   négociable : « il ne recouvre jamais le contenu principal ». Les deux ne
   peuvent pas être tenus par un simple `position: fixed` : un élément fixe
   est peint AU-DESSUS du document, donc il recouvre tout ce qui défile
   dessous. Mesuré avant d'écrire ces règles (sonde de la carte, la carte
   réelle posée en `position: fixed` dans la page, cinq positions de
   défilement, quatre pages, 360 px) :

     · /faq   : 261 994 px² de texte recouverts, dont CINQ `<summary>`
                (les questions de la FAQ) devenus incliquables ;
     · /envoi :  67 849 px² ; /tarifs : 63 504 px² ; accueil : 57 061 px².

   C'est exactement le défaut qui a fait écarter la variante « carte
   flottante » de la carte parente. La seule façon d'obtenir À LA FOIS
   « suit l'écran » et « ne recouvre rien » est de RÉSERVER la place de la
   bande dans la fenêtre : la page défile dans la zone située AU-DESSUS, la
   bande occupe le bas. Elle n'est donc jamais peinte sur le contenu — elle
   est à côté. Mesuré après (mêmes pages, mêmes positions) : 0 px².

   Trois conséquences, assumées et documentées :

     1. Le défilement de la page devient celui du CORPS (`body`) et non plus
        celui du document : c'est la seule manière de réduire la zone de
        défilement sans toucher au balisage des vues. `html` garde la
        hauteur de la fenêtre et `overflow: hidden`. Le script de la carte
        remet `window.scrollY`, `window.scrollTo` et l'événement `scroll`
        sur ce défilement (voir `public/js/confidentialite.js`) : le reste du
        site — et les harnais de la maison qui défilent avec
        `window.scrollTo` — continue de fonctionner sans une ligne de
        changement ailleurs.
     2. La classe `carte-prive-actif` n'est posée QUE si la bande existe
        vraiment : le script la pose sur `html` après avoir trouvé le message
        dans le HTML servi et constaté que la fermeture n'a pas été
        mémorisée. Sans JavaScript, ou carte fermée : aucune de ces règles ne
        s'applique, la page défile exactement comme avant.
     3. En IMPRESSION, tout est remis à plat (bloc `@media print` plus bas) :
        une zone de défilement réduite tronquerait le document papier.

   La hauteur réservée est MESURÉE par le script (`--carte-prive-h`), jamais
   devinée : la bande est en pleine largeur, son texte fait donc plus ou moins
   de lignes selon la fenêtre.
   ========================================================================== */

/* 1. La fenêtre est partagée : la page défile au-dessus de la bande. */
html.carte-prive-actif {
  height: 100%;
  overflow: hidden;
}

html.carte-prive-actif body {
  /* `dvh` : la fenêtre change de hauteur quand la barre d'adresse du
     téléphone se replie ; `vh` la surestime (barre masquée). La seconde
     déclaration corrige la première là où `dvh` est connu, la première sert
     de repli là où il ne l'est pas. */
  height: calc(100vh - var(--carte-prive-h, 0px));
  height: calc(100dvh - var(--carte-prive-h, 0px));
  overflow-y: auto;
  scroll-behavior: smooth;
}

/* 2. La bande elle-même : pleine largeur, collée au bas de la fenêtre,
   au-dessus de l'en-tête collant (40) et sous le lien d'évitement (100). */
html.carte-prive-actif .carte-prive {
  position: fixed;
  z-index: 50;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 16px;
  /* Le texte s'aligne sur la colonne de la page (`--wrap`), pas sur les
     bords de la fenêtre. */
  padding: 12px max(var(--gutter), calc((100% - var(--wrap)) / 2));
  max-width: none;
  margin: 0;
  border: 0;
  border-top: 1px solid var(--line-strong);
  border-radius: 0;
  /* Une ombre portée VERS LE HAUT : la bande se détache sans crier. */
  box-shadow: 0 -10px 30px -22px rgba(6, 26, 51, 0.38);
  background: var(--paper);
  color: var(--text);
  font-size: 0.9rem;
  line-height: 1.5;
}

/* 3. Le message. Plafonné en hauteur : sur une fenêtre très courte (ou avec
   un zoom fort), le texte défile DANS la bande plutôt que de repousser la
   page hors de l'écran. `overscroll-behavior: contain` empêche que ce
   défilement interne entraîne celui de la page. */
html.carte-prive-actif .carte-prive__texte {
  order: 1;
  flex: 1 1 320px;
  max-width: 78ch;
  max-height: 45dvh;
  overflow-y: auto;
  overscroll-behavior: contain;
}

/* 4. « Fermer » reste HORS de la zone défilante : la commande est visible en
   permanence, quel que soit l'état du texte. */
html.carte-prive-actif .carte-prive__fermer {
  order: 2;
  flex: 0 0 auto;
  margin-top: 0;
}

/* 5. Téléphone : bande plus serrée, cible tactile de la maison conservée. */
@media (max-width: 620px) {
  html.carte-prive-actif .carte-prive {
    padding: 10px var(--gutter) 12px;
    font-size: 0.8rem;
    line-height: 1.45;
  }
  html.carte-prive-actif .carte-prive__fermer {
    margin-top: 2px;
  }
}

/* 6. Impression : la zone de défilement réduite tronquerait le document. */
@media print {
  html.carte-prive-actif {
    height: auto;
    overflow: visible;
  }
  html.carte-prive-actif body {
    height: auto;
    overflow: visible;
  }
  html.carte-prive-actif .carte-prive {
    position: static;
  }
}

/* ══ Tableau d'ARRIVÉE du back-office (carte t_65e6c6c3) ═══════════════════
   Deux listes ajoutées à l'écran du matin : la liste des actions
   (`.matin`) et les listes de connexions (`.connexions`).

   Partis pris, mesurés à 360 px :
     · aucune colonne de grille `1fr` : une piste `1fr` a pour minimum le
       min-contenu de ses items et peut tomber à ZÉRO (défaut déjà rencontré
       sur ce dépôt) — les lignes sont donc EMPILÉES, le nombre à gauche et
       le texte à droite, avec `min-width: 0` sur le texte pour qu'il se
       coupe au lieu de pousser la page ;
     · `overflow-wrap: anywhere` sur le détail : une adresse de dossier ou
       un identifiant de compte n'a aucun point de coupure et imposerait sa
       largeur (même défaut que les noms d'événements Stripe).
   Aucune couleur nouvelle : la palette de la maison (var(--…)). */
.matin,
.connexions {
  list-style: none;
  margin: 10px 0 0;
  padding: 0;
}

.matin__item,
.connexions__item {
  border-bottom: 1px solid var(--line);
}

.matin__item:last-child,
.connexions__item:last-child {
  border-bottom: 0;
}

.matin__lien {
  display: flex;
  align-items: baseline;
  gap: 12px;
  padding: 9px 0;
  color: inherit;
  text-decoration: none;
}

.matin__lien:hover .matin__quoi,
.matin__lien:focus-visible .matin__quoi {
  text-decoration: underline;
}

.matin__n {
  flex: 0 0 auto;
  min-width: 1.5em;
  text-align: right;
  font-family: var(--mono);
  font-size: 1.15rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

.matin__detail {
  flex: 1 1 auto;
  min-width: 0;
}

.matin__quoi {
  display: block;
  font-weight: 600;
}

.matin__suite {
  display: block;
  font-size: 0.8125rem;
  line-height: 1.45;
  color: var(--muted);
  overflow-wrap: anywhere;
}

/* L'anomalie de rapprochement : le nombre passe en rouge d'incident. La
   couleur ne porte jamais l'information seule — le libellé de la ligne la
   dit déjà (« sans dossier mis à jour », « sans machine arrivée »). */
.matin__item--alerte .matin__n {
  color: #b3261e;
}

.matin__vide {
  margin: 10px 0 0;
  color: var(--muted);
}

/* L'information de sécurité (tentatives refusées) : un liseré, pas un
   bandeau d'alerte — elle doit se voir sans dramatiser. */
.matin__securite {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 10px;
  align-items: baseline;
  margin: 14px 0 0;
  padding: 10px 12px;
  border-left: 3px solid #b3261e;
  background: #fdf4f3;
  border-radius: 0 var(--radius) var(--radius) 0;
  font-size: 0.9rem;
}

.matin__securite strong {
  font-family: var(--mono);
  font-size: 0.7rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #8c1d18;
}

.connexions__item {
  padding: 8px 0;
}

.connexions__quand {
  display: block;
  font-family: var(--mono);
  font-size: 0.75rem;
  color: var(--muted);
}

.connexions__quoi {
  display: block;
  overflow-wrap: anywhere;
}

/* Même liseré que l'encadré du matin, sans fond : la liste reste sobre. */
.connexions--alerte {
  border-left: 3px solid #b3261e;
  padding-left: 12px;
}

.connexions--alerte .connexions__quoi {
  color: #8c1d18;
}
