/* ══════════════════════════════════════════════════════════════════════
   ARCSTUD — interface tablette client (§3)
   ══════════════════════════════════════════════════════════════════════

   Charte reprise des maquettes `docs/maquettes/01-client-tablette.html` et
   `04-client-ecrans-reference.html` : palette navy/teal/rose/or, Public Sans,
   cartes blanches sur fond gris clair, bandeau supérieur permanent.

   ── Ce qui diffère des maquettes, et pourquoi ──────────────────────────

   Les maquettes sont des vignettes de 340 px de large affichées sur un
   écran de bureau. Les tailles y sont choisies pour cette vignette : 10 px
   pour le bandeau, 12,5 px pour un nom de résident. Reprises telles quelles
   sur l'appareil réel — 8,7 pouces, tenu à bout de bras, dans un hall
   d'entrée, souvent par quelqu'un qui n'a pas ses lunettes — elles seraient
   illisibles.

   Les proportions, les couleurs et la structure des maquettes sont donc
   respectées ; les tailles sont redonnées pour le matériel de la §2.4. Les
   cibles tactiles ne descendent jamais sous 56 px.
   ══════════════════════════════════════════════════════════════════════ */

:root {
  /* Palette — CLAUDE.md */
  --navy: #1D3557;
  --teal: #2A9D8F;
  --rose: #B33951;
  --or: #E9C46A;

  --fond: #F4F6F8;
  --bordure: #D8DEE4;
  --texte: #1B1F23;
  --texte-second: #5C6B7A;
  --blanc: #fff;

  /* Teintes dérivées, une seule fois ici plutôt qu'en dur dans les règles */
  --navy-pale: #EAF0F4;
  --teal-pale: #E4F3F1;
  --teal-fonce: #1F7A6E;
  --rose-pale: #F9E3E7;
  --or-pale: #FBF1D8;
  --or-fonce: #8A6D18;

  --rayon: 10px;
  --rayon-petit: 7px;

  /* Cible tactile minimale. Ce n'est pas une préférence esthétique : en
     dessous, le taux d'erreur au pavé numérique devient sensible, et une
     erreur de PIN coûte un essai sur les cinq autorisés (§3.1). */
  --cible: 56px;

  /* Échelle typographique fluide. `vmin` plutôt que `vw` : la tablette est
     en portrait, mais les maquettes de référence et les écrans de recette
     sont en paysage — l'échelle doit tenir dans les deux sens. */
  --t-xs: clamp(12px, 1.7vmin, 15px);
  --t-s: clamp(14px, 2.1vmin, 18px);
  --t-m: clamp(16px, 2.5vmin, 21px);
  --t-l: clamp(19px, 3.1vmin, 26px);
  --t-xl: clamp(23px, 4vmin, 34px);
  --t-xxl: clamp(30px, 5.4vmin, 46px);

  --ombre: 0 2px 6px rgba(29, 53, 87, 0.06);
}

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

/* L'attribut `hidden` ne vaut qu'un `display: none` de feuille de style du
   navigateur : n'importe quelle classe qui pose un `display` le neutralise.
   C'est ainsi que le bouton URGENCE restait affiché sur l'écran
   d'installation, où il ne mène nulle part — `.bouton { display: inline-flex }`
   l'emportait. La règle est posée une fois, pour tous les composants. */
[hidden] { display: none !important; }

html, body {
  height: 100%;
  background: var(--fond);
  color: var(--texte);
  /* Public Sans ne couvre ni l'arabe ni le géorgien (§3.6). Les replis
     nommés sont les polices présentes sur Android — l'appareil sait rendre
     ces écritures, embarquer Noto coûterait plusieurs mégaoctets. */
  font-family: 'Public Sans', 'Noto Naskh Arabic', 'Noto Sans Georgian', system-ui, sans-serif;
  font-size: var(--t-m);
  line-height: 1.45;
  -webkit-text-size-adjust: 100%;
}

