/* ═══════════════════════════════════════════════
   Kmroulant — feuille de styles
   ═══════════════════════════════════════════════ */

:root{
  /* Marque */
  --green:#0B5B44;
  --green-d:#084636;
  --green-l:#0F7255;
  --lime:#C7E82F;
  --lime-d:#AFCF1F;

  /* Neutres */
  --ink:#16211D;
  --ink-2:#48554F;
  --muted:#79867F;
  --line:#E2E8E4;
  --line-2:#EFF3F0;
  --surface:#FFFFFF;
  --surface-2:#F5F8F6;

  /* Données */
  --route:#1A2FCB;
  --route-casing:#0C1470;
  --start:#E03131;
  --end:#1A2FCB;
  --via:#006C57;
  --elev:#57A83B;
  --warn:#C0341A;

  --r-sm:6px;
  --r-md:10px;
  --r-lg:16px;

  --shadow-1:0 1px 2px rgba(22,33,29,.08);
  --shadow-2:0 2px 8px rgba(22,33,29,.09), 0 16px 40px rgba(22,33,29,.14);

  /* Le bandeau de marque appartient à la page hôte : le planificateur ne
     réserve plus rien en tête. La variable subsiste pour les calculs de
     position, qui restent lisibles avec une valeur nulle. */
  --topbar-h:0px;
  /*  Bande réservée à la page hôte : 70 px. En desktop elle est en tête — le
      bandeau de marque —, en mobile en pied. Même hauteur, deux positions :
      d'où les deux noms, qui pointent sur la même valeur. Le planificateur
      s'arrête à sa limite, feuille, dialogues et notifications compris.    */
  --host-h:70px;
  --footer-h:var(--host-h);
  --panel-w:392px;      /* largeur du panneau */
  --sidebar-w:392px;    /* décalage appliqué à la carte : 0 quand il est replié */
  --dock-h:214px;

  --ui:"Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  --display:"Poppins", var(--ui);
}

*{box-sizing:border-box}
html,body{margin:0;height:100%;overflow:hidden;overscroll-behavior:none}
body{
  /* Laissée à la feuille de la page hôte, qui impose déjà sa famille. */
  /* font-family:var(--ui); */
  color:var(--ink);
  background:var(--surface-2);
  -webkit-font-smoothing:antialiased;
  -webkit-tap-highlight-color:transparent;
}
button,input{font:inherit;color:inherit}
button{background:none;border:0;padding:0;cursor:pointer;touch-action:manipulation}

/* Neutralisations imposées par la feuille de la page hôte, qui pose un
   rembourrage sur `section` et une largeur sur `button`. */
section{padding:unset}
button{width:unset}
ol{margin:0;padding:0;list-style:none}
p{margin:0}
:focus-visible{outline:2px solid var(--green-l);outline-offset:2px;border-radius:4px}

/* Le bandeau de marque est désormais fourni par la page hôte : 70 px que le
   planificateur laisse au-dessus de lui. */
#app{
  position:fixed;
  height:calc(100% - var(--footer-h));width:100%;
  bottom:0;left:0;right:0;
}
/*  En mobile, les 70 px sont en bas — c'est le pied de page — et non en tête.
    `top` et `height` étant tous deux posés, `bottom` est écarté : le conteneur
    s'arrête donc pile au-dessus du pied. Le point de bascule est celui de tout
    le reste de la feuille (899 px) : à 810 px, la feuille glissante était déjà
    en place alors que le conteneur réservait encore ses 70 px en tête, et elle
    venait mordre sur le pied entre les deux valeurs. */
@media (max-width:899px){
  #app{top:0;left:0;right:0}
}

/* ─────────────────────────────────────────────
   Carte
   ───────────────────────────────────────────── */
#map{
  height:100%;
  width:100%;
  position:relative;
}
#map canvas{outline:none}

.maplibregl-ctrl-group{border-radius:var(--r-md)!important;box-shadow:var(--shadow-1)!important}
@media (max-width:899px){
  .maplibregl-ctrl-bottom-right,.maplibregl-ctrl-bottom-left{display:none}
}

/* ─────────────────────────────────────────────
   Conteneur : « display:contents » en desktop,
   feuille glissante en mobile
   ───────────────────────────────────────────── */
@media (min-width:900px){
  #sheet{display:contents}

  #sidebar{
    position:absolute;z-index:30;
    top:calc(var(--topbar-h) + env(safe-area-inset-top));
    left:0;bottom:0;width:var(--panel-w);
    transition:transform .28s cubic-bezier(.32,.72,0,1);
    background:var(--surface);
    border-right:1px solid var(--line);
    overflow-y:auto;overscroll-behavior:contain;
  }
  #dock{
    position:absolute;z-index:30;
    left:var(--sidebar-w);right:0;bottom:0;
    transition:left .28s cubic-bezier(.32,.72,0,1);
    background:var(--surface);
    border-top:1px solid var(--line);
    box-shadow:0 -2px 14px rgba(22,33,29,.07);
  }
  #dock[hidden]{display:none}
  .maplibregl-ctrl-top-left{margin-left:calc(var(--sidebar-w) + 10px)}
}

@media (max-width:899px){
  #sheet{
    position:absolute;left:0;right:0;bottom:0;z-index:30;
    height:min(88dvh, 88vh);
    background:var(--surface);
    border-radius:var(--r-lg) var(--r-lg) 0 0;
    box-shadow:var(--shadow-2);
    display:flex;flex-direction:column;
    /* Repli de départ : la poignée et les onglets, à peu près — la valeur
       exacte vient du JS dès la première mesure. Un repli à 45 % faisait
       apparaître la feuille à mi-écran avant de la voir se rétracter. */
    transform:translateY(var(--sheet-y, calc(100% - 80px)));
    transition:transform .34s cubic-bezier(.32,.72,0,1);
    padding-bottom:env(safe-area-inset-bottom);
  }
  #sheet.dragging{transition:none}
  /* Posée dans le HTML, retirée après la première mesure : le passage du repli
     approché à la position calculée ne doit pas s'animer. */
  #sheet.booting{transition:none}
  /* La feuille garde sa hauteur pleine pour l'animation ; c'est la zone
     défilante qui se limite à la portion réellement visible, sinon le contenu
     part sous le bas de l'écran au lieu de défiler. */
  #sidebar, #dock{
    max-height:calc(var(--sheet-open, 60vh) - var(--sheet-strip, 64px));
  }
  #sidebar{order:3;overflow-y:auto;overscroll-behavior:contain;flex:1 1 auto}
  #dock{order:2;flex:1 1 auto;border-bottom:0;overflow-y:auto;overscroll-behavior:contain}

  /* Sélecteur d'identifiant : la règle générique .grip plus bas dans le
     fichier l'emporterait autrement et masquerait la poignée. */
  #sheet > .grip{display:flex}
  #dock[hidden]{display:none}
  .grip{display:flex;flex:0 0 auto;order:0}

  /* Bandeau permanent : onglets + GPX, visibles à tous les crans.
     Sélecteur d'identifiant : la règle générique .sheet-tabs plus bas dans le
     fichier l'emporterait autrement et masquerait tout le bandeau. */
  #sheet > .sheet-tabs[hidden]{display:none}
  #sheet > .sheet-tabs{
    display:flex;order:1;flex:0 0 auto;
    align-items:center;gap:10px;
    /* Hauteur fixe et rembourrage symétrique : le rembourrage dissymétrique
       d'avant (2 px en haut, 10 en bas) décalait les boutons vers le haut. */
    height:54px;padding:0 16px;
    border-bottom:1px solid var(--line-2);
  }
  .sheet-tabs[hidden]{display:none}

  /* Un seul mode à la fois */
  #sheet[data-tab="elev"]  #sidebar{display:none}
  #sheet[data-tab="route"] #dock{display:none}

  /* Mode Élévation : rien ne défile à l'intérieur, c'est la poignée qui
     règle ce qu'on voit. Le bandeau prend donc sa hauteur naturelle. */
  #sheet[data-tab="elev"] #dock{
    flex:0 0 auto;max-height:none;overflow:visible;
  }

  /* En mode profil, la feuille ne contient que la barre d'info et le graphe */
}

.sheet-tabs{display:none}
.seg{
  flex:1 1 auto;display:flex;gap:3px;
  background:var(--surface-2);padding:3px;border-radius:var(--r-md);
}
.seg button{
  flex:1 1 0;padding:7px 4px;border-radius:7px;
  font-size:13px;font-weight:500;color:var(--ink-2);
  transition:background .15s,color .15s;
}
.seg button[aria-pressed="true"]{
  background:var(--surface);color:var(--ink);font-weight:600;box-shadow:var(--shadow-1);
}
.seg button:disabled{color:var(--line);cursor:default;background:none;box-shadow:none}
.gpx:disabled{background:var(--line-2);color:var(--muted);cursor:default}
.gpx:disabled:hover{background:var(--line-2)}
.gpx.sm{margin-left:0;flex:0 0 auto;padding:8px 13px;font-size:12.5px}

/* Effacement en mobile : corbeille rouge posée à droite de « Terminer ».
   Le bouton libellé du panneau lui reste réservé au desktop. */
