:root {
  --primary: #1c64d9;
  --bg: #eef1f7;
  --card: #ffffff;
  --text: #1c2330;
  /* #67718c ne tenait que 4.30:1 sur le fond de l'application (#eef1f7) —
     détecté par axe-core sur le pied de page. Assombri à 5.31:1 sur ce fond,
     6.01:1 sur les cartes blanches. */
  --muted: #5a6379;
  --line: #e3e8f2;
  --ok: #1e9e62;
  --warn: #c9810a;
}

* {
  box-sizing: border-box;
}

/* Visible uniquement des lecteurs d'écran : sert à porter en texte ce que
   l'interface n'exprime que par la couleur ou par une icône. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Le focus clavier doit rester visible partout, y compris sur les éléments
   que l'on rend focalisables par programme (titre du dialogue). */
:focus-visible {
  outline: 3px solid #1c64d9;
  outline-offset: 2px;
  border-radius: 4px;
}
.statusbar :focus-visible,
.overlay :focus-visible {
  outline-color: #fff;
}

/* L'attribut hidden doit gagner même sur les éléments avec un display explicite */
[hidden] {
  display: none !important;
}

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  background: #d9dde6; /* toile de fond derrière le cadre (desktop) */
  color: var(--text);
}

/* Cadre englobant : look « carte app » centré (desktop),
   plein écran sans bordure sur mobile (vrai cas d'usage du proche) */
.app {
  max-width: 480px;
  margin: 18px auto;
  background: var(--bg);
  border-radius: 24px;
  overflow: hidden;
  box-shadow: 0 12px 40px rgba(15, 22, 40, 0.18);
}
@media (max-width: 540px) {
  body {
    background: var(--bg);
  }
  .app {
    max-width: none;
    margin: 0;
    border-radius: 0;
    box-shadow: none;
    min-height: 100vh;
  }
}

/* ── Bandeau d'état : couleur selon body[data-state] ──────────────────── */
.statusbar {
  padding: 20px 18px 18px;
  color: #fff;
  transition: background 0.4s;
}
/* Contrastes mesurés contre le blanc du texte, niveau AA (4.5:1 minimum pour
   du texte normal). Les deux dégradés ci-dessous ont été assombris : l'ambre
   d'origine (#d99417) plafonnait à 2.56:1 et le vert (#1e9e62) à 3.43:1 —
   c'est-à-dire illisibles pour le sous-titre, sur les deux états qui portent
   justement l'information la plus importante pour l'aidant.
     enroute #157a4c → 5.36:1 · #0f6640 → 7.01:1
     stale   #9a6500 → 4.96:1 · #7d5200 → 6.82:1
     arrived #1c64d9 → 5.42:1 · wait/error #67718c → 4.86:1 (déjà conformes) */