body {
  /* Kiosque : ni sélection de texte, ni loupe de sélection, ni menu
     contextuel sur appui long, ni rebond élastique en fin de liste. Chacun
     de ces gestes laisse l'écran dans un état dont un résident ne sait pas
     sortir, sur un appareil sans bouton retour. */
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
  -webkit-tap-highlight-color: transparent;
  overscroll-behavior: none;
  touch-action: manipulation;
}

/* Le champ de description d'urgence et celui du jeton d'appareil sont les
   deux seuls endroits où l'on saisit du texte : la sélection y est rendue. */
input, textarea { -webkit-user-select: text; user-select: text; }

button { font: inherit; color: inherit; border: none; background: none; cursor: pointer; }

svg { display: block; flex: none; }

/* ── Ossature ────────────────────────────────────────────────────────── */

.app {
  display: grid;
  grid-template-rows: auto auto 1fr auto;
  /* `dvh` et non `vh` : la barre système du navigateur kiosque peut
     apparaître au premier chargement, et `vh` placerait alors le bouton
     urgence sous le bord de l'écran. */
  height: 100dvh;
  overflow: hidden;
}

/* ── Bandeau : créneau + lieu, en permanence ─────────────────────────── */
/* « Le bandeau supérieur rappelle le créneau horaire en permanence, jamais
   besoin de deviner si on peut signer » (maquette 04). */

.bandeau {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px clamp(14px, 2.6vmin, 30px);
  background: var(--navy);
  color: var(--blanc);
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: 0.2px;
}

.bandeau--urgence { background: var(--rose); }

.bandeau__etat { display: flex; align-items: center; gap: 7px; min-width: 0; }
.bandeau__etat svg { width: 1.1em; height: 1.1em; }
.bandeau__lieu { opacity: 0.85; white-space: nowrap; }

/* ── En-tête : titre de l'écran + sélecteur de langue ────────────────── */

.entete {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 14px;
  padding: clamp(12px, 2.2vmin, 22px) clamp(14px, 2.6vmin, 30px);
  background: var(--blanc);
  border-bottom: 1px solid var(--bordure);
}

.entete__texte { min-width: 0; }
.entete__titre { font-size: var(--t-l); font-weight: 800; color: var(--navy); }
.entete__sous-titre {
  margin-top: 3px;
  font-size: var(--t-xs);
  color: var(--texte-second);
  /* Deux lignes maximum : le nom d'un résident et celui d'un logement sont
     de longueur inconnue, et l'en-tête ne doit pas repousser le corps. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.entete__sous-titre:empty { display: none; }

/* ── Sélecteur de langue (§3.6) ──────────────────────────────────────── */

.langue { position: relative; flex: none; }

.langue__bouton {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: var(--cible);
  padding: 0 16px;
  border: 1px solid var(--bordure);
  border-radius: var(--rayon-petit);
  background: var(--fond);
  color: var(--navy);
  font-size: var(--t-s);
  font-weight: 700;
}
.langue__bouton svg { width: 1.2em; height: 1.2em; }
.langue__bouton[aria-expanded="true"] { border-color: var(--navy); }

.langue__menu {
  position: absolute;
  inset-inline-end: 0;
  top: calc(100% + 6px);
  z-index: 20;
  min-width: 230px;
  padding: 6px;
  list-style: none;
  background: var(--blanc);
  border: 1px solid var(--bordure);
  border-radius: var(--rayon);
  box-shadow: 0 10px 26px rgba(29, 53, 87, 0.18);
}

.langue__item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  min-height: var(--cible);
  padding: 0 12px;
  border-radius: var(--rayon-petit);
  font-size: var(--t-s);
  font-weight: 600;
  text-align: start;
}
.langue__item[aria-selected="true"] { background: var(--navy); color: var(--blanc); }
.langue__item svg { width: 1.1em; height: 1.1em; margin-inline-start: auto; }
/* Le libellé de chaque langue est écrit dans cette langue : il doit se lire
   dans son propre sens, quel que soit celui de l'interface au moment où le
   menu est ouvert. Sans ça, « العربية » s'affiche à l'envers pour un
   francophone qui cherche à passer à l'arabe. */
.langue__item[data-sens="rtl"] { direction: rtl; }
.langue__item[data-sens="ltr"] { direction: ltr; }