.trash{
  flex:0 0 auto;display:grid;place-items:center;
  width:36px;height:36px;border-radius:var(--r-md);
  border:1px solid #F3C7C2;background:#FFF5F4;color:var(--warn);
}
.trash[hidden]{display:none}
.trash:hover{background:#FDE8E5;border-color:var(--warn)}
.trash svg{width:17px;height:17px;stroke-width:1.9;fill:none;stroke:currentColor}

.grip{
  display:none;justify-content:center;align-items:center;
  padding:11px 0 9px;touch-action:none;cursor:grab;
}
.grip:active{cursor:grabbing}
.grip i{display:block;width:42px;height:5px;border-radius:3px;background:#CFD6D1}
.grip:hover i{background:var(--muted)}

/* ─────────────────────────────────────────────
   Colonne de gauche
   ───────────────────────────────────────────── */
.pane{padding:16px 16px 28px}

/*  Les étiquettes reprennent la couleur du texte courant : en gris, elles se
    lisaient comme une note de bas de page alors qu'elles nomment les trois
    blocs de la colonne.                                                      */
.label{
  display:flex;align-items:center;gap:7px;
  font-size:11px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;
  margin:0 0 8px;
}
/* `color` seul : chaque pictogramme choisit par attribut s'il se dessine au
   trait (épingle) ou au remplissage (tracé). */
.label svg{flex:0 0 auto;width:18px;height:18px;stroke-width:1.8;color:var(--green)}
.pts-head .label svg{width:20px;height:20px}
.only-desktop{display:none}
@media (min-width:900px){ .only-desktop{display:block} }
.label:not(:first-child){margin-top:20px}

/* Sélecteur de profil */
.picker{position:relative}
.picker-btn{
  width:100%;display:flex;align-items:center;gap:10px;
  padding:11px 12px;border-radius:var(--r-md);
  border:1.5px solid var(--line);background:var(--surface);
  font-size:14px;font-weight:600;text-align:left;
  transition:border-color .15s;
}
.picker-btn:hover{border-color:var(--muted)}
.picker-btn[aria-expanded="true"]{border-color:var(--green)}
/*  Teinte posée sur `color` et non sur `stroke` : les pictogrammes de profil
    mêlent traits et aplats — la tête du cycliste est un disque plein, qui
    porte `fill="currentColor"`. Sans `color`, elle resterait noire quand le
    reste du dessin passe au vert.                                            */
.picker-btn > svg:first-child{
  width:22px;height:22px;flex:0 0 auto;
  fill:none;color:var(--green);stroke:currentColor;stroke-width:1.7;
}
.picker-btn .chev{
  width:16px;height:16px;margin-left:auto;flex:0 0 auto;
  fill:none;stroke:var(--muted);stroke-width:2;transition:transform .18s;
}
.picker-btn[aria-expanded="true"] .chev{transform:rotate(180deg)}

.picker-list{
  position:absolute;z-index:60;top:calc(100% + 6px);left:0;right:0;
  background:var(--surface);border:1.5px solid var(--line);
  border-radius:var(--r-md);box-shadow:var(--shadow-2);
  overflow:hidden;max-height:290px;overflow-y:auto;
}
.picker-list[hidden]{display:none}
.picker-list button{
  display:flex;align-items:center;gap:10px;width:100%;text-align:left;
  padding:10px 12px;border-bottom:1px solid var(--line-2);
}
.picker-list button:last-child{border-bottom:0}
.picker-list button:hover{background:var(--surface-2)}
.picker-list button[aria-selected="true"]{background:var(--surface-2)}
.picker-list svg{
  width:21px;height:21px;flex:0 0 auto;
  fill:none;color:var(--ink-2);stroke:currentColor;stroke-width:1.7;
}
.picker-list button[aria-selected="true"] svg{color:var(--green)}
.picker-list .txt{flex:1 1 auto;min-width:0}
.picker-list .txt b{display:block;font-size:13.5px;font-weight:600}
.picker-list .txt small{display:block;font-size:11.5px;color:var(--muted);margin-top:1px}
.picker-list .tick{color:var(--green);stroke-width:2.4;width:16px;height:16px}

/* Recherche */
.search{
  display:flex;align-items:center;gap:8px;
  padding:0 10px;border-radius:var(--r-md);
  /* Le champ portait un cadre transparent sur fond gris : posé dans la carte
     verte, il ne se distinguait plus. Le cadre du focus devient donc l'état
     de repos, et le focus se contente d'appuyer le trait. */
  background:var(--surface);border:1.5px solid var(--line);
  transition:border-color .15s,background .15s,box-shadow .15s;
}
.search:hover{border-color:var(--muted)}
.search:focus-within{
  border-color:var(--green);
  box-shadow:0 0 0 3px rgba(11,91,68,.12);
}
.search > svg{width:17px;height:17px;stroke-width:1.9;color:var(--muted);flex:0 0 auto}
.search input{flex:1 1 auto;min-width:0;padding:11px 0;border:0;background:none;font-size:14px}
.search input::placeholder{color:var(--muted)}
.search input:focus{outline:none}

.icon{
  width:26px;height:26px;flex:0 0 auto;
  display:grid;place-items:center;border-radius:var(--r-sm);color:var(--muted);
}
.icon svg{width:15px;height:15px;stroke-width:1.9;fill:none;stroke:currentColor}
.icon:hover{color:var(--ink);background:var(--line-2)}

/* Suggestions */
.suggest{
  margin-top:6px;border:1.5px solid var(--line);border-radius:var(--r-md);
  overflow:hidden;max-height:260px;overflow-y:auto;background:var(--surface);
  box-shadow:var(--shadow-1);
}
.suggest[hidden]{display:none}
.suggest button{
  display:block;width:100%;text-align:left;padding:10px 12px;
  border-bottom:1px solid var(--line-2);
}
.suggest button:last-child{border-bottom:0}
.suggest button:hover,.suggest button.on{background:var(--surface-2)}
.suggest b{display:block;font-size:13.5px;font-weight:600}
.suggest small{display:block;font-size:11.5px;color:var(--muted);margin-top:1px}

/* Liste des points */
.pts-tools{display:flex;gap:6px;margin-bottom:8px;align-items:center}
.pts-tools button{
  display:inline-flex;align-items:center;gap:6px;
  padding:7px 12px;border-radius:var(--r-md);
  border:1.5px solid var(--line);
  font-size:12.5px;font-weight:600;color:var(--green);
  transition:border-color .15s,background .15s;
}
.pts-tools button svg{width:14px;height:14px;stroke-width:2;fill:none;stroke:currentColor}
.pts-tools button:hover{border-color:var(--green);background:var(--surface-2)}
/* Annuler et rétablir : cadre et flèche au vert de la marque. Le rouge était
   réservé à ce qui détruit, or revenir en arrière ne détruit rien. */
.pts-tools .icon{
  width:auto;height:auto;padding:7px 10px;
  border:1.5px solid var(--line);border-radius:var(--r-md);
  color:var(--green);
}
.pts-tools .icon svg{width:15px;height:15px;stroke:currentColor}
.pts-tools .icon:hover{border-color:var(--green);background:var(--surface-2)}
.pts-tools .icon:disabled{opacity:.4;cursor:default}
.pts-tools .icon:disabled:hover{border-color:var(--line);background:none}

/* Effacer : corbeille seule, sans libellé. */
.pts-tools .icon-only{padding:7px 9px}

#clear{color:var(--warn);border-color:#F0CFCA}
#clear svg{stroke:var(--warn)}
#clear:hover{border-color:var(--warn);background:#FFF6F5}
.pts-tools button[hidden]{
  display:inline-block;      /* neutralise le display:none de l'attribut hidden */
  visibility:hidden;         /* la place reste réservée : les flèches ne bougent pas */
}

.pts li{
  display:flex;align-items:center;gap:9px;
  padding:9px 4px 9px 0;border-bottom:1px solid var(--line-2);
  background:var(--surface);
}
.pts li:last-child{border-bottom:0}
.pts li.dragging{
  background:var(--surface-2);border-radius:var(--r-md);
  box-shadow:var(--shadow-1);border-bottom-color:transparent;
}
.drag{
  flex:0 0 18px;height:26px;display:grid;place-items:center;
  color:var(--line);cursor:grab;touch-action:none;
}
.drag:hover{color:var(--muted)}
.drag:active{cursor:grabbing}
.drag svg{width:16px;height:16px}
.badge{
  flex:0 0 28px;height:28px;border-radius:50%;
  display:grid;place-items:center;
  font-size:12px;font-weight:700;color:#fff;background:var(--via);
}
.pts li[data-role="start"] .badge{background:var(--start)}
.pts li[data-role="end"] .badge{background:var(--end)}
.pt-name{
  flex:1 1 auto;min-width:0;font-size:14px;font-weight:500;line-height:1.3;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.pt-name em{display:block;font-style:normal;font-size:12px;font-weight:400;color:var(--muted);margin-top:1px}
.pt-act{display:flex;gap:2px;flex:0 0 auto}
.pt-act [data-act="up"]{color:var(--green)}
.pt-act [data-act="up"]:hover{color:var(--green-d);background:var(--surface-2)}

.hint{margin-top:14px;font-size:12.5px;line-height:1.5;color:var(--muted)}
.hint[hidden]{display:none}
/* ─────────────────────────────────────────────
   Bandeau statistiques
   ───────────────────────────────────────────── */
.stats{
  display:flex;align-items:center;gap:22px;
  padding:12px 18px;border-bottom:1px solid var(--line-2);
}
.stat-list{display:flex;align-items:center;min-width:0}

/*  UNE CASE : intitulé et pictogramme en haut, valeur dessous. Les cases sont
    séparées par un filet vertical, porté par chacune sauf la première. Voir
    `fillStats` pour le contenu.                                            */
.stat{
  display:flex;flex-direction:column;gap:5px;flex:0 0 auto;min-width:0;
  padding:0 20px;
}
.stat + .stat{border-left:1px solid var(--line)}
.stat:first-child{padding-left:0}

.stat-k{
  display:flex;align-items:center;gap:6px;
  font-size:12.5px;font-weight:600;line-height:1.2;color:var(--ink-2);
}
.stat-k svg{
  flex:0 0 auto;width:15px;height:15px;
  fill:none;stroke:currentColor;stroke-width:1.9;stroke-linecap:round;stroke-linejoin:round;
}

.stat-v{
  display:block;
  font-size:21px;font-weight:700;line-height:1.1;letter-spacing:-.01em;
  font-variant-numeric:tabular-nums;color:var(--ink);white-space:nowrap;
}
.stat-v small{margin:0 4px 0 3px;font-size:.62em;font-weight:600;color:var(--ink-2)}
.stat-v small:last-child{margin-right:0}
.stat-dist .stat-v{font-size:25px;color:var(--green)}
.stat-dist .stat-v small{color:var(--green)}

/*  Dénivelé : montée et descente, chacune avec sa flèche. */
/*  Le seul écart entre morceaux d'une valeur : celui qui sépare montée et
    descente. Entre un chiffre et son unité, il n'y en a pas — `small` porte
    sa propre marge.                                                       */
.stat-deniv .stat-v{display:flex;align-items:baseline;gap:14px;font-size:18px}
.dn{display:inline-block;white-space:nowrap}
.dn-ar{display:inline-block;width:10px;height:10px;margin-right:5px;vertical-align:.08em}
.dn.up .dn-ar{fill:#D9480F}
.dn.down .dn-ar{fill:#1C64D8}

.gpx{
  margin-left:auto;flex:0 0 auto;
  display:inline-flex;align-items:center;gap:7px;
  padding:9px 15px;border-radius:var(--r-md);
  background:var(--green);color:#fff;font-size:13px;font-weight:600;
}
.gpx svg{width:15px;height:15px;stroke-width:2;fill:none;stroke:currentColor}
.gpx:hover{background:var(--green-l)}
.toggle{
  flex:0 0 auto;transition:transform .25s;
  border:1px solid var(--line);border-radius:8px;
}
#dock.folded .toggle{transform:rotate(180deg)}
#dock.folded .elev,
#dock.folded .shares{display:none}
#dock.folded .stats{border-bottom:0}

/* ─────────────────────────────────────────────
   Profil altimétrique
   ───────────────────────────────────────────── */
.elev{display:flex;gap:14px;padding:12px 18px 16px;align-items:stretch}
.readout{
  flex:0 0 92px;display:flex;flex-direction:column;justify-content:center;gap:9px;
}
.readout div{display:flex;flex-direction:column;gap:1px}
.readout span{font-size:10px;font-weight:600;letter-spacing:.05em;text-transform:uppercase;color:var(--muted)}
.readout b{font-size:13.5px;font-weight:600;font-variant-numeric:tabular-nums}

/*  LE MESSAGE D'UNE PENTE RAIDE PREND LA PLACE DES TROIS CASES, le temps de se
    lire — voir `montrerPente` dans planner-main.js. La même phrase que la bulle
    du desktop, sans son titre : le chiffre en rouge dit « pente raide » mieux
    que les mots, et ceux-ci ne tenaient pas dans la largeur.

    Les cases sont masquées plutôt que vidées : `renderReadout` continue de les
    tenir à jour dessous, et elles reparaissent justes au retour.          */
/*  LA HAUTEUR DU BLOC NE BOUGE PAS. Masquer les cases faisait prendre au
    bloc la hauteur de la phrase — une ligne ou deux selon la longueur —, et
    tout ce qui suit sautait d'autant. Les cases restent donc en place,
    seulement invisibles, et c'est la phrase qui vient se poser par-dessus,
    centrée dans les deux sens. Interligne serré : deux lignes tiennent dans
    la hauteur des cases.                                                   */
.readout{position:relative}
.readout-msg{
  display:none;position:absolute;inset:0;margin:0;
  align-items:center;justify-content:center;text-align:center;
  font-size:13.5px;line-height:1.2;color:var(--ink-2);
}
.readout.is-message > div{visibility:hidden}
.readout.is-message .readout-msg{display:flex}
.readout-msg b{color:#B42318;font-size:inherit}

.chart{
  flex:1 1 auto;position:relative;height:132px;min-width:0;
  padding-right:40px;padding-bottom:18px;
  cursor:crosshair;touch-action:pan-y;
}
.chart-svg{position:absolute;inset:0;right:40px;bottom:18px}
.chart-svg svg{width:100%;height:100%;display:block;overflow:visible}
.elev-grid{stroke:var(--line);stroke-width:1;stroke-dasharray:3 4}
.elev-area{stroke:none}
.elev-line{stroke:var(--elev);stroke-width:1.8;stroke-linejoin:round;fill:none}

.y-max,.y-min{
  position:absolute;right:0;font-size:10.5px;color:var(--muted);
  font-variant-numeric:tabular-nums;
}
.y-max{top:-4px}
.y-min{bottom:14px}
.x-axis{
  position:absolute;left:0;right:40px;bottom:0;height:16px;
}
.x-axis span{
  position:absolute;transform:translateX(-50%);
  font-size:10.5px;color:var(--muted);font-variant-numeric:tabular-nums;
  white-space:nowrap;
}
.x-axis span:first-child{transform:none}

.cursor{position:absolute;top:0;bottom:18px;width:0;pointer-events:none}
.cursor::before{
  content:"";position:absolute;top:0;bottom:0;left:0;
  border-left:1px solid var(--ink);opacity:.35;
}
.cursor i{
  position:absolute;width:9px;height:9px;margin:-4.5px 0 0 -4.5px;
  border-radius:50%;background:var(--elev);border:2px solid #fff;
  box-shadow:0 1px 3px rgba(0,0,0,.3);
}
.cursor[hidden]{display:none}

.no-elev{
  flex:1 1 auto;align-self:center;font-size:12.5px;line-height:1.5;color:var(--muted);
}
.no-elev[hidden]{display:none}

@media (max-width:899px){
  #dock{display:flex;flex-direction:column}
  .elev{flex:0 0 auto;flex-direction:column;gap:10px;padding:12px 16px 16px}
  .readout{flex:0 0 auto;flex-direction:row;justify-content:space-between;gap:0}
  .chart{flex:0 0 auto;height:120px}

  /* La recherche vit dans la modale plein écran, ouverte depuis la carte */
  #searchBlock{display:none}

  /* L'ordre des blocs mobiles n'est plus forcé ici : le volet suit la source,
     et les réglages s'ordonnent dans leur carte — voir « Panneau en cartes ». */
}

#searchBlock .suggest{margin-top:8px}

/* ─────────────────────────────────────────────
   Proposition d'ajout d'un point (mobile)
   Remplace la popup de carte : la feuille
   s'ouvre juste ce qu'il faut au-dessus de ses
   onglets, et un repère marque le point désigné.
   ───────────────────────────────────────────── */
.propose{display:none}

@media (max-width:899px){
  /*  `--accent` est posé par le JS sur la feuille quand la barre parle d'une
      trace : elle prend alors la teinte de son activité. C'est le seul lien
      visible entre ce qu'on lit ici et le trait mis en évidence sur la carte,
      que la feuille recouvre en partie. Sans trace, le vert du programme.   */
  #sheet > .propose{
    display:block;order:1;flex:0 0 auto;position:relative;
    padding:0 16px 12px;
    background:var(--accent, var(--green));
  }
  #sheet > .propose[hidden]{display:none}

  /*  Tant qu'un point attend une décision, le haut de la feuille est vert d'un
      seul tenant — poignée comprise, sans quoi une bande blanche flotterait
      au-dessus du bloc. La classe est posée par le JS avec la barre.        */
  #sheet.proposing > .grip{
    background:var(--accent, var(--green));
    border-radius:var(--r-lg) var(--r-lg) 0 0;
    /*  Deux blocs verts qui se touchent laissent parfois voir un cheveu blanc
        entre eux : les hauteurs tombent sur des demi-pixels et l'arrondi ne
        va pas dans le même sens d'un navigateur à l'autre. Cette ombre d'un
        pixel comble la couture sans déplacer quoi que ce soit.             */
    box-shadow:0 1px 0 0 var(--accent, var(--green));
  }
  #sheet.proposing > .grip i{background:rgba(255,255,255,.55)}
  #sheet.proposing > .grip:hover i{background:rgba(255,255,255,.8)}
}

/* Une ligne d'en-tête donne sa place à l'annulation : posée en pastille
   flottante, elle chevauchait les actions sans qu'on sache à quoi elle se
   rapportait. Le lieu désigné la précède, ce qui rattache le tout au point. */
.propose-head{
  display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding-bottom:2px;
}
/*  Le titre de la barre porte l'essentiel — « Supermarché · à 132 m du tracé ».
    À onze pixels il se lisait comme une étiquette de section alors qu'il est ce
    qu'on vient lire.                                                        */
.propose-head span{
  min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  font-size:14px;font-weight:600;letter-spacing:.02em;text-transform:uppercase;
  color:var(--muted);
}
/* Sur le fond vert du bloc, le lieu désigné se lit en blanc. */
#proposeTitle{color:#FFFFFF}
.propose-close{
  flex:0 0 auto;display:flex;align-items:center;gap:6px;
  padding:6px 11px;border-radius:999px;
  border:1px solid var(--line);background:var(--surface);
  font-size:12.5px;font-weight:500;color:var(--ink-2);
}
.propose-close:hover{background:var(--surface-2);color:var(--ink)}
.propose-close svg{width:14px;height:14px;stroke-width:2.2;fill:none;stroke:currentColor}

.propose-acts{display:flex;gap:10px;margin-top:12px}
.propose-acts button{
  flex:1 1 0;min-width:0;
  display:flex;align-items:center;justify-content:center;gap:11px;text-align:left;
  padding:12px 13px;border-radius:var(--r-lg);
  border:1.5px solid var(--line);background:var(--surface);
}
/* La dernière action est celle qui referme le parcours : elle se détache. */
.propose-acts button.end{border-color:#CFE5DB;background:var(--surface)}
.propose-acts button:active{background:var(--surface-2)}
.propose-acts svg{
  flex:0 0 auto;width:22px;height:22px;
  fill:none;stroke:var(--accent, var(--green));
  stroke-linecap:round;stroke-linejoin:round;
}
/*  Le verbe seul. La ligne d'explication tenait sous chaque action — « Partir
    de ce point », « Le retirer du parcours » — et faisait monter la barre d'une
    trentaine de pixels sur un écran qui n'en a pas à donner. Les trois actions
    se nomment assez : départ, étape, arrivée.                               */
.propose-txt{display:flex;min-width:0}
.propose-txt b{font-size:14.5px;font-weight:600}

/* Repère du point désigné : anneau vert cerné d'un halo, posé au centre du
   point cliqué — il n'a pas de pointe, rien ne se lit sous lui. */
/*  Mêmes dimensions que le repère du champ de recherche de lieu, en pixels
    d'écran : halo de 36 px à 16 % d'opacité, point blanc de 18 px cerclé de
    3 px. `box-sizing:border-box` est global, la bordure est donc comprise dans
    les 18 px et il reste 12 px de blanc — soit `circle-radius:6` cerclé de 3
    côté MapLibre. La teinte #006C57 est celle de `--via`. */
/*  MÊMES VALEURS QUE LE REPÈRE DE RECHERCHE DE LIEU, pour que les deux se
    lisent comme un seul objet — c'est le même geste, désigner un point qu'on
    n'a pas encore posé.

    Halo : disque de 36 px, `--via` à 16 % d'opacité — l'équivalent d'un
    `circle-radius` de 18 côté MapLibre. Point : disque blanc de 18 px cerclé
    de 3 px, soit un rayon de 6 plus son contour. La bordure est comptée dans
    la largeur (`border-box` général), d'où 18 px pour un blanc de 12.       */
.pending-mark{
  width:36px;height:36px;border-radius:50%;
  background:rgba(0,108,87,.16);
  display:grid;place-items:center;
  animation:pending-in .22s cubic-bezier(.32,.72,0,1);
}
.pending-mark::after{
  content:"";width:18px;height:18px;border-radius:50%;
  background:#FFFFFF;
  border:3px solid var(--via);
}
@keyframes pending-in{from{transform:scale(.4);opacity:0}}
@media (prefers-reduced-motion:reduce){ .pending-mark{animation:none} }

/* ─────────────────────────────────────────────
   Repères de carte
   ───────────────────────────────────────────── */
/*  ⚠ `position:absolute`, ET SURTOUT PAS `relative`.

    MapLibre place ses repères par une transformation :
    `translate(-50%,-50%) translate(Xpx, Ypx)`, où X et Y sont la projection du
    point à l'écran. Cela ne fonctionne que si l'élément part de l'origine du
    conteneur — c'est ce que fait `.maplibregl-marker`, en `position:absolute`
    avec `top:0;left:0`.

    Passé en `relative`, l'élément reprend sa place dans le flux et la
    transformation s'applique DEPUIS CETTE PLACE. Le premier repère paraît
    juste, parce que le flux le pose justement à l'origine ; tous les suivants
    sont décalés de la hauteur de ceux qui les précèdent. Et comme le décalage
    est en pixels d'écran quand la position, elle, est géographique, les
    repères semblent glisser sur la carte à chaque cran de zoom.

    On l'avait mis pour ancrer la pastille de ravitaillement. C'était inutile :
    un élément `absolute` est déjà un bloc conteneur pour ses descendants
    absolus. La pastille tient donc sans cela.                               */
.mk{
  position:absolute;
  width:26px;height:26px;border-radius:50%;
  display:grid;place-items:center;cursor:grab;
  font-size:11px;font-weight:700;color:#fff;
  border:2px solid #fff;background:var(--via);
  box-shadow:0 1px 4px rgba(0,0,0,.3);
}
.mk:active{cursor:grabbing}
/* Vue de loin, la carte ne garde que le départ et l'arrivée : `far` est posée
   sur le conteneur par mapview.js, sous son seuil d'échelle. */
#map.far .mk[data-role="via"]{display:none}
.mk[data-role="start"]{background:var(--start)}
.mk[data-role="end"]{background:var(--end)}
.mk[data-role="via"]{width:23px;height:23px;border-width:2px;font-size:10.5px}

/* Étape née d'un point d'intérêt : second liseré à la couleur des épingles.
   Un clic dessus rouvre la fiche du POI, il faut que cela se devine. */
.mk.from-poi{box-shadow:0 0 0 2px #7A1418, 0 1px 4px rgba(0,0,0,.3)}

/* Étape posée sur un point d'eau ou un ravitaillement : la goutte ou le panier,
   à la couleur de la famille, en bas à droite du repère. Hors du disque et non
   dedans — la lettre de l'étape occupe déjà le centre, et deux signes
   superposés ne se lisent ni l'un ni l'autre.
   Le contenu est posé par mapview.js APRÈS `textContent`, qui vide l'élément. */
.mk-amenity{
  position:absolute;right:-6px;bottom:-6px;
  width:15px;height:15px;border-radius:50%;
  display:grid;place-items:center;
  background:var(--amenity,#6CA0DC);
  border:1.5px solid #fff;
  box-shadow:0 1px 3px rgba(0,0,0,.35);
  pointer-events:none;              /* le repère entier reste saisissable */
}
.mk-amenity svg{width:9.5px;height:9.5px;display:block}
/* Le repère intermédiaire est plus petit : la pastille se rapproche pour ne
   pas flotter à côté. */
.mk[data-role="via"] .mk-amenity{right:-5px;bottom:-5px;width:14px;height:14px}

.hover-dot{
  width:14px;height:14px;border-radius:50%;
  background:var(--elev);border:2.5px solid #fff;
  box-shadow:0 1px 4px rgba(0,0,0,.35);pointer-events:none;
}

/* ─────────────────────────────────────────────
   Popup « Nouveau point »
   ───────────────────────────────────────────── */
/*  Sous la colonne, le bandeau du profil et les contrôles de carte, qui sont
    à 20 et 30. La popup est censée tenir dans la portion de carte visible —
    `keepPopupInView` fait glisser la carte pour cela — mais quand elle
    déborde malgré tout, mieux vaut qu'elle passe dessous que par-dessus.   */
.maplibregl-popup{z-index:15}
.maplibregl-popup-content{
  padding:0!important;border-radius:var(--r-md)!important;
  box-shadow:var(--shadow-2)!important;overflow:hidden;
  font-family:var(--ui);
}
.maplibregl-popup-close-button{display:none}

/* Pointe : sa couleur suit le bord du contenu qu'elle touche. Le haut de la
   fiche est blanc, le bas est vert. Sur les côtés la pointe arrive au milieu,
   là où les deux se rejoignent : on la laisse blanche. */
.maplibregl-popup-anchor-bottom .maplibregl-popup-tip,
.maplibregl-popup-anchor-bottom-left .maplibregl-popup-tip,
.maplibregl-popup-anchor-bottom-right .maplibregl-popup-tip{
  border-top-color:var(--green)!important;
}
.maplibregl-popup-anchor-top .maplibregl-popup-tip,
.maplibregl-popup-anchor-top-left .maplibregl-popup-tip,
.maplibregl-popup-anchor-top-right .maplibregl-popup-tip{
  border-bottom-color:var(--surface)!important;
}
.maplibregl-popup-anchor-left .maplibregl-popup-tip{border-right-color:var(--surface)!important}
.maplibregl-popup-anchor-right .maplibregl-popup-tip{border-left-color:var(--surface)!important}

/* Ancrage d'angle (mobile) : la pointe se colle au coin de la fiche, mais
   notre `border-radius` en `!important` écrasait le coin carré que MapLibre
   pose justement là — d'où le croissant de vide entre la pointe et la fiche.
   On le rétablit, avec la même arme. */
.maplibregl-popup-anchor-top-left .maplibregl-popup-content{border-top-left-radius:0!important}
.maplibregl-popup-anchor-top-right .maplibregl-popup-content{border-top-right-radius:0!important}
.maplibregl-popup-anchor-bottom-left .maplibregl-popup-content{border-bottom-left-radius:0!important}
.maplibregl-popup-anchor-bottom-right .maplibregl-popup-content{border-bottom-right-radius:0!important}

/* Le titre s'aligne à gauche, comme les actions qui le suivent : centré, il
   flottait au-dessus d'elles sans les rattacher à rien. */
.pop-head{
  position:relative;display:flex;align-items:center;gap:9px;
  padding:13px 42px 11px 15px;background:var(--surface);
}
/*  Étiquette d'activité, à gauche du nom. En capitales et à la teinte de
    l'activité : on lit de quoi il s'agit avant de lire lequel, comme sur un
    rayon dont on repère d'abord la catégorie.                               */
.pop-tag{
  flex:0 0 auto;align-self:flex-start;margin-top:2px;
  font-size:10.5px;font-weight:800;letter-spacing:.07em;
  color:var(--accent, var(--green));
}
.pop-head b{
  font-size:11px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;
  color:var(--muted);line-height:1.3;max-width:240px;
}
.pop-head .icon{position:absolute;top:8px;right:8px}
/* Boutons détachés, posés sur le fond de la popup plutôt que collés à ses
   bords : en bandes pleine largeur, on ne voyait plus le lien avec le titre —
   la popup semblait faite de trois blocs sans rapport. */
.pop-acts{
  display:flex;flex-direction:column;gap:8px;
  padding:0 12px 12px;background:var(--surface);
}
.pop-acts button{
  padding:11px 14px;font-size:13.5px;font-weight:500;
  display:flex;align-items:center;justify-content:center;gap:9px;white-space:nowrap;
  border-radius:var(--r-md);
  border:1.5px solid var(--green);background:var(--green);color:#fff;
  transition:background .15s,border-color .15s;
}
.pop-acts button:hover{background:var(--green-l);border-color:var(--green-l)}

/* Dernière action — « Nouvelle arrivée » : couleurs inversées, pour qu'elle ne
   se confonde pas avec l'ajout d'un point de passage. */
.pop-acts button:last-child:not(:only-child){
  background:var(--surface);color:var(--green);border-color:var(--line);
}
.pop-acts button:last-child:not(:only-child):hover{
  background:var(--surface-2);border-color:var(--green);
}
.pop-acts button:last-child:not(:only-child) svg{stroke:var(--green)}
.pop-acts svg{width:13px;height:13px;stroke-width:2;fill:none;stroke:var(--lime)}

/*  FICHE À LA COULEUR DE CE QU'ELLE DÉSIGNE.

    Une trace touchée sur la carte ouvre sa fiche par-dessus le trait qu'elle
    vient de mettre en évidence, et le recouvre en partie. La teinte de
    l'activité est ce qui rattache l'une à l'autre : sans elle, au milieu d'un
    lacis de traces qui se croisent, rien ne dit de laquelle on parle.

    C'est la bande d'actions qui porte la couleur, et non les boutons : la
    pointe prolonge le bas de la fiche, et un triangle teinté sous un bloc
    blanc flotterait sans rien toucher. Boutons blancs par-dessus, comme dans
    la barre mobile — les deux formats disent la même chose de la même façon. */
/*  Le rembourrage haut n'existait pas : sans lui, le bouton venait coller
    contre le titre, et sur fond teinté cela se voyait comme un débordement —
    le bloc paraissait sortir de son cadre.                                  */
.pop-accent .pop-acts{background:var(--accent);padding-top:12px}
.pop-accent .pop-acts button{
  background:var(--surface);border-color:var(--surface);color:var(--ink);
}
.pop-accent .pop-acts button:hover{background:var(--surface-2);border-color:var(--surface-2)}
.pop-accent .pop-acts button svg{stroke:var(--accent)}

/*  VARIANTE : LES ACTIONS PORTENT LA TEINTE, PAS LA BANDE.

    Une trace désignée se lit puis s'ouvre — la bande colorée la rattache au
    trait qu'elle recouvre. Un repère de ravitaillement, lui, est touché POUR
    en faire une étape : ce sont les boutons qu'on regarde, et c'est à eux de
    porter la couleur de la catégorie.

    Le rond du bouton passe au blanc : le vert citron du réglage ordinaire n'a
    rien à voir avec l'eau ni avec un commerce, et sur un aplat coloré le blanc
    est ce qui se détache le mieux.                                          */
.pop-fill .pop-acts button{
  background:var(--accent);border-color:var(--accent);color:#fff;
}
.pop-fill .pop-acts button:hover{filter:brightness(1.07)}
.pop-fill .pop-acts button svg{stroke:#FFFFFF}

/*  La dernière action garde son renversement — c'est ce qui la distingue des
    autres — mais en teinte de catégorie, et non en vert.                    */
.pop-fill .pop-acts button:last-child:not(:only-child){
  background:var(--surface);color:var(--accent);border-color:var(--line);
}
.pop-fill .pop-acts button:last-child:not(:only-child):hover{
  background:var(--surface-2);border-color:var(--accent);filter:none;
}
.pop-fill .pop-acts button:last-child:not(:only-child) svg{stroke:var(--accent)}

/*  La pointe est dessinée par MapLibre hors de notre contenu : elle ne se
    teinte que d'ici, et seulement du côté qui touche la bande d'actions.    */
.pop-accent.maplibregl-popup-anchor-bottom .maplibregl-popup-tip,
.pop-accent.maplibregl-popup-anchor-bottom-left .maplibregl-popup-tip,
.pop-accent.maplibregl-popup-anchor-bottom-right .maplibregl-popup-tip{
  border-top-color:var(--accent)!important;
}

/* ─────────────────────────────────────────────
   Chargement
   ───────────────────────────────────────────── */
.loader{
  position:absolute;left:0;right:0;z-index:45;height:3px;overflow:hidden;
  top:calc(var(--topbar-h) + env(safe-area-inset-top));
  background:rgba(11,91,68,.12);
}
.loader[hidden]{display:none}
.loader i{display:block;height:100%;width:32%;background:var(--lime);
  animation:slide 1.05s cubic-bezier(.6,0,.4,1) infinite}
@keyframes slide{0%{transform:translateX(-100%)}100%{transform:translateX(420%)}}

@media (prefers-reduced-motion:reduce){
  *{animation-duration:.01ms!important;transition-duration:.01ms!important}
}

/* Niveau et interrupteur aller-retour : voir « Panneau en cartes », en fin de
   fichier. */

/* ─────────────────────────────────────────────
   Répartition des surfaces
   ───────────────────────────────────────────── */
.shares{padding:0 18px 16px}
.shares[hidden]{display:none}
.share-bar{
  display:flex;height:7px;border-radius:4px;overflow:hidden;
  background:var(--line-2);border:1px solid var(--line);
}
.share-bar i{display:block;height:100%}
.share-keys{
  display:flex;flex-wrap:wrap;gap:6px 16px;margin-top:9px;
  font-size:11.5px;color:var(--ink-2);
}
.share-keys span{display:inline-flex;align-items:center;gap:6px}
.sw{
  width:14px;height:8px;border-radius:2px;flex:0 0 auto;
  border:1px solid rgba(22,33,29,.22);
}
.sw[data-cat="trail"]{
  background:linear-gradient(var(--sw-inner),var(--sw-inner)) center/100% 3px no-repeat, #fff;
}

@media (max-width:899px){
  .shares{padding:0 16px 14px}
}

/* ─────────────────────────────────────────────
   Recherche plein écran (mobile)
   ───────────────────────────────────────────── */
.search-modal{
  position:fixed;inset:0;z-index:200;
  background:var(--surface);display:flex;flex-direction:column;
  padding-top:env(safe-area-inset-top);
  padding-bottom:env(safe-area-inset-bottom);
}
.search-modal[hidden]{display:none}
.search-modal header{
  flex:0 0 auto;display:flex;align-items:center;gap:8px;
  padding:12px 14px;border-bottom:1px solid var(--line-2);
}
.search-modal header .search{flex:1 1 auto}
.search-modal .back{width:36px;height:36px;flex:0 0 auto}
.search-modal .back svg{width:19px;height:19px}
.modal-list{
  margin:0;border:0;border-radius:0;box-shadow:none;
  flex:1 1 auto;max-height:none;
}
.modal-list button{padding:14px 16px}
.modal-list b{font-size:15px}
.modal-list small{font-size:12.5px}
.modal-hint{padding:20px 16px;font-size:13px;color:var(--muted)}
.modal-hint[hidden]{display:none}

/* Sur mobile, le champ de la colonne n'est qu'un déclencheur */
@media (max-width:899px){
  #search input{pointer-events:none}
}

/* ─────────────────────────────────────────────
   Carte de détail d'un POI
   ───────────────────────────────────────────── */
.poi-card{
  position:absolute;z-index:35;
  background:var(--surface);border-radius:var(--r-lg);
  box-shadow:var(--shadow-2);overflow:hidden;
  display:flex;flex-direction:column;
}
.poi-card[hidden]{display:none}
.poi-close{
  position:absolute;top:8px;right:8px;z-index:2;
  width:30px;height:30px;border-radius:50%;
  background:rgba(255,255,255,.92);color:var(--ink);
  box-shadow:var(--shadow-1);
}
.poi-close:hover{background:#fff}
.poi-body{padding:13px 15px 15px;flex:1 1 auto}
/* `--poi-color`, `--poi-tint` et `--poi-ink` sont posées en JS depuis
   POI_TYPES : la première pour le pictogramme, les deux autres pour le fond et
   le texte du bandeau, les teintes du référentiel étant trop pâles pour porter
   du texte telles quelles. */
.poi-type{
  display:inline-flex;align-items:center;gap:8px;align-self:center;
  padding:7px 14px 7px 8px;border-radius:999px;
  background:var(--poi-tint, var(--surface-2));
  font-size:12px;font-weight:700;letter-spacing:.07em;text-transform:uppercase;
  color:var(--poi-ink, var(--green));
}
.poi-glyph{
  /*  26 px, dont 5 de marge intérieure : le pictogramme n'en occupait que 16.
      À cette taille, un profil de terrain se réduit à trois inflexions qu'on
      devine plus qu'on ne les lit. Le cadre passe à 34 et la marge à 4 — le
      dessin double presque, la pastille ne grandit que de huit pixels.      */
  flex:0 0 auto;display:grid;place-items:center;
  width:34px;height:34px;border-radius:50%;padding:4px;
  background:var(--surface);
  border:1.5px solid var(--poi-ink, var(--green));
}
.poi-glyph svg{width:100%;height:100%;display:block;overflow:visible}

.poi-title{
  margin:14px 0 0;font-family:var(--display);
  font-size:24px;font-weight:700;line-height:1.15;color:var(--green);
}

/* Bandeau du type : reprend le fond et l'encre de la pastille. */
.poi-notice{
  display:flex;align-items:center;gap:10px;
  margin:12px 0 0;padding:11px 14px;border-radius:var(--r-md);
  background:var(--poi-tint, var(--surface-2));
  color:var(--poi-ink, var(--ink));
  font-size:14px;font-weight:500;line-height:1.35;
}
.poi-notice[hidden]{display:none}
.poi-notice svg{
  flex:0 0 auto;width:20px;height:20px;
  stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;
}

.poi-desc{margin-top:14px;font-size:14.5px;line-height:1.55;color:var(--ink)}
.poi-desc[hidden]{display:none}

/*  Encadré explicatif, propre au type de terrain.

    IL REPREND LE FOND ET L'ENCRE DE LA PASTILLE, qui étaient ceux du bandeau
    d'alerte — lequel a disparu : il annonçait « Terrain fortement dégradé »
    trois lignes au-dessus d'un encadré qui disait la même chose en plus long.
    Ce qu'il apportait vraiment était sa couleur, qui situait le passage d'un
    coup d'œil ; elle se loge ici, où elle manquait. Le vert d'interface
    convenait mal pour parler d'un terrain impraticable.

    Les deux valeurs de repli servent au cas « Autre », qui n'a pas de teinte
    de terrain à porter.                                                     */
.poi-about{
  margin-top:18px;padding:15px 16px;
  background:var(--poi-tint, #F3F7F4);border-radius:var(--r-lg);
  color:var(--poi-ink, var(--ink));
}
.poi-about[hidden]{display:none}
.poi-about h4{
  display:flex;align-items:center;gap:9px;margin:0 0 8px;
  font-family:var(--display);font-size:15px;font-weight:600;
  color:var(--poi-ink, var(--green));
}
.poi-about h4 svg{flex:0 0 auto;width:19px;height:19px;stroke-width:1.7}
/*  Le texte reste plus sourd que le titre, mais dans la même famille : à
    `--ink-2` il retombait dans le gris commun et l'encadré perdait son unité. */
.poi-about p{margin:0;font-size:14px;line-height:1.55;color:var(--poi-ink, var(--ink-2));opacity:.9}

/* Carrousel de photos, entre la pastille de type et le titre. */
/*  `relative` PORTE LES FLÈCHES ET LES PASTILLES, qui se posent sur la photo.
    Sans lui, elles s'ancreraient au premier ancêtre positionné — c'est-à-dire
    n'importe où dans la fiche.                                              */
.poi-shots{position:relative;margin-top:14px}
.poi-shots[hidden]{display:none}
.poi-track{
  display:flex;gap:8px;overflow-x:auto;scroll-snap-type:x mandatory;
  scrollbar-width:none;-webkit-overflow-scrolling:touch;
}
.poi-track::-webkit-scrollbar{display:none}
.poi-shot{
  flex:0 0 100%;scroll-snap-align:center;
  border-radius:var(--r-md);overflow:hidden;line-height:0;
  background:var(--surface-2);
}
.poi-shot img{width:100%;height:190px;object-fit:cover;display:block}

/*  Flèches. Elles ne servent qu'au pointeur — au doigt, le balayage fait le
    même travail sans rien recouvrir de la photo —, mais elles restent posées
    dans les deux cas : les masquer sur écran tactile supposerait de deviner
    l'appareil, alors qu'un même écran peut avoir les deux.                  */
.poi-arrow{
  position:absolute;top:calc(95px - 17px);
  width:34px;height:34px;display:grid;place-items:center;
  border-radius:50%;border:0;
  background:rgba(255,255,255,.92);color:var(--ink);
  box-shadow:0 1px 6px rgba(0,0,0,.28);
  transition:opacity .15s,background .15s;
}
.poi-arrow.prev{left:8px}
.poi-arrow.next{right:8px}
.poi-arrow svg{width:19px;height:19px;stroke-width:2.4}
.poi-arrow:hover{background:#fff}
/*  ÉTEINTE AUX EXTRÉMITÉS, PAS RETIRÉE : une flèche qui disparaît emporte sa
    place, et la photo glisserait sous le doigt à chaque bout de course.     */
.poi-arrow:disabled{opacity:.32;box-shadow:none;cursor:default}
.poi-arrow[hidden]{display:none}

/*  Pastilles posées SUR la photo, en bas : sous elle, elles ajoutaient une
    ligne de hauteur à une fiche qui en manque déjà sur un téléphone.        */
.poi-dots{
  position:absolute;left:0;right:0;bottom:9px;
  display:flex;justify-content:center;gap:6px;
}
.poi-dots[hidden]{display:none}
.poi-dots button{
  width:7px;height:7px;padding:0;border:0;border-radius:50%;
  background:rgba(255,255,255,.6);box-shadow:0 0 3px rgba(0,0,0,.45);
  transition:background .18s,transform .18s;
}
.poi-dots button.on{background:#fff;transform:scale(1.3)}

/* Actions : lignes pleine largeur, la première en fond plein. */
.poi-acts{flex:0 0 auto;display:flex;flex-direction:column;gap:10px;padding:0 16px 16px}
.poi-acts button{
  display:flex;align-items:center;gap:12px;width:100%;text-align:left;
  padding:13px 15px;border-radius:var(--r-lg);
  border:1.5px solid var(--green);background:var(--surface);color:var(--green);
  transition:background .15s,border-color .15s;
}
.poi-acts button.primary{background:var(--green);border-color:var(--green);color:#fff}
.poi-acts button.primary:hover{background:var(--green-l);border-color:var(--green-l)}
.poi-acts button:not(.primary):hover{background:var(--surface-2)}
.poi-act-txt{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;gap:2px}
.poi-act-txt b{font-size:15px;font-weight:600}
.poi-act-txt em{font-style:normal;font-size:12.5px;opacity:.78}
.poi-acts > button > svg:first-of-type{
  flex:0 0 auto;width:20px;height:20px;fill:none;
  stroke:var(--lime);stroke-width:2.2;
}
.poi-acts button:not(.primary) > svg:first-of-type{stroke:var(--green)}
.poi-act-go{flex:0 0 auto;width:19px;height:19px;stroke-width:2.2}

/* En desktop la fiche prend toute la colonne : elle remplace le contenu du
   panneau le temps de la consultation, plutôt que de flotter par-dessus la
   carte. Même largeur, même bord droit, même repli. */
@media (min-width:900px){
  .poi-card{
    left:0;width:var(--panel-w);z-index:31;
    top:calc(var(--topbar-h) + env(safe-area-inset-top));bottom:0;
    border-radius:0;box-shadow:none;
    border-right:1px solid var(--line);
    transition:transform .28s cubic-bezier(.32,.72,0,1);
  }
  #app.panel-hidden .poi-card{transform:translateX(-100%)}

  /* Exactement la boîte de la colonne : même largeur, même bord droit — sinon
     un liseré de carte apparaît là où la colonne s'est effacée. */
  /* Les actions suivent le texte au lieu d'être plaquées en bas de colonne :
     le corps ne pousse donc plus, il se contente de rétrécir si le descriptif
     est long — et c'est alors lui seul qui défile. */
  .poi-body{
    flex:0 1 auto;padding:18px 16px 20px;
    overflow-y:auto;overscroll-behavior:contain;
  }
  .poi-title{font-size:19px}
  .poi-desc{font-size:13.5px}
  /*  ═══════════════════════════════════════════════════════════════════════
      LA CROIX SE VOYAIT À PEINE, ET C'EST EN MOBILE QUE ÇA COMPTE.
      ═══════════════════════════════════════════════════════════════════════

      Un trait de deux pixels sur trente-quatre, blanc sur blanc à quatre-vingt-
      douze pour cent d'opacité, posé sur une photo dont on ne sait pas la
      couleur : le rond disparaissait sur les clairs, le trait sur les sombres.
      Et c'est en mobile que la fiche occupe tout l'écran, donc le seul format
      où cette croix est la SEULE issue — ailleurs, un clic sur la carte suffit.

      Trois choses, et aucune ne suffirait seule : le rond devient franchement
      opaque et gagne un contour, l'ombre s'appuie, et la croix elle-même
      grossit dans son rond. Une cible de 42 px reste au-dessus des 44 px
      recommandés une fois la marge de frappe comptée.                       */
  .poi-close{
    top:10px;right:10px;width:42px;height:42px;
    background:#fff;
    border:1px solid rgba(22,33,29,.1);
    box-shadow:0 2px 10px rgba(0,0,0,.28);
  }
  .poi-close svg{width:22px;height:22px;stroke-width:2.4}

  /* La colonne s'efface le temps de la consultation. `visibility` plutôt que
     `display` : la boîte reste mesurable, et c'est son bord droit qui sert à
     calculer la zone de carte visible. */
  #app.poi-open #sidebar{visibility:hidden}
}

/* En mobile elle occupe toute la largeur, sous la bande de contrôles, et
   arrondit ses quatre coins. */
/* En mobile la fiche prend toute la page. Les actions suivent le texte : les
   plaquer en bas de l'écran ouvrirait un grand vide au milieu. */
@media (max-width:899px){
  .poi-card{
    left:0;right:0;bottom:0;
    top:calc(var(--topbar-h) + env(safe-area-inset-top));
    border-radius:0;box-shadow:none;
  }
  .poi-body{flex:0 1 auto;padding:14px 15px 16px;overflow-y:auto}
  .poi-desc{display:block}

  /*  LA CROIX DU DESKTOP, UN CRAN PLUS PETITE. La règle renforcée — rond
      opaque, contour, ombre appuyée — n'existait que dans la requête desktop,
      alors que c'est ici que la fiche couvre tout l'écran et que la croix est
      la seule issue. Mobile gardait le rond translucide de base, invisible
      sur une photo claire. 36 px : assez pour le pouce sans manger la photo. */
  .poi-close{
    top:9px;right:9px;width:36px;height:36px;
    background:#fff;
    border:1px solid rgba(22,33,29,.1);
    box-shadow:0 2px 8px rgba(0,0,0,.26);
  }
  .poi-close svg{width:19px;height:19px;stroke-width:2.4}

}

/* ─────────────────────────────────────────────
   Dialogue
   ───────────────────────────────────────────── */
/*  AU-DESSUS DES MODALES, ET NON DESSOUS.

    Le dialogue était à 300, la fiche de zone et celle de trace à 380 : une
    confirmation demandée depuis l'une d'elles s'ouvrait derrière, invisible et
    bloquante. On le remontait jusqu'ici en refermant la modale d'abord — ce
    qui obligeait à la rouvrir quand on renonçait.

    410 le place au-dessus des modales et sous la visionneuse de photo (420),
    qui couvre tout par définition. Le rang du dialogue est le bon : il pose
    une question dont la réponse conditionne le reste, rien ne doit le
    recouvrir.                                                               */
.dialog{position:fixed;inset:0;z-index:410;display:flex}
.dialog[hidden]{display:none}
.dialog-scrim{
  position:absolute;inset:0;background:rgba(12,26,20,.44);
  opacity:0;transition:opacity .16s;
}
.dialog.on .dialog-scrim{opacity:1}
/*  Le dialogue s'est allongé — liste de calques, pastilles d'activité, notice
    d'aide : il dépassait de l'écran sur un téléphone tenu à l'horizontale. Il
    défile désormais, en gardant sa marge et ses angles.                     */
/*  UNE COLONNE : UN EN-TÊTE QUI NE BOUGE PAS, UNE ZONE QUI DÉFILE.

    La boîte défilait dans son entier, titre compris : on se retrouvait au
    milieu d'une liste de réglages sans savoir de quoi elle parlait. Un bandeau
    collant réglait la disparition mais pas le reste — le contenu passait
    DESSOUS, et l'on voyait les lignes glisser derrière le titre.

    Ici le défilement est confié à un enfant. L'en-tête n'est pas dans la zone
    qui défile, rien ne peut donc le traverser, et le rembourrage horizontal
    descend sur les deux blocs plutôt que sur la boîte — sans quoi la barre de
    défilement se collerait au texte au lieu de longer le bord.             */
.dialog-box{
  position:relative;margin:auto;width:min(432px, calc(100% - 32px));
  max-height:calc(100% - 32px);
  display:flex;flex-direction:column;overflow:hidden;
  background:var(--surface);border-radius:22px;
  box-shadow:var(--shadow-2);
  opacity:0;transform:translateY(10px) scale(.98);
  transition:opacity .16s, transform .16s;
}
.dialog-scroll{
  flex:1 1 auto;min-height:0;
  overflow-y:auto;overscroll-behavior:contain;
  padding:0 24px 24px;
}
.dialog.on .dialog-box{opacity:1;transform:none}
/*  L'EN-TÊTE RESTE EN VUE PENDANT LE DÉFILEMENT.

    Le titre et la croix étaient posés dans le flux, en haut de la boîte : dès
    que le contenu dépassait, ils partaient vers le haut. On se retrouvait au
    milieu d'une liste de réglages sans savoir de quoi elle parlait ni comment
    en sortir — le menu de la carte, avec ses calques, ses activités et ses
    actions, y arrivait vite.

    Les marges négatives font déborder le bandeau jusqu'aux bords de la boîte :
    sans elles, le contenu défilerait dans les gouttières, de part et d'autre
    d'un fond qui ne les couvre pas.                                         */
.dialog-head{
  flex:0 0 auto;
  display:flex;align-items:flex-start;gap:12px;
  padding:26px 24px 14px;
  background:var(--surface);border-radius:22px 22px 0 0;
}

.dialog-close{
  flex:0 0 auto;
  width:38px;height:38px;border-radius:50%;
  border:1.5px solid var(--line);color:var(--ink-2);
}
.dialog-close[hidden]{display:none}
.dialog-close svg{width:17px;height:17px}
.dialog-close:hover{background:var(--surface-2);border-color:var(--muted)}

.dialog-title{
  flex:1 1 auto;min-width:0;margin:0;
  font-family:var(--display);font-size:21px;font-weight:700;
  letter-spacing:-.02em;line-height:1.2;
}
.dialog-text{margin-top:6px;font-size:13.5px;line-height:1.5;color:var(--muted)}
.dialog-text[hidden]{display:none}

/*  « Terminer le parcours ». La ligne de contexte n'y est pas du commentaire
    mais LE RÉSULTAT — distance, durée, dénivelé du parcours qu'on vient de
    tracer. En gris, elle se lisait comme une mention légale sous le titre. La
    couleur de marque la remet à sa place : c'est le chiffre qu'on est venu
    voir.

    Passe par `data-variant` plutôt que par une règle sur `#dialogText` : le
    conteneur est unique, une règle directe teindrait le contexte de tous les
    dialogues.                                                              */
.dialog-box[data-variant="finish"] .dialog-text{
  color:var(--green);font-weight:600;
}

/*  Liste à choix unique du dialogue. Une pastille marque la ligne retenue :
    trois interrupteurs identiques ne disaient pas qu'un seul pouvait servir.

    Le groupe est posé dans un encadré à lui : sans cela, ses lignes et les
    actions du dialogue se ressemblaient trop, et rien ne disait que les unes
    changent l'affichage quand les autres ouvrent autre chose. Choisir la
    ligne déjà retenue la relâche — c'est ce qui remplace l'entrée « Rien ».  */
.dialog-choice{
  margin-top:16px;padding:14px;
  background:var(--surface-2);
  border:1px solid var(--line-2);border-radius:var(--r-lg);
}
.dialog-choice[hidden]{display:none}
/*  Même raison que `.label` : ces titres nomment un groupe de réglages, ils
    ne le commentent pas — ils reprennent donc la couleur du texte.           */
.d-choice-label{
  margin:0 0 4px;
  font-size:11px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;
}
.d-choice-hint{margin:0 0 10px;font-size:12.5px;line-height:1.4;color:var(--ink-2)}
.dialog-choice [role="radiogroup"]{display:flex;flex-direction:column;gap:6px}
.dialog-choice [data-choice]{
  display:flex;align-items:flex-start;gap:12px;width:100%;text-align:left;
  padding:12px 14px;border-radius:var(--r-md);
  border:1.5px solid var(--line);background:var(--surface);
  transition:border-color .15s,background .15s;
}
.dialog-choice [data-choice]:hover{background:var(--surface-2)}

/*  ─── Relevé de l'eau et du ravitaillement, dans le dialogue ─────────── */
.supply-counts{display:flex;flex-wrap:wrap;gap:16px;margin:2px 0 12px}
.supply-row{display:flex;align-items:center;gap:7px;font-size:13.5px;color:var(--ink-2)}
.supply-row b{font-size:19px;font-weight:700;color:var(--ink)}
.supply-row i, .supply-list i{
  flex:0 0 auto;width:10px;height:10px;border-radius:50%;background:var(--chip);
}
.supply-list{
  list-style:none;margin:0 0 12px;padding:10px 0 0;
  border-top:1px solid var(--line-2);
  display:flex;flex-direction:column;gap:9px;
}
.supply-list li{display:flex;align-items:center;gap:10px;min-width:0}
.supply-list span{display:flex;flex-direction:column;gap:1px;min-width:0}
.supply-list b{
  font-size:13.5px;font-weight:600;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.supply-list em{font-style:normal;font-size:12px;color:var(--ink-2)}

/*  Ce qui explique une absence vaut mieux qu'une liste vide : la couche de
    points d'intérêt du fond ne se charge qu'à fort zoom, et ne rien voir ne
    dit rien du terrain.                                                     */
.supply-note{
  margin:0 0 4px;padding:9px 11px;border-radius:var(--r-md);
  background:var(--surface-2);
  font-size:12.5px;line-height:1.45;color:var(--ink-2);
}

/*  Entrée indisponible : elle reste en place, en retrait. La retirer de la
    liste ferait croire que l'option n'existe pas, alors qu'elle attend
    seulement qu'on libère la place — sa ligne d'explication le dit.        */
.dialog-choice [data-choice]:disabled{opacity:.5;cursor:default}
.dialog-choice [data-choice]:disabled:hover{background:none}
.dialog-choice [data-choice] i{
  flex:0 0 auto;width:18px;height:18px;margin-top:1px;border-radius:50%;
  border:2px solid var(--line);
  display:grid;place-items:center;
  transition:border-color .15s;
}
.dialog-choice [data-choice] i::after{
  content:"";width:9px;height:9px;border-radius:50%;
  background:var(--green);transform:scale(0);transition:transform .15s;
}
.dialog-choice [data-choice] span{display:flex;flex-direction:column;gap:2px;min-width:0}
.dialog-choice [data-choice] b{font-size:14px;font-weight:600}
.dialog-choice [data-choice] em{font-style:normal;font-size:12.5px;color:var(--ink-2)}

.dialog-choice [aria-checked="true"]{border-color:var(--green);background:#F3F9F6}
.dialog-choice [aria-checked="true"] i{border-color:var(--green)}
.dialog-choice [aria-checked="true"] i::after{transform:scale(1)}

/*  Une entrée mise en avant. Le fond vert plein la faisait passer pour
    l'action principale du dialogue, alors qu'elle n'est qu'un calque parmi
    d'autres : seuls le texte et la bordure prennent la teinte. Les règles
    suivent celles de l'état retenu, plus bas dans le fichier, pour
    l'emporter sur elles.                                                    */
.dialog-choice [data-feature]{
  border-color:var(--green);background:var(--surface);
}
.dialog-choice [data-feature] b{color:var(--green)}
.dialog-choice [data-feature]:hover{background:#F3F9F6}
.dialog-choice [data-feature][aria-checked="true"]{background:#F3F9F6}

/*  Pastilles à cocher — les activités des traces. Elles suivent la liste des
    calques dans le même encadré : ce sont deux réglages du même affichage.  */
.dialog-filters{
  margin-top:12px;padding:14px;
  background:var(--surface-2);
  border:1px solid var(--line-2);border-radius:var(--r-lg);
}
.dialog-filters[hidden]{display:none}
.d-chips{display:flex;flex-wrap:wrap;gap:8px}
.d-chips button{
  --chip:var(--green);
  display:inline-flex;align-items:center;gap:8px;
  padding:9px 13px;border-radius:999px;
  /*  Éteinte, la pastille se voit comme telle : bordure en pointillé, texte
      pâli, fond grisé. Un simple changement de couleur ne disait pas assez
      qu'on peut la rallumer d'un doigt.                                     */
  border:1.5px dashed var(--line);background:var(--surface-2);
  font-size:13.5px;font-weight:600;color:var(--muted);
  transition:border-color .15s,background .15s,color .15s;
}
/* La pastille de couleur dit quelle teinte porte l'activité sur la carte. */
.d-chips button i{
  width:11px;height:11px;border-radius:50%;
  background:var(--chip);opacity:.35;transition:opacity .15s;
}
.d-chips button[aria-pressed="true"]{
  border-style:solid;border-color:var(--chip);
  background:var(--surface);color:var(--ink);
}
.d-chips button[aria-pressed="true"] i{opacity:1}

/* Champ de saisie du dialogue — nom du parcours. */
.dialog-field{display:block;margin-top:16px}
.dialog-field[hidden]{display:none}
/*  En noir, et non en gris comme les autres intitulés de groupe. Ceux-là
    nomment un réglage qu'on survole ; celui-ci nomme le seul endroit du
    dialogue où l'on écrit, et il doit se distinguer du texte de contexte
    posé juste au-dessus.                                                   */
.dialog-field span{
  display:block;margin-bottom:7px;
  font-size:11px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;
  color:var(--ink);
}
.dialog-field input{
  width:100%;padding:12px 13px;border-radius:var(--r-md);
  background:var(--surface);border:1.5px solid var(--line);
  transition:border-color .15s,box-shadow .15s;
}
.dialog-field input:focus{
  outline:none;border-color:var(--green);
  box-shadow:0 0 0 3px rgba(11,91,68,.12);
}

.dialog-actions{display:flex;gap:8px;margin-top:20px}
/* Un dialogue peut n'avoir aucune action — la notice se ferme par la croix ou
   le voile. Sans cette règle, la marge du bloc vide laisserait un blanc. */
.dialog-actions:empty{display:none}

/* Filet de séparation entre deux groupes d'actions : à mi-largeur et centré,
   il sépare sans couper. */
.d-sep{
  width:50%;margin:4px auto;border:0;
  border-top:1px solid var(--line-2);
}
.dialog-box[data-layout="stack"] .dialog-actions{flex-direction:column;gap:10px}
.dialog-box[data-layout="row"] .dialog-actions{justify-content:flex-end}

.d-btn{
  display:flex;align-items:flex-start;gap:14px;text-align:left;
  padding:16px 18px;border-radius:15px;
  border:1.5px solid var(--line);
  transition:background .15s,border-color .15s,color .15s;
}
.d-icon{
  flex:0 0 34px;height:34px;border-radius:50%;
  display:grid;place-items:center;
  border:2px solid currentColor;
}
/*  DIX-HUIT PIXELS, ET C'EST AU GLYPHE DE REMPLIR SA CASE.

    Le « i » de l'aide se lisait mal, et j'avais agrandi la case pour tous les
    pictogrammes — la flèche, la disquette, le repère s'en sont trouvés
    boursouflés. La case revient à sa taille : c'est le tracé du « i » qui a été
    redessiné pour occuper toute la sienne. Un pictogramme qui paraît petit est
    presque toujours un tracé qui laisse du vide autour de lui.              */
.d-icon svg{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:2;
  stroke-linecap:round;stroke-linejoin:round}
.d-txt{flex:1 1 auto;min-width:0}
.d-txt b{display:block;font-size:15.5px;font-weight:600;line-height:1.3}
.d-txt em{
  display:block;font-style:normal;font-weight:400;
  font-size:13px;line-height:1.45;margin-top:3px;color:var(--muted);
}

.dialog-box[data-layout="row"] .dialog-actions .d-btn{
  padding:11px 18px;align-items:center;
}
.dialog-box[data-layout="row"] .d-txt b{font-size:14px}

.d-btn.plain{border-color:var(--green);color:var(--green)}
.d-btn.plain .d-txt b{color:var(--ink)}
.d-btn.plain:hover{background:var(--surface-2)}
.d-btn.primary{background:var(--green);border-color:var(--green);color:#fff}
.d-btn.primary .d-icon{color:var(--lime)}
.d-btn.primary .d-txt em{color:rgba(255,255,255,.76)}
.d-btn.primary:hover{background:var(--green-l);border-color:var(--green-l)}
.d-btn.danger{background:var(--warn);border-color:var(--warn);color:#fff}
.d-btn.danger .d-txt em{color:rgba(255,255,255,.76)}
.d-btn.danger:hover{filter:brightness(1.08)}
.d-btn.ghost{border-color:transparent;color:var(--ink-2)}
.d-btn.ghost:hover{background:var(--surface-2)}

@media (max-width:899px){
  .dialog-box{
    margin:auto 0 0;width:100%;
    border-radius:22px 22px 0 0;
    /*  DEUX MARGES BASSES S'ADDITIONNAIENT : ces 18 px sur la boîte, et les
        24 px de `.dialog-scroll`. Le rembourrage de la boîte date du temps où
        elle défilait elle-même ; depuis que le défilement est confié à
        `.dialog-scroll`, c'est à lui de porter la marge — 24 px, comme en
        desktop. Les 42 px qui en résultaient faisaient flotter les longs
        dialogues, « Carte » et « Terminer le parcours » en tête.

        LA ZONE SÛRE NE COMPTE QUE POUR CE QUE LE PIED NE COUVRE PAS. Le
        dialogue s'arrête au-dessus du pied de la page hôte — voir
        `--footer-h` en fin de fichier —, qui recouvre déjà la barre du
        système : l'ajouter en entier faisait gagner une trentaine de pixels de
        vide sur un iPhone. Elle ne ressort que si le pied devient plus mince
        qu'elle.                                                             */
    padding-bottom:max(0px, calc(env(safe-area-inset-bottom, 0px) - var(--footer-h)));
    transform:translateY(16px);
  }
}

/* ─────────────────────────────────────────────
   Notification
   En haut d'écran, sous le bandeau. Fond et
   bordure sont posés en JS depuis la palette de
   `modal.js` — ici, seule la boîte est décrite.
   ───────────────────────────────────────────── */
/*  `--host-shift` vaut la bande de la page hôte là où elle est en tête, zéro
    ailleurs : en mobile elle est en pied et ne gêne rien par le haut.      */
.toast{
  --host-shift:0px;
  position:fixed;z-index:430;left:50%;
  top:calc(var(--topbar-h) + var(--host-shift) + env(safe-area-inset-top) + 18px);
  transform:translate(-50%, -10px);
  display:flex;align-items:flex-start;gap:14px;
  width:max-content;max-width:min(460px, calc(100% - 24px));
  padding:14px 14px 14px 18px;
  border:1px solid var(--line);border-radius:var(--r-md);
  color:var(--ink);font-size:13.5px;line-height:1.45;
  box-shadow:var(--shadow-2);
  opacity:0;transition:opacity .2s, transform .2s;
}
.toast[hidden]{display:none}
.toast.on{opacity:1;transform:translate(-50%, 0)}

.toast-msg{display:flex;flex-direction:column;gap:2px;min-width:0}
.toast-msg strong{font-weight:600}
.toast-msg span{color:var(--ink-2)}

.toast-x{
  flex:0 0 auto;width:26px;height:26px;margin-top:-1px;
  display:grid;place-items:center;border-radius:50%;
  color:var(--muted);background:none;
}
.toast-x:hover{background:rgba(22,33,29,.07);color:var(--ink)}
.toast-x svg{width:16px;height:16px}

/*  LES PASTILLES DU CARROUSEL ÉTAIENT DÉFINIES ICI UNE SECONDE FOIS, et cette
    définition-ci l'emportait : même spécificité, mais plus bas dans la feuille.
    Elle les posait en `absolute` — sans qu'aucun parent ne soit positionné,
    elles allaient donc s'ancrer au premier ancêtre qui l'était — et en blanc
    translucide sur un fond blanc. Elles n'étaient pas discrètes, elles étaient
    ailleurs et invisibles.

    Les deux intentions sont fondues dans le bloc unique de `.poi-shots`, plus
    haut : posées SUR la photo, ce qui était l'idée de celle-ci, et rendues
    atteignables. Le plein écran, lui, a ses propres `.lb-dots` — il n'a jamais
    partagé cette classe, et c'est ce qui a laissé le doublon passer.        */

/* ─────────────────────────────────────────────
   Contrôles de carte
   Capsules blanches empilées ; les contrôles
   natifs de MapLibre sont masqués mais actifs.
   ───────────────────────────────────────────── */
.maplibregl-ctrl-top-right{display:none!important}

/* Colonne pleine hauteur : les groupes restent centrés dans la portion de
   carte réellement visible, quel que soit leur nombre. `--ctrl-bottom` est
   posé en JS — hauteur du bandeau d'élévation en desktop, part visible de la
   feuille en mobile. Le conteneur laisse passer les clics, seuls les groupes
   les captent, sinon toute la bande droite bloquerait la carte. */
/* Centrés sur la hauteur de l'écran en permanence : la pile grandit et
   rétrécit autour de son milieu, sans jamais glisser vers le haut ou le bas. */
#app:has(#sheet.dragging) .map-ctrl{transition:none}
.map-ctrl{
  position:absolute;z-index:20;right:14px;
  /* `--ctrl-shift` est posée en JS : la moitié de la hauteur du bandeau
     d'élévation, de sorte que la pile reste au milieu de la carte visible et
     non du conteneur. Nulle tant qu'aucun bandeau n'est affiché. */
  top:50%;transform:translateY(calc(-50% - var(--ctrl-shift, 0px)));
  transition:transform .28s cubic-bezier(.32,.72,0,1);
  display:flex;flex-direction:column;align-items:center;gap:14px;
  pointer-events:none;
}
.ctrl-group{
  pointer-events:auto;
  background:var(--surface);border-radius:999px;
  box-shadow:0 1px 3px rgba(22,33,29,.14), 0 6px 18px rgba(22,33,29,.13);
  display:flex;flex-direction:column;overflow:hidden;
}
.ctrl-group button{
  width:40px;height:40px;flex:0 0 auto;position:relative;
  display:grid;place-items:center;color:var(--green);
  transition:background .15s,color .15s;
}
.ctrl-group button svg{
  width:20px;height:20px;fill:none;stroke:currentColor;
  stroke-width:2;stroke-linecap:round;stroke-linejoin:round;
}
.ctrl-group button:hover{background:var(--surface-2)}
.ctrl-group button:active{background:var(--line-2)}

/* Filet de séparation entre boutons d'un même groupe */
.ctrl-group button + button::before{
  content:"";position:absolute;top:0;left:11px;right:11px;
  border-top:1px solid var(--line-2);
}

.ctrl-group button:disabled{color:var(--line);cursor:default}
.ctrl-group button:disabled:hover{background:none}

/* Groupes réservés à un format */
/* `.ctrl-group button` fixe déjà un `display` : sans une règle au moins aussi
   spécifique, la loupe resterait visible en desktop. */
.ctrl-group button.only-mobile{display:none}

.only-mobile{display:none}
@media (max-width:899px){
  .only-mobile{display:flex}
  .ctrl-group button.only-mobile{display:grid}
  /* Le bouton « Effacer » libellé cède la place à la corbeille des onglets */
  #clear{display:none}
  /* Annuler et rétablir vivent sur la carte, plus dans la feuille */
  .pts-tools .icon{display:none}
}

/* Actif : géolocalisation en suivi */
.ctrl-group button[aria-pressed="true"]{background:var(--green);color:#fff}
.ctrl-group button[aria-pressed="true"]:hover{background:var(--green-l)}
.ctrl-group button[aria-pressed="true"] + button::before,
.ctrl-group button[aria-pressed="true"]::before{border-color:transparent}

@media (max-width:899px){
  .map-ctrl{right:10px;gap:11px}

  /*  LE BLOC DE NAVIGATION SE DÉTACHE DU RESTE. Zoom et position sont les
      boutons qu'on touche sans regarder ; trente pixels d'écart — au lieu des
      onze entre les autres groupes — les rendent trouvables au doigt sans
      risquer d'effleurer les options juste au-dessus. La marge complète
      l'écart de la pile, d'où la soustraction.

      La pile reste centrée sur la carte visible, comme en desktop : elle a
      été un temps ancrée au bas de l'écran, et le dézoom passait sous la
      feuille. Voir `measureCtrl`, qui compte cette marge dans la hauteur.  */
  .map-ctrl .ctrl-nav{margin-top:calc(30px - 11px)}

  /* Une fiche POI est ouverte : les contrôles restent à leur place mais
     passent derrière elle — elle couvre l'écran, ils n'ont plus de prise. */
  #app.poi-open .map-ctrl{z-index:10}

  /*  Même raison pour les cartes flottantes — l'invitation au départ et la
      liste des traces. En mobile la fiche POI prend toute la page, mais elle
      est posée à 35 quand `.map-panels` est à 36 : les deux cartes restaient
      donc au-dessus d'elle, en pleine lecture d'un point d'intérêt.

      On les efface plutôt que de les faire passer dessous : la fiche est
      opaque, elles n'apporteraient rien derrière, et l'effacement coupe aussi
      la prise du doigt. C'est déjà ce que fait `.dialog-open`, plus bas.

      En desktop, rien à corriger : la fiche occupe la colonne et les cartes
      commencent après elle.                                                 */
  #app.poi-open .map-panels{opacity:0;pointer-events:none}
}


/* ─────────────────────────────────────────────
   Fiche POI — ajustements de format
   ───────────────────────────────────────────── */
.poi-shot{padding:0;border:0;cursor:zoom-in;width:100%}

@media (max-width:899px){
  .poi-acts{padding:0 13px 14px}
}

/* ─────────────────────────────────────────────
   Avancement d'une zone du nid d'abeille
   ───────────────────────────────────────────── */
.zone-modal{
  position:fixed;inset:0;z-index:380;
  display:flex;align-items:center;justify-content:center;padding:20px;
  background:rgba(12,26,20,.28);
  /* Le flou détache la fiche du fond sans le masquer : on garde le repère
     visuel de l'endroit dont on parle. */
  backdrop-filter:blur(7px);
  -webkit-backdrop-filter:blur(7px);
  opacity:0;transition:opacity .2s;
}
.zone-modal[hidden]{display:none}
.zone-modal.on{opacity:1}

/*  LA FICHE TIENT DANS SON CADRE.

    `.zone-modal` s'arrête déjà au-dessus du pied de page en mobile et sous
    l'en-tête en desktop — c'est le rôle du bloc de fin de feuille. Mais une
    fiche plus haute que ce cadre en débordait des DEUX côtés à la fois :
    `align-items:center` centre le contenu, et ce qui dépasse part
    symétriquement en haut et en bas, hors de portée du défilement. La fiche de
    trace, avec son profil altimétrique, atteignait cette limite.

    `max-height` la borne, `overflow-y` lui rend le défilement. Le contenu a
    par ailleurs été raccourci — aperçu et bilan côte à côte, actions
    secondaires repliées — de sorte que le défilement reste l'exception.     */
.zone-card{
  position:relative;width:min(430px, 100%);
  /*  DEUX PIXELS DE TOLÉRANCE, ET C'EST TOUT CE QU'ILS FONT.

      À `max-height:100%` exact, une fiche qui dépasse d'une fraction de pixel
      — hauteurs de ligne fractionnaires, arrondis du navigateur — devient une
      fiche qui défile : une barre paraît, le contenu tremble de deux pixels
      sous la molette, et il n'y a rien à y lire de plus. C'est ce qu'on voyait
      en desktop, où le cadre est borné par l'en-tête, et pas en mobile, où il
      reste de la place.

      Ces deux pixels de marge ne changent rien au cas où la fiche est
      RÉELLEMENT trop haute : elle est alors bornée à peu près comme avant et
      défile normalement. Ils suppriment le seul cas où le défilement n'apporte
      rien. Ce qui dépasse — un pixel en haut, un en bas, `align-items:center`
      répartissant l'excédent — tombe dans le rembourrage de la modale.      */
  max-height:calc(100% + 2px);
  overflow-y:auto;overscroll-behavior:contain;
  padding:30px 30px 26px;
  background:var(--surface);border-radius:var(--r-lg);
  box-shadow:var(--shadow-2);
  transform:translateY(10px) scale(.98);
  transition:transform .22s cubic-bezier(.32,.72,0,1);
}
.zone-modal.on .zone-card{transform:none}

.zone-close{position:absolute;top:14px;right:14px;width:32px;height:32px;color:var(--muted)}
.zone-close:hover{color:var(--ink)}
.zone-close svg{width:19px;height:19px;stroke-width:2;fill:none;stroke:currentColor}

.zone-pct{
  display:flex;align-items:baseline;justify-content:center;gap:3px;
  font-family:var(--display);color:var(--green);
}
.zone-pct b{font-size:44px;font-weight:700;line-height:1}
.zone-pct span{font-size:19px;font-weight:600}

.zone-sub{
  margin-top:5px;text-align:center;
  font-size:11.5px;font-weight:600;letter-spacing:.13em;text-transform:uppercase;
  color:var(--muted);
}

.zone-bar{
  margin:20px 0 4px;height:9px;border-radius:999px;
  background:var(--surface-2);overflow:hidden;
}
.zone-bar i{
  display:block;height:100%;border-radius:999px;
  background:linear-gradient(90deg, var(--green), var(--lime));
  transition:width .35s cubic-bezier(.32,.72,0,1);
}

.zone-rows{margin:14px 0 0}
.zone-rows > div{
  display:flex;align-items:center;justify-content:space-between;gap:16px;
  padding:13px 0;border-top:1px solid var(--line-2);
}
.zone-rows dt{font-size:13.5px;color:var(--ink-2)}
.zone-rows dd{margin:0;font-size:15px;font-weight:700;color:var(--green)}

/*  Aperçu à gauche, bilan à droite.

    L'aperçu occupait toute la largeur et le bilan s'étalait dessous : deux
    blocs larges et courts, pour une fiche qui manquait de hauteur et non de
    largeur. Resserré, l'aperçu dit toujours la même chose — c'est la FORME du
    parcours qui renseigne — et les trois valeurs se lisent en colonne dans la
    place ainsi libérée.

    `minmax(0, …)` sur la première colonne : sans lui, le SVG impose sa largeur
    intrinsèque et refuse de se laisser rogner.                              */
/*  L'aperçu occupe désormais toute sa colonne : le SVG est découpé au plus
    près du tracé (voir `miniTrack`), il n'y a plus de marge morte à combler.
    Sa hauteur est bornée pour qu'une boucle étroite et haute ne fasse pas
    grandir la fiche ; au-delà, elle se centre dans ce qui reste.           */
.track-preview{
  display:grid;grid-template-columns:minmax(0, 1.25fr) minmax(0, 1fr);
  align-items:center;gap:14px;margin-top:16px;
}

/*  Bilan d'une trace : le libellé au-dessus de sa valeur, les trois en
    colonne. Un filet les sépare plutôt qu'un encadrement, qui ferait un second
    cadre dans le cadre.                                                     */
.track-stats{
  display:flex;flex-direction:column;justify-content:center;gap:11px;
  margin:0;padding:2px 0 2px 14px;
  border-left:1px solid var(--line-2);
}
.track-stats > div{display:flex;flex-direction:column;gap:2px;min-width:0}
.track-stats dt{
  font-size:11px;color:var(--ink-2);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.track-stats dd{
  margin:0;font-size:16px;font-weight:700;color:var(--green);
  font-variant-numeric:tabular-nums;
}

/*  Profil de la trace : le même graphe que celui du planificateur, en plus
    court. Les classes sont partagées, seule la hauteur change.              */
.track-elev{margin-top:16px}
.track-elev[hidden]{display:none}
.track-elev-label{
  margin:0 0 8px;
  font-size:11px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;
  color:var(--muted);
}
.track-elev .chart{height:96px}
.track-readout{
  margin:0 0 8px;min-height:18px;
  font-size:12.5px;line-height:1.4;color:var(--ink-2);
  font-variant-numeric:tabular-nums;
}
.track-readout b{color:var(--ink);font-weight:700}
/* La bande de pente, en pastille : la couleur est celle du profil dessous. */
.track-readout i{
  display:inline-block;width:9px;height:9px;border-radius:2px;
  margin-right:5px;vertical-align:baseline;
}

.zone-acts{display:flex;gap:12px;margin-top:20px}
.zone-acts button{
  flex:1 1 0;padding:14px 10px;border-radius:var(--r-md);
  display:flex;align-items:center;justify-content:center;gap:8px;
  font-size:14.5px;font-weight:600;
  border:1.5px solid var(--green);background:var(--surface);color:var(--green);
  transition:background .15s;
}
.zone-acts button:hover{background:var(--surface-2)}
.zone-acts button svg{flex:0 0 auto;width:19px;height:19px}
.zone-acts button.primary{background:var(--green);color:#fff}
/* La boussole reprend le lime de la marque sur le fond plein. */
.zone-acts button.primary svg{color:var(--lime)}
.zone-acts button.primary:hover{background:var(--green-l)}

/* Trace d'explorateur : même boîte que l'avancement de zone, contenu propre. */
.track-card{text-align:left}
.track-kind{
  font-size:11px;font-weight:700;letter-spacing:.11em;text-transform:uppercase;
}
.track-name{
  margin:6px 0 0;font-family:var(--display);
  font-size:21px;font-weight:700;line-height:1.2;color:var(--green);
  padding-right:34px;      /* la croix de fermeture */
  /*  Une ligne, coupée au besoin. Deux lignes de titre poussaient tout le
      reste vers le bas, et une fiche dont la hauteur dépend de la longueur
      d'un nom se lit mal — on ne sait jamais où retrouver les actions.     */
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}

/* Aperçu du tracé : le fond neutre laisse la forme parler. */
.track-mini{
  padding:6px;border-radius:var(--r-md);
  background:var(--surface-2);line-height:0;min-height:96px;
  display:grid;place-items:center;
}
.track-mini svg{width:100%;height:auto;max-height:150px;display:block}
.track-mini-fail{
  font-size:12.5px;line-height:1.4;color:var(--muted);text-align:center;
}

/*  Ce qu'on lit au-dessus, ce qu'on décide en dessous. Sans ce filet, la
    bascule paraissait appartenir au bilan.

    DEUX COLONNES, DEUX LIGNES. « Planifier » et son réglage s'empilent à
    gauche ; le chevron occupe la colonne de droite sur toute la hauteur des
    deux. C'est la grille qui l'aligne, et non des valeurs recopiées : son haut
    tombe sur celui de « Planifier » et son bas sur celui de la bascule, quoi
    qu'il advienne de leurs hauteurs respectives.

    `--cta-h` fixe à la fois la hauteur du bouton principal et la LARGEUR du
    chevron : c'est ce qui les rend carrés l'un par rapport à l'autre, sans
    avoir à mesurer quoi que ce soit à l'exécution.                          */
.track-acts{
  --cta-h:48px;
  position:relative;
  display:grid;grid-template-columns:minmax(0, 1fr) var(--cta-h);
  gap:9px;
  margin-top:18px;padding-top:16px;border-top:1px solid var(--line-2);
}
/*  L'intitulé et le choix courent sur les deux colonnes : le chevron ne
    concerne que « Planifier », il n'a pas à leur voler de la largeur.       */
/*  L'INTITULÉ « Départ » NE S'AFFICHE PLUS, mais il n'est pas retiré du
    document : c'est lui que désigne l'`aria-labelledby` du groupe de boutons
    radio, et le supprimer laisserait deux choix sans question. Il est donc
    seulement soustrait au regard, à la manière habituelle — sorti du flux et
    réduit à un pixel, ce qui le garde lisible par les technologies
    d'assistance là où `display:none` l'effacerait pour tout le monde.

    Les deux boutons qu'il coiffait se lisent d'eux-mêmes : « Départ suggéré »
    et « Mon départ » portent le mot. La fiche gagne une ligne, ce qui compte
    sur un téléphone où elle frôlait déjà le bord.                            */
.track-acts .track-start-label{
  position:absolute;width:1px;height:1px;
  padding:0;margin:-1px;overflow:hidden;
  clip-path:inset(50%);white-space:nowrap;
}
/*  La rangée qu'il occupait disparaît avec lui : sortie du flux, la grille
    n'aurait plus rien à y mettre et aurait gardé une gouttière vide.        */
.track-acts .track-start{grid-column:1 / -1;grid-row:1}
.track-acts #trackPlan{grid-column:1;grid-row:2;min-height:var(--cta-h)}
/*  Le chevron s'aligne sur « Planifier » seul : carré, à sa hauteur. Étiré sur
    tout le bloc, il faisait un grand rectangle vide à côté d'un choix qui,
    lui, n'a rien à voir avec lui.                                           */
.track-acts .track-more{grid-column:2;grid-row:2;height:var(--cta-h)}

/*  ACTIONS SECONDAIRES EN SURIMPRESSION, VERS LE HAUT.

    Dépliées dans le flux, elles rallongeaient la fiche de la hauteur qu'on
    venait de lui faire gagner. Posées par-dessus le contenu et ouvertes vers
    le haut, elles ne lui coûtent rien : la fiche garde la même hauteur
    qu'elles soient visibles ou non.

    L'une sur l'autre et non côte à côte : deux libellés côte à côte dans une
    boîte étroite se coupaient au milieu d'un mot. Et chacune s'explique — un
    verbe seul ne dit pas ce qu'il va faire, « Sauvegarder » surtout, qu'on
    peut confondre avec un export.                                           */
.track-acts-row{
  position:absolute;z-index:3;left:0;right:0;
  /*  HUIT PIXELS AU-DESSUS DU BOUTON, ET NON DU BLOC.

      `bottom:calc(100% + 10px)` comptait depuis le haut de `.track-acts` :
      c'est-à-dire au-dessus de l'intitulé, du choix de départ ET de la ligne
      des boutons — trois rangées plus haut que le bouton qui l'ouvre. Le menu
      paraissait flotter sans rapport avec lui.

      La ligne des boutons fait `--cta-h` et occupe le bas du bloc : partir de
      là remet le menu juste au-dessus des trois points. La mesure suit la
      grille, elle n'est pas recopiée.                                       */
  bottom:calc(var(--cta-h) + 8px);
  display:flex;flex-direction:column;
  padding:6px;border-radius:var(--r-lg);
  background:var(--surface);border:1px solid var(--line-2);
  box-shadow:var(--shadow-2);
}
.track-acts-row[hidden]{display:none}

/*  Filet entre les entrées, jamais avant la première ni après la dernière :
    un trait au bord se confondrait avec la bordure de la boîte.             */
.track-acts-row button + button{border-top:1px solid var(--line-2)}

/*  ─── CHOIX DU DÉPART ────────────────────────────────────────────────────

    UNE BASCULE NE POSAIT PAS LA QUESTION. « Depuis mon point de départ »,
    éteinte, ne disait pas ce qui se passait à la place — on ne savait pas si
    la boucle serait prise telle quelle, ni d'où. Deux entrées nommées le
    disent : l'une ou l'autre, et on lit les deux termes.

    Le second gain est de place. La bascule occupait une ligne pleine largeur
    pour un seul terme ; les deux entrées tiennent sur la même hauteur et en
    portent deux.

    LES SOUS-TITRES SONT RETIRÉS. Ils redisaient l'intitulé et coupaient les
    mots à demi-largeur, dans une fiche dont on cherche justement à contenir la
    hauteur.                                                                 */
.track-start-label{
  font-size:11px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;
  color:var(--muted);
}

/*  `1fr 1fr` et non `auto` : les deux entrées font la même largeur quelle que
    soit la longueur de leur intitulé, sans quoi la ligne penche du côté du
    plus bavard et le choix n'a plus l'air d'en être un.                     */
.track-start{display:grid;grid-template-columns:1fr 1fr;gap:9px}

.track-start button{
  display:flex;align-items:center;gap:10px;min-width:0;text-align:left;
  padding:12px 12px;border-radius:var(--r-md);
  border:1.5px solid var(--line);background:var(--surface);
  transition:border-color .15s,background .15s;
}
.track-start button:hover{background:var(--surface-2)}
.track-start button b{
  min-width:0;font-size:13.5px;font-weight:600;line-height:1.25;color:var(--ink);
}

/*  Le rond du choix. Dessiné plutôt que confié à un `input[type=radio]` : le
    rendu natif diffère d'un système à l'autre, et il n'accepte pas la teinte
    de la marque sur toutes les WebView Android — précisément notre terrain.  */
.track-start button i{
  flex:0 0 auto;position:relative;
  width:18px;height:18px;border-radius:50%;
  border:1.5px solid var(--line);background:#fff;
  transition:border-color .15s;
}
.track-start button i::after{
  content:'';position:absolute;inset:3px;border-radius:50%;
  background:var(--green);transform:scale(0);transition:transform .15s;
}

/*  RETENUE : bordure verte ET fond teinté. La bordure seule ne se voyait pas
    assez entre deux cartes voisines de même taille — c'est le fond qui dit
    laquelle est prise, du premier coup d'œil.                               */
.track-start button[aria-checked="true"]{
  border-color:var(--green);background:var(--surface-2);
}
.track-start button[aria-checked="true"] i{border-color:var(--green)}
.track-start button[aria-checked="true"] i::after{transform:scale(1)}

/*  AUCUNE DES DEUX N'EST GRISÉE, même quand elle ne peut pas aboutir. Une
    entrée éteinte laisse croire que l'option n'existe pas ; touchée, elle dit
    ce qui manque et comment l'obtenir. C'est une phrase de plus contre un
    malentendu de moins.                                                     */

/*  Chevron sans libellé : « Autres actions » écrit en toutes lettres prenait
    la place de ce qu'il fallait justement économiser. Le nom reste dans
    `aria-label` et dans l'infobulle. Sa largeur vient de `--cta-h`, sa hauteur
    de la grille — voir `.track-acts`.                                       */
.track-more{
  display:flex;align-items:center;justify-content:center;
  border-radius:var(--r-md);
  border:1.5px solid var(--line);background:var(--surface);color:var(--ink-2);
  transition:background .15s,border-color .15s,color .15s;
}
.track-more:hover{background:var(--surface-2);border-color:var(--green);color:var(--green)}
.track-more[aria-expanded="true"]{border-color:var(--green);color:var(--green)}
/*  Les trois points sont un aplat, non un trait : `fill` et non `stroke`. Et
    ils ne pivotent pas — un chevron dit dans quel sens ça s'ouvre, trois points
    ne disent rien de tel et n'ont donc rien à retourner.                    */
.track-more svg{width:19px;height:19px;fill:currentColor;stroke:none}
.track-acts-row button{flex:1 1 0;min-width:0}
.track-acts > button{
  display:flex;align-items:center;justify-content:center;gap:10px;width:100%;
  padding:13px 15px;border-radius:var(--r-md);
  font-size:14.5px;font-weight:600;
  border:1.5px solid var(--green);background:var(--surface);color:var(--green);
  transition:background .15s;
}
.track-acts > button:hover{background:var(--surface-2)}
.track-acts > button.primary{background:var(--green);color:#fff}
.track-acts > button.primary:hover{background:var(--green-l)}
.track-acts > button svg{flex:0 0 auto;width:19px;height:19px;stroke-width:1.9}
.track-acts > button.primary svg{color:var(--lime)}

/*  Entrées du menu : pictogramme dans une pastille, intitulé en gras, et sous
    lui ce que l'action fait. Alignées à gauche, comme tout ce qui se lit.   */
.track-acts-row button{
  display:flex;align-items:center;gap:13px;width:100%;text-align:left;
  padding:11px 12px;border-radius:var(--r-md);
  background:none;border:0;color:var(--ink);
  transition:background .15s;
}
.track-acts-row button:hover{background:var(--surface-2)}
.track-acts-row button i{
  flex:0 0 auto;display:grid;place-items:center;
  width:38px;height:38px;border-radius:50%;
  background:var(--surface-2);color:var(--green);
}
.track-acts-row button svg{width:19px;height:19px;stroke-width:1.9;fill:none;stroke:currentColor}
.track-acts-row button b{display:block;font-size:14.5px;font-weight:700;line-height:1.25}
.track-acts-row button em{
  display:block;font-style:normal;font-size:12.5px;line-height:1.3;
  color:var(--ink-2);margin-top:1px;
}

@media (max-width:899px){
  .zone-card{
    padding:26px 20px 20px;
    /*  LA TOLÉRANCE DE DEUX PIXELS NE SUFFISAIT PAS ICI. Elle est posée sur la
        règle de base et vaut donc aussi en mobile — ce bloc ne redéclare que le
        rembourrage —, mais l'excédent y est un peu plus grand : la fiche compte
        une rangée de plus, les hauteurs de ligne diffèrent, et le cadre est
        borné par le pied de page.

        Quatre pixels, donc. C'est un réglage empirique et il s'assume comme
        tel : le navigateur ne dit pas de combien il dépasse, et CSS ne sait pas
        exprimer « ne défile que si cela en vaut la peine ». Ce qui déborde
        tombe dans le rembourrage de la modale, un pixel ou deux de chaque côté.

        Si le micro-défilement revient après un changement de contenu, c'est
        cette valeur qu'il faut monter — pas `overflow`, dont on a besoin le
        jour où la fiche est vraiment trop haute.                            */
    max-height:calc(100% + 4px);
  }
  .zone-pct b{font-size:38px}
  .track-name{font-size:19px}
  /*  L'écran est plus étroit : l'aperçu cède un peu de terrain au bilan, dont
      les libellés ne se coupent pas.                                        */
  .track-preview{grid-template-columns:minmax(0, 1fr) minmax(0, 1fr);gap:12px}
  .track-stats{padding-left:11px}
  .track-mini svg{max-height:124px}
}

/* ─────────────────────────────────────────────
   Photo plein écran
   ───────────────────────────────────────────── */
.lightbox{
  position:fixed;inset:0;z-index:420;
  background:rgba(8,14,11,.94);
  display:flex;align-items:center;justify-content:center;
  padding:calc(20px + env(safe-area-inset-top)) 20px
          calc(20px + env(safe-area-inset-bottom));
  touch-action:none;
}
.lightbox[hidden]{display:none}
.lightbox img{
  max-width:100%;max-height:100%;object-fit:contain;
  border-radius:6px;user-select:none;-webkit-user-drag:none;
}
.lb-close,.lb-nav{
  position:absolute;z-index:1;
  width:46px;height:46px;border-radius:50%;
  display:grid;place-items:center;
  background:rgba(255,255,255,.12);color:#fff;
  backdrop-filter:blur(6px);
}
.lb-close:hover,.lb-nav:hover{background:rgba(255,255,255,.24)}
.lb-close svg,.lb-nav svg{width:20px;height:20px;stroke-width:2}
.lb-close{top:calc(16px + env(safe-area-inset-top));right:16px}
.lb-nav.prev{left:16px}
.lb-nav.next{right:16px}
.lb-nav[hidden]{display:none}
.lb-dots{
  position:absolute;left:0;right:0;
  bottom:calc(20px + env(safe-area-inset-bottom));
  display:flex;justify-content:center;gap:7px;
}
.lb-dots i{width:8px;height:8px;border-radius:50%;background:rgba(255,255,255,.4)}
.lb-dots i.on{background:#fff}
.lb-dots[hidden]{display:none}

@media (max-width:899px){
  .lb-nav{display:none}
}


/* Repère d'information à côté d'une étiquette */
.info{
  display:inline-flex;vertical-align:-2px;margin-left:3px;
  color:var(--muted);cursor:help;
}
.info svg{width:13px;height:13px;stroke-width:2}
.info:hover{color:var(--ink-2)}

/* Recherche : champ, puis raccourci « ma position ». */
.search-row{display:flex;gap:8px;align-items:stretch}
.search-row .search{flex:1 1 auto;min-width:0}
.here{
  flex:0 0 44px;display:grid;place-items:center;
  border:1.5px solid var(--line);border-radius:var(--r-md);
  color:var(--green);transition:border-color .15s,background .15s;
}
.here svg{width:19px;height:19px;stroke-width:1.9;fill:none;stroke:currentColor}
.here:hover{border-color:var(--green);background:var(--surface-2)}
.here:disabled{color:var(--line);cursor:default}
.here:disabled:hover{border-color:var(--line);background:none}
/* .here impose un display : sans cette règle, l'attribut hidden reste sans
   effet et le bouton survit à la pose du départ. */
.here[hidden]{display:none}

/* Attente d'un relevé : l'icône cède la place à un anneau qui tourne. */
.here.busy svg{display:none}
.here.busy{color:var(--green)}
.here.busy::after{
  content:"";width:17px;height:17px;border-radius:50%;
  border:2px solid var(--line);border-top-color:var(--green);
  animation:spin .7s linear infinite;
}
@keyframes spin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){
  .here.busy::after{animation-duration:2.4s}
}

/* Le bouton de position de la carte attend lui aussi un relevé : même anneau
   que dans le volet, pour que l'appui ne reste pas sans réponse. */
.ctrl-group button.busy svg{display:none}
.ctrl-group button.busy::after{
  content:"";width:17px;height:17px;border-radius:50%;
  border:2px solid var(--line);border-top-color:var(--green);
  animation:spin .7s linear infinite;
}
@media (prefers-reduced-motion:reduce){
  .ctrl-group button.busy::after{animation-duration:2.4s}
}


/* La feuille reste visible derrière le voile d'un dialogue en mobile :
   on l'escamote le temps de la décision. */
@media (max-width:899px){
  .dialog-open #sheet{opacity:0;pointer-events:none}
  .dialog-open .map-ctrl{opacity:0;pointer-events:none}
  .dialog-open .startcard{opacity:0;pointer-events:none}
}

/* ─────────────────────────────────────────────
   Cartes flottantes posées sur la carte

   Un seul conteneur pour l'invitation au départ
   et la liste des traces : elles s'empilent, et
   le décalage dû à la colonne latérale ne se
   règle qu'ici. Le conteneur ne reçoit pas le
   doigt — seules ses cartes le reçoivent — sinon
   il couvrirait toute la largeur de la carte.
   ───────────────────────────────────────────── */
.map-panels{
  position:absolute;z-index:36;
  left:12px;right:12px;
  top:calc(12px + env(safe-area-inset-top));
  display:flex;flex-direction:column;gap:8px;
  pointer-events:none;
}
.map-panels > *{pointer-events:auto}

/*  ─── Boutons latéraux ────────────────────────────────────────────────────
    Posés sous la liste des traces, alignés à gauche comme elle. Ils ne prennent
    pas toute la largeur : ce ne sont pas des cartes à lire mais des accès, et
    leur indice doit rester au ras de leur propre bord.

    Une seule famille pour les deux — zones d'exploration, eau et
    ravitaillement : même forme, même indice, même place. Deux styles distincts
    auraient donné deux objets là où il n'y en a qu'un, décliné.             */
/*  ─── Dernier départ proposé ──────────────────────────────────────────────
    PLUS DE RÈGLE ICI : le repère est devenu une couche de la carte, pour passer
    sous les hexagones d'avancement, et son comprimé est dessiné au canevas —
    voir `imageDernierDépart` dans mapview.js, qui en reprend les mesures, la
    police et les jetons (`--green`, `--surface`, `--line-2`).              */

/*  ─── Avertissements : pente raide, chemins inconnus ──────────────────────

    Posés sur la carte ET sur le profil altimétrique, par la même fabrique —
    voir `warnMark` dans utils.js. Deux habillages parallèles auraient fini par
    ne plus ouvrir leur bulle de la même façon.

    ⚠ AUCUNE RÈGLE DE `position` ICI. Sur la carte, MapLibre pose ses marqueurs
    en `position:absolute` — sa feuille le fait sur `.maplibregl-marker` — puis
    écrit un `transform` qui part de l'origine du conteneur. Un `relative` posé
    ici l'emporterait, par ordre de cascade, et chaque marqueur repartirait de
    SA position dans le flux, donc à la suite du précédent : le premier tombe
    juste, le dixième est décalé de dix pictogrammes, et tout dérive au zoom.
    Sur le profil, c'est `.elev-warns > *` plus bas qui pose le `absolute`.

    LE MESSAGE S'OUVRE AU SURVOL ET AU TOUCHER : `:hover` ne s'atteint pas au
    doigt, `is-open` est posé par le clic. Un seul habillage pour les deux.
    ──────────────────────────────────────────────────────────────────────── */
.warn-mark{
  display:grid;place-items:center;
  width:30px;height:30px;padding:0;
  background:none;border:0;cursor:pointer;
  /*  La bulle sort du cadre du bouton, et rien n'empile ces éléments entre
      eux : sans cela elle passerait sous le pictogramme voisin.            */
  z-index:1;
}
.warn-mark.is-open,
.warn-mark:hover{z-index:3}

.warn-mark .warn-pic{
  display:grid;place-items:center;
  width:26px;height:26px;border-radius:50%;
  background:#fff;box-shadow:var(--shadow-1);
  border:1.5px solid currentColor;
}
.warn-mark svg{width:17px;height:17px}

/*  Deux teintes, deux natures d'avertissement. L'orange dit « préparez-vous »,
    l'ardoise dit « on ne sait pas » : la seconde n'est pas un danger, et la
    peindre en rouge ferait renoncer à des chemins qui vont très bien.       */
/*  LE ROUGE EST CELUI DU TITRE AUTANT QUE DU PICTOGRAMME : « Pente raide »
    écrit en gris sous un triangle rouge se lit comme une légende, pas comme un
    avertissement — et c'est la ligne qu'on lit, pas le triangle.            */
.warn-mark[data-kind="pente"]  {color:#B42318}
.warn-mark[data-kind="inconnu"]{color:#475467}

/*  Le « ? » collé au repère A, et ses trois règles de taille, ont été retirés :
    les chemins inconnus sont maintenant le badge `.unk`, plus bas. La teinte
    ci-dessus reste, pour le cas où une autre nature viendrait à s'en servir. */

/*  `--tip-shift` EST POSÉ PAR LE SCRIPT, à l'ouverture, quand la bulle
    déborderait de l'écran — voir `recaler` dans utils.js. Il vaut zéro le reste
    du temps, et la bulle reste centrée sur son pictogramme.

    La largeur est bornée en `vw` ET la bulle est recalée : la borne seule ne
    suffit pas, une bulle de 62 % de la largeur centrée sur un pictogramme posé
    à 5 % de l'écran déborde toujours.                                       */
.warn-mark .warn-tip{
  position:absolute;bottom:calc(100% + 7px);left:50%;
  transform:translateX(calc(-50% + var(--tip-shift, 0px))) translateY(3px);
  display:block;width:max-content;max-width:min(78vw, 250px);
  padding:7px 10px;border-radius:10px;
  background:var(--surface);border:1px solid var(--line-2);
  box-shadow:var(--shadow-2, var(--shadow-1));
  color:var(--text, #101828);text-align:left;
  opacity:0;visibility:hidden;pointer-events:none;
  transition:opacity .14s ease, transform .14s ease, visibility .14s;
}
.warn-mark .warn-tip b{display:block;font:600 12.5px/1.25 var(--font, inherit)}
.warn-mark[data-kind="pente"] .warn-tip b{color:#B42318}

/*  LE PASSAGE TOUCHÉ S'ALLUME — fond rouge plein, triangle blanc —, et son
    jumeau aussi : celui de la carte quand on touche le profil, et
    inversement. C'est ce qui relie les deux, qui sans cela sont deux
    triangles parmi d'autres. Voir `allumer` dans utils.js.                 */
.warn-mark[data-kind="pente"].is-active .warn-pic{
  background:#B42318;border-color:#B42318;color:#fff;
}
.warn-mark.is-active{z-index:3}

/*  LA BULLE DES PENTES DE LA CARTE, SANS PICTOGRAMME. Les triangles y sont
    dessinés par une couche — pour passer sous les hexagones —, et la bulle est
    un marqueur à part, posé dessus. Elle hérite de tout l'habillage de
    `.warn-mark` mais ne doit pas recevoir le doigt : c'est le triangle,
    dessous, qui le reçoit. Voir `setWarnings` dans mapview.js.             */
.warn-mark.warn-float{pointer-events:none;cursor:default}

/*  LA CROIX DE LA BULLE ÉPINGLÉE. Absente au survol, où la bulle part toute
    seule ; présente au clic, où elle reste — voir `armerBulle` dans utils.js.
    Épinglée, la bulle devient cliquable : sans cela la croix serait dessinée
    mais hors d'atteinte, la bulle laissant passer le doigt au travers.
    Le rembourrage de droite lui fait sa place sans recouvrir le texte.     */
.warn-mark .warn-close{
  display:none;position:absolute;top:5px;right:5px;
  width:20px;height:20px;border-radius:50%;
  place-items:center;cursor:pointer;color:var(--muted, #667085);
}
.warn-mark .warn-close svg{width:13px;height:13px}
.warn-mark .warn-close:hover{background:var(--surface-2);color:var(--ink, #101828)}
.warn-mark.is-pinned .warn-tip{padding-right:30px;pointer-events:auto;cursor:default}
.warn-mark.is-pinned .warn-close{display:grid}
.warn-mark .warn-tip em{
  display:block;margin-top:2px;
  font:400 12px/1.35 var(--font, inherit);font-style:normal;
  color:var(--text-2, #475467);
}

.warn-mark:hover .warn-tip,
.warn-mark:focus-visible .warn-tip,
.warn-mark.is-open .warn-tip{
  opacity:1;visibility:visible;
  transform:translateX(calc(-50% + var(--tip-shift, 0px))) translateY(0);
}

/*  `tip-below` est posée par le script quand la bulle sortirait par le haut de
    ce qui la rogne — voir `recaler` dans utils.js. Elle bascule dessous plutôt
    que de glisser vers le bas, ce qui la poserait sur son pictogramme.      */
.warn-mark.tip-below .warn-tip{
  bottom:auto;top:calc(100% + 7px);
  transform:translateX(calc(-50% + var(--tip-shift, 0px))) translateY(-3px);
}
.warn-mark.tip-below:hover .warn-tip,
.warn-mark.tip-below:focus-visible .warn-tip,
.warn-mark.tip-below.is-open .warn-tip{
  transform:translateX(calc(-50% + var(--tip-shift, 0px))) translateY(0);
}

/*  AU DOIGT, LE SURVOL NE VAUT RIEN ET MENT. Un appareil tactile garde l'état
    `:hover` sur le dernier élément touché : la bulle resterait ouverte après
    que la personne a refermé, et un second appui ne la rouvrirait pas. Sur ces
    appareils, seul `is-open` compte.                                        */
@media (hover:none){
  .warn-mark:hover .warn-tip{opacity:0;visibility:hidden}
  .warn-mark.is-open .warn-tip{opacity:1;visibility:visible}
}

/*  ─── Les mêmes, sur le profil altimétrique ───────────────────────────────

    LES MARGES SONT PORTÉES ICI, ET C'EST CE QUI PERMET DE PLACER EN POURCENTAGE.
    Le curseur de survol se place en pixels, à partir d'une mesure prise au
    moment du geste ; les pictogrammes, eux, sont posés par `draw`, qui passe
    avant que le graphique ne soit rendu visible — une mesure y rendrait zéro et
    les empilerait tous à gauche. Le conteneur reprend donc les mêmes retraits
    que `showAt` : 40 px de gouttière d'altitudes à droite, 18 px d'axe des
    distances en bas. Voir `drawWarnings` dans elevation.js.
    ──────────────────────────────────────────────────────────────────────── */
.elev-warns{
  position:absolute;left:0;right:40px;top:0;bottom:18px;
  pointer-events:none;          /* le graphique reste survolable au travers */
}
.elev-warns > *{
  position:absolute;
  transform:translate(-50%, -100%);
  pointer-events:auto;
}
/*  Plus petits que sur la carte : ils se suivent de près sur un versant, et le
    graphique est bas.                                                       */
.elev-warns .warn-mark{width:22px;height:22px}

/*  PAS DE BULLE SUR TÉLÉPHONE, dans le profil seulement. `#dock` y défile, et
    un conteneur défilant rogne en largeur comme en hauteur : la bulle n'y
    tenait jamais entière. Le message part dans le bloc de valeurs — voir
    `montrerPente` dans planner-main.js. On la cache ici plutôt que de compter
    sur le seul clic : l'état `:hover` reste collé au doigt sur un écran
    tactile, et la ferait paraître quand même.                              */
@media (max-width:899px){
  .elev-warns .warn-tip{display:none}
}
.elev-warns .warn-pic{width:18px;height:18px}
.elev-warns .warn-mark svg{width:12px;height:12px}

/*  ─── Chemins non vérifiés — le badge ─────────────────────────────────────

    Un comprimé blanc : pastille grise au point d'interrogation, distance en
    gras, « non vérifiés » dessous. Voir `renderUnknownBadge` dans
    planner-main.js.

    LE GRIS DE LA LÉGENDE. `--unk` est réécrite par le script avec
    `SURFACE.inconnu.color` — la teinte du trait et de la case « Inconnu » de
    la barre de composition —, pour que le badge se lise comme la même chose.
    La valeur ci-dessous n'est qu'un repli. Le texte, lui, reste à l'encre : ce
    gris-là, sur du blanc, ne se lirait pas en toutes lettres.

    DEUX PLACES — le script le déplace au passage du seuil, voir `placerUnk` :
    — desktop : dans `#app`, au bas de la carte visible, à gauche ;
    — mobile  : dans la ligne du bouton des zones, centré sur l'écran.
    ──────────────────────────────────────────────────────────────────────── */
.unk{
  --unk:#98A2B3;
  position:absolute;z-index:25;
}
.unk[hidden]{display:none}

.unk-badge{
  display:flex;align-items:center;gap:10px;
  padding:6px 18px 6px 6px;margin:0;
  border:0;border-radius:999px;
  background:var(--surface);color:var(--ink);
  box-shadow:0 1px 3px rgba(22,33,29,.14), 0 6px 18px rgba(22,33,29,.13);
  font:inherit;text-align:left;cursor:pointer;
  white-space:nowrap;
  -webkit-tap-highlight-color:transparent;
}
.unk-badge:focus-visible{outline:2px solid var(--ink-2);outline-offset:2px}

.unk-pic{
  flex:0 0 auto;display:grid;place-items:center;
  width:36px;height:36px;border-radius:50%;
  background:var(--unk);color:#fff;
}
.unk-pic svg{width:22px;height:22px}

.unk-txt b{display:block;font-size:16px;font-weight:700;line-height:1.15}
.unk-txt em{
  display:block;font-size:13.5px;font-weight:400;font-style:normal;line-height:1.2;
  color:var(--ink-2);
}

/*  La bulle. Même habillage que celle des pentes — voir `.warn-mark .warn-tip`
    —, sans le recalage : à ses deux places, elle tient dans l'écran d'elle-même.
    Au-dessus du badge en desktop, dessous en mobile — voir plus bas.        */
.unk-tip{
  position:absolute;
  width:max-content;max-width:min(calc(100vw - 24px), 270px);
  padding:8px 12px;border-radius:10px;
  background:var(--surface);border:1px solid var(--line-2);
  box-shadow:var(--shadow-2);
  text-align:left;white-space:normal;
  opacity:0;visibility:hidden;pointer-events:none;
  transition:opacity .14s ease, transform .14s ease, visibility .14s;
}
.unk-tip b{display:block;font-size:12.5px;font-weight:600;line-height:1.25;color:var(--ink)}
.unk-tip em{
  display:block;margin-top:2px;
  font-size:12px;font-weight:400;font-style:normal;line-height:1.35;
  color:var(--text-2, #475467);
}
.unk.is-open .unk-tip{opacity:1;visibility:visible}

/*  La croix de `warnCloseHTML`, habillée ici : les règles de `.warn-mark` ne
    l'atteignent pas hors d'un pictogramme. Présente seulement épinglée.     */
.unk .warn-close{
  display:none;position:absolute;top:6px;right:6px;
  width:20px;height:20px;border-radius:50%;
  place-items:center;cursor:pointer;color:var(--muted, #667085);
}
.unk .warn-close svg{width:13px;height:13px}
.unk .warn-close:hover{background:var(--surface-2);color:var(--ink, #101828)}
.unk.is-pinned .unk-tip{padding-right:32px;pointer-events:auto;cursor:default}
.unk.is-pinned .warn-close{display:grid}

.dialog-open .unk{opacity:0;pointer-events:none}

/*  ─── Desktop : au bas de la carte visible ───────────────────────────────

    SA HAUTEUR EST UNE TRANSLATION, pas un `bottom` : `--unk-lift` vaut la
    hauteur du bandeau du profil, posée par `setUnkLift`. Une translation ne
    recalcule pas la mise en page.

    28 PX APRÈS LA COLONNE, ET NON 14 : la languette de repli du panneau
    déborde de la colonne sur 22 px, et le badge venait s'y coller. Il suit la
    colonne quand elle se replie — même jeton, même courbe que `.map-panels`.

    Z-INDEX 25 : au-dessus de la carte et des contrôles (20), sous le bandeau
    (30).                                                                    */
@media (min-width:900px){
  .unk{
    left:calc(var(--sidebar-w) + 28px);bottom:14px;
    transform:translateY(calc(-1 * var(--unk-lift, 0px)));
    transition:transform .28s cubic-bezier(.32,.72,0,1),
               left .28s cubic-bezier(.32,.72,0,1);
  }
  .unk-tip{
    left:0;bottom:calc(100% + 8px);
    transform:translateY(3px);
  }
  .unk.is-open .unk-tip{transform:none}
}

/*  ─── Mobile : sur la ligne du bouton des zones, centré sur l'écran ──────

    Le badge est un enfant de `.side-line` — voir `placerUnk` —, sorti du flux
    pour ne pas pousser le bouton ni en être poussé. Centré sur l'ÉCRAN et non
    sur la ligne : celle-ci commence à 12 px du bord gauche et s'arrête à
    64 px du droit, pour laisser passer la pile des contrôles. Son milieu n'est
    donc pas celui de l'écran — d'où `50vw` moins le retrait gauche de
    `.map-panels`.

    La bulle s'ouvre DESSOUS, centrée : au-dessus, il n'y a que la liste des
    traces et le bord de l'écran.                                            */
@media (max-width:899px){
  .side-line{position:relative}

  .unk{
    left:calc(50vw - 12px);top:50%;
    transform:translate(-50%, -50%);
  }
  .unk-tip{
    left:50%;top:calc(100% + 8px);
    transform:translate(-50%, -3px);
  }
  .unk.is-open .unk-tip{transform:translate(-50%, 0)}

  #app.poi-open .unk{opacity:0;pointer-events:none}
}

/*  ─── Barres de défilement, en desktop ────────────────────────────────────

    CELLE DE CHROME EST ÉNORME. Dix-sept pixels de gouttière permanente le long
    du volet, en gris franc, qui prennent autant de largeur qu'une colonne de
    pictogrammes et se lisent comme un élément de l'interface — alors qu'elles
    ne disent qu'une chose, et seulement pendant qu'on défile.

    Elles sont donc remplacées par une barre étroite et transparente au repos.
    REMPLACÉES ET NON SUPPRIMÉES : sur un long volet, rien d'autre ne dit qu'il
    reste du contenu plus bas, ni où l'on en est. La faire disparaître tout à
    fait rendrait le volet muet — c'est acceptable pour une bande d'onglets qui
    tient en une ligne, comme `.poi-track` ou `#statsM` plus haut, pas pour une
    colonne qui se parcourt.

    Rien de tout cela en mobile : le système y pose déjà une barre flottante
    qui s'efface seule, et qui est la bonne.

    ⚠ LES SÉLECTEURS SONT NOMMÉS UN À UN, et c'est volontaire. Une règle en
    `*` l'emporterait, par sa spécificité, sur les deux conteneurs qui cachent
    délibérément la leur — et les leur rendrait.
    ──────────────────────────────────────────────────────────────────────── */
@media (min-width:900px) and (hover:hover){
  #sidebar, #dock, .picker-list, .suggest, .dialog-scroll, .poi-body{
    scrollbar-width:thin;
    scrollbar-color:var(--line-2) transparent;
  }

  #sidebar::-webkit-scrollbar,
  #dock::-webkit-scrollbar,
  .picker-list::-webkit-scrollbar,
  .suggest::-webkit-scrollbar,
  .dialog-scroll::-webkit-scrollbar,
  .poi-body::-webkit-scrollbar{
    width:8px;height:8px;
  }

  #sidebar::-webkit-scrollbar-track,
  #dock::-webkit-scrollbar-track,
  .picker-list::-webkit-scrollbar-track,
  .suggest::-webkit-scrollbar-track,
  .dialog-scroll::-webkit-scrollbar-track,
  .poi-body::-webkit-scrollbar-track{
    background:transparent;
  }

  /*  Le curseur est dessiné dans sa bordure : c'est ce qui lui donne sa marge
      sans réserver de gouttière. `background-clip:content-box` sur une bordure
      transparente est le seul moyen d'y arriver en WebKit.                  */
  #sidebar::-webkit-scrollbar-thumb,
  #dock::-webkit-scrollbar-thumb,
  .picker-list::-webkit-scrollbar-thumb,
  .suggest::-webkit-scrollbar-thumb,
  .dialog-scroll::-webkit-scrollbar-thumb,
  .poi-body::-webkit-scrollbar-thumb{
    background:var(--line-2);
    background-clip:content-box;
    border:2px solid transparent;
    border-radius:999px;
  }

  #sidebar:hover::-webkit-scrollbar-thumb,
  #dock:hover::-webkit-scrollbar-thumb,
  .picker-list:hover::-webkit-scrollbar-thumb,
  .suggest:hover::-webkit-scrollbar-thumb,
  .dialog-scroll:hover::-webkit-scrollbar-thumb,
  .poi-body:hover::-webkit-scrollbar-thumb{
    background:var(--line);
    background-clip:content-box;
  }
}

/*  ─── Colonne des calques ─────────────────────────────────────────────────
    Elle tient les boutons de calque, empilés, chacun sur sa ligne avec la
    place d'une phrase à sa droite.

    `pointer-events:none` SUR LA COLONNE ET SES LIGNES, `auto` SUR LES BOUTONS.
    Le conteneur s'étire sur toute la largeur de la carte ; sans cela il
    recevrait le doigt partout, et un appui destiné à poser une étape tomberait
    dans le vide.
    ──────────────────────────────────────────────────────────────────────── */
.side-stack{
  display:flex;flex-direction:column;align-items:flex-start;gap:8px;
  pointer-events:none;
}
.side-line{
  display:flex;align-items:center;gap:9px;
  pointer-events:none;
}
.side-line > *{pointer-events:auto}
/*  Une ligne dont le bouton est caché ne doit pas laisser son écart : sans
    cela, la colonne garderait un trou là où le ravitaillement n'est pas.    */
.side-line:not(:has(.side-btn:not([hidden]))){display:none}


.side-btn{
  align-self:flex-start;position:relative;
  width:42px;height:42px;border-radius:var(--r-md);
  display:grid;place-items:center;
  background:var(--surface);border:1px solid var(--line-2);
  box-shadow:var(--shadow-1);color:var(--green);
}
.side-btn[hidden]{display:none}

.side-btn:hover{background:var(--surface-2)}
.side-btn svg{width:21px;height:21px;stroke-width:1.8}

/*  Indice collé au coin haut-droit, débordant du cadre : posé à l'intérieur il
    mangerait le pictogramme, et il doit se lire avant lui.                  */
/*  L'indice du nid d'abeille porte « 25 % » et non plus un nombre de zones :
    deux chiffres et un signe là où il y en avait un. La largeur minimale suit,
    le reste ne bouge pas.                                                   */
.side-badge{
  position:absolute;top:-6px;right:-6px;
  min-width:19px;height:19px;padding:0 5px;border-radius:999px;
  display:grid;place-items:center;
  font-size:11px;font-weight:700;line-height:1;
  color:#fff;background:var(--green);
  border:2px solid var(--surface);
  font-variant-numeric:tabular-nums;
}
.side-badge[hidden]{display:none}

/*  Pendant l'attente, l'indice porte un point et le bouton s'atténue : un zéro
    affirmerait qu'il n'y a rien alors qu'on ne le sait pas encore.          */
.side-btn.is-loading{opacity:.6}
.side-btn.is-loading .side-badge{background:var(--ink-2)}

/*  LE BOUTON DES ZONES SE DISTINGUE DES AUTRES. Le nid d'abeille ne montre pas
    un calque de plus : il dit ce que vaut le terrain sous le tracé. Plein vert
    et citron, il se repère du premier coup d'œil parmi des boutons blancs.  */
#hexBtn{background:var(--green);border-color:var(--green);color:var(--lime)}
#hexBtn:hover{background:var(--green-l);border-color:var(--green-l)}
#hexBtn .side-badge{background:var(--lime);color:var(--green);border-color:var(--green)}

/*  Éteint, il revient au blanc des autres : il reste atteignable — c'est par
    lui qu'on rallume — mais ne prétend plus désigner ce qui est à l'écran.

    ⚠ ÉCRIT SUR `#hexBtn` ET NON SUR `.side-btn` SEUL. C'est ce qui faisait que
    l'état éteint ne se voyait jamais : `.side-btn.is-off` pèse deux classes,
    `#hexBtn` un identifiant, et l'identifiant gagne quel que soit l'ordre. Le
    bouton restait vert plein, allumé ou non.

    LE PICTOGRAMME RESTE VERT, lui. Blanc sur blanc il disparaîtrait ; en gris
    il se lirait comme un bouton désactivé, qu'on ne peut pas toucher. Vert sur
    blanc, c'est le même bouton, simplement au repos.                        */
.side-btn.is-off{background:var(--surface);border-color:var(--line-2);color:var(--ink-2)}
.side-btn.is-off:hover{background:var(--surface-2);border-color:var(--line-2)}
.side-btn.is-off .side-badge{background:var(--muted);color:#fff;border-color:var(--surface)}

#hexBtn.is-off{background:var(--surface);border-color:var(--line-2);color:var(--green)}
#hexBtn.is-off:hover{background:var(--surface-2);border-color:var(--line-2)}

/*  LA JAUGE DU DÉLAI, SUR LE CONTOUR. Elle se remplit depuis le haut, dans le
    sens des aiguilles d'une montre, pendant les quelques secondes qui séparent
    l'arrêt de la carte du rechargement des zones — la même horloge que le
    cercle posé sur la carte, qui sort de l'écran à fort zoom.

    Posée SUR la bordure : décalée d'un pixel depuis le bord intérieur, qui
    est la référence des enfants positionnés, elle rejoint le bord extérieur. Le
    sélecteur d'identifiant l'emporte sur `.side-btn svg`, qui la réduirait à
    la taille du pictogramme.

    Citron sur le vert plein du bouton allumé. Éteint, il n'y a rien à
    attendre : le calque ne se recharge pas, la jauge ne paraît pas.        */
#hexBtn .hex-gauge{
  /*  Dimensions explicites et non `inset` seul : un SVG est un élément
      remplacé, et en position absolue il garde sa taille intrinsèque au lieu
      de s'étirer entre ses bords.                                         */
  position:absolute;top:-1px;left:-1px;
  width:calc(100% + 2px);height:calc(100% + 2px);
  pointer-events:none;overflow:visible;
}
#hexBtn .hex-gauge rect{
  fill:none;stroke:var(--lime);stroke-width:2.4;stroke-linecap:round;
  stroke-dasharray:100;stroke-dashoffset:100;
  opacity:0;transition:opacity .2s ease;
}
#hexBtn.is-waiting .hex-gauge rect{opacity:1}

@media (max-width:899px){
  /*  LES CARTES FLOTTANTES S'ARRÊTENT AVANT LA PILE DE CONTRÔLES.

      L'invitation au départ et la liste des traces occupaient toute la largeur
      et passaient sous les boutons de la carte — zoom, position, calques —,
      qui se retrouvaient posés dessus. Le texte disparaissait dessous et les
      boutons devenaient difficiles à viser.

      La pile fait 40 px et se tient à 10 px du bord : 64 px la dégagent
      entièrement, marge de respiration comprise. Les cartes ne sont donc plus
      centrées sur l'écran, et c'est voulu — mieux vaut un décalage assumé
      qu'un chevauchement.

      LA RÈGLE EST ICI, ET PAS AILLEURS. Elle avait d'abord été posée dans le
      bloc mobile du haut de la feuille — donc AVANT la déclaration de
      `.map-panels`, qui la réécrasait quelques centaines de lignes plus bas.
      Une requête de média n'ajoute pas de spécificité : à égalité, c'est la
      dernière écrite qui l'emporte. Toute retouche de cette règle doit rester
      après la déclaration de base.                                          */
  .map-panels{right:64px}

  /*  SOUS LA FEUILLE, ET NON PLUS DESSUS. À 36, la colonne des calques restait
      au-dessus de la feuille quand on la tirait : le bouton du ravitaillement
      — le plus bas — venait se poser sur le contenu du parcours. Rien de ce
      qui est posé sur la carte n'a à passer devant la feuille, qui est ce
      qu'on lit : 29 la met juste dessous (30), et toujours au-dessus des
      contrôles (20). Même règle, et même raison, pour l'invitation au départ,
      la liste des traces et le badge des chemins, qui vivent dans le même
      conteneur.

      La fiche POI (35) n'en est pas affectée : `.map-panels` s'efface déjà
      devant elle, plus haut.                                               */
  .map-panels{z-index:29}
}

@media (min-width:900px){
  /* La colonne occupe la gauche : les cartes commencent après elle, et
     reviennent au bord quand elle se replie. */
  .map-panels{
    left:calc(var(--panel-w) + 14px);right:auto;width:min(330px, 34vw);
    top:calc(var(--topbar-h) + 14px);
    transition:left .28s cubic-bezier(.32,.72,0,1);
  }
  #app.panel-hidden .map-panels{left:14px}
}
.dialog-open .map-panels{opacity:0;pointer-events:none}

/* ─────────────────────────────────────────────
   Traces des explorateurs dans la vue
   ───────────────────────────────────────────── */
.tracklist{
  background:var(--surface);border-radius:var(--r-lg);
  box-shadow:var(--shadow-2);overflow:hidden;
}
.tracklist[hidden]{display:none}

.tracklist-head{
  display:flex;align-items:center;gap:9px;width:100%;
  padding:10px 12px;text-align:left;
  font-size:13.5px;font-weight:600;color:var(--ink);
}
.tracklist-count{
  flex:0 0 auto;min-width:22px;height:22px;padding:0 6px;
  border-radius:11px;background:var(--green);color:#fff;
  display:grid;place-items:center;
  font-size:12px;font-weight:700;font-variant-numeric:tabular-nums;
}
.tracklist-title{flex:1 1 auto;min-width:0;font-weight:500;color:var(--ink-2)}
.tracklist-chevron{
  flex:0 0 auto;width:18px;height:18px;stroke-width:2;color:var(--muted);
  transition:transform .18s;
}
.tracklist-head[aria-expanded="true"] .tracklist-chevron{transform:rotate(180deg)}

.tracklist-items{
  margin:0;padding:0 6px 6px;list-style:none;
  max-height:min(46vh, 340px);overflow-y:auto;overscroll-behavior:contain;
}
.tracklist-items[hidden]{display:none}
.tracklist-items button{
  display:flex;align-items:center;gap:10px;width:100%;text-align:left;
  padding:9px 8px;border-radius:var(--r-sm);
}
.tracklist-items button:hover{background:var(--surface-2)}
/* Pastille de l'activité : même teinte que le tracé sur la carte. */
.tracklist-items i{
  flex:0 0 auto;width:9px;height:9px;border-radius:50%;background:var(--chip);
}
.tracklist-items .tl-name{
  flex:1 1 auto;min-width:0;font-size:13.5px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.tracklist-items .tl-num{
  flex:0 0 auto;font-size:12.5px;color:var(--ink-2);
  font-variant-numeric:tabular-nums;
}

/*  La trace qui EST dans le parcours, parmi celles qu'on pourrait prendre.
    Elle ne s'affiche plus en pointillé sur la carte — le tracé plein a pris sa
    place — et rien dans la liste ne la distinguait plus des autres. Le gras
    suffit : c'est un état, pas une catégorie de plus.                       */
.tracklist-items button[data-current] .tl-name{font-weight:700;color:var(--green)}
.tracklist-items button[data-current] .tl-num{color:var(--ink)}
.tracklist-items button[data-current] i{box-shadow:0 0 0 2.5px var(--surface-2)}
.tracklist-empty{padding:4px 8px 8px;font-size:12.5px;color:var(--muted)}

/* ─────────────────────────────────────────────
   Invitation au départ (mobile)
   Tant qu'aucun point n'est posé, une carte
   flottante demande d'où l'on part : le champ
   ouvre la recherche plein écran, le bouton rond
   propose la position relevée.
   ───────────────────────────────────────────── */
.startcard{display:none}

@media (max-width:899px){
  .startcard{
    display:flex;align-items:center;gap:8px;
    padding:8px;
    background:var(--surface);border-radius:var(--r-lg);
    box-shadow:var(--shadow-2);
    animation:startcard-in .22s cubic-bezier(.32,.72,0,1);
  }
  .startcard[hidden]{display:none}
}
@keyframes startcard-in{from{transform:translateY(-8px);opacity:0}}
@media (prefers-reduced-motion:reduce){ .startcard{animation:none} }

/* Un bouton déguisé en champ : il n'y a rien à saisir ici, la frappe se fait
   dans la recherche plein écran. Le déguisement dit quoi en attendre. */
.startcard-field{
  flex:1 1 auto;min-width:0;
  display:flex;align-items:center;gap:9px;
  height:44px;padding:0 12px;border-radius:var(--r-md);
  border:1.5px solid var(--line);background:var(--surface-2);
  text-align:left;color:var(--muted);font-size:14px;
}
.startcard-field:active{background:var(--line-2)}
.startcard-field svg{
  flex:0 0 auto;width:18px;height:18px;
  fill:none;stroke:var(--green);stroke-width:1.9;
}
.startcard-field span{
  min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.startcard .here{height:44px;background:var(--surface)}

/* Interrupteur inactif tant que le parcours n'a pas deux points */
.switch:has(input:disabled){opacity:.45;cursor:default}
.switch:has(input:disabled):hover{border-color:var(--line)}

/* Bloc de valeurs : en mobile il fait office de bilan quand on ne touche pas */
@media (max-width:899px){
  .readout{gap:14px}
  .readout div{flex:1 1 0;min-width:0}
  .readout b{font-size:15px}
  #sheet[data-tab="elev"] .elev{padding:10px 16px 12px;gap:8px}
  #sheet[data-tab="elev"] .chart{height:120px}
  #sheet[data-tab="elev"] .shares{padding:0 16px 14px}
}

/* ─────────────────────────────────────────────
   Repli du panneau latéral (desktop)
   Un seul jeton pilote tout : le décalage de la
   carte, le bandeau, la fiche POI, les contrôles.
   ───────────────────────────────────────────── */
.sidebar-toggle{display:none}

@media (min-width:900px){
  .sidebar-toggle{
    display:grid;place-items:center;position:absolute;z-index:31;
    left:var(--sidebar-w);top:50%;transform:translate(-1px, -50%);
    width:22px;height:56px;
    background:var(--surface);color:var(--ink-2);
    border:1px solid var(--line);border-left:0;
    border-radius:0 8px 8px 0;
    box-shadow:2px 0 6px rgba(22,33,29,.08);
    transition:left .28s cubic-bezier(.32,.72,0,1), color .15s;
  }
  .sidebar-toggle:hover{color:var(--green)}
  .sidebar-toggle svg{width:15px;height:15px;stroke-width:2.2;transition:transform .28s}

  #app.panel-hidden{--sidebar-w:0px}
  #app.panel-hidden #sidebar{transform:translateX(-100%)}
  #app.panel-hidden .sidebar-toggle svg{transform:rotate(180deg)}
}

/* ─────────────────────────────────────────────
   Bilan en mobile — il vit en tête de l'onglet
   Parcours, et non plus dans le bandeau du
   profil altimétrique.

   Les règles de base viennent d'abord, la
   requête média ensuite : à spécificité égale
   c'est la dernière qui l'emporte, et l'inverse
   a déjà coûté trois bugs (voir REPRISE.md §6).
   ───────────────────────────────────────────── */
/* Marges négatives : la zone défilante file d'un bord à l'autre du volet,
   sinon le dégradé s'ouvrirait sur une bande vide de 16 px. */
#statsBox{display:none;position:relative;margin:0 -16px 14px}
#statsBox[hidden]{display:none}

/* Dégradés latéraux : ils n'apparaissent que du côté où il reste à défiler. */
#statsBox::before,
#statsBox::after{
  content:"";position:absolute;top:0;bottom:0;width:30px;z-index:1;
  pointer-events:none;opacity:0;transition:opacity .18s;
}
#statsBox::before{left:0;background:linear-gradient(90deg,var(--surface),rgba(255,255,255,0))}
#statsBox::after{right:0;background:linear-gradient(270deg,var(--surface),rgba(255,255,255,0))}
#statsBox.can-left::before,
#statsBox.can-right::after{opacity:1}

#statsM{
  overflow-x:auto;overflow-y:hidden;scrollbar-width:none;
  -webkit-overflow-scrolling:touch;
  gap:24px;padding:2px 16px;
}
#statsM::-webkit-scrollbar{display:none}

@media (max-width:899px){
  #statsBox{display:block}
  #statsBox[hidden]{display:none}
  /* Le bandeau du bas ne garde que le graphe : le bilan a déménagé. */
  #dock > .stats{display:none}
}

/* ─────────────────────────────────────────────
   Dialogue : corps libre, notice, interrupteur
   ───────────────────────────────────────────── */
.dialog-body{margin:4px 0 14px}
.dialog-body[hidden]{display:none}

/*  Action posée en tête du dialogue, dans le corps libre : elle doit avoir
    l'aplomb d'une entrée de `.dialog-actions`, à laquelle elle n'appartient
    pas. Une marge basse la détache du premier groupe de réglages.            */
.d-lead{margin:10px 0 2px}
.d-lead .d-btn{width:100%}

.legend + .legend{margin-top:16px;padding-top:14px;border-top:1px solid var(--line-2)}
.legend h4{
  margin:0 0 9px;font-size:11px;font-weight:600;letter-spacing:.06em;
  text-transform:uppercase;color:var(--muted);
}
.legend ul{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:8px}
.legend li{display:flex;align-items:center;gap:10px;font-size:13px;line-height:1.35}
.legend p{margin:9px 0 0;font-size:12.5px;line-height:1.5;color:var(--ink-2)}

/* Pastille de légende : la forme et la couleur viennent d'un style en ligne,
   calculé depuis config.js — ici, seule la boîte est décrite. */
.lg-sw{
  flex:0 0 26px;width:26px;height:26px;box-sizing:border-box;
  display:grid;place-items:center;font-style:normal;
}
.lg-sw svg{width:100%;height:100%;display:block;overflow:visible}

/* Entrée de dialogue à bascule : l'interrupteur remplace le chevron. */
/*  Le pion est rentré par le rembourrage de la glissière, et non plus par sa
    propre marge : la glissière n'ayant ni bordure ni rembourrage, la marge
    haute du pion s'échappait au travers — elle poussait la glissière vers le
    bas au lieu de rentrer le pion, qui se retrouvait collé en haut. C'est le
    décentrage vu en desktop.

    `display:flex` referme la fuite, et le rembourrage tient le pion à égale
    distance des quatre bords.                                                */
.d-btn[data-toggle] .d-switch{
  flex:0 0 auto;margin-left:auto;
  display:flex;align-items:center;padding:2px;
  width:40px;height:23px;border-radius:999px;
  background:var(--line);transition:background .18s;
}
.d-btn[data-toggle] .d-switch i{
  display:block;width:19px;height:19px;border-radius:50%;
  background:#fff;box-shadow:var(--shadow-1);
  transition:transform .18s;
}
.d-btn[data-toggle][aria-pressed="true"] .d-switch{background:var(--green)}
.d-btn[data-toggle][aria-pressed="true"] .d-switch i{transform:translateX(17px)}

/*  Sur un bouton plein, la glissière grise disparaît dans le vert et la
    glissière verte encore plus. Blanc translucide à l'arrêt, citron en
    marche : les deux se lisent sur le fond, et le citron est déjà la couleur
    de ce qui est actif ailleurs dans l'interface.                           */
.d-btn.primary[data-toggle] .d-switch{background:rgba(255,255,255,.3)}
.d-btn.primary[data-toggle][aria-pressed="true"] .d-switch{background:var(--lime)}

/*  DANS LE DIALOGUE DES ZONES, C'EST L'ÉTAT QUI PEINT LE BOUTON, PAS SA PLACE.

    Le premier interrupteur était marqué `primary` et restait vert qu'il soit
    allumé ou non, pendant que le second restait blanc allumé. Avec deux
    calques exclusifs, cela se lisait à l'envers : on voyait en plein celui
    qu'on venait d'éteindre. Le fond vert suit donc l'interrupteur allumé, et
    lui seul.

    Limité à ce dialogue par sa variante : ailleurs, un interrupteur isolé au
    milieu d'autres entrées n'a pas à devenir un aplat.                     */
.dialog-box[data-variant="zones"] .d-btn[data-toggle][aria-pressed="true"]{
  background:var(--green);border-color:var(--green);color:#fff;
}
.dialog-box[data-variant="zones"] .d-btn[data-toggle][aria-pressed="true"]:hover{
  background:var(--green-l);border-color:var(--green-l);
}
.dialog-box[data-variant="zones"] .d-btn[data-toggle][aria-pressed="true"] .d-switch{
  background:var(--lime);
}

/*  Le libellé en citron, comme le pictogramme du bouton hexagone allumé : les
    deux disent la même chose, « ce calque est à l'écran ». La règle nomme le
    `<b>` parce que `.d-btn.plain .d-txt b` lui impose l'encre sombre des
    entrées ordinaires, et qu'hériter de la couleur du bouton ne suffit donc
    pas.                                                                     */
.dialog-box[data-variant="zones"] .d-btn[data-toggle][aria-pressed="true"] .d-txt b{
  color:var(--lime);
}

/*  La ligne de contexte du même dialogue. Toujours en demi-gras : elle dit
    l'état du calque, pas une remarque en passant. Et en vert profond quand un
    calque est allumé — `is-on`, posé par `hexContext` dans planner-main.js —,
    pour que « Affichées à zoom faible » se lise comme une confirmation et
    « L'affichage est désactivé » comme un simple constat.

    Portée par la variante : la classe reste sur l'élément, qui est unique et
    réemployé par tous les dialogues, et ne doit rien teinter ailleurs.     */
.dialog-box[data-variant="zones"] .dialog-text{font-weight:600}
.dialog-box[data-variant="zones"] .dialog-text.is-on{color:#006c57}

/* ═══════════════════════════════════════════════
   Pied de page de la page hôte

   En dernier, et non près de chacune des règles
   concernées : `.zone-modal` et `.search-modal`
   posent `inset:0` plus bas dans le fichier, et
   à spécificité égale c'est la dernière écrite
   qui l'emporte — un `bottom` posé plus haut
   serait remis à zéro sans qu'on voie pourquoi.

   #app s'arrête déjà au-dessus du pied ; ces
   trois-là sont posées sur la fenêtre et lui
   échappent. La fiche POI est dans #app, elle
   n'a rien à corriger. La visionneuse de photo
   fait exception : elle couvre tout.
   ═══════════════════════════════════════════════ */
@media (max-width:899px){
  .dialog, .search-modal, .zone-modal{bottom:var(--footer-h)}
}

/*  En desktop la bande est en tête : les mêmes surcouches doivent s'arrêter
    sous elle. Sans cela, un dialogue devenu haut — la liste des calques, les
    pastilles, la notice d'aide — passait derrière le bandeau de marque, et
    c'est son titre qu'on ne voyait plus.                                    */
@media (min-width:900px){
  .dialog, .search-modal, .zone-modal{top:var(--host-h)}
}

/*  En desktop, la même bande est en tête : la notification s'y perdait, à
    moitié cachée par le bandeau de marque de la page hôte.                 */
@media (min-width:900px){
  .toast{--host-shift:var(--host-h)}
}

/* ═══════════════════════════════════════════════
   Panneau en cartes

   UN SEUL BALISAGE, DEUX HABILLAGES.
   — Desktop : trois cartes sur fond gris clair —
     recherche (verte), réglages, parcours.
   — Mobile, onglet Parcours : le bilan dans un
     cadre, puis trois pastilles côte à côte —
     aller-retour, profil, niveau —, un filet, et
     « Inverser le sens du tracé » en lien centré.

   EN FIN DE FICHIER, ET C'EST VOULU : ces règles
   remplacent celles de l'ancienne colonne, dont
   plusieurs étaient réparties plus haut. Les
   anciennes ont été retirées ; ce bloc passe de
   toute façon après, à spécificité égale.

   Base d'abord, requêtes média ensuite — voir la
   note de `#statsBox` plus haut.
   ═══════════════════════════════════════════════ */

/* ─── En-tête de carte ─────────────────────── */
.card-head{display:flex;align-items:center;gap:10px}
.card-head h2{
  flex:1 1 auto;min-width:0;margin:0;
  font-size:14.5px;font-weight:700;line-height:1.2;color:var(--ink);
}
.card-ic{
  flex:0 0 30px;width:30px;height:30px;border-radius:9px;
  display:grid;place-items:center;
  background:#E6F1EC;color:var(--green);
}
.card-ic svg{width:17px;height:17px;stroke-width:1.9}

/*  Compte des étapes, en tête de la carte « Parcours ». */
.pts-count{
  flex:0 0 auto;padding:3px 9px;border-radius:999px;
  background:#E3F1EA;color:var(--green);
  font-size:11.5px;font-weight:700;line-height:1.3;white-space:nowrap;
}
.pts-count[hidden]{display:none}

/* ─── Réglages ─────────────────────────────── */
.set-label{margin:0 0 8px;font-size:12.5px;font-weight:600;color:var(--ink-2)}

/*  Texte d'une pastille : petit intitulé au-dessus, valeur dessous. En desktop
    l'intitulé est porté par `.set-label`, au-dessus du champ : il est masqué. */
.chip-txt{flex:1 1 auto;min-width:0;display:flex;flex-direction:column}
.chip-txt small{display:none}
.chip-txt > span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/*  Pastille du niveau : mobile seulement. */
.level-btn{display:none}
.lvl-bars path{stroke:#CFD6D1;stroke-width:2.6;stroke-linecap:round}
.lvl-bars path.on{stroke:var(--green)}

/*  Niveau — un sélecteur segmenté : un rail gris, la valeur retenue pleine. */
.levels{
  display:grid;grid-template-columns:repeat(4,1fr);gap:2px;
  padding:3px;border-radius:11px;background:var(--surface-2);
}
.levels button{
  padding:9px 2px;border-radius:8px;
  font-size:13px;font-weight:500;color:var(--ink-2);
  transition:background .15s,color .15s;
}
.levels button:hover{color:var(--ink)}
.levels button[aria-pressed="true"]{
  background:var(--green);color:#fff;font-weight:600;
  box-shadow:0 1px 2px rgba(11,91,68,.25);
}

/*  Aller-retour — intitulé et note à gauche, interrupteur à droite. L'ordre
    visuel est posé par `order` : dans la source, la case et sa glissière
    viennent d'abord, pour que `input:checked + .track` et `input:checked ~ …`
    atteignent tout le reste.                                               */
.switch{position:relative;display:flex;align-items:center;gap:12px;cursor:pointer}
.switch[hidden]{display:none}
.switch input{position:absolute;opacity:0;width:0;height:0}
.switch .track{
  order:2;margin-left:auto;flex:0 0 44px;height:26px;border-radius:13px;
  position:relative;background:var(--line);transition:background .18s;
}
.switch .track i{
  position:absolute;top:3px;left:3px;width:20px;height:20px;border-radius:50%;
  background:#fff;box-shadow:var(--shadow-1);transition:transform .18s;
}
.switch input:checked + .track{background:var(--green)}
.switch input:checked + .track i{transform:translateX(18px)}
.switch input:focus-visible + .track{outline:2px solid var(--green-l);outline-offset:2px}

.sw-ic{display:none}
.switch-txt{order:1;display:flex;flex-direction:column;gap:2px;min-width:0}
.sw-name{font-size:14px;font-weight:700;line-height:1.2;color:var(--ink)}
.switch-txt em{font-style:normal;font-size:12px;line-height:1.35;color:var(--muted)}
.sw-state{display:none}
.switch input:checked ~ .switch-txt .st-off,
.switch input:not(:checked) ~ .switch-txt .st-on{display:none}

/* ─── Parcours ─────────────────────────────── */
.rev-more{display:none}
/*  EN VERT, dans les deux formats : c'est une action sur le tracé, au même
    titre que « Terminer », et non un réglage.                             */
#reverse{color:var(--green)}
#reverse svg{width:15px;height:15px}

/*  L'unité en retrait du chiffre — voir `valeurHTML`. */

/* ─── Desktop : trois cartes ───────────────── */
@media (min-width:900px){
  #sidebar{background:#F2F5F3}
  .pane{display:flex;flex-direction:column;gap:12px;padding:12px 12px 24px}

  .card{
    background:var(--surface);
    border:1px solid var(--line);border-radius:14px;
    padding:14px;
  }
  .card > .card-head{margin-bottom:14px}

  /*  La recherche, en vert : c'est par elle qu'on commence. */
  .card-search{background:var(--green);border-color:var(--green)}
  .card-search .card-head h2{color:#fff}
  .card-search .card-ic{background:rgba(255,255,255,.14);color:#fff}
  .card-search .search{border-color:transparent}
  .card-search .search:hover{border-color:transparent}
  .card-search .search:focus-within{
    border-color:var(--lime);box-shadow:0 0 0 3px rgba(199,232,47,.28);
  }
  .card-search .here{background:var(--surface);border-color:transparent}
  .card-search .here:hover{background:var(--surface-2);border-color:transparent}

  /*  Un filet entre deux réglages. */
  .settings > * + *{margin-top:14px;padding-top:14px;border-top:1px solid var(--line-2)}

  /*  Le bandeau du profil : plus d'air, et « Terminer » à la hauteur des
      valeurs qu'il suit.                                                   */
  #dock > .stats{padding:14px 20px;gap:20px}
  #gpx{padding:12px 20px;border-radius:12px;font-size:15px;gap:9px}
  #gpx svg{width:17px;height:17px}
  #dockToggle{width:40px;height:40px;border-radius:10px}

  /*  Barre d'outils : annuler, rétablir, inverser à gauche, la corbeille
      repoussée à droite. */
  .card-route .pts-tools{margin:0 0 10px}
  .pts-tools .icon{width:34px;height:34px;padding:0;display:grid;place-items:center;color:var(--ink-2)}
  #clear{margin-left:auto;width:34px;height:34px;padding:0;justify-content:center}
  .pts:not(:empty){border-top:1px solid var(--line-2)}
  .card-route .hint{margin-top:4px}
}

/* ─── Mobile : bilan, pastilles, inverser ──── */
@media (max-width:899px){
  /*  Rangée d'onglets : plus haute, la corbeille avant « Terminer ». La
      hauteur de la bande est mesurée par `stripH` : la changer ici suffit. */
  #sheet > .sheet-tabs{height:66px}
  .sheet-tabs .seg{padding:4px;border-radius:12px}
  .sheet-tabs .seg button{padding:10px 6px;border-radius:9px;font-size:15px}

  /*  L'ONGLET ACTIF EN VERT PÂLE. Blanc sur le gris très clair du rail, il ne
      se distinguait qu'à son ombre, et au soleil on ne savait plus lequel
      était ouvert.                                                        */
  .sheet-tabs .seg button[aria-pressed="true"]{
    background:#DDEFE6;color:var(--green);font-weight:700;
    box-shadow:inset 0 0 0 1px #BFDDCF;
  }
  #clearM{order:1;width:46px;height:46px;border-radius:12px}
  #clearM svg{width:19px;height:19px}
  #gpxM{order:2;height:46px;padding:0 18px;gap:8px;border-radius:12px;font-size:15px}
  #gpxM svg{width:17px;height:17px}

  .pane{padding:14px 16px 24px}

  /*  Le bilan dans un cadre, les cinq valeurs réparties sur la largeur. Il
      défile encore à l'horizontale sur un écran trop étroit : les dégradés de
      bord restent en place pour le dire.                                  */
  #statsBox{margin:0 0 12px;background:var(--surface);overflow:hidden}
  /*  Quatre colonnes séparées par un filet ; le dénivelé sur deux lignes,
      montée au-dessus de descente. Les colonnes prennent la largeur de leur
      contenu et se partagent le reste.                                    */
  #statsM{gap:0;padding:12px 4px;align-items:stretch}
  /*  Une colonne s'élargit s'il reste de la place, NE RÉTRÉCIT JAMAIS : sur
      un écran trop étroit, c'est la rangée qui défile, avec ses dégradés. */
  #statsM .stat{flex:1 0 auto;padding:0 10px;gap:6px}
  #statsM .stat:first-child{padding-left:10px}
  #statsM .stat-k{font-size:12.5px;gap:5px}
  #statsM .stat-k svg{width:14px;height:14px}
  #statsM .stat-v{font-size:19px}
  #statsM .stat-dist .stat-v{font-size:21px}
  #statsM .stat-deniv .stat-v{flex-direction:column;align-items:flex-start;gap:3px;font-size:15px}

  /*  Les cartes perdent leur habillage : en-têtes, intitulés et filets
      disparaissent, il ne reste que les pastilles et la liste.            */
  .card > .card-head,
  .set-label{display:none}

  /*  LES MENUS S'OUVRENT SUR TOUTE LA LARGEUR DE LA RANGÉE, pas sur celle
      d'une pastille : un tiers d'écran ne tiendrait pas « VTT engagé » et son
      explication. `.settings` devient donc leur bloc de référence, et
      `.picker` rend la main.                                              */
  /*  PAS DE `position` SUR LA RANGÉE NI SUR `.picker` : les menus doivent
      avoir `#sheet` pour bloc de référence, sans quoi la colonne défilante
      les rognerait en s'ouvrant vers le haut — voir `placerMenu`, qui les
      pose d'après la rangée.                                              */
  /*  UNE RANGÉE QUI DÉFILE, COMME LE BILAN. Les pastilles gardent leur taille
      naturelle — pictogramme, intitulé et valeur, chevron — et s'élargissent
      s'il reste de la place ; sur un écran trop étroit, la rangée défile à
      l'horizontale au lieu de les tasser. Elle file d'un bord à l'autre de la
      feuille (marges négatives), pour que ce qui dépasse se voie passer.  */
  .settings{
    display:flex;gap:8px;
    margin:0 -16px;padding:0 16px;
    overflow-x:auto;overflow-y:hidden;
    scrollbar-width:none;-webkit-overflow-scrolling:touch;
  }
  .settings::-webkit-scrollbar{display:none}
  .settings > .set,
  .settings > .switch{flex:1 0 auto}

  /*  LES DÉGRADÉS DE BORD SONT COLLANTS, ET DANS LA RANGÉE MÊME. Le bilan les
      pose sur son conteneur, positionné ; ici c'est impossible : tout
      positionnement autour de la rangée deviendrait le bloc de référence des
      menus, qui seraient alors rognés par la colonne en s'ouvrant vers le
      haut — voir `placerMenu`. Un masque ne va pas non plus : il effacerait
      les menus hors de la rangée.

      Deux pseudo-éléments, donc, collés aux bords de la zone visible. Leur
      marge négative — largeur plus écart de la rangée — les empêche de
      prendre de la place. `can-left` / `can-right` sont posées par
      `syncChipsFade`, comme pour le bilan.

      ⚠ DÉCALÉS DU REMBOURRAGE DE LA RANGÉE. Un élément collant reste dans la
      zone de contenu de son conteneur défilant, rembourrage déduit : collés
      à `left:0` / `right:0`, les dégradés s'arrêtaient à 16 px du bord de la
      feuille, et les pastilles passaient dessous sans s'estomper. Les
      décalages négatifs les ramènent au bord.                              */
  .settings::before,
  .settings::after{
    content:"";position:sticky;z-index:2;flex:0 0 26px;align-self:stretch;
    pointer-events:none;opacity:0;transition:opacity .18s;
  }
  /*  `order` explicite : les pastilles en portent un (1 à 3), et un
      pseudo-élément sans ordre passerait devant elles — le dégradé de droite
      se retrouvait collé au bord gauche.                                  */
  .settings::before{
    order:-1;left:-16px;margin-right:-34px;
    background:linear-gradient(90deg,var(--surface),rgba(255,255,255,0));
  }
  .settings::after{
    order:99;right:-16px;margin-left:-34px;
    background:linear-gradient(270deg,var(--surface),rgba(255,255,255,0));
  }
  .settings.can-left::before,
  .settings.can-right::after{opacity:1}
  .settings .picker-list,
  .set-level .levels{top:auto;right:auto;overflow-y:auto}
  #loopRow{order:1}
  .set-profile{order:2}
  .set-level{order:3}
  .picker{position:static}

  /*  Une pastille : pictogramme, intitulé et valeur, chevron. */
  .settings .picker-btn{
    min-height:60px;padding:9px 8px 9px 10px;gap:7px;
    border:1px solid var(--line);border-radius:14px;
  }
  .settings .picker-btn > svg:first-child{width:20px;height:20px}

  /*  LE PROFIL EN BLEU PÂLE. C'est le réglage qui change le plus le tracé,
      et il se perdait entre ses deux voisins. Pas en vert : c'est déjà la
      teinte de l'aller-retour quand il est activé, et deux pastilles vertes
      côte à côte se liraient comme deux choses activées.                  */
  .set-profile .picker-btn{background:#EEF4FF;border-color:#C7D8F8}
  .set-profile .picker-btn:hover{border-color:#8FB0EC}
  .set-profile .picker-btn[aria-expanded="true"]{border-color:#2E6BD6}
  .set-profile .picker-btn > svg:first-child{color:#2E6BD6}
  .set-profile .chip-txt small{color:#5474AE}
  .set-profile .chip-txt > span{color:#1D3B73}
  .set-profile .picker-btn .chev{stroke:#5474AE}

  /*  Dans la liste, le profil retenu porte le même bleu que la pastille :
      c'est la même valeur, vue de l'intérieur.                            */
  .picker-list button[aria-selected="true"]{background:#EEF4FF}
  .picker-list button[aria-selected="true"] svg{color:#2E6BD6}
  .picker-list button[aria-selected="true"] .txt b{color:#1D3B73}
  .picker-list button[aria-selected="true"] .tick{color:#2E6BD6;stroke:#2E6BD6}
  .settings .picker-btn .chev{width:14px;height:14px}
  .chip-txt small{
    display:block;font-size:11.5px;font-weight:500;line-height:1.25;color:var(--muted);
  }
  .chip-txt > span{font-size:15px;font-weight:700;line-height:1.25;color:var(--ink);overflow:visible}

  .level-btn{display:flex}
  .set-level .levels{
    display:none;position:absolute;z-index:60;
    grid-template-columns:1fr;gap:2px;padding:4px;
    background:var(--surface);border:1.5px solid var(--line);
    border-radius:var(--r-md);box-shadow:var(--shadow-2);
  }
  .set-level.is-open .levels{display:grid}
  .set-level .levels button{padding:12px;text-align:left;font-size:14px}
  .set-level .levels button[aria-pressed="true"]{
    background:var(--surface-2);color:var(--green);box-shadow:none;
  }

  /*  L'aller-retour en pastille. SON FOND EST LA GLISSIÈRE, étendue sous tout
      le libellé : `input:checked + .track` la colore quand il est actif, sans
      `:has()`. Le pion, lui, disparaît : c'est l'état écrit qui le remplace. */
  .switch{min-height:60px;padding:9px 10px;gap:7px}
  .switch .track{
    position:absolute;inset:0;z-index:0;
    order:0;margin:0;width:auto;height:auto;flex:none;
    border-radius:14px;background:var(--surface);border:1px solid var(--line);
  }
  .switch .track i{display:none}
  .switch input:checked + .track{background:#EEF7F2;border-color:var(--green)}

  .sw-ic{
    display:block;position:relative;z-index:1;
    flex:0 0 20px;width:20px;height:20px;stroke-width:1.9;color:var(--ink-2);
  }
  .switch-txt{position:relative;z-index:1;gap:0}
  .sw-name{font-size:11.5px;font-weight:500;line-height:1.25;color:var(--muted)}
  .switch-txt em{display:none}
  .sw-state{
    display:block;font-size:15px;font-weight:700;line-height:1.25;color:var(--ink);
    overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  }
  .switch input:checked ~ .sw-ic,
  .switch input:checked ~ .switch-txt .sw-name,
  .switch input:checked ~ .switch-txt .sw-state{color:var(--green)}

  /*  Un filet, puis « Inverser le sens du tracé » en lien centré. */
  .card-route{margin-top:14px;padding-top:4px;border-top:1px solid var(--line-2)}
  .card-route .pts-tools{justify-content:center;margin:0}
  #reverse{
    border:0;background:none;padding:12px 8px;
    font-size:14.5px;font-weight:600;color:var(--green);
  }
  #reverse:hover{background:none;color:var(--green-l)}

  /*  PLUS DE LISTE DES ÉTAPES EN MOBILE : elles se gèrent sur la carte, où
      sont leurs repères. La carte « Parcours » ne garde qu'« Inverser le
      sens du tracé », et se retire quand il n'y a rien à inverser — voir
      `renderPoints`.                                                      */
  .card-route .pts,
  .card-route .hint{display:none}
  .card-route[data-reverse="0"]{display:none}
  #reverse svg{width:17px;height:17px}
  .rev-more{display:inline}
}