body[data-state='enroute'] .statusbar {
  background: linear-gradient(135deg, #157a4c, #0f6640);
}
body[data-state='stale'] .statusbar {
  background: linear-gradient(135deg, #9a6500, #7d5200);
}
body[data-state='arrived'] .statusbar {
  background: linear-gradient(135deg, #1c64d9, #1450b3);
}
body[data-state='wait'] .statusbar,
body[data-state='ended'] .statusbar,
body[data-state='error'] .statusbar {
  background: linear-gradient(135deg, #67718c, #525c75);
}

.brandrow {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.75rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  margin-bottom: 14px;
}
.brand {
  font-weight: 700;
  margin-right: auto;
} /* pousse les chips à droite */

.seen {
  display: flex;
  align-items: center;
  gap: 6px;
  background: rgba(255, 255, 255, 0.18);
  padding: 4px 10px;
  border-radius: 999px;
  text-transform: none;
  letter-spacing: 0;
}
.dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #fff;
}
body[data-state='enroute'] .dot {
  animation: pulse 1.6s infinite;
}

/* Chip batterie du voyageur — même base que .seen, couleur selon le niveau */
.battery {
  display: flex;
  align-items: center;
  gap: 5px;
  background: rgba(255, 255, 255, 0.18);
  padding: 4px 10px;
  border-radius: 999px;
  text-transform: none;
  letter-spacing: 0;
  font-variant-numeric: tabular-nums;
}
.battery-ico {
  font-size: 0.95em;
  line-height: 1;
}
.battery.low {
  background: rgba(245, 158, 11, 0.32);
} /* < 20 % : ambre */
.battery.critical {
  background: rgba(220, 38, 38, 0.42);
} /* < 10 % : rouge */
.battery.charging {
  background: rgba(34, 197, 94, 0.32);
} /* en charge : vert */
.battery.charging .battery-ico {
  animation: pulse-soft 1.6s infinite;
}
@keyframes pulse-soft {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0.45;
  }
}
@keyframes pulse {
  0% {
    box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.7);
  }
  70% {
    box-shadow: 0 0 0 7px rgba(255, 255, 255, 0);
  }
  100% {
    box-shadow: 0 0 0 0 rgba(255, 255, 255, 0);
  }
}

.headline {
  font-size: 1.5rem;
  font-weight: 800;
  line-height: 1.2;
  margin: 0 0 4px;
}
/* Pas d'opacité : le blanc reste plein, sinon le contraste mesuré ci-dessus
   ne vaut plus rien. La hiérarchie passe par la taille et la graisse. */
.subline {
  font-size: 0.95rem;
  font-weight: 500;
  margin: 0;
}

.eta {
  margin-top: 14px;
  background: rgba(255, 255, 255, 0.16);
  border-radius: 14px;
  padding: 12px 14px;
  display: flex;
  align-items: baseline;
  gap: 10px;
}
.eta .big {
  font-size: 1.7rem;
  font-weight: 800;
  line-height: 1;
}
.eta .lbl {
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}
.eta .in {
  margin-left: auto;
  font-size: 0.95rem;
  font-weight: 600;
  background: rgba(255, 255, 255, 0.22);
  padding: 6px 12px;
  border-radius: 999px;
}

/* ── Corps ────────────────────────────────────────────────────────────── */
main {
  padding: 14px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.card {
  background: var(--card);
  border-radius: 16px;
  padding: 16px;
  box-shadow: 0 1px 3px rgba(20, 30, 60, 0.07);
}
.card h2 {
  margin: 0 0 12px;
  font-size: 0.78rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--muted);
}

/* Position actuelle en langage humain */
.nowloc {
  display: flex;
  gap: 12px;
  align-items: flex-start;
}
.nowloc .pin {
  font-size: 1.6rem;
  line-height: 1;
}
.nowloc .txt {
  font-size: 1.05rem;
  font-weight: 600;
}
.nowloc .hint {
  font-size: 0.85rem;
  color: var(--muted);
  font-weight: 400;
  margin-top: 3px;
}

/* Note rassurante quand le signal se tait */
.quiet {
  background: #fdf3e1;
  border: 1px solid #f0d9a8;
  border-radius: 12px;
  padding: 12px 14px;
  font-size: 0.9rem;
  color: #7a5408;
  display: flex;
  gap: 10px;
  margin-top: 12px;
}
.quiet .i {
  font-size: 1.1rem;
}

/* En-tête de trajet */
.route {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  align-items: baseline;
  text-transform: none;
  letter-spacing: 0;
  font-size: 0.95rem;
  color: var(--text);
}
.route .arrow {
  color: var(--muted);
}

#map {
  height: 220px;
  border-radius: 12px;
  overflow: hidden;
}

/* Légende sous la carte : fraîcheur de la dernière position reçue */
.map-cap {
  display: flex;
  align-items: center;
  gap: 7px;
  margin-top: 10px;
  font-size: 0.82rem;
  color: var(--muted);
}
.map-cap .locdot {
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: var(--primary);
  border: 2px solid #fff;
  box-shadow: 0 0 0 1px var(--primary);
  flex: none;
}

/* Frise verticale du trajet */
.timeline {
  list-style: none;
  margin: 0;
  padding: 0;
}
.timeline li {
  position: relative;
  padding: 0 0 18px 30px;
}
.timeline li:last-child {
  padding-bottom: 0;
}
.timeline li::before {
  content: '';
  position: absolute;
  left: 7px;
  top: 2px;
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: #fff;
  border: 2px solid var(--line);
  z-index: 1;
}
.timeline li::after {
  content: '';
  position: absolute;
  left: 12px;
  top: 13px;
  bottom: 0;
  width: 2px;
  background: var(--line);
}
.timeline li:last-child::after {
  display: none;
}
.timeline li.done::before {
  background: var(--ok);
  border-color: var(--ok);
}
.timeline li.done::after {
  background: var(--ok);
}
.timeline li.current::before {
  background: var(--primary);
  border-color: var(--primary);
  box-shadow: 0 0 0 5px rgba(28, 100, 217, 0.18);
  animation: pulse2 1.8s infinite;
}
@keyframes pulse2 {
  0% {
    box-shadow: 0 0 0 0 rgba(28, 100, 217, 0.35);
  }
  70% {
    box-shadow: 0 0 0 9px rgba(28, 100, 217, 0);
  }
  100% {
    box-shadow: 0 0 0 0 rgba(28, 100, 217, 0);
  }
}
.timeline .lbl {
  font-weight: 600;
}
.timeline li.upcoming .lbl {
  color: var(--muted);
  font-weight: 500;
}
.timeline li.current .lbl {
  color: var(--primary);
}