/* ── Corps ───────────────────────────────────────────────────────────── */

.corps {
  padding: clamp(14px, 2.6vmin, 30px);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

/* Écrans qui se centrent dans la hauteur disponible plutôt que de s'empiler
   en haut : confirmation, hors créneau, messages d'erreur.

   `safe center` et non `center` : un contenu plus haut que la zone, centré,
   déborde des DEUX côtés, et la partie sortie par le haut est inatteignable
   au défilement. C'est le cas de l'écran de repli d'urgence en paysage — les
   numéros de secours passaient sous le pied de page. `safe` recale le
   contenu en début d'axe dès qu'il ne tient plus, et le défilement redevient
   possible. */
.corps--centre {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: safe center;
  gap: 14px;
  text-align: center;
}

/* Écrans dont le contenu doit occuper toute la hauteur (zone de signature). */
.corps--pleine { display: flex; flex-direction: column; overflow: hidden; }

.attente { color: var(--texte-second); font-size: var(--t-s); }

/* ── Pied de page : marque + bouton urgence ──────────────────────────── */
/* « Bouton urgence toujours visible en bas à droite, sur tous les écrans »
   (maquette 04), y compris hors créneau (§3.2). */

.pied {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: clamp(10px, 1.8vmin, 18px) clamp(14px, 2.6vmin, 30px);
  background: var(--blanc);
  border-top: 1px solid var(--bordure);
  /* Marge de sécurité sous l'encoche / la barre de gestes Android. */
  padding-bottom: max(clamp(10px, 1.8vmin, 18px), env(safe-area-inset-bottom));
}

.pied__marque {
  font-size: var(--t-xs);
  font-weight: 700;
  letter-spacing: 0.6px;
  color: var(--texte-second);
}

/* ── Boutons ─────────────────────────────────────────────────────────── */

.bouton {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  min-height: var(--cible);
  padding: 0 clamp(16px, 2.4vmin, 26px);
  border-radius: var(--rayon-petit);
  font-size: var(--t-s);
  font-weight: 700;
  transition: filter 120ms ease, background-color 120ms ease;
}
.bouton svg { width: 1.25em; height: 1.25em; }
.bouton:active { filter: brightness(0.93); }
.bouton[disabled] { opacity: 0.45; cursor: default; }
.bouton[disabled]:active { filter: none; }

.bouton--urgence {
  background: var(--rose);
  color: var(--blanc);
  letter-spacing: 0.5px;
  /* Le seul bouton de l'interface dont la taille ne dépend pas du contenu :
     il doit être atteignable sans le lire, y compris par quelqu'un qui ne
     lit aucune des langues proposées. */
  padding-inline: clamp(20px, 3.2vmin, 34px);
}

.bouton--primaire { background: var(--teal); color: var(--blanc); }

.bouton--secondaire {
  background: var(--blanc);
  color: var(--navy);
  border: 1.5px solid var(--navy);
}

.bouton--neutre {
  background: var(--blanc);
  color: var(--texte-second);
  border: 1.5px solid var(--bordure);
}

.bouton--large { width: 100%; }

/* ── Cartes et titres de section ─────────────────────────────────────── */

.carte {
  background: var(--blanc);
  border: 1px solid var(--bordure);
  border-radius: var(--rayon);
  box-shadow: var(--ombre);
}

.bloc-titre { font-size: var(--t-l); font-weight: 800; color: var(--navy); }
.bloc-texte { font-size: var(--t-s); color: var(--texte-second); max-width: 46ch; }

/* ── Accueil ─────────────────────────────────────────────────────────── */

.accueil {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
  width: 100%;
  max-width: 560px;
  padding: clamp(22px, 4vmin, 40px);
  text-align: center;
}

.accueil__pastille {
  display: flex;
  align-items: center;
  justify-content: center;
  width: clamp(84px, 15vmin, 128px);
  aspect-ratio: 1;
  border-radius: 50%;
  background: var(--teal-pale);
  color: var(--teal-fonce);
}
.accueil__pastille svg { width: 52%; height: 52%; }

.accueil__etat { font-size: var(--t-xl); font-weight: 800; color: var(--navy); }
.accueil__action { font-size: var(--t-s); color: var(--texte-second); }

/* ── Liste des résidents ─────────────────────────────────────────────── */
/*
   Aucune pastille de statut, contrairement aux maquettes 01 et 04 qui
   montrent « Signé — 10h42 » et « En attente ». La §3.4 tranche l'autre
   sens : « une fois signé, le nom disparaît » et « aucune indication
   visuelle de qui a déjà signé/pas signé ». Les deux ne tiennent ensemble
   que si le nom disparaît — une ligne grisée afficherait, dans le hall
   d'entrée, qui a dormi là et qui n'y a pas dormi.

   L'API applique déjà ce filtre (`GET /residents` ne renvoie ni compteur, ni
   total, ni statut) ; il n'y a donc rien à dessiner ici.
*/

.liste { display: flex; flex-direction: column; gap: 10px; }

.resident {
  display: flex;
  align-items: center;
  gap: 14px;
  width: 100%;
  min-height: clamp(68px, 9vmin, 88px);
  padding: 12px 16px;
  background: var(--blanc);
  border: 1px solid var(--bordure);
  border-inline-start: 4px solid var(--navy);
  border-radius: var(--rayon-petit);
  text-align: start;
}
.resident:active { background: var(--navy-pale); }

.resident__pastille {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--navy-pale);
  color: var(--navy);
}
.resident__pastille svg { width: 22px; height: 22px; }

