/* =======================================================================
   Bulletin — direction « Lichen »
   Deux polices seulement : Space Grotesk pour les titres, les chiffres et
   tout ce qui se compare d'un coup d'œil ; la police système pour le texte
   courant, qui se lit et ne se scanne pas.
   Une seule couleur d'accent (--accent). Toutes les autres couleurs de
   l'application sont sémantiques : elles disent une surface, une pluie, un
   vent, un niveau de praticabilité, et ne sont donc pas ici — elles vivent
   dans app.js et practicability.js, où elles ont un sens.
   ======================================================================= */

:root {
  --ink:        #1e221e;   /* texte principal */
  --ink-2:      #3a3f3a;   /* libellés de tableau */
  --muted:      #6c736c;   /* texte secondaire */
  --muted-2:    #8d948d;   /* notes, unités */
  --faint:      #9aa09a;   /* graduations, mentions */

  --hair:       #eceee9;   /* filets internes */
  --line:       #e5e7e2;   /* bordures de cartes */
  --line-2:     #dfe2dc;   /* bordures de conteneurs */

  --paper:      #fbfbf8;   /* fonds de panneau */
  --canvas:     #f5f6f2;   /* fond de la page Analyse */
  --sunk:       #f4f5f1;   /* champs et pastilles enfoncées */

  --accent:     #5f7a63;
  --accent-ink: #526a56;

  /* Bandeau : le seul aplat sombre de l'application. */
  --band:       linear-gradient(105deg, #101a13 0%, #243024 44%, #41563f 100%);
  --band-fg:    #eef0ec;
  --band-dim:   #c9cfc7;
  --band-mark:  #aebfae;

  --r-sm: 9px;
  --r-md: 12px;
  --r-lg: 16px;

  --display: "Space Grotesk", system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
  --ui: system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;

  --shadow-float: 0 2px 12px rgba(30, 34, 30, 0.16);
  --shadow-menu:  0 10px 30px rgba(30, 34, 30, 0.2);

  /* Une seule courbe et deux durées pour toute l'application. Court : rien
     ici ne mérite d'être attendu, le mouvement accompagne l'action, il ne
     la met pas en scène. */
  --ease:   cubic-bezier(0.2, 0.6, 0.3, 1);
  --t-fast: 110ms;
  --t-base: 170ms;
}

* { box-sizing: border-box; }

/* Un seul sens pour « masqué », partout dans l'application : les états
   (panneau replié, catégorie sans données, mode inactif) sont pilotés par
   cette classe, et rien ne doit pouvoir la contredire. */
.hidden,
[hidden] { display: none !important; }

html, body {
  height: 100%;
  margin: 0;
  font-family: var(--ui);
  color: var(--ink);
  background: var(--paper);
}

/* Colonne pleine hauteur : l'en-tête prend ce qu'il lui faut, le reste va à
   `main`. Une hauteur d'en-tête codée en dur ne tient pas — il passe à deux ou
   trois lignes dès que la fenêtre se resserre, et `main` débordait alors par
   le bas en emportant le profil d'altitude hors de l'écran. */
body {
  display: flex;
  flex-direction: column;
}

button { font-family: inherit; }

/* Barres de défilement discrètes : le panneau et la page Analyse défilent
   beaucoup, et une barre système large mange 17 px de panneau. */
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: #d3d7d0; border-radius: 4px; }
::-webkit-scrollbar-thumb:hover { background: #bfc5bd; }

/* =======================================================================
   0. Mouvement et focus
   Les transitions sont regroupées ici plutôt qu'éparpillées sur vingt
   règles : une seule liste dit exactement ce qui bouge dans l'application,
   et rien ne peut y entrer par inadvertance.
   Deux principes :
   — on n'anime que ce qui répond. Une carte du tableau de bord qui réagit
     au survol se donne l'air cliquable alors qu'elle ne l'est pas.
   — on n'anime que des propriétés composées (couleur, ombre, opacité,
     transform). Animer une largeur ou une hauteur relance le calcul de mise
     en page à chaque image ; sur une page qui porte une carte Leaflet et
     quatre graphiques SVG, ça se voit.
   Rien de tout cela ne touche le curseur partagé (trait des graphiques et
   des rubans) : il doit coller au pointeur au pixel près, une transition
   dessus le ferait traîner derrière la souris.
   ======================================================================= */

.file-btn,
.mode-toggle button,
.rs-edit,
.view-picker-btn,
.view-picker-chevron,
.view-menu button,
.supply-type,
.supply-radius button,
.supply-item,
.panel-nav button,
.panel-ticks button,
.leaflet-control-zoom a {
  transition: background-color var(--t-base) var(--ease),
              border-color var(--t-base) var(--ease),
              color var(--t-base) var(--ease),
              box-shadow var(--t-base) var(--ease),
              transform var(--t-fast) var(--ease);
}

/* Retour d'appui : l'élément s'enfonce légèrement sous le doigt ou le clic.
   Seulement sur les vraies commandes — pas sur les lignes de liste, où le
   fond qui s'allume suffit. */
.file-btn:active,
.mode-toggle button:active,
.supply-radius button:active:not(:disabled),
.panel-nav button:active { transform: scale(0.97); }

/* Le chevron pivote au lieu de changer de glyphe : un caractère qu'on
   remplace ne peut pas s'animer, et tous les jeux de caractères ne portent
   pas le triangle pointant vers le haut. */
.view-picker-btn[aria-expanded="true"] .view-picker-chevron { transform: rotate(180deg); }

@keyframes pop-in { from { opacity: 0; transform: translateY(-6px); } }
@keyframes fade-in { from { opacity: 0; } }
@keyframes toast-in { from { opacity: 0; transform: translate(-50%, -8px); } }

/* Ces trois-là s'animent à l'apparition. Passer de `display: none` à visible
   relance l'animation : c'est ce qui la déclenche, sans une ligne de JS. */
.view-menu { animation: pop-in var(--t-base) var(--ease); }
main,
.dashboard { animation: fade-in var(--t-base) var(--ease); }

/* Focus visible au clavier. `:focus-visible` et non `:focus` : le contour ne
   doit apparaître que pour qui navigue au clavier, jamais après un clic. */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
/* Sur le bandeau vert foncé, le vert d'accent ne se détache pas. */
.bandeau :focus-visible,
body.settings-open .settings :focus-visible { outline-color: var(--band-mark); }
/* Le champ de fichier est transparent et couvre tout son libellé : c'est le
   libellé qui doit porter le contour, sinon il se dessine sur du vide. */
.file-btn:has(input:focus-visible) {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
body.settings-open .file-btn:has(input:focus-visible) { outline-color: var(--band-mark); }

/* Réglage système « réduire les animations » : on le respecte. Des durées
   quasi nulles plutôt que `none`, pour que les événements de fin
   d'animation continuent d'être émis. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* =======================================================================
   1. En-tête : bandeau (parcours chargé) et accueil (parcours absent)
   ======================================================================= */

/* `body >` : sans lui la règle habillait aussi les <header> des cartes du
   tableau de bord, qui se retrouvaient en vert foncé sur fond blanc. */
body > header {
  position: relative;   /* repère du bandeau d'état, qui déborde par le bas */
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  background: var(--band);
  color: var(--band-fg);
}

.bandeau {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 12px 20px;
}

.brand {
  display: flex;
  align-items: center;
  gap: 9px;
  font: 600 15.5px var(--display);
  letter-spacing: -0.01em;
  white-space: nowrap;
}
/* 28 px : en dessous, la trame du dessin se referme et le cycliste n'est
   plus qu'une tache grise. C'est le plancher de lisibilité de cette gravure,
   mesuré, pas choisi. */
.brand-art {
  width: 41px;
  height: 28px;
  flex: none;
  background-color: var(--band-mark);
  -webkit-mask: url("logo.png") no-repeat center / contain;
  mask: url("logo.png") no-repeat center / contain;
}

/* Résumé du parcours : ce qui a été chargé et sous quelles hypothèses. Les
   réglages qui l'ont produit sont à un clic, repliés — on les consulte
   rarement, on les relit souvent. */
.route-summary {
  display: flex;
  align-items: center;
  gap: 11px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.rs-km { font: 500 13px var(--display); }
.rs-dim { font-size: 13px; color: var(--band-dim); }
.rs-rule { width: 1px; height: 13px; background: rgba(238, 240, 236, 0.2); }
.rs-edit {
  background: none;
  border: none;
  color: var(--band-mark);
  font: 500 12.5px var(--display);
  cursor: pointer;
  padding: 4px 0;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.rs-edit:hover { color: var(--band-fg); }

/* Bascule Carte / Analyse : changement de page, pas changement de calque —
   d'où la forme pleine, distincte du sélecteur de vue posé sur la carte. */
.mode-toggle {
  display: flex;
  background: rgba(238, 240, 236, 0.08);
  border-radius: 10px;
  padding: 3px;
  white-space: nowrap;
}
.mode-toggle button {
  border: none;
  cursor: pointer;
  padding: 6px 15px;
  border-radius: 8px;
  font: 500 12.5px var(--display);
  background: transparent;
  color: var(--band-dim);
}
.mode-toggle button:hover { color: var(--band-fg); }
.mode-toggle button.active { background: var(--band-fg); color: #232a24; }

/* ---- Accueil ----------------------------------------------------------
   Tant qu'aucun parcours n'est chargé, l'en-tête *est* la page. Le bandeau
   se replie, l'accueil se déplie, et les champs de réglage — les mêmes
   nœuds, jamais dupliqués — passent du tiroir à la carte blanche. */
.landing-hero,
.landing-foot { display: none; }

body.no-route > header {
  flex: 1;
  justify-content: center;
  align-items: center;
  padding: 40px 26px 44px;
  background: var(--paper);
  color: var(--ink);
  text-align: center;
}
body.no-route .bandeau { display: none; }
body.no-route .landing-hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
  max-width: 340px;
}
body.no-route .landing-foot {
  display: block;
  max-width: 340px;
  margin: 20px 0 0;
  font: 400 12px/1.5 var(--ui);
  color: var(--faint);
}

.landing-art {
  width: 100%;
  max-width: 260px;
  height: auto;
  margin-bottom: 12px;
}

body.no-route h1 {
  margin: 0 0 8px;
  font: 600 27px/1.15 var(--display);
  letter-spacing: -0.02em;
}
.tagline {
  margin: 0 0 24px;
  font: 400 14.5px/1.5 var(--ui);
  color: var(--muted);
}

/* Les deux zones de contenu sont vides tant qu'aucun GPX n'est lu : sans ça
   elles gardent leur part de la hauteur et l'accueil n'est plus centré. */
body.no-route main,
body.no-route .dashboard { display: none; }

/* ---- Réglages : carte à l'accueil, tiroir dans le bandeau -------------- */
.settings { display: none; }
body.no-route .settings,
body.settings-open .settings { display: flex; }

body.no-route .settings {
  width: 100%;
  max-width: 340px;
  flex-direction: column;
  gap: 14px;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 18px;
}
body.settings-open .settings {
  align-items: center;
  flex-wrap: wrap;
  gap: 12px 18px;
  padding: 0 20px 14px;
}

.file-btn {
  position: relative;
  display: block;
  text-align: center;
  background: var(--accent);
  color: #fff;
  border-radius: 11px;
  padding: 14px;
  cursor: pointer;
  font: 500 15px var(--display);
}
.file-btn:hover { background: var(--accent-ink); }
.file-btn input { position: absolute; inset: 0; opacity: 0; cursor: pointer; }
body.settings-open .file-btn { padding: 9px 16px; font-size: 13px; border-radius: var(--r-sm); }

.fields { display: flex; flex-wrap: wrap; gap: 9px; }
/* Étiquette sur sa propre ligne : « Départ » suivi de deux champs de saisie
   ne tient pas en largeur dans une carte de 340 px, et une date qui déborde
   de son cadre est pire qu'une ligne de plus. */
/* `text-align: left` : l'accueil centre tout son contenu, mais à l'intérieur
   d'un champ l'étiquette et la valeur doivent s'aligner l'une sous l'autre.
   Centrée, « ALLURE » flottait au-dessus d'un « 23 km/h » resté à gauche. */
.date-field {
  flex: 1 1 150px;
  min-width: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 6px;
  background: var(--sunk);
  border-radius: 10px;
  padding: 8px 12px;
  font: 500 13px var(--display);
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  text-align: left;
}
.field-name {
  flex-basis: 100%;
  font: 500 10px var(--ui);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted-2);
}
/* Encre fixée, et non héritée : le champ garde son fond blanc dans le tiroir
   du bandeau, où le conteneur passe en texte clair. Hérité, le contenu saisi
   devenait blanc sur blanc — date, heure et allure invisibles. */
.date-field input {
  min-width: 0;
  padding: 3px 6px;
  border-radius: 6px;
  border: 1px solid var(--line);
  background: #fff;
  font: inherit;
  color: var(--ink);
}
.date-field input[type="number"] { width: 56px; }
.date-field .unit { color: var(--muted-2); font-weight: 400; }
/* Dans le tiroir sombre, les mêmes champs repassent en clair sur le vert et
   reprennent une seule ligne : la place manque en hauteur, pas en largeur. */
body.settings-open .date-field {
  flex: 0 0 auto;
  background: rgba(238, 240, 236, 0.08);
  color: var(--band-fg);
}
body.settings-open .fields { flex: 0 1 auto; }
body.settings-open .field-name { flex-basis: auto; }
body.settings-open .field-name,
body.settings-open .date-field .unit { color: var(--band-dim); }

/* Bandeau d'état : messages de chargement et d'erreur. Posé sous l'en-tête
   plutôt qu'à l'intérieur — il apparaît et disparaît sans jamais décaler le
   bandeau ni recalculer la hauteur de la carte. */
.status {
  font: 400 12.5px var(--ui);
  color: var(--muted);
}
.status:empty { display: none; }
body:not(.no-route) .status {
  position: absolute;
  z-index: 1100;   /* au-dessus des commandes Leaflet, qui montent à 1000 */
  top: calc(100% + 10px);
  left: 50%;
  transform: translateX(-50%);
  max-width: min(560px, calc(100vw - 32px));
  background: #232a24;
  color: var(--band-fg);
  border-radius: 999px;
  padding: 7px 15px;
  box-shadow: var(--shadow-float);
  text-align: center;
  animation: toast-in var(--t-base) var(--ease);
}
body.no-route .status { margin-top: 16px; }

/* =======================================================================
   2. Mode Carte
   ======================================================================= */

main {
  flex: 1;
  min-height: 0;
  display: flex;
  background: var(--paper);
}

.map-col {
  position: relative;   /* repère du sélecteur de vue */
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  height: 100%;
  border-right: 1px solid var(--line);
}

#map {
  flex: 1;
  min-height: 0;
  background: #e8e9e4;
}
.leaflet-container { font-family: var(--ui); }

/* ---- Sélecteur de vue posé sur la carte -------------------------------
   Verre dépoli : le fond de carte reste lisible dessous, et le sélecteur se
   lit comme un objet posé sur la carte plutôt que comme un morceau de
   l'interface qui la recouvre. */
.view-picker {
  position: absolute;
  z-index: 1000;   /* même plan que les commandes Leaflet, qu'il ne recouvre pas */
  top: 14px;
  left: 14px;
  width: 262px;
}
.view-picker-btn {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 9px;
  background: rgba(255, 255, 255, 0.72);
  backdrop-filter: blur(14px) saturate(1.4);
  -webkit-backdrop-filter: blur(14px) saturate(1.4);
  border: 1px solid rgba(255, 255, 255, 0.6);
  border-radius: var(--r-md);
  padding: 11px 13px;
  box-shadow: var(--shadow-float);
  font: 500 13.5px var(--display);
  color: var(--ink);
  cursor: pointer;
  text-align: left;
}
.view-picker-btn:hover {
  background: rgba(255, 255, 255, 0.88);
  box-shadow: 0 4px 16px rgba(30, 34, 30, 0.2);
}
.view-picker-chevron {
  margin-left: auto;
  color: var(--muted-2);
  font-size: 11px;
}
.view-picker-chevron::before { content: "\25BE"; display: block; line-height: 1; }

.view-dot {
  width: 9px;
  height: 9px;
  border-radius: 3px;
  flex: none;
  display: inline-block;
}

.view-menu {
  margin-top: 6px;
  background: rgba(255, 255, 255, 0.88);
  backdrop-filter: blur(20px) saturate(1.5);
  -webkit-backdrop-filter: blur(20px) saturate(1.5);
  border: 1px solid rgba(255, 255, 255, 0.6);
  border-radius: 14px;
  box-shadow: var(--shadow-menu);
  padding: 8px 6px;
  max-height: min(430px, calc(100vh - 190px));
  overflow-y: auto;
}
.view-group {
  margin: 0;
  font: 500 10px var(--ui);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--faint);
  padding: 11px 9px 6px;
}
.view-group:first-child { padding-top: 4px; }
.view-menu button {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 9px;
  border: none;
  cursor: pointer;
  padding: 8px 9px;
  border-radius: var(--r-sm);
  text-align: left;
  font: 400 13px var(--ui);
  color: var(--muted);
  background: transparent;
}
.view-menu button:hover { background: #f4f5f1; }
.view-menu button.active {
  background: #f0f2ed;
  color: var(--ink);
  font-weight: 500;
}
.view-menu button .view-dot { border-radius: 2px; width: 8px; height: 8px; }

/* ---- Commandes Leaflet, accordées au sélecteur ------------------------ */
.leaflet-touch .leaflet-bar,
.leaflet-bar {
  border: none;
  box-shadow: none;
}
.leaflet-control-zoom a,
.leaflet-touch .leaflet-control-zoom a {
  width: 30px;
  height: 30px;
  line-height: 30px;
  margin-bottom: 5px;
  background: rgba(255, 255, 255, 0.72);
  backdrop-filter: blur(12px) saturate(1.4);
  -webkit-backdrop-filter: blur(12px) saturate(1.4);
  border: none;
  border-radius: var(--r-sm);
  color: #565c56;
  font-size: 17px;
  font-weight: 400;
  box-shadow: 0 1px 5px rgba(0, 0, 0, 0.13);
}
.leaflet-control-zoom a:hover { background: rgba(255, 255, 255, 0.9); color: var(--ink); }

.leaflet-control-attribution {
  background: rgba(255, 255, 255, 0.55);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  color: var(--muted);
  font-size: 10px;
  padding: 3px 7px;
}
.leaflet-control-attribution a { color: var(--muted); }

.legend {
  background: rgba(255, 255, 255, 0.7);
  backdrop-filter: blur(14px) saturate(1.4);
  -webkit-backdrop-filter: blur(14px) saturate(1.4);
  border: 1px solid rgba(255, 255, 255, 0.55);
  border-radius: 11px;
  padding: 10px 12px;
  box-shadow: 0 1px 6px rgba(30, 34, 30, 0.12);
  display: flex;
  flex-direction: column;
  gap: 6px;
  font: 400 11.5px var(--ui);
  color: #565c56;
}
.legend div { display: flex; align-items: center; gap: 8px; white-space: nowrap; }
.legend span.sw {
  width: 15px;
  height: 3px;
  border-radius: 2px;
  flex: none;
  display: inline-block;
}

/* ---- Profil d'altitude ------------------------------------------------ */
.elevation-panel {
  flex: none;
  height: 206px;
  display: flex;
  flex-direction: column;
  background: #fff;
  border-top: 1px solid var(--line);
  padding: 12px 16px 8px;
}
.elevation-head {
  display: flex;
  align-items: baseline;
  gap: 12px;
  margin-bottom: 6px;
}
.elevation-title {
  font: 500 12px var(--display);
  letter-spacing: 0.02em;
}
.elevation-stat {
  font: 400 11.5px var(--ui);
  color: var(--muted-2);
  font-variant-numeric: tabular-nums;
}
.elevation-chart { flex: 1; min-height: 0; }

/* =======================================================================
   3. Panneau latéral
   ======================================================================= */

.stats {
  width: 300px;
  flex: none;
  padding: 16px 18px 22px;
  overflow-y: auto;
  background: var(--paper);
}

/* Navigation par sous-pages : sans objet sur grand écran, où le sélecteur
   posé sur la carte fait le travail. Réactivée par la requête média. */
.panel-nav,
.panel-ticks { display: none; }

.stats h2 {
  margin: 0 0 14px;
  font: 600 15px var(--display);
  letter-spacing: -0.01em;
}

.stat-row {
  display: flex;
  align-items: center;
  gap: 9px;
  font: 400 12.5px var(--ui);
  color: var(--ink-2);
  margin-bottom: 8px;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.stat-swatch {
  width: 9px;
  height: 9px;
  border-radius: 2px;
  flex-shrink: 0;
}
.stat-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.stat-value { margin-left: auto; color: var(--muted); }

.total-row {
  display: flex;
  margin-top: 3px;
  padding-top: 9px;
  border-top: 1px solid var(--hair);
  font: 500 12.5px var(--display);
  font-variant-numeric: tabular-nums;
}
.total-row span { margin-left: auto; }

.note {
  margin: 14px 0 0;
  font: 400 11.5px/1.65 var(--ui);
  color: var(--muted-2);
  text-wrap: pretty;
}

.metric-chart {
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px solid var(--hair);
  height: 164px;
  flex-shrink: 0;
}

/* =======================================================================
   4. Graphiques SVG (charts.js)
   Le SVG est dessiné en pixels réels : ne pas lui imposer de largeur en CSS,
   il se dimensionne sur son conteneur et se re-dessine via ResizeObserver.
   ======================================================================= */

.chart-wrap { display: flex; flex-direction: column; height: 100%; }
.chart-svg-host { flex: 1; min-height: 0; overflow: hidden; }
.chart-caption-row {
  display: flex;
  justify-content: flex-end;
  font: 500 11.5px var(--display);
  color: #565c56;
  min-height: 14px;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.chart-legend-row {
  display: flex;
  gap: 14px;
  justify-content: center;
  font: 400 10.5px var(--ui);
  color: var(--muted);
  padding-top: 3px;
}
.chart-legend-item { display: flex; align-items: center; gap: 5px; }
.chart-legend-item i { width: 9px; height: 9px; border-radius: 2px; display: inline-block; }
.chart-cursor line { stroke: #232a24; stroke-width: 1; }
.chart-grid { stroke: var(--hair); stroke-width: 1; }
.chart-ytick { font: 400 11px var(--display); fill: var(--faint); }
.chart-xtick { font: 400 11px var(--display); fill: var(--muted-2); }
.chart-zero { stroke: var(--faint); stroke-width: 1; stroke-dasharray: 4 4; }
.chart-area { opacity: 0.2; }
/* Profil d'altitude : la pente est portée par le contour, l'aire ne sert plus
   qu'à asseoir la silhouette. */
.chart-elevation-area { fill: #eef1ea; }
.chart-elevation-line {
  stroke-width: 2.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.chart-empty { font: 400 11px var(--ui); fill: var(--faint); }

/* =======================================================================
   5. Surcouches de la carte : vent, sens, ravitaillement
   ======================================================================= */

/* Les flèches de vent sont dessinées par Leaflet comme des icônes HTML ;
   la rotation est portée par le SVG lui-même. */
.wind-arrow { background: none; border: none; }
.wind-arrow svg {
  display: block;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.35));
}
/* Vitesse en clair sous la flèche : la taille donne l'impression d'ensemble,
   le chiffre lève l'ambiguïté. Halo blanc pour rester lisible sur la carte. */
.wind-arrow .wind-label {
  position: absolute;
  left: 50%;
  top: 100%;
  transform: translate(-50%, -1px);
  font: 500 11px/1 var(--display);
  color: #3d423c;
  white-space: nowrap;
  text-shadow: 0 0 3px #fff, 0 0 3px #fff, 0 0 2px #fff, 0 0 2px #fff;
}

/* Flèches de sens de parcours : posées sur le tracé, non interactives, plus
   discrètes que les flèches de vent pour ne pas rivaliser avec elles. */
.direction-arrow { background: none; border: none; pointer-events: none; }
.direction-arrow svg { display: block; opacity: 0.8; filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.35)); }

.supply-marker { background: none; border: none; }
/* Pastille blanche cerclée de la couleur de la catégorie : les émojis ont
   leurs propres couleurs, une goutte bleue sur un disque bleu disparaîtrait.
   Le code couleur tient donc dans le cercle, l'icône dit le reste. */
.supply-marker span {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  border: 2.5px solid;
  background: #fff;
  box-shadow: 0 1px 4px rgba(30, 34, 30, 0.35);
  font-size: 13px;
  line-height: 1;
}

/* =======================================================================
   6. Panneau Ravitaillement
   ======================================================================= */

/* Deux colonnes dès que la place le permet, une seule sinon : à 300 px de
   panneau, « Station-service » et « Réparateur vélo » passeraient à la ligne. */
.supply-types {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(118px, 1fr));
  gap: 6px 8px;
  margin-bottom: 14px;
}
/* Case à cocher présentée comme une puce : la case native reste dans le
   document — c'est elle qui porte l'état, le focus et le clavier — mais on
   coche en visant toute la puce, pas un carré de 13 px. */
.supply-type {
  display: flex;
  align-items: center;
  gap: 7px;
  border: 1px solid var(--line);
  background: #fff;
  border-radius: var(--r-sm);
  padding: 7px 8px;
  cursor: pointer;
  font: 400 12px var(--ui);
  color: var(--ink-2);
  white-space: nowrap;
  min-width: 0;
}
.supply-type:hover { border-color: #c3ccc2; }
.supply-type:has(input:checked) { background: #f0f2ed; border-color: #c3ccc2; }
.supply-type:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 1px; }
.supply-type-name { overflow: hidden; text-overflow: ellipsis; }
.supply-type input {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
}
/* Repli pour les navigateurs sans `:has` : la case reste visible, la puce
   reste utilisable — on perd l'habillage, jamais la fonction. */
@supports not selector(:has(*)) {
  .supply-type input { position: static; opacity: 1; width: auto; height: auto; }
}

/* Le rayon et le bouton vont ensemble : on règle, puis on cherche. */
.supply-radius {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-bottom: 16px;
}
.supply-radius label {
  flex: 1;
  min-width: 120px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  padding: 7px 10px;
  font: 500 10px var(--ui);
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--muted-2);
}
.supply-radius .supply-radius-value {
  display: flex;
  align-items: baseline;
  gap: 4px;
  font: 500 13.5px var(--display);
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.supply-radius input {
  width: 46px;
  border: none;
  padding: 0;
  background: none;
  font: inherit;
  color: inherit;
}
.supply-radius input:focus { outline: none; }
.supply-radius .unit { color: var(--muted-2); font: 400 12px var(--ui); }
.supply-radius button {
  border: none;
  border-radius: var(--r-sm);
  padding: 11px 14px;
  cursor: pointer;
  font: 500 12.5px var(--display);
  background: var(--accent);
  color: #fff;
  white-space: nowrap;
}
.supply-radius button:hover { background: var(--accent-ink); }
.supply-radius button:disabled { background: var(--line); color: var(--faint); cursor: default; }

.supply-msg {
  margin: 0 0 14px;
  font: 400 12.5px/1.6 var(--ui);
  color: var(--muted);
  text-wrap: pretty;
}

.supply-list { list-style: none; margin: 12px 0 0; padding: 0; }
.supply-item {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  padding: 8px;
  border-radius: var(--r-sm);
  cursor: pointer;
}
.supply-item:hover { background: #f2f4f0; }
/* La même pastille sert partout — liste, décompte, filtres, légende — pour
   qu'une catégorie se reconnaisse d'un seul coup d'œil, où qu'elle apparaisse. */
.supply-pin {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  border: 2px solid;
  background: #fff;
  flex-shrink: 0;
  font-size: 10px;
  line-height: 1;
}
.supply-item .supply-pin { margin-top: 1px; }
.supply-type .supply-pin,
.stat-row .supply-pin,
.legend .supply-pin { width: 18px; height: 18px; font-size: 9px; }
.legend .supply-pin { margin-right: 0; }
.supply-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.supply-text strong { font: 500 12.5px var(--ui); }
.supply-text small { font: 400 11.5px var(--ui); color: var(--muted-2); font-variant-numeric: tabular-nums; }
.supply-text .supply-open { color: var(--accent); font-weight: 500; }

/* =======================================================================
   7. Page Analyse
   ======================================================================= */

.dashboard {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  background: var(--canvas);
}

.dash-inner {
  max-width: 1180px;
  margin: 0 auto;
  padding: 30px 30px 44px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.dash-hero,
.dash-card,
.dash-section {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
}

.dash-hero {
  display: flex;
  align-items: center;
  gap: 40px;
  padding: 32px 34px;
  border-radius: 18px;
  flex-wrap: wrap;
}
.hero-ring { flex: none; }
.hero-nodata {
  width: 148px;
  height: 148px;
  display: flex;
  align-items: center;
  justify-content: center;
  font: 400 44px var(--display);
  color: #c9c9c3;
}
.hero-text { flex: 1; min-width: 260px; }
.hero-text h2 {
  margin: 0 0 8px;
  font: 500 11px var(--ui);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted-2);
}
.hero-verdict {
  margin-bottom: 10px;
  font: 600 28px var(--display);
  letter-spacing: -0.01em;
}
.hero-summary {
  margin: 0 0 14px;
  max-width: 520px;
  font: 400 14.5px/1.55 var(--ui);
  color: #565c56;
  text-wrap: pretty;
}
.dash-badge {
  display: inline-block;
  font: 500 12px var(--ui);
  color: var(--muted);
  background: var(--sunk);
  border-radius: 999px;
  padding: 6px 13px;
}
/* Les quatre chiffres du parcours : lus ensemble, jamais isolément — d'où le
   bloc à part, séparé du verdict par un filet plutôt que par du vide. */
.hero-figures {
  flex: none;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 18px 30px;
  font-variant-numeric: tabular-nums;
}
/* Le filet ne sépare que si les deux blocs sont réellement côte à côte :
   dès que le bloc passe à la ligne, une bordure gauche ne sépare plus rien. */
@media (min-width: 1080px) {
  .hero-figures { border-left: 1px solid var(--hair); padding-left: 32px; }
}
.hero-figures div { display: flex; flex-direction: column; gap: 4px; }
.hero-figures span {
  font: 500 10.5px var(--ui);
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--muted-2);
}
.hero-figures strong { font: 600 20px var(--display); white-space: nowrap; }

.ring-value {
  font-family: var(--display);
  font-weight: 600;
  fill: var(--ink);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}
.ring-sub {
  font-family: var(--ui);
  font-size: 11px;
  font-weight: 500;
  fill: var(--muted-2);
}

.dash-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(285px, 1fr));
  gap: 14px;
}
.dash-card {
  padding: 18px 20px 20px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.dash-card header {
  display: flex;
  align-items: center;
  gap: 12px;
}
.dash-card header > div { min-width: 0; }
.dash-card h3 {
  margin: 0;
  font: 600 14px var(--display);
  letter-spacing: -0.01em;
  display: inline;
}
.card-headline {
  margin: 3px 0 0;
  font: 400 12.5px/1.4 var(--ui);
  color: #565c56;
  text-wrap: pretty;
}
.card-weight {
  margin-left: 7px;
  font: 500 10px var(--ui);
  color: #7d847d;
  background: #f2f4f0;
  border-radius: 999px;
  padding: 2px 7px;
  white-space: nowrap;
}
.card-chart { height: 92px; }
.card-detail {
  margin: 0;
  font: 400 11.5px/1.55 var(--ui);
  color: var(--muted-2);
  text-wrap: pretty;
}
/* État dégradé : ambre, jamais rouge — c'est une donnée manquante, pas un
   danger sur le parcours. */
.dash-card-warn {
  background: #fdf6e8;
  border-color: #e6d3a8;
}
.dash-card-warn h3 { color: #7a5c14; }
.dash-card-warn .card-detail { color: #6f5a24; font-size: 12.5px; }

/* Carte Pneus : seule tuile avec ses propres entrées. */
.tire-form {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}
.tire-form label {
  display: flex;
  flex-direction: column;
  gap: 2px;
  background: #f6f7f3;
  border-radius: var(--r-sm);
  padding: 7px 10px;
  font: 500 10px var(--ui);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted-2);
}
.tire-input {
  display: flex;
  align-items: baseline;
  gap: 4px;
  font: 500 13px var(--display);
  text-transform: none;
  letter-spacing: 0;
  color: var(--muted-2);
}
.tire-input input {
  flex: 1;
  min-width: 0;
  border: none;
  background: none;
  padding: 0;
  font: inherit;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.tire-input input:focus { outline: none; }
.tire-form select {
  border: none;
  background: none;
  padding: 0;
  font: 500 13px var(--display);
  text-transform: none;
  letter-spacing: 0;
  color: var(--ink);
}
.tire-pressure { display: flex; gap: 22px; font-variant-numeric: tabular-nums; }
.tire-pressure div { display: flex; flex-direction: column; gap: 2px; }
.tire-pressure span {
  font: 500 10.5px var(--ui);
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--muted-2);
}
.tire-pressure strong { font: 600 26px var(--display); letter-spacing: -0.02em; }
.tire-pressure strong i { font: 400 13px var(--ui); color: var(--muted-2); font-style: normal; }
#tireOutput { display: flex; flex-direction: column; gap: 12px; }

/* Barre empilée : la part de chaque classe en distance. Plus rapide à comparer
   qu'une colonne de pourcentages. */
.dash-bar {
  display: flex;
  height: 16px;
  border-radius: 3px;
  overflow: hidden;
  background: var(--hair);
}
.dash-bar span { display: block; height: 100%; }
.dash-keys { display: flex; flex-wrap: wrap; gap: 8px 14px; margin-top: 10px; }
.dash-key {
  display: flex;
  align-items: center;
  gap: 5px;
  font: 400 11px var(--ui);
  color: var(--muted);
}
.dash-key i { width: 9px; height: 9px; border-radius: 2px; flex-shrink: 0; }
.dash-key b { color: var(--ink); font-variant-numeric: tabular-nums; }

.dash-section { padding: 20px 24px 22px; }
.dash-section-head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 16px;
}
.dash-section h3 {
  margin: 0;
  font: 600 15px var(--display);
  letter-spacing: -0.01em;
}
.dash-section-sub { font: 400 12px var(--ui); color: var(--muted-2); }
.dash-map { height: 390px; border-radius: var(--r-md); overflow: hidden; }
.dash-elevation { height: 224px; }
.dash-endpoint {
  background: #232a24;
  color: #fff;
  border: 2.5px solid #fff;
  border-radius: 50%;
  font: 600 10px/17px var(--display);
  text-align: center;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
}

/* Rubans : quatre lectures du parcours sur le même axe kilométrique. */
/* Le conteneur épouse exactement les quatre rubans — d'où la marge retirée au
   dernier : le curseur s'y cale en `top:0 / bottom:0` et couvre le dernier
   ruban jusqu'en bas. */
.ribbons { position: relative; }
.ribbons .ribbon-row:last-child { margin-bottom: 0; }
/* Un seul trait traverse les quatre rubans : c'est ce qui fait lire d'un coup
   d'œil « ici, revêtu, roulant, sec, mais vent de face ». */
.ribbon-cursor {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 1px;
  background: #232a24;
  pointer-events: none;
  display: none;
}
.ribbon-cursor::before {
  content: "";
  position: absolute;
  left: -3.5px;
  top: -4px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #232a24;
}
.ribbon-row { display: flex; align-items: center; gap: 12px; margin-bottom: 9px; }
.ribbon-label {
  width: 96px;
  flex-shrink: 0;
  font: 400 11.5px var(--ui);
  color: var(--muted);
  white-space: nowrap;
}
.ribbon {
  flex: 1;
  display: flex;
  height: 16px;
  border-radius: 3px;
  overflow: hidden;
  background: var(--hair);
}
.ribbon span { display: block; height: 100%; }
.ribbon-axis {
  flex: 1;
  display: flex;
  justify-content: space-between;
  font: 400 10px var(--display);
  color: var(--faint);
  font-variant-numeric: tabular-nums;
}

.watchouts { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 12px; }
.watchouts li {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  font: 400 13px/1.5 var(--ui);
}
.watchouts i {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  flex-shrink: 0;
  margin-top: 5px;
}
.watch-when {
  width: 118px;
  flex-shrink: 0;
  font: 500 12px var(--display);
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}
.watch-what { color: #565c56; text-wrap: pretty; }
.dash-empty { margin: 0; font: 400 13px var(--ui); color: var(--muted); }

/* =======================================================================
   8. Mise en page mobile (mode Carte)
   Le panneau latéral de 300 px et le sélecteur de vue posé sur la carte ne
   tiennent pas sur un écran de téléphone. On empile : carte pleine largeur
   en haut, à hauteur fixe pour qu'elle reste toujours entièrement visible,
   et dessous un panneau qui défile seul, une catégorie à la fois. Le mode
   Analyse est déjà responsive, il n'est pas concerné.
   ======================================================================= */

@media (max-width: 768px) {
  /* Deux lignes exactement : marque et mode d'un côté, résumé du parcours
     sur toute la largeur en dessous. Laissé au seul `flex-wrap`, le résumé
     s'intercalait entre les deux et en faisait trois. */
  .bandeau { flex-wrap: wrap; gap: 6px 12px; padding: 10px 14px; }
  .brand { order: 0; font-size: 14px; }
  .mode-toggle { order: 1; }
  .route-summary { order: 2; flex-basis: 100%; gap: 8px; }
  .rs-km { font-size: 12.5px; }
  .rs-dim { font-size: 11.5px; }
  .rs-edit { margin-left: auto; }
  body.settings-open .settings { padding: 0 14px 12px; gap: 10px; }
  .fields { flex: 1; flex-wrap: wrap; }

  /* Les catégories se parcourent dans le panneau, plus sur la carte : le
     sélecteur flottant couvrirait le tiers d'un écran de téléphone. */
  .view-picker { display: none; }

  main { flex-direction: column; }
  /* Base fixe, ni compressible ni extensible : c'est ce qui garantit que faire
     défiler le panneau ne fait jamais bouger la carte. */
  .map-col { flex: 0 0 45%; min-height: 210px; border-right: none; }

  .stats {
    width: 100%;
    flex: 1;
    min-height: 0;
    padding: 0;
    overflow: hidden;      /* le défilement passe à .stats-scroll */
    display: flex;
    flex-direction: column;
    border-top: 1px solid var(--line);
  }
  .panel-nav {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
    padding: 10px 10px 0;
    background: var(--paper);
  }
  .panel-nav button {
    width: 44px;
    height: 44px;
    flex: none;
    border: none;
    background: #f0f2ed;
    border-radius: 50%;
    cursor: pointer;
    color: #3a453b;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
  }
  .panel-nav button svg { width: 16px; height: 16px; }
  .panel-nav button:active { background: #e4e8e1; }
  .panel-nav-text {
    flex: 1;
    min-width: 0;
    height: 44px;
    display: flex;
    align-items: center;
    gap: 9px;
    background: #fff;
    border: 1px solid #eaece7;
    border-radius: 22px;
    padding: 0 15px;
    font: 500 14.5px var(--display);
    letter-spacing: -0.01em;
  }
  .panel-nav-text > span:first-of-type {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .panel-pos {
    margin-left: auto;
    font: 400 11.5px var(--display);
    color: var(--faint);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
  }
  /* Repères de position : huit traits qui disent où l'on est dans la série,
     et qui s'atteignent d'un doigt sans passer par les flèches. */
  .panel-ticks {
    display: flex;
    gap: 4px;
    flex-shrink: 0;
    padding: 9px 12px;
    background: var(--paper);
    border-bottom: 1px solid var(--line);
  }
  .panel-ticks button {
    flex: 1;
    height: 3px;
    padding: 0;
    border: none;
    border-radius: 2px;
    background: var(--line-2);
    cursor: pointer;
  }

  .stats-scroll {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    padding: 15px 16px 24px;
  }
  .stats h2 { font-size: 14px; }
  .stat-row { font-size: 13px; }

  /* Dans le panneau, le profil n'a plus de bordure haute à porter : il n'est
     plus collé sous la carte. */
  .elevation-panel { height: 224px; padding: 0; border-top: none; }

  /* La légende posée sur la carte mangeait un bon quart de l'écran alors que le
     tableau juste en dessous porte déjà les mêmes pastilles de couleur. */
  .legend { display: none; }

  /* Accueil sur téléphone : mêmes proportions, en plus resserré. */
  body.no-route > header { padding: 32px 22px 36px; }
  body.no-route h1 { font-size: 25px; }
  .landing-art { max-width: 220px; }

  .dash-inner { padding: 18px 14px 36px; }
  .dash-hero { gap: 22px; padding: 22px; }
  .hero-figures { border-left: none; padding-left: 0; }
  /* Plus assez de place pour une colonne de repères alignés : le « quand »
     reprend sa largeur naturelle et le texte suit à la ligne. */
  .watch-when { width: auto; }
}