.foot {
  margin: 0;
  padding: 4px 18px 22px;
  font-size: 0.78rem;
  color: var(--muted);
  text-align: center;
}

/* Overlay arrivée */
.overlay {
  position: fixed;
  inset: 0;
  background: rgba(15, 22, 40, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
.overlay-card {
  background: #fff;
  border-radius: 20px;
  padding: 28px 26px;
  text-align: center;
  max-width: 320px;
}
.overlay-emoji {
  font-size: 3rem;
}
.overlay-card h2 {
  margin: 8px 0;
}
.overlay-card p {
  color: var(--muted);
}
.overlay-card button {
  margin-top: 14px;
  padding: 10px 24px;
  border: none;
  border-radius: 999px;
  background: var(--primary);
  color: #fff;
  font-size: 1rem;
  cursor: pointer;
}

/* Mouvement réduit : les trois animations de la page sont décoratives — le
   point qui bat, l'icône de charge, la pastille de l'étape en cours. Aucune ne
   porte d'information que le texte ne donne pas déjà. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  body[data-state='enroute'] .dot,
  .battery.charging .battery-ico,
  .timeline li.current::before {
    animation: none;
  }
}

/* L'état d'une étape ne doit pas reposer que sur la couleur : la puce change
   aussi de forme, et un texte masqué visuellement le dit aux lecteurs d'écran. */
.timeline li.done::before {
  border-width: 3px;
}
.timeline li.current::before {
  border-width: 4px;
}

/* ── Information RGPD (art. 13/14) ────────────────────────────────────
   Visible dans les cinq états, y compris l'état d'erreur. Discrète mais
   lisible : la taille reste au-dessus du seuil de confort, et la couleur du
   texte est celle, contrastée, des textes secondaires. */
/* Repli de l'information RGPD — le conteneur porte la marge, la carte
   intérieure ne l'ajoute plus une seconde fois. */
.datacard {
  margin: 0 14px 18px;
}

/* Un intitulé en texte souligné, comme demandé, mais qui reste un contrôle :
   la zone cliquable fait toute la largeur et 44 px de haut, seuil tactile des
   recommandations WCAG — le proche ouvre ce lien sur un téléphone, souvent
   d'une main. */
.datacard-toggle {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 44px;
  padding: 4px 8px;
  font-size: 0.82rem;
  color: var(--muted);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
  /* Retire le triangle natif : Chrome/Safari via le pseudo-élément WebKit,
     Firefox et les navigateurs récents via `list-style`. */
  list-style: none;
}
.datacard-toggle::-webkit-details-marker {
  display: none;
}

/* Chevron dessiné en CSS plutôt qu'en glyphe : il pivote à l'ouverture et
   reste net à toutes les tailles. `aria-hidden` n'est pas nécessaire, un
   pseudo-élément décoratif n'est pas dans l'arbre d'accessibilité. */
.datacard-toggle::after {
  content: '';
  width: 7px;
  height: 7px;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: translateY(-2px) rotate(45deg);
  transition: transform 0.15s ease;
}
.datacard[open] .datacard-toggle::after {
  transform: translateY(1px) rotate(-135deg);
}

/* Le survol renforce l'affordance sans changer la mise en page. */
.datacard-toggle:hover {
  color: var(--text);
}

.notice {
  margin: 10px 0 0;
  padding: 16px;
  background: var(--card);
  border-radius: 16px;
  border: 1px solid var(--line);
  font-size: 0.82rem;
  line-height: 1.5;
  color: var(--muted);
}
.notice h2 {
  margin: 0 0 10px;
  font-size: 0.78rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--muted);
}
.notice dl {
  margin: 0;
}
.notice dt {
  font-weight: 700;
  color: var(--text);
  margin-top: 10px;
}
.notice dt:first-child {
  margin-top: 0;
}
.notice dd {
  margin: 2px 0 0;
}
.notice strong {
  color: var(--text);
}
.notice a {
  color: var(--primary);
}
.notice-links {
  margin: 12px 0 0;
}