.resident__nom { flex: 1; min-width: 0; font-size: var(--t-m); font-weight: 700; }
.resident__chevron { color: var(--texte-second); }
.resident__chevron svg { width: 24px; height: 24px; }
/* Symétrie de lecture : en écriture de droite à gauche, la flèche « la suite
   est par ici » pointe vers la gauche. */
[dir="rtl"] .resident__chevron { transform: scaleX(-1); }

/* Sans PIN, la personne ne peut pas signer (§3.1) : la ligne reste visible
   mais renvoie vers un intervenant plutôt que d'échouer au pavé numérique. */
.resident--sans-pin { border-inline-start-color: var(--or); }
.resident--sans-pin .resident__chevron { display: none; }

.resident__note {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 11px;
  border-radius: var(--rayon-petit);
  background: var(--or-pale);
  color: var(--or-fonce);
  font-size: var(--t-xs);
  font-weight: 700;
  white-space: nowrap;
}
.resident__note svg { width: 1.1em; height: 1.1em; }

.liste-vide {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  padding: clamp(28px, 6vmin, 56px) 20px;
  color: var(--texte-second);
  text-align: center;
}
.liste-vide svg { width: 42px; height: 42px; opacity: 0.5; }

/* ── Code PIN ────────────────────────────────────────────────────────── */

.pin { display: flex; flex-direction: column; align-items: center; gap: clamp(14px, 2.6vmin, 26px); }

.pin__points { display: flex; gap: 20px; }

.pin__point {
  width: clamp(18px, 2.6vmin, 24px);
  aspect-ratio: 1;
  border: 2.5px solid var(--navy);
  border-radius: 50%;
  transition: background-color 90ms ease, transform 90ms ease;
}
.pin__point--plein { background: var(--navy); transform: scale(1.12); }

.pin__pave {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(9px, 1.6vmin, 16px);
  width: 100%;
  max-width: 440px;
}

.pin__touche {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: clamp(62px, 9vmin, 88px);
  background: var(--blanc);
  border: 1px solid var(--bordure);
  border-radius: var(--rayon);
  box-shadow: var(--ombre);
  font-size: var(--t-xl);
  font-weight: 700;
  color: var(--navy);
  /* `tabular-nums` : les chiffres ne bougent pas d'un pixel d'une touche à
     l'autre. Sur un pavé, un « 1 » plus étroit que les autres se voit. */
  font-variant-numeric: tabular-nums;
}
.pin__touche:active { background: var(--navy-pale); }
.pin__touche--action { background: var(--fond); color: var(--texte-second); box-shadow: none; }
.pin__touche--action svg { width: 26px; height: 26px; }
.pin__touche--valider { background: var(--teal); border-color: var(--teal); color: var(--blanc); box-shadow: none; }
.pin__touche[disabled] { opacity: 0.4; }

/* ── Signature ───────────────────────────────────────────────────────── */

.signature { display: flex; flex-direction: column; gap: 12px; flex: 1; min-height: 0; }

.signature__zone {
  position: relative;
  flex: 1;
  min-height: 180px;
  background: var(--blanc);
  border: 2px dashed #C7D0D9;
  border-radius: var(--rayon);
  overflow: hidden;
}
.signature__zone--tracee { border-style: solid; border-color: var(--bordure); }

.signature__toile {
  display: block;
  width: 100%;
  height: 100%;
  /* Indispensable : sans ça, le premier mouvement du doigt est interprété
     comme un défilement et le tracé se coupe. */
  touch-action: none;
}

/* Consigne affichée dans la zone vide, effacée au premier trait. */
.signature__consigne {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  color: var(--texte-second);
  font-size: var(--t-s);
  font-weight: 600;
  pointer-events: none;
  transition: opacity 160ms ease;
}
.signature__consigne svg { width: 44px; height: 44px; opacity: 0.35; }
.signature__zone--tracee .signature__consigne { opacity: 0; }

.signature__actions { display: flex; gap: 10px; }
.signature__actions .bouton--primaire { flex: 1; }

/*
   Pictogramme caméra permanent — §3.3.

   « Un pictogramme caméra permanent et discret doit figurer sur l'écran de
   signature tous les jours (que la photo soit prise ce jour-là ou non), avec
   renvoi au contrat d'hébergement. »

   Il n'a donc aucun état : ni classe conditionnelle, ni variante selon le
   tirage. Le jour où il en aurait un, sa présence deviendrait elle-même
   l'indice que la §3.3 interdit de donner.
*/
.mention-camera {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  border-radius: var(--rayon-petit);
  background: var(--navy-pale);
  color: var(--texte-second);
  font-size: var(--t-xs);
  line-height: 1.35;
}
.mention-camera svg { width: 20px; height: 20px; color: var(--navy); }

/* ── Confirmation ────────────────────────────────────────────────────── */

.confirmation__pastille {
  display: flex;
  align-items: center;
  justify-content: center;
  width: clamp(88px, 16vmin, 140px);
  aspect-ratio: 1;
  border-radius: 50%;
  background: var(--teal-pale);
  color: var(--teal-fonce);
}
.confirmation__pastille svg { width: 52%; height: 52%; }
.confirmation__titre { font-size: var(--t-xl); font-weight: 800; color: var(--navy); }
.confirmation__sous-titre { font-size: var(--t-m); color: var(--texte-second); }

/* ── Hors créneau ────────────────────────────────────────────────────── */

.ferme__pastille {
  display: flex;
  align-items: center;
  justify-content: center;
  width: clamp(80px, 14vmin, 120px);
  aspect-ratio: 1;
  border-radius: 50%;
  background: var(--navy-pale);
  color: var(--texte-second);
}
.ferme__pastille svg { width: 50%; height: 50%; }

.ferme__heure {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 6px;
  padding: 12px 20px;
  border-radius: var(--rayon-petit);
  background: #E9EEF2;
  color: var(--navy);
  font-size: var(--t-m);
  font-weight: 700;
}
.ferme__heure svg { width: 1.2em; height: 1.2em; }

/* ── Urgence ─────────────────────────────────────────────────────────── */

.categories {
  /* Trois colonnes au maximum, comme la maquette en paysage : au-delà, les
     six catégories s'étalent sur une ligne et demie, et la dernière se
     retrouve seule sous les cinq autres. */
  max-width: 760px;
  margin-inline: auto;
  display: grid;
  /* Deux colonnes en portrait, trois dès que la largeur le permet — les
     maquettes 01 et 04 montrent les deux cas selon l'orientation. */
  grid-template-columns: repeat(auto-fit, minmax(clamp(140px, 30vmin, 210px), 1fr));
  gap: clamp(10px, 1.8vmin, 16px);
}

.categorie {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: clamp(118px, 17vmin, 160px);
  padding: 16px 10px;
  background: var(--blanc);
  border: 1.5px solid var(--bordure);
  border-radius: var(--rayon);
  text-align: center;
}
.categorie:active { border-color: var(--rose); background: var(--rose-pale); }

.categorie__pastille {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 54px;
  height: 54px;
  border-radius: 50%;
  background: var(--rose-pale);
  color: var(--rose);
}
.categorie__pastille svg { width: 27px; height: 27px; }
/* Icône + texte systématiquement, jamais l'icône seule (§3.6). */
.categorie__libelle { font-size: var(--t-s); font-weight: 700; line-height: 1.25; }

.urgence-forme { display: flex; flex-direction: column; gap: 14px; }

.urgence-forme__champ {
  width: 100%;
  min-height: clamp(120px, 18vmin, 180px);
  padding: 14px 16px;
  background: var(--blanc);
  border: 1.5px solid var(--bordure);
  border-radius: var(--rayon);
  font: inherit;
  font-size: var(--t-s);
  color: var(--texte);
  resize: none;
}
.urgence-forme__champ:focus { outline: 2px solid var(--rose); outline-offset: 1px; }

.canaux { display: flex; flex-direction: column; gap: 8px; width: 100%; max-width: 460px; }

.canal {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  background: var(--blanc);
  border: 1px solid var(--bordure);
  border-radius: var(--rayon-petit);
  font-size: var(--t-s);
  text-align: start;
}
.canal__pastille { width: 10px; height: 10px; border-radius: 50%; background: var(--teal); flex: none; }
.canal--echec .canal__pastille { background: var(--rose); }
.canal__nom { font-weight: 600; }
.canal__etat { margin-inline-start: auto; color: var(--texte-second); font-size: var(--t-xs); }

/*
   Repli téléphonique — affiché quand l'alerte n'est pas partie.

   Tant que le module urgence serveur (§4) n'existe pas, c'est l'écran que
   voit systématiquement un résident qui appuie sur URGENCE. Il est donc
   traité comme un écran de plein droit, pas comme un message d'erreur : les
   numéros y sont la plus grosse chose de la page.
*/
/* ── Information à recopier — écran de repli d'urgence (§4.2) ────────────
 *
 * Tout ce bloc existe pour une seule opération : lire une information sur un
 * écran vissé au mur et la taper sur son propre téléphone. Rien n'y est
 * cliquable — le mode kiosque (§3.5) ne peut ouvrir ni le téléphone ni
 * WhatsApp, et la règle est posée dans CLAUDE.md.
 *
 * D'où les trois partis pris : le libellé s'efface (petit, gris), la valeur
 * domine (très grand, navy), et `user-select` reste actif — inutile au doigt,
 * mais c'est ce qui permet de relever le numéro depuis un poste ouvert sur la
 * même page pendant une astreinte.
 */

.recopie {
  display: flex;
  flex-direction: column;
  gap: 12px;
  width: 100%;
  max-width: 460px;
  padding: 18px 20px;
  background: var(--blanc);
  border: 1px solid var(--bordure);
  border-inline-start: 4px solid var(--rose);
  border-radius: var(--rayon-petit);
  text-align: start;
}

.recopie__libelle {
  font-size: var(--t-xs);
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--texte-second);
}

.recopie__valeur {
  font-size: var(--t-l);
  font-weight: 700;
  color: var(--navy);
  user-select: text;
  overflow-wrap: anywhere;
}

/* Le numéro de contact, seule information de l'écran qu'on lit chiffre à
   chiffre en tapant sur un autre appareil. `tabular-nums` aligne les chiffres
   sur une largeur constante : deux « 1 » de suite ne se resserrent pas, et on
   ne perd pas sa place en levant les yeux. Le `letter-spacing` sépare les
   groupes que l'admin a saisis, sans les réécrire. */
.recopie__valeur--numero {
  font-size: var(--t-xxl);
  font-weight: 800;
  line-height: 1.15;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
}

.recopie__mention {
  display: inline-flex;
  align-self: start;
  padding: 5px 12px;
  border-radius: 999px;
  background: var(--teal-pale);
  color: var(--teal-fonce);
  font-size: var(--t-xs);
  font-weight: 700;
}

/* ── Numéros publics ────────────────────────────────────────────────────── */

.secours { display: flex; flex-direction: column; gap: 9px; width: 100%; max-width: 460px; }

.secours__titre {
  font-size: var(--t-xs);
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--texte-second);
  text-align: start;
}

.secours__ligne {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 12px 18px;
  background: var(--blanc);
  border: 1px solid var(--bordure);
  border-inline-start: 4px solid var(--rose);
  border-radius: var(--rayon-petit);
  text-align: start;
}

/* Chiffres d'abord et en grand : c'est ce qu'on tape. Largeur fixée pour que
   les quatre lignes alignent leurs noms de service, « 112 » compris. */
.secours__numero {
  flex: none;
  min-width: 2.6em;
  font-size: var(--t-xl);
  font-weight: 800;
  color: var(--rose);
  font-variant-numeric: tabular-nums;
  user-select: text;
}

.secours__service {
  font-size: var(--t-s);
  font-weight: 600;
  color: var(--navy);
}

/* ── Messages d'état : réseau, appareil refusé, erreur générique ─────── */

.message { display: flex; flex-direction: column; align-items: center; gap: 14px; text-align: center; }

.message__pastille {
  display: flex;
  align-items: center;
  justify-content: center;
  width: clamp(72px, 12vmin, 104px);
  aspect-ratio: 1;
  border-radius: 50%;
  background: var(--navy-pale);
  color: var(--texte-second);
}
.message__pastille svg { width: 48%; height: 48%; }
.message--alerte .message__pastille { background: var(--rose-pale); color: var(--rose); }
.message__titre { font-size: var(--t-l); font-weight: 800; color: var(--navy); }

/* Bandeau d'erreur en ligne — code faux, signature vide. Le message remplace
   le sous-titre plutôt que d'ouvrir une boîte de dialogue : sur un écran
   tactile sans clavier, une modale de plus est une chose de plus à fermer. */
.alerte-ligne {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 16px;
  border-radius: var(--rayon-petit);
  background: var(--rose-pale);
  color: #8A2036;
  font-size: var(--t-s);
  font-weight: 600;
  text-align: start;
}
.alerte-ligne svg { width: 1.3em; height: 1.3em; flex: none; }

/* ── Formulaire d'installation ───────────────────────────────────────── */

.config { display: flex; flex-direction: column; gap: 14px; width: 100%; max-width: 520px; }

.config__champ {
  width: 100%;
  min-height: var(--cible);
  padding: 0 16px;
  background: var(--blanc);
  border: 1.5px solid var(--bordure);
  border-radius: var(--rayon-petit);
  font: inherit;
  font-size: var(--t-s);
  color: var(--texte);
}
.config__champ:focus { outline: 2px solid var(--navy); outline-offset: 1px; }

/* ── Divers ──────────────────────────────────────────────────────────── */

.chargement { display: inline-flex; animation: tourne 900ms linear infinite; }
@keyframes tourne { to { transform: rotate(360deg); } }

.secousse { animation: secousse 320ms ease; }
@keyframes secousse {
  10%, 90% { transform: translateX(-4px); }
  30%, 70% { transform: translateX(7px); }
  50% { transform: translateX(-7px); }
}

.noscript {
  padding: 28px;
  color: var(--rose);
  font-size: var(--t-m);
  font-weight: 700;
  text-align: center;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 1ms !important; transition-duration: 1ms !important; }
}

/* Retour d'écran — posé au début de l'en-tête, hors de portée des boutons
   d'action du corps (voir `vue.js`). Symétrisé en écriture de droite à
   gauche : la flèche « en arrière » y pointe vers la droite. */
.entete__retour {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: var(--cible);
  height: var(--cible);
  margin-inline-end: 4px;
  border: 1px solid var(--bordure);
  border-radius: var(--rayon-petit);
  background: var(--fond);
  color: var(--navy);
}
.entete__retour:active { background: var(--navy-pale); }
.entete__retour svg { width: 24px; height: 24px; }
[dir="rtl"] .entete__retour svg { transform: scaleX(-1); }
