/* ============================================================
   DESIGN 3.0 — refonte visuelle et ergonomique
   Chargé en dernier. Trois rôles :
     1. corriger les composants historiques (styles.css / ui.css) pour
        qu'ils suivent les tokens : rayons, graisses, titres, couleurs ;
     2. définir les primitives partagées (boutons, chips, segmented,
        états vides, toast) ;
     3. styler les nouveaux écrans : Aujourd'hui, semaine datée,
        journal de séance, suivi de charge, guide, activités.
   Les tokens vivent dans styles.css (:root) et ui.css (thème clair).
   ============================================================ */

/* ------------------------------------------------------------
   1. Base & typographie
   ------------------------------------------------------------ */
html { -webkit-text-size-adjust: 100%; }
body {
  font-family: var(--font);
  font-size: var(--fs-md);
  color: var(--text);
  background: var(--bg);
  font-feature-settings: "tnum" 1, "ss01" 1;
  -webkit-font-smoothing: antialiased;
}
h1, h2, h3, h4 { font-weight: 600; letter-spacing: -0.01em; color: var(--text); }
strong { font-weight: 600; }
button, input, select, textarea { font-family: inherit; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
button:focus:not(:focus-visible) { outline: none; }
::selection { background: var(--accent-soft); }
/*  LARGEUR DE PAGE — un seul réglage, deux consommateurs.
    `.container` (le contenu) et `.topbar-inner` (l'en-tête collant) doivent
    s'aligner au pixel près : une barre plus étroite que le contenu, et le
    nom de l'athlète ne tombe plus au-dessus du titre de la page. Les deux
    portaient jusqu'ici leur propre nombre, dans deux fichiers différents
    (860 dans ui.css/styles.css, 880 ici) — c'est exactement le genre de
    valeur qui dérive. Elle est maintenant unique.

    POURQUOI ELLE GRANDIT PAR PALIERS, et pas d'un coup :
      · en dessous de 1024 px, rien ne change — la colonne étroite est la
        bonne réponse sur mobile et sur tablette ;
      · au-dessus, la place existe et la laisser vide est du gâchis : sur un
        écran de 1900 px, on affichait 880 px de contenu et 780 px de fond.
    Le plafond de 1680 px n'est pas une coquetterie : au-delà, ce n'est plus
    de la place, c'est une ligne de texte qu'on ne suit plus du regard. Sur
    un écran de 1900 px (colonne de nav déduite) il n'est jamais atteint —
    la page occupe donc TOUTE la largeur disponible. Il ne sert qu'aux
    très grands écrans.

    La largeur seule ne suffit pas : élargir une colonne unique donne des
    cartes de 1600 px avec trois mots dedans. Ce que la place gagnée sert à
    faire est plus bas, section « Densité en grand écran ». */
:root { --page-w: 880px; --page-pad: 16px; }

@media (min-width: 1024px) { :root { --page-w: 1180px; --page-pad: 24px; } }
@media (min-width: 1360px) { :root { --page-w: min(100%, 1680px); --page-pad: 32px; } }

.container { max-width: var(--page-w); padding-left: var(--page-pad); padding-right: var(--page-pad); }
.tab-content { margin-top: 20px; }

.page-head { margin: 4px 0 18px; }
.page-title { font-size: var(--fs-xl); font-weight: 600; margin: 0 0 4px; }
.page-sub { margin: 0; font-size: var(--fs-sm); color: var(--text-2); line-height: 1.5; max-width: 62ch; }
.section-title { font-size: var(--fs-lg); font-weight: 600; margin: 0; }
.section-sub { margin: 2px 0 0; font-size: var(--fs-sm); color: var(--text-2); }

/* Cartes : une seule surface, bordure fine, rayon modéré */
.card,
.timeline-card, .cal-wrapper, .zone-card, .distrib-card, .phase-btn, .phase-detail-card,
.progress-bar-card, .principle-card, .badge-card, .prog-sport-card, .ev-card, .landing-card,
.landing-feat, .swim-tips-card, .danger-tips-card, .prog-hero, .club-hero {
  border-radius: var(--r-lg);
  box-shadow: none;
}
.card { padding: 20px; margin-top: 16px; background: var(--surface); border: 1px solid var(--border); }
.card + .card { margin-top: 16px; }
/*  RELIEF DOUX (07/10/2026) — pour les cartes de PREMIER NIVEAU, celles
    qui découpent une page en blocs. La bordure reste : une zone ne doit
    jamais être délimitée par la seule ombre (en sombre, on ne la voit
    presque pas). Restent à plat, parce que le relief répété fatigue :
      · une carte posée dans une carte ;
      · les pages d'événement et l'administration (listes, tableaux,
        kanban) — leurs conteneurs ont leurs propres classes, à plat. */
.card, .timeline-card, .cal-wrapper, .prog-hero { box-shadow: var(--elev-raised); }
.card .card, #tab-events .card, #tab-admin .card { box-shadow: none; }
.card-title {
  margin: 0 0 12px;
  font-size: var(--fs-lg);
  font-weight: 600;
  color: var(--text);
  letter-spacing: -0.01em;
  text-transform: none;
  display: flex;
  align-items: center;
  gap: 8px;
}
.card-title-spaced { margin-top: 22px; }
.card-title [data-icon] { color: var(--text-3); font-size: 16px; display: inline-flex; }

/* Formulaires */
.form-label { font-size: var(--fs-xs); font-weight: 600; color: var(--text-2); text-transform: none; letter-spacing: 0; }
.form-input, .form-select, .schedule-select, .sdp-note-input, .sdp-perf-input, .coach-comment-input {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  color: var(--text);
  font-size: var(--fs-md);
}
.form-input:focus, .form-select:focus, .schedule-select:focus, .sdp-note-input:focus, .sdp-perf-input:focus, .coach-comment-input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.form-hint { font-size: var(--fs-xs); color: var(--text-3); margin: 4px 0 0; line-height: 1.45; }
.form-hint-lead { margin: -4px 0 14px; }
.form-row-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
@media (max-width: 480px) { .form-row-2 { grid-template-columns: 1fr; } }
.form-select { appearance: none; -webkit-appearance: none; padding-right: 34px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%239aa3b2' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 12px center; }

/* Boutons */
.btn, .btn-ghost, .ev-btn, .strava-btn, .sdp-validate-btn, .btn-profile-save, .btn-profile-reset,
.ev-create-btn, .member-add-btn, .coach-comment-send, .sdp-note-send, .landing-skip, .club-invite-chip {
  font-family: inherit;
  font-weight: 600;
  border-radius: var(--r-md);
  transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease, box-shadow 0.15s ease;
}
/*  BOUTONS (relief doux, 07/10/2026)
      · secondaire (.btn) : posé sur la carte, il s'ENFONCE au clic ;
      · principal (.btn-primary) : le seul aplat de couleur — l'action de
        l'écran (Voir la séance, Voir l'analyse, Enregistrer). Il était à
        l'encre : noir en clair, blanc en sombre, donc sans hiérarchie
        face aux titres ;
      · petit principal (.btn-sm.btn-primary) : il valide un bandeau ou
        une barre d'outils, pas l'écran — il reste à l'encre, pour qu'un
        écran ne montre jamais deux boutons colorés ;
      · fantôme, danger : à plat, ils ne doivent pas attirer l'œil. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 10px 16px; font-size: var(--fs-sm); line-height: 1.2;
  border: 1px solid var(--border); background: var(--surface); color: var(--text); cursor: pointer;
  min-height: 40px; box-shadow: var(--elev-raised-sm);
}
.btn:hover { background: var(--raised); border-color: var(--border-strong); }
.btn:active { background: var(--sunk); box-shadow: var(--elev-pressed); }
.btn:disabled { opacity: 0.4; cursor: not-allowed; box-shadow: none; }
.btn-primary {
  background: var(--accent-strong); color: var(--on-accent); border-color: transparent;
  box-shadow: 0 4px 12px color-mix(in srgb, var(--accent-strong) 35%, transparent);
}
.btn-primary:hover { background: color-mix(in srgb, var(--accent-strong) 90%, #000); border-color: transparent; }
.btn-primary:active { background: color-mix(in srgb, var(--accent-strong) 80%, #000); box-shadow: none; }
.btn-sm.btn-primary { background: var(--text); color: var(--bg); border-color: var(--text); box-shadow: none; }
.btn-sm.btn-primary:hover, .btn-sm.btn-primary:active { background: color-mix(in srgb, var(--text) 88%, var(--bg)); border-color: var(--text); }
.btn-success { background: var(--success); color: #fff; border-color: var(--success); }
.btn-success:hover, .btn-success:active { background: color-mix(in srgb, var(--success) 88%, #000); border-color: var(--success); }
.btn-danger { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 40%, transparent); background: transparent; box-shadow: none; }
.btn-danger:hover, .btn-danger:active { background: var(--danger-soft); border-color: color-mix(in srgb, var(--danger) 40%, transparent); box-shadow: none; }
.btn-ghost { background: transparent; border: 1px solid var(--border); color: var(--text-2); box-shadow: none; }
.btn-ghost:hover { color: var(--text); border-color: var(--border-strong); background: var(--surface-2); }
.btn-ghost:active { background: var(--sunk); box-shadow: var(--elev-pressed); }
.btn-sm { padding: 6px 10px; min-height: 32px; font-size: var(--fs-xs); border-radius: var(--r-sm); }
/* Au doigt, une cible de 44 px (les petits boutons de barre gardent 32). */
@media (pointer: coarse) { .btn:not(.btn-sm) { min-height: 44px; } }
.btn-block { width: 100%; }
.btn [data-icon], .btn svg { font-size: 15px; display: inline-flex; }
.btn-profile-save { background: var(--text); color: var(--bg); border: 1px solid var(--text); box-shadow: none; }
.btn-profile-save:hover { background: color-mix(in srgb, var(--text) 88%, var(--bg)); color: var(--bg); box-shadow: none; }
.btn-profile-reset { border-style: solid; }
.link-btn {
  display: inline; background: none; border: none; padding: 0; color: var(--accent); font: inherit;
  font-size: inherit; font-weight: 600; cursor: pointer; text-decoration: underline; text-underline-offset: 3px;
}
.link-btn:hover { color: var(--text); }
.ev-btn { min-height: 38px; }
.ev-btn-in { background: var(--success-soft); border-color: color-mix(in srgb, var(--success) 40%, transparent); color: var(--success); }
.strava-btn { border-radius: var(--r-md); }

/* Chips / badges */
.chip {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: var(--fs-xs); font-weight: 600; line-height: 1;
  padding: 5px 9px; border-radius: 999px;
  border: 1px solid var(--border); background: var(--surface-2); color: var(--text-2);
  white-space: nowrap;
}
.chip [data-icon], .chip svg { font-size: 13px; }
.chip-success { color: var(--success); background: var(--success-soft); border-color: transparent; }
.chip-warning { color: var(--warning); background: var(--warning-soft); border-color: transparent; }
.chip-danger { color: var(--danger); background: var(--danger-soft); border-color: transparent; }
.chip-accent { color: var(--accent); background: var(--accent-soft); border-color: transparent; }
.chip-sport { color: var(--sport); background: color-mix(in srgb, var(--sport) 14%, transparent); border-color: transparent; }
.chip-dot::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }

/* Segmented control */
/* Une piste creusée, une pastille en relief pour le choix en cours. */
.segmented { display: inline-flex; gap: 2px; padding: 4px; background: var(--sunk); border: 0; border-radius: 999px; box-shadow: var(--elev-pressed); margin-bottom: 18px; max-width: 100%; overflow-x: auto; }
.segmented-btn {
  background: transparent; border: none; color: var(--text-2); font-family: inherit;
  font-size: var(--fs-sm); font-weight: 600; padding: 7px 14px; border-radius: 999px; cursor: pointer; white-space: nowrap;
  transition: background 0.2s ease, box-shadow 0.2s ease, color 0.15s ease;
}
.segmented-btn.active { background: var(--raised); color: var(--text); box-shadow: var(--elev-raised-sm); }
.segmented-btn:hover:not(.active) { color: var(--text); }

/* États vides & notes */
.empty-state {
  border: 1px dashed var(--border-strong); border-radius: var(--r-lg); padding: 28px 20px; text-align: center;
  color: var(--text-2); font-size: var(--fs-sm); line-height: 1.5;
}
.empty-state [data-icon], .empty-state svg { font-size: 26px; color: var(--text-3); display: block; margin: 0 auto 10px; }
.empty-state strong { display: block; color: var(--text); font-size: var(--fs-md); margin-bottom: 4px; }
.guide-note { font-size: var(--fs-sm); color: var(--text-2); margin: 0 0 14px; line-height: 1.5; }
.guide-note strong { color: var(--text); }

/* Toast */
#profile-toast {
  position: fixed; left: 50%; bottom: calc(76px + env(safe-area-inset-bottom)); transform: translate(-50%, 16px);
  background: var(--text); color: var(--bg); padding: 11px 16px; border-radius: var(--r-md);
  font-weight: 600; font-size: var(--fs-sm); box-shadow: var(--shadow-md); z-index: 1000; opacity: 0;
  transition: opacity 0.25s ease, transform 0.25s ease; max-width: min(92vw, 460px); text-align: center; line-height: 1.4;
}
#profile-toast.show { opacity: 1; transform: translate(-50%, 0); }
@media (min-width: 769px) { #profile-toast { bottom: 28px; } }

/* ------------------------------------------------------------
   2. Topbar, onglets, navigation basse
   ------------------------------------------------------------ */
.topbar { background: color-mix(in srgb, var(--bg) 90%, transparent); }
.topbar-inner { max-width: var(--page-w); padding: 10px var(--page-pad); }
.topbar-profile { border-radius: var(--r-md); }
.topbar-avatar { background: var(--surface-2); }
.topbar-name { font-weight: 600; font-size: var(--fs-md); }
.topbar-sub { font-size: var(--fs-xs); font-weight: 500; }
/*  LOGO TRIPULSE — la marque (tuile) est une image ; le mot « TRIPULSE »
    en est une aussi, en deux versions : « TRI » bleu nuit sur fond clair,
    blanc sur fond sombre. Il est posé en fond plutôt qu'en <img> pour
    suivre le thème sans script (icons/logo-wordmark-*.png, ratio 4,77). */
.brand-mark { width: 28px; height: 28px; flex: none; display: block; }
.brand-word {
  display: inline-block; flex: none;
  height: 17px; aspect-ratio: 457 / 96;
  background: url("/icons/logo-wordmark-dark.png") left center / contain no-repeat;
}
[data-theme="light"] .brand-word { background-image: url("/icons/logo-wordmark-light.png"); }
.topbar-btn { border-radius: var(--r-md); background: transparent; }
.topbar-btn:hover { background: var(--surface-2); }

/* `.tab-btn` ne vit plus que dans la colonne de navigation : les règles
   d'onglet horizontal héritées de styles.css (rayon en haut, soulignement
   du bas) sont annulées ici — cf. la section « colonne de navigation ». */

/* Fond = la surface des cartes (et non la page) : le libellé actif, en
   accent, y garde 4,5:1 dans les deux thèmes. */
.bottom-nav { background: color-mix(in srgb, var(--surface) 94%, transparent); align-items: flex-end; }
.bottom-nav button { color: var(--text-3); gap: 3px; }
.bottom-nav button.active { color: var(--accent); }
.bottom-nav .bn-label { font-size: 10px; font-weight: 600; letter-spacing: 0; }
/* « Enregistrer » : un disque plein qui dépasse de la barre. L'anneau à la
   couleur de la barre le détache du contenu qui défile dessous. */
.bottom-nav .bn-rec { color: var(--text); overflow: visible; }
.bn-rec-dot {
  width: 52px; height: 52px; margin-top: -26px; border-radius: 50%;
  display: grid; place-items: center; font-size: 22px;
  background: var(--accent-strong); color: var(--on-accent);
  box-shadow: 0 6px 14px color-mix(in srgb, var(--accent-strong) 45%, transparent), 0 0 0 5px var(--surface);
  transition: transform 0.15s ease;
}
.bn-rec:active .bn-rec-dot { transform: scale(0.94); }
@media (prefers-reduced-motion: reduce) { .bn-rec-dot { transition: none; } }
.bn-sheet { border-radius: var(--r-lg); box-shadow: var(--shadow-md); }
.bn-sheet button { font-weight: 500; }

/* ------------------------------------------------------------
   3. Aujourd'hui (tableau de bord)
   ------------------------------------------------------------ */
.today-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; margin: 4px 0 18px; flex-wrap: wrap; }
.today-greet { font-size: var(--fs-2xl); font-weight: 600; letter-spacing: -0.02em; margin: 0; line-height: 1.1; }
.today-date { font-size: var(--fs-sm); color: var(--text-2); margin: 4px 0 0; text-transform: capitalize; }
.today-countdown { text-align: right; }
/* En-tête : compte à rebours et « Personnaliser » empilés à droite. */
.today-head-side { display: flex; flex-direction: column; align-items: flex-end; gap: 8px; }
.today-custom-btn { color: var(--text-2); }
@media (max-width: 640px) { .today-head-side { flex-direction: row; align-items: center; justify-content: space-between; width: 100%; } }

/* Accueil personnalisable (js/today.js, TodayHome). */
.home-edit { border-color: var(--brand-green); }
.home-edit-list { list-style: none; margin: 12px 0 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.home-edit-row {
  display: grid; grid-template-columns: auto auto 1fr auto; align-items: center; gap: 8px;
  padding: 6px 8px; border-radius: var(--r-md); background: var(--surface-2); position: relative;
}
/* Poignée de glisser-déposer : seule zone qui capte le doigt (touch-action),
   le reste de la ligne laisse défiler la page. */
.home-grip {
  display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 36px;
  border: 0; border-radius: var(--r-sm); background: transparent; color: var(--text-3); cursor: grab;
  font-size: 18px; touch-action: none; user-select: none; -webkit-user-select: none;
}
.home-grip:hover { color: var(--text); background: var(--surface-3); }
.home-grip:focus-visible { outline: 2px solid var(--brand-green); outline-offset: 2px; }
.home-edit-list.is-sorting, .home-edit-list.is-sorting * { cursor: grabbing; user-select: none; -webkit-user-select: none; }
.home-edit-row.is-dragging {
  z-index: 2; background: var(--surface); box-shadow: var(--shadow-md);
  outline: 2px solid color-mix(in srgb, var(--brand-green) 60%, transparent);
}
.home-edit-row.is-off .home-edit-lab { color: var(--text-3); text-decoration: line-through; text-decoration-color: var(--border-strong); }
.home-edit-lab { font-size: var(--fs-sm); font-weight: 600; min-width: 0; }
.home-edit-lab small { display: block; font-weight: 400; font-size: var(--fs-xs); color: var(--text-3); }
.home-eye, .home-move button {
  display: inline-flex; align-items: center; justify-content: center; width: 36px; height: 36px;
  border-radius: var(--r-sm); border: 1px solid var(--border); background: var(--surface); color: var(--text); cursor: pointer; font-size: 16px;
}
.home-eye[aria-pressed="true"] { color: var(--brand-green); border-color: color-mix(in srgb, var(--brand-green) 45%, var(--border)); }
.home-eye[aria-pressed="false"] { color: var(--text-3); }
.home-move { display: inline-flex; gap: 4px; }
.home-move button:disabled { opacity: 0.35; cursor: default; }
.home-eye:focus-visible, .home-move button:focus-visible { outline: 2px solid var(--brand-green); outline-offset: 2px; }
.home-edit-foot { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px; margin-top: 14px; }
.home-start { display: inline-flex; align-items: center; gap: 8px; font-size: var(--fs-sm); color: var(--text-2); }
.home-start .form-select { width: auto; }

.home-shortcuts { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 8px; margin-top: 10px; }
.home-shortcut {
  display: flex; align-items: center; gap: 8px; min-height: 44px; padding: 8px 12px; border-radius: var(--r-md);
  border: 1px solid var(--border); background: var(--surface-2); color: var(--text); font: inherit; font-size: var(--fs-sm); font-weight: 600; cursor: pointer; text-align: left;
}
.home-shortcut:hover { border-color: var(--border-strong); }
.home-shortcut svg { color: var(--brand-green); flex: none; }
.today-last .next-row { margin-top: 6px; }
.today-countdown-num { font-size: var(--fs-hero); font-weight: 700; letter-spacing: -0.03em; line-height: 1; font-variant-numeric: tabular-nums; }
.today-countdown-lab { font-size: var(--fs-xs); color: var(--text-2); margin-top: 3px; }

/* minmax(0, …) et non 1fr : une piste 1fr ne descend jamais sous la largeur
   minimale de son contenu. Un titre en nowrap/ellipse (.next-title) l'élargissait
   au-delà de l'écran et toute la page débordait à droite sur mobile. */
.today-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; }
@media (min-width: 720px) { .today-grid { grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); } .today-span, .today-fill { grid-column: 1 / -1; } }

.today-session { padding: 0; overflow: hidden; margin-top: 0; }
.today-session-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 14px 20px; border-bottom: 1px solid var(--border); }
.today-kicker { font-size: var(--fs-xs); font-weight: 600; color: var(--text-2); text-transform: uppercase; letter-spacing: 0.06em; }
.today-session-body { padding: 18px 20px; display: flex; gap: 16px; align-items: flex-start; }
.sport-glyph {
  width: 48px; height: 48px; border-radius: 12px; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center; font-size: 22px;
  color: var(--sport, var(--text-2)); background: color-mix(in srgb, var(--sport, var(--text-3)) 14%, transparent);
}
.sport-glyph-sm { width: 36px; height: 36px; border-radius: 10px; font-size: 17px; }
.today-session-title { font-size: var(--fs-xl); font-weight: 600; letter-spacing: -0.01em; line-height: 1.2; }
.today-session-meta { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.today-session-desc { margin: 12px 0 0; font-size: var(--fs-sm); color: var(--text-2); line-height: 1.55; }
.today-session-actions { display: flex; gap: 8px; flex-wrap: wrap; padding: 0 20px 18px; }
.today-rest { color: var(--text-2); }

.today-week { margin-top: 0; }
.today-week-head { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; margin-bottom: 12px; }
.today-week-head .card-title { margin: 0; }
.today-week-stat { font-size: var(--fs-sm); color: var(--text-2); }
.today-week-stat strong { color: var(--text); }
.week-dots { display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px; }
.week-dot {
  display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 8px 2px;
  border-radius: var(--r-md); border: 1px solid transparent; background: transparent; cursor: pointer; color: var(--text-2);
}
.week-dot:hover { background: var(--surface-2); }
.week-dot.is-today { border-color: var(--border-strong); background: var(--surface-2); color: var(--text); }
.week-dot-dow { font-size: 11px; font-weight: 600; text-transform: capitalize; }
.week-dot-mark {
  width: 26px; height: 26px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center;
  font-size: 13px; color: var(--text-3); background: var(--surface-2); border: 1px solid var(--border);
}
.week-dot.done .week-dot-mark { background: var(--success); color: #fff; border-color: var(--success); }
.week-dot.planned .week-dot-mark { color: var(--sport); border-color: color-mix(in srgb, var(--sport) 45%, transparent); background: color-mix(in srgb, var(--sport) 12%, transparent); }
.week-dot.missed .week-dot-mark { color: var(--warning); border-color: color-mix(in srgb, var(--warning) 45%, transparent); background: var(--warning-soft); }
.week-dot.skipped .week-dot-mark { color: var(--text-3); border-style: dashed; }
.week-dot.rest .week-dot-mark { background: transparent; border-color: transparent; }
/* Jour à plusieurs séances : la pastille s'allonge en gélule, une icône
   par séance (tenue dans la colonne, même sur téléphone). */
.week-dot.is-multi .week-dot-mark { width: auto; min-width: 26px; max-width: 100%; padding: 0 5px; gap: 2px; border-radius: 13px; font-size: 11px; }
.week-progress-line { margin-top: 12px; height: 6px; border-radius: 3px; background: var(--surface-3); overflow: hidden; }
.week-progress-line > div { height: 100%; background: var(--success); border-radius: 3px; }

.today-next { margin-top: 0; }
.next-list { display: flex; flex-direction: column; }
.next-row { display: flex; align-items: center; gap: 12px; padding: 10px 0; border-top: 1px solid var(--border); cursor: pointer; }
.next-row:first-child { border-top: none; padding-top: 0; }
.next-row:last-child { padding-bottom: 0; }
.next-date { width: 44px; flex-shrink: 0; text-align: center; line-height: 1.1; }
.next-date-dow { display: block; font-size: 11px; color: var(--text-3); font-weight: 600; text-transform: capitalize; }
.next-date-dom { display: block; font-size: var(--fs-lg); font-weight: 600; }
.next-main { flex: 1; min-width: 0; }
.next-title { font-size: var(--fs-md); font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.next-meta { font-size: var(--fs-xs); color: var(--text-2); margin-top: 1px; }
.next-arrow { color: var(--text-3); font-size: 16px; }

.today-load { margin-top: 0; }
/* Charge : trois chiffres côte à côte, sans jauge colorée (le ratio
   aigu:chronique ne prédit pas la blessure, cf. js/today.js). */
.load-trio { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; margin-bottom: 12px; }
.load-trio-val { font-size: var(--fs-xl); font-weight: 600; letter-spacing: -0.01em; line-height: 1.1; white-space: nowrap; }
.load-trio-val small { font-size: var(--fs-xs); font-weight: 500; color: var(--text-2); }
.load-trio-lab { font-size: var(--fs-xs); color: var(--text-3); margin-top: 3px; line-height: 1.3; }
.today-load .advice-line { margin-bottom: 10px; }
.load-hint { font-size: var(--fs-sm); color: var(--text-2); line-height: 1.5; margin: 10px 0 0; }

/* Flamme de régularité (js/flame.js). La teinte de la carte suit l'état :
   allumée (orange), protégée par un arrêt déclaré (bleu), éteinte (gris).
   `--flame` est la seule variable à changer. */
.today-flame { --flame: var(--text-3); margin-top: 0; }
.today-flame.is-lit { --flame: var(--sport-run); }
.today-flame.is-safe { --flame: var(--accent); }
.flame-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; }
.flame-main { display: flex; align-items: center; gap: 12px; }
.flame-glyph {
  flex: none; width: 46px; height: 46px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center; font-size: 24px;
  color: var(--flame); background: color-mix(in srgb, var(--flame) 15%, transparent);
}
.today-flame.is-lit .flame-glyph svg { fill: color-mix(in srgb, var(--flame) 30%, transparent); animation: flame-flicker 2.4s ease-in-out infinite; transform-origin: 50% 90%; }
.flame-count { flex: 1; min-width: 0; display: flex; align-items: baseline; gap: 8px; }
.flame-num { font-size: var(--fs-2xl, 30px); font-weight: 700; letter-spacing: -0.02em; line-height: 1; color: var(--text); }
.flame-lab { font-size: var(--fs-sm); color: var(--text-2); }
/* Les dernières semaines : pleine = tenue, bouclier bleu = protégée,
   creuse = non tenue, anneau = en cours. */
.flame-trail { display: flex; gap: 6px; margin-top: 14px; }
.flame-dot { flex: 1; max-width: 34px; height: 8px; border-radius: 4px; background: var(--surface-3); }
.flame-dot.is-held { background: var(--sport-run); }
.flame-dot.is-safe { background: color-mix(in srgb, var(--accent) 55%, transparent); }
.flame-dot.is-lost { background: transparent; box-shadow: inset 0 0 0 1.5px var(--border-strong); }
.flame-dot.is-now { box-shadow: 0 0 0 2px var(--surface), 0 0 0 3.5px var(--flame); }
.flame-week { display: flex; align-items: center; gap: 10px; margin-top: 14px; font-size: var(--fs-xs); color: var(--text-2); white-space: nowrap; }
.flame-bar { flex: 1; height: 6px; border-radius: 3px; background: var(--surface-3); overflow: hidden; }
.flame-bar > i { display: block; height: 100%; border-radius: 3px; background: var(--sport-run); }
.today-flame .load-hint svg { vertical-align: -2px; color: var(--accent); }
.flame-rule { font-size: var(--fs-xs); color: var(--text-3); line-height: 1.45; margin: 6px 0 0; }
@keyframes flame-flicker { 0%, 100% { transform: scale(1) rotate(0); } 35% { transform: scale(1.07, 1.1) rotate(-2deg); } 70% { transform: scale(.97, 1.03) rotate(2deg); } }
@media (prefers-reduced-motion: reduce) { .today-flame.is-lit .flame-glyph svg { animation: none; } }
/* Garde-fou (js/safety.js) : ligne d'état de la carte de charge et
   encadré « avant → après » de la page de séance. */
.guard-line { display: flex; align-items: flex-start; gap: 8px; font-size: var(--fs-sm); color: var(--text-2); line-height: 1.5; padding: 10px 12px; border-radius: var(--r-md); background: var(--surface-2); }
.guard-line svg { flex-shrink: 0; margin-top: 2px; color: var(--brand-green); }
.guard-line strong { color: var(--text); }
.guard-off svg { color: var(--text-3); }
.advice-line.guard-callout { flex-wrap: wrap; align-items: flex-start; margin: 0 0 14px; }
.guard-callout .advice-icon { margin-top: 3px; }
.guard-callout-body { flex: 1; min-width: 220px; line-height: 1.5; }
.guard-callout .adapt-actions { flex-basis: 100%; justify-content: flex-end; }

.today-coach { margin-top: 0; }
.today-banner {
  display: flex; align-items: center; gap: 12px; padding: 14px 16px; border-radius: var(--r-lg);
  background: var(--warning-soft); border: 1px solid color-mix(in srgb, var(--warning) 35%, transparent);
  font-size: var(--fs-sm); line-height: 1.45; color: var(--text); margin-bottom: 16px;
}
.today-banner [data-icon], .today-banner svg { color: var(--warning); font-size: 20px; flex-shrink: 0; }
.today-banner .btn { margin-left: auto; flex-shrink: 0; }
@media (max-width: 520px) { .today-banner { flex-wrap: wrap; } .today-banner .btn { margin-left: 0; width: 100%; } }

/* ------------------------------------------------------------
   4. Plan : semaine datée
   ------------------------------------------------------------ */
.timeline-card { padding: 18px 20px; background: var(--surface); border: 1px solid var(--border); margin-bottom: 16px; }
.timeline-header { margin-bottom: 14px; align-items: flex-start; }
.vol-badge { background: var(--surface-2); color: var(--text-2); border: 1px solid var(--border); border-radius: 999px; font-weight: 600; font-size: var(--fs-xs); padding: 5px 10px; }
.timeline-track { gap: 6px; padding-bottom: 6px; scroll-snap-type: x proximity; }
.tl-week {
  flex: 0 0 auto; min-width: 74px; padding: 8px 8px 10px; position: relative; overflow: hidden;
  background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--r-md); cursor: pointer;
  display: flex; flex-direction: column; align-items: flex-start; gap: 2px; color: var(--text); text-align: left;
  scroll-snap-align: start; transition: border-color 0.15s ease, background 0.15s ease;
}
.tl-week:hover { border-color: var(--border-strong); }
.tl-week.active { border-color: var(--text); background: var(--surface-3); }
.tl-week.is-current::before { content: ""; position: absolute; top: 8px; right: 8px; width: 6px; height: 6px; border-radius: 50%; background: var(--accent); }
.tl-num { font-size: var(--fs-sm); font-weight: 600; }
.tl-dates { font-size: 10.5px; color: var(--text-3); white-space: nowrap; }
.tl-tag { font-size: 10px; font-weight: 600; color: var(--text-2); }
.tl-tag.rec { color: var(--zone-1); }
.tl-tag.race { color: var(--danger); }
.tl-bar { position: absolute; left: 0; right: 0; bottom: 0; height: 3px; background: color-mix(in srgb, var(--phase) 22%, transparent); }
.tl-bar > i { display: block; height: 100%; background: var(--phase); }
.tl-week.active .tl-bar { background: color-mix(in srgb, var(--phase) 30%, transparent); }
.timeline-footer { border-top: none; padding-top: 0; margin-top: 8px; font-size: var(--fs-xs); color: var(--text-3); }
.weekly-progress-wrapper { margin-top: 6px; }
.weekly-progress-bar-bg { height: 6px; border: none; background: var(--surface-3); border-radius: 3px; }
.weekly-progress-bar-fill { background: var(--success); }
.weekly-progress-text { color: var(--text-2); font-weight: 600; font-size: var(--fs-xs); }
.week-focus-banner { background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--r-md); align-items: center; }
.week-focus-icon { color: var(--text-2); font-size: 18px; display: inline-flex; }
.week-focus-text { color: var(--text-2); font-size: var(--fs-sm); }

.plan-banner-missing-date { background: var(--warning-soft); border-color: color-mix(in srgb, var(--warning) 35%, transparent); border-radius: var(--r-md); font-weight: 500; }
.plan-banner-missing-date strong { color: var(--warning); }
.plan-banner-missing-date [data-icon], .plan-banner-missing-date svg { color: var(--warning); font-size: 18px; }

.cal-wrapper { margin-top: 0; border-radius: var(--r-lg); background: var(--surface); border: 1px solid var(--border); }
.cal-header { background: transparent; padding: 14px 18px 10px; border-bottom: 1px solid var(--border); flex-direction: row; align-items: baseline; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.cal-header-title { font-size: var(--fs-lg); font-weight: 600; }
.cal-header-sub { font-size: var(--fs-xs); color: var(--text-3); }

.sess-list { display: flex; flex-direction: column; }
.sess-row {
  display: grid; grid-template-columns: 46px 40px 1fr auto auto; align-items: center; gap: 12px;
  padding: 11px 18px; border-bottom: 1px solid var(--border); cursor: pointer; position: relative;
  transition: background 0.12s ease;
}
.sess-row:hover { background: var(--surface-2); }
.sess-row.selected { background: var(--surface-2); }
.sess-row.selected::before { content: ""; position: absolute; left: 0; top: 8px; bottom: 8px; width: 3px; border-radius: 0 2px 2px 0; background: var(--text); }
.sess-row.rest { opacity: 0.55; }
.sess-row.rest:hover { opacity: 0.8; }
.sess-date { text-align: center; line-height: 1.05; }
.sess-dow { display: block; font-size: 10.5px; font-weight: 600; color: var(--text-3); text-transform: capitalize; }
.sess-dom { display: block; font-size: var(--fs-lg); font-weight: 600; }
.sess-row.is-today .sess-dom { color: var(--accent); }
.sess-row.is-today .sess-dow { color: var(--accent); }
.sess-icon {
  width: 36px; height: 36px; border-radius: 10px; display: inline-flex; align-items: center; justify-content: center; font-size: 17px;
  color: var(--sport, var(--text-3)); background: color-mix(in srgb, var(--sport, var(--text-3)) 14%, transparent);
}
.sess-row.rest .sess-icon { background: transparent; border: 1px dashed var(--border-strong); }
.sess-main { min-width: 0; }
.sess-title { font-size: var(--fs-md); font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sess-meta { font-size: var(--fs-xs); color: var(--text-2); margin-top: 2px; }
.sess-status { display: inline-flex; align-items: center; gap: 6px; font-size: var(--fs-xs); font-weight: 600; color: var(--text-3); white-space: nowrap; }
.sess-status svg { font-size: 18px; }
.sess-row.done .sess-status { color: var(--success); }
.sess-row.done .sess-title { color: var(--text-2); }
.sess-row.missed .sess-status { color: var(--warning); }
.sess-row.skipped .sess-status { color: var(--text-3); }
.sess-row.is-today .sess-status .chip { margin-right: 2px; }
@media (max-width: 520px) {
  .sess-row { grid-template-columns: 40px 34px 1fr auto auto; gap: 10px; padding: 10px 14px; }
  .sess-wx-min { display: none; }
  .sess-status .sess-status-txt { display: none; }
}
/* Plusieurs séances le même jour (cf. PlanDay, app.js) : la séance
   supplémentaire se range sous la principale, sans seconde date — un « + »
   dans la colonne de date, et pas de filet entre les deux lignes. */
.sess-row:has(+ .sess-row.is-extra) { border-bottom-color: transparent; }
.sess-row.is-extra { padding-top: 4px; }
.sess-extra-mark {
  display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px;
  border-radius: 50%; border: 1px dashed var(--border-strong); color: var(--text-3); font-size: 13px; font-weight: 700; line-height: 1;
}
.sdp-add-more { margin-top: 14px; padding-top: 12px; border-top: 1px dashed var(--border); }

/* Page de détail de séance : remplace la liste de la semaine, avec retour */
#tab-week.session-open .timeline-card { display: none; }
.sess-page-bar { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 10px 12px; border-bottom: 1px solid var(--border); background: var(--surface); border-radius: var(--r-lg) var(--r-lg) 0 0; }
.sess-back { display: inline-flex; align-items: center; gap: 6px; border: 0; background: transparent; color: var(--text); font: inherit; font-size: var(--fs-sm); font-weight: 600; padding: 8px 10px; margin: -4px 0 -4px -4px; border-radius: var(--r-md); cursor: pointer; }
.sess-back:hover { background: var(--surface-2); }
.sess-back svg { font-size: 16px; }
.sess-page-ctx { font-size: var(--fs-xs); color: var(--text-3); font-weight: 500; white-space: nowrap; }
.session-open .session-detail-panel { animation: sdp-in .18s ease-out; }
@keyframes sdp-in { from { opacity: 0; transform: translateX(12px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .session-open .session-detail-panel { animation: none; } }

/* Panneau de détail de séance */
.session-detail-panel { padding: 20px 18px 22px; animation: none; }
.sdp-header { margin-bottom: 14px; }
.sdp-sport-chip { border-radius: 12px; font-size: 20px; width: 44px; height: 44px; }
.sdp-title { font-size: var(--fs-xl); font-weight: 600; letter-spacing: -0.01em; }
.sdp-day-label { font-size: var(--fs-sm); color: var(--text-2); font-weight: 500; text-transform: none; }
.sdp-day-label::first-letter { text-transform: uppercase; }
.sdp-badge { border-radius: 999px; background: var(--surface-2); font-weight: 600; font-size: var(--fs-xs); padding: 5px 10px; color: var(--text-2); }
.sdp-badge svg { font-size: 13px; }
.sdp-divider { margin: 14px 0; }
.sdp-body { background: var(--surface-2); border-radius: var(--r-md); border-left-width: 3px; }
.sdp-steps { gap: 8px; }
.sdp-step { background: var(--surface-2); border-radius: var(--r-md); padding: 12px 14px; }
.sdp-step-rail { width: 3px; }
.sdp-step-name { display: inline-flex; align-items: center; gap: 7px; font-weight: 600; }
.sdp-step-name svg { color: var(--text-3); font-size: 15px; }
.sdp-step-meta { font-weight: 500; }
.sdp-tips { background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--r-md); padding: 0; margin-top: 8px; }
.sdp-tips summary { list-style: none; cursor: pointer; display: flex; align-items: center; gap: 8px; padding: 12px 14px; font-size: var(--fs-sm); font-weight: 600; color: var(--text); }
.sdp-tips summary::-webkit-details-marker { display: none; }
.sdp-tips summary svg { color: var(--text-3); }
.sdp-tips summary .sdp-tips-chev { margin-left: auto; transition: transform 0.15s ease; }
.sdp-tips[open] summary .sdp-tips-chev { transform: rotate(180deg); }
.sdp-tips-list { padding: 0 14px 12px 32px; }
.sdp-tips-list li { color: var(--text-2); }
.sdp-coach-note { background: var(--accent-soft); border-color: color-mix(in srgb, var(--accent) 30%, transparent); border-radius: var(--r-md); }
.sdp-coach-note-head { color: var(--accent); font-weight: 600; text-transform: none; letter-spacing: 0; }
.sdp-rest-card { border-radius: var(--r-md); background: var(--surface-2); border: 1px solid var(--border); }
.sdp-rest-icon { color: var(--text-3); font-size: 26px; display: inline-flex; }
.sdp-rest-title { font-weight: 600; font-size: var(--fs-md); margin-bottom: 4px; }

/* Journal de séance */
.log { margin-top: 16px; border: 1px solid var(--border); border-radius: var(--r-lg); background: var(--surface-2); padding: 16px; }
.log-title { font-size: var(--fs-sm); font-weight: 600; color: var(--text); margin: 0 0 12px; display: flex; align-items: center; gap: 8px; }
.log-title svg { color: var(--text-3); }
.log-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.log-actions .btn { flex: 1 1 160px; }
.log-skip-reasons { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; }
.log-skip-reasons .chip { cursor: pointer; }
.log-skip-reasons .chip:hover { border-color: var(--border-strong); color: var(--text); }
.log-state { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; margin-bottom: 14px; }
.log-state-txt { display: inline-flex; align-items: center; gap: 8px; font-size: var(--fs-sm); font-weight: 600; }
.log-state-txt svg { font-size: 18px; }
.log-state.done .log-state-txt { color: var(--success); }
.log-state.skipped .log-state-txt { color: var(--text-2); }
.log-field { margin-top: 14px; }
.log-label { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; font-size: var(--fs-xs); font-weight: 600; color: var(--text-2); margin-bottom: 8px; }
.log-label span:last-child { color: var(--text-3); font-weight: 500; }
.rpe-scale { display: grid; grid-template-columns: repeat(10, 1fr); gap: 4px; }
.rpe-btn {
  height: 36px; border-radius: var(--r-sm); border: 1px solid var(--border); background: var(--surface); color: var(--text-2);
  font-size: var(--fs-sm); font-weight: 600; font-family: inherit; cursor: pointer; transition: all 0.12s ease;
}
.rpe-btn:hover { border-color: var(--border-strong); color: var(--text); }
.rpe-btn.active { color: #fff; border-color: transparent; background: var(--rpe); }
.rpe-legend { display: flex; justify-content: space-between; font-size: 10.5px; color: var(--text-3); margin-top: 5px; }
.perf-row { display: grid; grid-template-columns: 1fr 1fr auto; gap: 8px; align-items: end; }
.perf-field { display: flex; flex-direction: column; gap: 4px; }
.perf-field label { font-size: 10.5px; color: var(--text-3); font-weight: 600; }
.perf-input { width: 100%; padding: 9px 10px; }
.perf-result { margin-top: 8px; font-size: var(--fs-sm); color: var(--text-2); display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.perf-result strong { color: var(--text); font-size: var(--fs-md); }
.perf-source { font-size: 10.5px; color: var(--text-3); }
@media (max-width: 480px) { .perf-row { grid-template-columns: 1fr 1fr; } .perf-row .btn { grid-column: 1 / -1; } }
.log-load { display: flex; align-items: center; gap: 10px; margin-top: 14px; padding: 10px 12px; border-radius: var(--r-md); background: var(--surface); border: 1px solid var(--border); font-size: var(--fs-sm); color: var(--text-2); }
.log-load strong { color: var(--text); }
.log-load svg { color: var(--text-3); }
.log-note-row { display: flex; gap: 8px; }
.log-note-row .form-input { flex: 1; }
.log-foot { margin-top: 14px; display: flex; justify-content: flex-end; }

/* ------------------------------------------------------------
   5. Progression
   ------------------------------------------------------------ */
.prog-hero { background: var(--surface); border: 1px solid var(--border); padding: 20px; gap: 20px; }
[data-theme="light"] .prog-hero { background: var(--surface); }
.prog-ring-fill { stroke: var(--success); filter: none; }
.prog-ring-bg { stroke: var(--surface-3); }
.prog-ring-pct { color: var(--text); font-weight: 600; font-size: 26px; }
.prog-hero-title { font-size: var(--fs-lg); font-weight: 600; }
.prog-hero-text { color: var(--text-2); }
.prog-stat { background: var(--surface-2); border-radius: var(--r-md); text-align: left; padding: 12px 14px; }
.prog-stat-val { font-weight: 600; font-size: 22px; letter-spacing: -0.01em; }
.prog-stat-unit { font-weight: 500; }
.prog-stat-lab { text-transform: none; letter-spacing: 0; font-size: var(--fs-xs); color: var(--text-3); margin-top: 3px; }
.level-chip { border-radius: 999px; background: var(--surface-2); border: 1px solid var(--border); color: var(--text); font-weight: 600; }
.level-bar-bg { background: var(--surface-3); border: none; height: 6px; }
.level-bar-fill { background: var(--accent); }
.prog-sport-card { background: var(--surface); }
.prog-sport-count { font-weight: 600; }
.prog-sport-icon { display: inline-flex; font-size: 20px; }
.badge-group-title { text-transform: none; letter-spacing: 0; font-size: var(--fs-md); font-weight: 600; color: var(--text); }
.badge-card { background: var(--surface); }
.badge-card.badge-earned { background: var(--surface); }
.badge-card.badge-earned:hover { transform: none; }
.badge-icon { background: var(--surface-2); border-radius: 10px; }
.badge-name { font-weight: 600; }
.badge-prog-bar { background: var(--surface-3); border: none; height: 5px; }
.advice-line { background: var(--surface-2); border-radius: var(--r-md); border-left-width: 3px; align-items: center; }
.advice-icon { display: inline-flex; color: var(--text-3); font-size: 16px; }
.advice-good { border-left-color: var(--success); }
.advice-warn { border-left-color: var(--warning); }
.advice-recap { border-left-color: var(--accent); }
.charge-hint { background: var(--surface-2); border-radius: var(--r-md); color: var(--text-2); display: flex; align-items: center; gap: 8px; }
.charge-hint svg { color: var(--text-3); flex-shrink: 0; }
.perf-chip { background: var(--surface-2); border-radius: 999px; font-weight: 500; }
.perf-latest { font-weight: 600; }
.perf-chart { width: 100%; height: 100px; display: block; margin: 6px 0 4px; }
.perf-chart-line { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }

/* Suivi de charge — graphique hebdo (sRPE) */
.load-kpis { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin-bottom: 18px; }
@media (max-width: 560px) { .load-kpis { grid-template-columns: 1fr; } }
.kpi { background: var(--surface-2); border-radius: var(--r-md); padding: 12px 14px; }
.kpi-val { font-size: 22px; font-weight: 600; letter-spacing: -0.01em; line-height: 1.1; display: flex; align-items: baseline; gap: 4px; }
.kpi-val small { font-size: var(--fs-sm); font-weight: 500; color: var(--text-2); }
.kpi-lab { font-size: var(--fs-xs); color: var(--text-3); margin-top: 4px; }
.kpi-status { display: inline-flex; align-items: center; gap: 5px; font-size: var(--fs-xs); font-weight: 600; margin-top: 6px; }
.kpi-status::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: currentColor; }
.kpi-good { color: var(--success); }
.kpi-warn { color: var(--warning); }
.kpi-bad { color: var(--danger); }
.kpi-low { color: var(--zone-1); }

.load-chart { display: flex; gap: 5px; align-items: stretch; height: 150px; margin-top: 4px; }
.load-col { flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 4px; border-radius: 8px; padding: 4px 1px 2px; transition: background-color .15s; }
.load-col:hover { background: color-mix(in srgb, var(--text) 5%, transparent); }
.load-col.is-current { background: var(--surface-2); }
.load-col.is-selected { outline: 1px solid var(--border-strong); }
/* Barres dans le style des graphiques D3 : sommets arrondis, le prévu en
   piste claire, le réalisé en dégradé, une ligne de base. */
.load-bars { flex: 1; width: 100%; position: relative; display: flex; align-items: flex-end; justify-content: center; border-bottom: 1px solid color-mix(in srgb, var(--text) 22%, transparent); }
.load-bar-planned { position: absolute; bottom: 0; width: 72%; border-radius: 6px 6px 0 0; background: color-mix(in srgb, var(--text) 10%, transparent); }
.load-bar-done { position: absolute; bottom: 0; width: 44%; border-radius: 5px 5px 0 0; background: linear-gradient(180deg, var(--success), color-mix(in srgb, var(--success) 55%, transparent)); }
.load-bar-bonus { position: absolute; width: 44%; border-radius: 5px 5px 0 0; background: linear-gradient(180deg, var(--accent), color-mix(in srgb, var(--accent) 60%, transparent)); }
.stack-seg { position: absolute; width: 66%; border-radius: 2px; }
.load-val { font-size: 10px; color: var(--text-2); font-weight: 600; height: 12px; line-height: 12px; font-variant-numeric: tabular-nums; }
.load-week { font-size: 10px; color: var(--text-3); font-weight: 600; }
.load-col.is-current .load-week { color: var(--text); }
.load-legend { display: flex; flex-wrap: wrap; gap: 6px 14px; margin-top: 10px; font-size: var(--fs-xs); color: var(--text-2); }
.load-legend i { display: inline-block; width: 10px; height: 10px; border-radius: 3px; margin-right: 5px; vertical-align: -1px; }
.load-legend .l-planned { background: var(--surface-3); border: 1px solid var(--border-strong); }
.load-legend .l-done { background: var(--success); }
.load-legend .l-bonus { background: var(--accent); }
.load-footnote { font-size: var(--fs-xs); color: var(--text-3); margin-top: 10px; line-height: 1.5; }
@media (max-width: 560px) { .load-val { display: none; } .load-week { font-size: 8.5px; } }

/* ------------------------------------------------------------
   6. Guide (zones, phases, principes)
   ------------------------------------------------------------ */
.guide-section { display: none; }
.guide-section.active { display: block; }
.zone-card { background: var(--surface); padding: 14px 16px; border-radius: var(--r-md); }
.zone-badge { border-radius: 10px; width: 40px; height: 40px; font-weight: 600; font-size: 14px; border-width: 1px !important; }
.zone-name { font-weight: 600; }
.zone-bpm { font-weight: 600; font-size: 18px; }
.zone-pct { font-weight: 600; }
.distrib-card { margin-top: 12px; }
.distrib-title { font-weight: 600; }
.distrib-block { color: #fff; font-weight: 600; font-size: 10.5px; }
.distrib-bar { border-radius: 6px; }
/* Légende de la répartition : la pastille reprend les zones qu'elle
   regroupe (Z1+Z2, Z3 à Z5), dans les couleurs de la barre. */
.distrib-legend .legend-dot { width: 18px; height: 10px; }

/* Zones personnalisées (js/hrzones.js) */
#zones-fcm-note .link-btn { margin-left: 4px; }
#zones-fcm-note .link-btn svg { width: 14px; height: 14px; }
.zones-tag { display: inline-flex; align-items: center; gap: 4px; font-weight: 600; color: var(--brand-green, var(--success)); margin-right: 4px; }
.zones-tag svg { width: 14px; height: 14px; }
.zed-card { display: flex; flex-direction: column; gap: 12px; }
.zed-rows { display: flex; flex-direction: column; gap: 8px; }
.zed-row { display: grid; grid-template-columns: 40px minmax(0, 1fr) auto auto; align-items: center; gap: 10px; }
.zed-name { font-weight: 600; font-size: var(--fs-sm); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.zed-field { display: inline-flex; align-items: center; gap: 6px; }
.zed-lab { font-size: var(--fs-xs); color: var(--text-3); }
.zed-input { width: 76px; text-align: right; font-variant-numeric: tabular-nums; }
.zed-to { font-size: var(--fs-sm); color: var(--text-2); min-width: 84px; font-variant-numeric: tabular-nums; }
.zed-error { min-height: 1.2em; font-size: var(--fs-sm); color: var(--danger); }
.zed-error:empty { display: none; }
.zed-fill, .zed-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.zed-actions { justify-content: flex-end; }
@media (max-width: 480px) {
  .zed-row { grid-template-columns: 36px minmax(0, 1fr) auto; }
  .zed-row .zone-badge { width: 36px; height: 36px; }
  .zed-to { grid-column: 2 / -1; min-width: 0; font-size: var(--fs-xs); margin-top: -6px; text-align: right; }
}
.phases-grid { gap: 8px; }
.phase-btn { background: var(--surface); padding: 14px; border-radius: var(--r-md); }
.phase-btn.active { border-color: var(--phase) !important; background: color-mix(in srgb, var(--phase) 10%, var(--surface)) !important; }
.phase-icon { color: var(--phase, var(--text-2)); display: inline-flex; font-size: 18px; margin-bottom: 8px; }
.phase-name { font-weight: 600; }
.phase-detail-card { background: var(--surface); border-color: var(--border) !important; }
.phase-detail-badge { display: inline-flex; font-size: 22px; color: var(--phase, var(--text-2)); width: 40px; height: 40px; border-radius: 10px; align-items: center; justify-content: center; background: color-mix(in srgb, var(--phase, var(--text-3)) 14%, transparent); }
.phase-detail-title { font-weight: 600; font-size: var(--fs-lg); color: var(--text) !important; }
.phase-vol-badge { border-radius: 999px; }
.phase-focus-item { background: var(--surface-2); border-radius: var(--r-md); align-items: center; }
.phase-focus-arrow { display: inline-flex; color: var(--phase, var(--text-3)) !important; }
.progress-bar-card { background: var(--surface); }
.progress-title { text-transform: none; letter-spacing: 0; }
.progress-segment { border-radius: 4px; font-weight: 600; }
.principle-card { background: var(--surface); }
.principle-icon { display: inline-flex; color: var(--text-2); font-size: 20px; width: 36px; height: 36px; border-radius: 10px; align-items: center; justify-content: center; background: var(--surface-2); }
.principle-name { font-weight: 600; }
.swim-tips-card { background: var(--surface); border-color: var(--border); }
.swim-tips-card .card-title { color: var(--sport-swim); }
.danger-tips-card { background: var(--surface); border-color: var(--border); }
.danger-tips-card .card-title { color: var(--danger); }
.tip-check, .danger-check { display: inline-flex; font-size: 16px; margin-top: 1px; }
.tip-check { color: var(--sport-swim); }
.danger-check { color: var(--danger); }
.tip-row { color: var(--text-2); }

/* ------------------------------------------------------------
   7. Profil
   ------------------------------------------------------------ */
.profile-container { gap: 28px; }
.avatar-option { border-radius: var(--r-sm); background: var(--surface-2); }
.avatar-option.active { border-color: var(--text); background: var(--surface-3); box-shadow: none; }
.avatar-photo-preview { background: var(--surface-2); }
.schedule-day-row { background: var(--surface-2); border-radius: var(--r-md); padding: 6px 10px 6px 14px; grid-template-columns: 90px 1fr 1fr; }
/* Les deux listes se partagent la ligne : sans min-width 0, la plus longue
   option impose sa largeur et la ligne déborde sur téléphone. */
.schedule-day-row .schedule-select { min-width: 0; width: 100%; text-overflow: ellipsis; }
/* 2e séance du jour : discrète tant qu'elle est vide. */
.schedule-select-2:not(.is-set) { color: var(--text-3); border-style: dashed; background: transparent; }
@media (max-width: 560px) {
  .schedule-day-row { grid-template-columns: 1fr 1fr; row-gap: 6px; }
  .schedule-day-row .schedule-day-name { grid-column: 1 / -1; }
}
.schedule-day-name { font-weight: 600; font-size: var(--fs-sm); color: var(--text); }
.schedule-select { background: var(--surface); }
.formats-grid { grid-template-columns: repeat(2, 1fr); gap: 8px; }
.format-btn { background: var(--surface-2); border-radius: var(--r-md); padding: 12px 14px; }
.format-btn.active { background: var(--surface-3); border: 1px solid var(--text); }
.format-btn .format-key { font-weight: 600; font-size: var(--fs-lg); }
.format-btn.active .format-key { color: var(--text); }
.format-btn .format-name { font-weight: 600; font-size: var(--fs-xs); color: var(--text-2); }
.format-btn .format-details { color: var(--text-3); }
.format-btn .format-vol { color: var(--text-3); font-weight: 500; }
.format-btn.active .format-vol { color: var(--text-2); }
.profile-countdown { margin-top: 8px; font-size: var(--fs-sm); color: var(--text-2); min-height: 20px; }
.profile-countdown strong { color: var(--text); }
.fcm-container { align-items: center; }
.fcm-slider { accent-color: var(--text); }
.fcm-value { color: var(--text); font-weight: 600; font-size: 40px; }
.fcm-slider-labels { color: var(--text-3); }
.fcm-info { color: var(--text-2); line-height: 1.5; }
.fcm-info span { color: var(--text); font-weight: 600; }
.fcm-info .link-btn { margin-top: 6px; display: inline-block; }
.vma-inline { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--border); display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; font-size: var(--fs-sm); color: var(--text-2); }
.vma-inline strong { color: var(--text); font-size: var(--fs-lg); font-weight: 600; margin-right: 4px; }
.plan-close-summary { background: var(--surface-2); border-radius: var(--r-md); }
.plan-history-badge { border-radius: 999px; background: var(--surface-2); border-color: var(--border); color: var(--text-2); }
.plan-history-row { border-radius: var(--r-md); }
.strava-note { color: var(--text-2); }
.strava-connected { color: var(--success); font-weight: 600; display: flex; align-items: center; gap: 8px; }
.strava-powered { color: var(--text-3); text-transform: none; letter-spacing: 0; }

/* ------------------------------------------------------------
   8. Accueil / onboarding
   ------------------------------------------------------------ */
.landing { background: var(--bg); padding-top: 48px; }
.landing-logo { width: 72px; height: 72px; border-radius: 0; background: none; border: none; }
.landing-logo img { width: 100%; height: 100%; display: block; }
.landing-title {
  font-size: clamp(26px, 6vw, 36px); font-weight: 600; letter-spacing: -0.02em;
  background: none; -webkit-background-clip: initial; background-clip: initial; -webkit-text-fill-color: initial; color: var(--text);
}
[data-theme="light"] .landing-title { background: none; -webkit-text-fill-color: initial; }
.landing-tagline { color: var(--text-2); font-size: var(--fs-md); }
.landing-card { border-radius: var(--r-lg); background: var(--surface); }
.landing-card-title { font-weight: 600; }
.wiz-progress { margin-top: 26px; }
.wiz-dot { width: 22px; height: 4px; border-radius: 2px; background: var(--surface-3); }
.wiz-dot.active { background: var(--text); }
.wiz-progress-label { color: var(--text-3); font-weight: 500; letter-spacing: 0; }
.wiz-hint { color: var(--text-3); }
.wiz-discipline-card { background: var(--surface-2); border-radius: var(--r-md); padding: 16px 10px; }
.wiz-discipline-card.active { border-color: var(--text); background: var(--surface-3); color: var(--text); }
.wiz-discipline-card:hover { transform: none; border-color: var(--border-strong); }
.wiz-discipline-icon { display: inline-flex; font-size: 24px; color: var(--sport, var(--text-2)); width: 42px; height: 42px; border-radius: 12px; align-items: center; justify-content: center; background: color-mix(in srgb, var(--sport, var(--text-3)) 14%, transparent); margin-bottom: 4px; }
.wiz-discipline-label { font-weight: 600; }
.wiz-level-chip { background: var(--surface-2); border-radius: var(--r-md); }
.wiz-level-chip.active { border-color: var(--text); background: var(--surface-3); }
.wiz-level-chip-label { font-weight: 600; }
.wiz-format-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; }
.wiz-format-btn {
  display: flex; flex-direction: column; align-items: flex-start; gap: 2px; padding: 10px 12px; text-align: left;
  background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--r-md); color: var(--text-2); font-family: inherit; cursor: pointer;
}
.wiz-format-btn.active { border-color: var(--text); background: var(--surface-3); color: var(--text); }
.wiz-format-key { font-weight: 600; font-size: var(--fs-md); color: var(--text); }
.wiz-format-sub { font-size: 10.5px; color: var(--text-3); }
.landing-skip { color: var(--text-3); font-weight: 500; }
.landing-note { color: var(--text-3); }

/* ------------------------------------------------------------
   10. Activités importées (Strava)
   ------------------------------------------------------------ */
.act-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; margin-bottom: 14px; }
.act-filters { display: flex; gap: 6px; flex-wrap: wrap; }
.act-list { display: flex; flex-direction: column; gap: 8px; }
.act-row { display: grid; grid-template-columns: 40px 1fr auto; gap: 12px; align-items: center; padding: 12px 14px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-md); }
.act-main { min-width: 0; }
.act-title { font-weight: 600; font-size: var(--fs-md); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.act-meta { font-size: var(--fs-xs); color: var(--text-2); margin-top: 2px; }
.act-actions { display: flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }
.act-suggest { grid-column: 1 / -1; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding: 10px 12px; margin-top: 2px; background: var(--accent-soft); border-radius: var(--r-sm); font-size: var(--fs-xs); color: var(--text); }
.act-suggest svg { color: var(--accent); }
@media (max-width: 520px) { .act-row { grid-template-columns: 36px 1fr; } .act-actions { grid-column: 1 / -1; justify-content: flex-start; } }

/* ------------------------------------------------------------
   11. Club / événements — cohérence minimale
   ------------------------------------------------------------ */
.club-hero { background: var(--surface); }
.lb-row, .member-row, .coach-day, .grp-card, .pb-plan { background: var(--surface-2); border-radius: var(--r-md); }
.lb-row.lb-me { background: var(--success-soft); }
.athlete-chip { border-radius: 999px; background: var(--surface-2); }
.athlete-chip.active { border-color: var(--text); background: var(--surface-3); color: var(--text); }
.ev-card { background: var(--surface); }

/* ------------------------------------------------------------
   12. Accessibilité : mouvement réduit
   ------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
}

/* ------------------------------------------------------------
   13. Compléments
   ------------------------------------------------------------ */
.log-skip-reasons { display: none; }
.log-skip-reasons.open { display: flex; }
.cal-wrapper > .plan-banner-missing-date { margin: 12px 12px 0; }
.sess-row:focus-visible { outline-offset: -2px; }
.sdp-badges { align-items: center; }
.avatar-emoji { line-height: 1; }
.session-detail-panel .sdp-badge svg { color: var(--text-3); }
@media (max-width: 768px) {
  .today-greet { font-size: 22px; }
  .page-title { font-size: 18px; }
  .card { padding: 16px; }
  .session-detail-panel { padding: 16px 14px 18px; }
  .rpe-btn { height: 34px; font-size: 12px; }
}
.today-date { text-transform: none; }
.today-date::first-letter { text-transform: uppercase; }
.today-week-head { flex-wrap: wrap; }
.today-week-head .card-title { white-space: nowrap; }
/* Téléphone : le J-x reste LE chiffre de l'écran, à droite de la
   salutation ; « Personnaliser » passe dessous (la colonne de droite est
   dissoute dans la grille de l'en-tête). */
@media (max-width: 520px) {
  .today-head { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: end; gap: 10px 12px; }
  .today-head-side { display: contents; }
  .today-countdown-num { font-size: 40px; }
  .today-custom-btn { grid-column: 1 / -1; justify-self: start; }
}

/* ------------------------------------------------------------
   14. Chargement, synchronisation, données
   ------------------------------------------------------------ */
#app-loading { display: none; position: fixed; inset: 0; z-index: 400; background: var(--bg); align-items: center; justify-content: center; flex-direction: column; gap: 14px; color: var(--text-2); font-size: var(--fs-sm); }
body.is-loading #app-loading { display: flex; }
body.is-loading .topbar, body.is-loading .container, body.is-loading .bottom-nav { visibility: hidden; }
.app-loading-mark { width: 56px; height: 56px; animation: tp-pulse 1.2s ease-in-out infinite; }
@keyframes tp-pulse { 0%, 100% { transform: scale(1); opacity: 1; } 50% { transform: scale(0.92); opacity: 0.7; } }
@media (prefers-reduced-motion: reduce) { .app-loading-mark { animation: none; } }

/*  ANIMATION D'ARRIVÉE — jouée une fois, juste après une connexion (cf. le
    script posé sous #app-welcome dans index.html : c'est lui qui la
    déclenche, puis la retire). Le logo se dessine : point bleu, pulsation,
    point orange, courbe, point vert — puis le nom de l'app et un bonjour.
    Elle RECOUVRE l'écran de chargement et ne retarde donc rien : les
    données se lisent pendant qu'elle joue. Le tracé est celui de
    login.html (.pulse) : même dessin de part et d'autre de la connexion. */
#app-welcome {
  position: fixed; inset: 0; z-index: 401; background: var(--bg);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 18px;
  transition: opacity .4s ease;
}
#app-welcome[hidden] { display: none; }
#app-welcome.is-leaving { opacity: 0; pointer-events: none; }
.aw-pulse { width: min(58vw, 260px); height: auto; overflow: visible; transition: transform .4s ease; }
#app-welcome.is-leaving .aw-pulse { transform: scale(1.12); }
.aw-pulse path {
  fill: none; stroke: var(--text); stroke-width: 12; stroke-linecap: round; stroke-linejoin: round;
  stroke-dasharray: 1; stroke-dashoffset: 1;
  animation: aw-draw 1s .15s cubic-bezier(.6, .05, .3, 1) forwards;
}
/*  Le rebond (1.6 dans la courbe) : chaque point « claque » à l'arrivée du
    trait, au lieu d'apparaître. Les délais suivent la position du point
    sur le tracé — l'orange est à mi-longueur. */
.aw-pulse circle {
  stroke: var(--bg); stroke-width: 6; transform-box: fill-box; transform-origin: center;
  opacity: 0; animation: aw-pop .45s cubic-bezier(.3, 1.6, .5, 1) forwards;
}
.aw-pulse circle:nth-of-type(2) { animation-delay: .6s; }
.aw-pulse circle:nth-of-type(3) { animation-delay: 1.05s; }
.aw-word { height: 26px; opacity: 0; animation: aw-rise .45s .95s ease-out forwards; }
.aw-hello { min-height: 1.4em; color: var(--text-2); font-size: var(--fs-md); opacity: 0; transition: opacity .3s ease; }
.aw-hello.on { opacity: 1; }
@keyframes aw-draw { to { stroke-dashoffset: 0; } }
@keyframes aw-pop { from { opacity: 0; transform: scale(.3); } to { opacity: 1; transform: scale(1); } }
@keyframes aw-rise { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

/*  CÉLÉBRATION (js/celebrate.js) — badge, niveau, record, flamme. Une
    carte au centre, au-dessus de tout sauf des messages (.toast, 1000) :
    le « Séance validée · Annuler » doit rester atteignable. Rien à
    fermer : un toucher n'importe où, ou cinq secondes. `--tone` est la
    couleur de l'occasion. */
.cel {
  position: fixed; inset: 0; z-index: 900; display: flex; align-items: center; justify-content: center;
  padding: 24px; background: color-mix(in srgb, var(--bg) 62%, transparent);
  -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px);
  cursor: pointer; animation: cel-in .25s ease-out both; transition: opacity .25s ease;
}
.cel.is-leaving { opacity: 0; pointer-events: none; }
.cel-card {
  position: relative; width: min(100%, 340px); padding: 26px 22px 22px; text-align: center;
  background: var(--surface); border: 1px solid color-mix(in srgb, var(--tone) 40%, var(--border));
  border-radius: var(--r-lg); box-shadow: var(--shadow-md), 0 0 0 6px color-mix(in srgb, var(--tone) 10%, transparent);
  animation: cel-card .45s cubic-bezier(.3, 1.5, .5, 1) both;
}
.cel-glyph {
  width: 76px; height: 76px; margin: 0 auto 14px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center; font-size: 36px;
  color: var(--tone); background: color-mix(in srgb, var(--tone) 16%, transparent);
  box-shadow: 0 0 0 8px color-mix(in srgb, var(--tone) 7%, transparent);
  animation: aw-pop .5s .12s cubic-bezier(.3, 1.6, .5, 1) both;
}
.cel-emoji { font-size: 40px; line-height: 1; }
.cel-kicker { font-size: var(--fs-xs); font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--tone); }
.cel-title { margin-top: 6px; font-size: var(--fs-xl); font-weight: 700; letter-spacing: -0.01em; line-height: 1.2; color: var(--text); overflow-wrap: anywhere; }
.cel-text { margin: 8px 0 0; font-size: var(--fs-sm); line-height: 1.5; color: var(--text-2); }
.cel-extras { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--border); }
.cel-extras .chip { white-space: normal; }
.cel-extras .cel-emoji { font-size: 13px; }
/*  Confettis : chaque pièce part du centre de la carte vers (--x, --y),
    puis retombe. Tout est dans la feuille — le script ne tire que les
    directions. */
.cel-confetti { position: absolute; left: 50%; top: 44%; width: 0; height: 0; pointer-events: none; }
.cel-confetti i {
  position: absolute; left: -4px; top: -7px; width: 8px; height: 14px; border-radius: 2px;
  background: var(--c); opacity: 0;
  animation: cel-burst var(--t) cubic-bezier(.12, .7, .3, 1) var(--d) both;
}
@keyframes cel-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes cel-card { from { opacity: 0; transform: translateY(14px) scale(.9); } to { opacity: 1; transform: none; } }
@keyframes cel-burst {
  0% { opacity: 0; transform: translate(0, 0) rotate(0) scale(.5); }
  8% { opacity: 1; }
  55% { opacity: 1; transform: translate(var(--x), var(--y)) rotate(var(--r)) scale(1); }
  100% { opacity: 0; transform: translate(calc(var(--x) * 1.12), calc(var(--y) + 170px)) rotate(calc(var(--r) * 1.6)) scale(.9); }
}
@media (prefers-reduced-motion: reduce) { .cel, .cel-card, .cel-glyph { animation: none; } }
@keyframes spin { to { transform: rotate(360deg); } }
.sync-btn { color: var(--text-3); }
.sync-btn[data-state="synced"] { color: var(--success); }
.sync-btn[data-state="pending"], .sync-btn[data-state="syncing"] { color: var(--warning); }
.sync-btn[data-state="offline"], .sync-btn[data-state="error"], .sync-btn[data-state="auth"] { color: var(--danger); }
.sync-btn[data-state="local"] { display: none; }
.sync-btn[data-state="nocloud"] { color: var(--text-3); }
.sync-btn.spin svg { animation: spin 1s linear infinite; }
.sync-banner { display: flex; align-items: center; gap: 10px; padding: 10px 16px; font-size: var(--fs-xs); color: var(--text); background: var(--warning-soft); border-bottom: 1px solid color-mix(in srgb, var(--warning) 35%, transparent); }
.sync-banner svg { color: var(--warning); flex-shrink: 0; }
.sync-banner .btn { margin-left: auto; }
.physio-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 12px 16px; margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--border); }
.data-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.data-meta { font-size: var(--fs-xs); color: var(--text-3); margin-top: 10px; line-height: 1.5; }
.check-row { display: flex; align-items: center; gap: 8px; font-size: var(--fs-sm); color: var(--text); cursor: pointer; }
.check-row input { width: 16px; height: 16px; accent-color: var(--text); }

/* ------------------------------------------------------------
   15. Check-in, forme, douleur, adaptation
   ------------------------------------------------------------ */
.ci-form { display: flex; flex-direction: column; gap: 10px; }
.ci-row { display: grid; grid-template-columns: minmax(140px, 1fr) 2fr; gap: 10px; align-items: center; }
@media (max-width: 520px) { .ci-row { grid-template-columns: 1fr; gap: 6px; } }
.ci-label { display: flex; flex-direction: column; }
.ci-label span:first-child { font-size: var(--fs-sm); font-weight: 600; }
.ci-hint { font-size: 11px; color: var(--text-3); }
/* Cinq touches en relief ; la note choisie est ENFONCÉE. L'état ne repose
   pas sur l'ombre seule : liseré et chiffre passent à l'accent. */
.ci-scale { display: grid; grid-template-columns: repeat(5, 1fr); gap: 8px; }
.ci-btn { height: 40px; border-radius: var(--r-md); border: 1px solid var(--border); background: var(--surface); color: var(--text-2); font-weight: 600; font-family: inherit; cursor: pointer; box-shadow: var(--elev-raised-sm); transition: box-shadow 0.15s ease, background 0.15s ease; }
.ci-btn:hover { border-color: var(--border-strong); color: var(--text); }
.ci-btn.active { background: var(--sunk); color: var(--accent); border-color: var(--accent); box-shadow: var(--elev-pressed); }
.ci-extra { display: flex; gap: 10px; flex-wrap: wrap; align-items: flex-end; margin-top: 4px; }
.ci-result { display: flex; align-items: center; gap: 16px; }
.ci-gauge { width: 72px; height: 72px; border-radius: 50%; flex-shrink: 0; display: grid; place-items: center;
  background: conic-gradient(var(--col) calc(var(--val) * 1%), var(--surface-3) 0); position: relative; }
.ci-gauge::before { content: ""; position: absolute; inset: 7px; border-radius: 50%; background: var(--surface); }
.ci-gauge-num { position: relative; font-size: var(--fs-xl); font-weight: 600; }
.ci-result-title { font-size: var(--fs-lg); font-weight: 600; }
.ci-result-sub { font-size: var(--fs-xs); color: var(--text-2); margin-top: 3px; line-height: 1.5; }
.pain-form { margin-top: 12px; padding: 14px; border-radius: var(--r-md); background: var(--surface-2); border: 1px solid var(--border); }
.pain-list { display: flex; flex-direction: column; gap: 8px; margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--border); }
.pain-item { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.pain-meta { font-size: var(--fs-xs); color: var(--text-2); flex: 1; min-width: 160px; }
.adapt-actions { display: flex; gap: 6px; flex-wrap: wrap; margin-left: auto; }
.wl-strip { display: grid; grid-template-columns: repeat(14, 1fr); gap: 3px; margin-top: 8px; }
.wl-day { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.wl-bar { width: 100%; height: 44px; border-radius: 4px; background: var(--surface-3); position: relative; overflow: hidden; }
.wl-bar > i { position: absolute; bottom: 0; left: 0; right: 0; border-radius: 4px; }
.wl-lab { font-size: 9px; color: var(--text-3); }

/* ------------------------------------------------------------
   16. Cibles, journal replié, ajustements, glisser-déposer, toast action
   ------------------------------------------------------------ */
.target-row { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.target-chip { display: inline-flex; align-items: center; gap: 6px; font-size: var(--fs-xs); font-weight: 600; padding: 4px 9px; border-radius: 6px; background: var(--surface); border: 1px solid var(--border); color: var(--text); font-variant-numeric: tabular-nums; }
.target-chip > span { color: var(--text-3); font-weight: 500; }
/*  Icône | texte | action, sur une ligne : le texte se replie DANS sa
    colonne. En `flex-wrap: wrap`, un texte long passait entier à la ligne
    et laissait l'icône seule au-dessus. */
.target-missing { display: flex; align-items: flex-start; gap: 8px; margin-top: 10px; font-size: var(--fs-xs); line-height: 1.5; color: var(--text-2); }
.target-missing svg { flex: none; margin-top: 2px; color: var(--text-3); }
.target-missing .link-btn { flex: none; }
.sdp-player-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 12px; }
.log-more { margin-top: 14px; border-top: 1px solid var(--border); padding-top: 4px; }
.log-more summary { list-style: none; cursor: pointer; display: flex; align-items: center; gap: 8px; padding: 8px 0; font-size: var(--fs-sm); font-weight: 600; color: var(--text-2); }
.log-more summary::-webkit-details-marker { display: none; }
.log-more summary svg { transition: transform 0.15s ease; }
.log-more[open] summary svg { transform: rotate(180deg); }
.log-more summary strong { color: var(--text); }
.log-adjust { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--border); }
.log-adjust-lab { display: inline-flex; align-items: center; gap: 6px; font-size: var(--fs-xs); font-weight: 600; color: var(--text-3); margin-right: 4px; }
.log-move { width: auto; max-width: 100%; padding: 6px 30px 6px 10px; font-size: var(--fs-xs); min-height: 32px; }
.cal-footer { display: flex; align-items: center; gap: 8px; padding: 10px 18px; font-size: var(--fs-xs); color: var(--text-2); border-bottom: 1px solid var(--border); }
.cal-footer svg { color: var(--text-3); }
/* Ajouter une séance à un jour de la semaine, même s'il en porte déjà une. */
.cal-add { display: flex; align-items: center; gap: 8px; padding: 10px 18px; border-bottom: 1px solid var(--border); color: var(--text-3); }
.cal-add .form-select { width: auto; max-width: 100%; padding: 6px 30px 6px 10px; font-size: var(--fs-xs); min-height: 32px; }
/* Jour vidé : sa séance se tient un autre jour (cf. PlanMoves, app.js). */
.sess-row.is-vacated .sess-meta { font-style: italic; }
.sess-row[draggable="true"] { cursor: grab; }
.sess-row.dragging { opacity: 0.5; }
.sess-row.drop-target { outline: 2px dashed var(--accent); outline-offset: -2px; background: var(--accent-soft); }
#profile-toast { display: flex; align-items: center; gap: 12px; }
.toast-action { background: transparent; border: 1px solid color-mix(in srgb, var(--bg) 40%, transparent); color: var(--bg); font: inherit; font-weight: 700; padding: 4px 10px; border-radius: 6px; cursor: pointer; }

/* ------------------------------------------------------------
   17. Records, Jour J, mode séance, courbe de forme, bilan
   ------------------------------------------------------------ */
.rec-list { display: flex; flex-direction: column; }
.rec-row { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; padding: 9px 0; border-top: 1px solid var(--border); }
.rec-row:first-child { border-top: none; padding-top: 0; }
.rec-lab { font-size: var(--fs-sm); font-weight: 600; min-width: 120px; }
.rec-val { font-size: var(--fs-md); font-weight: 600; font-variant-numeric: tabular-nums; }
.rec-empty { color: var(--text-3); font-weight: 500; }
.rec-hint { font-size: var(--fs-xs); color: var(--text-3); margin-left: auto; }
.test-field { background: var(--accent-soft); border-radius: var(--r-md); padding: 12px; }
.race-scenarios { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-bottom: 16px; }
.race-scenario { background: var(--surface-2); border-radius: var(--r-md); padding: 12px; text-align: center; border: 1px solid transparent; color: inherit; font: inherit; cursor: pointer; width: 100%; transition: background 0.15s, border-color 0.15s; }
.race-scenario:hover { background: var(--surface-3); }
.race-scenario.race-main { border-color: var(--text); }
.race-scenario-lab { font-size: var(--fs-xs); color: var(--text-3); font-weight: 600; }
.race-scenario-val { font-size: var(--fs-2xl); font-weight: 600; letter-spacing: -0.02em; margin-top: 2px; }
.race-main .race-scenario-val { color: var(--text); }
.race-segs { display: flex; flex-direction: column; }
.race-seg { display: flex; align-items: center; gap: 12px; padding: 10px 0; border-top: 1px solid var(--border); }
.race-seg:first-child { border-top: none; }
.race-seg-main { flex: 1; min-width: 0; }
.race-seg-title { font-weight: 600; font-size: var(--fs-md); }
.race-seg-sub { font-size: var(--fs-xs); color: var(--text-2); }
.race-seg-time { font-size: var(--fs-lg); font-weight: 600; font-variant-numeric: tabular-nums; }
.race-check { display: flex; flex-direction: column; }
.race-check-row { display: grid; grid-template-columns: 24px 56px 1fr; gap: 10px; align-items: start; text-align: left; padding: 10px 0; border-top: 1px solid var(--border); background: none; border-left: none; border-right: none; border-bottom: none; color: var(--text); font: inherit; cursor: pointer; }
.race-check-row:first-child { border-top: none; }
.race-check-box { color: var(--text-3); font-size: 20px; display: inline-flex; }
.race-check-row.done .race-check-box { color: var(--success); }
.race-check-row.done .race-check-txt { color: var(--text-3); text-decoration: line-through; }
.race-check-when { font-size: var(--fs-xs); font-weight: 600; color: var(--text-2); padding-top: 3px; }
.race-check-txt { font-size: var(--fs-sm); line-height: 1.45; }
.race-teaser .today-week-head { margin-bottom: 0; }
@media (max-width: 520px) { .race-scenarios { grid-template-columns: 1fr; } .race-scenario { display: flex; justify-content: space-between; align-items: baseline; } }

/* Mode séance et mode course : même coque plein écran, deux contenus.
   Écran pensé pour être lu à bout de bras, en mouvement : un chrono
   dominant, une consigne, des boutons d'au moins 52 px. */
#player, #race-coach, #freerec { position: fixed; inset: 0; z-index: 500; background: var(--bg); display: flex; align-items: stretch; justify-content: center; overflow-y: auto; }
.pl-sheet { width: 100%; max-width: 560px; padding: 20px 20px calc(24px + env(safe-area-inset-bottom)); display: flex; flex-direction: column; gap: 16px; }
.pl-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.pl-head-actions { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
.pl-kicker { font-size: var(--fs-xs); font-weight: 600; color: var(--text-3); text-transform: uppercase; letter-spacing: 0.06em; }
.pl-title { font-size: var(--fs-lg); font-weight: 600; }
.pl-audio { gap: 6px; }
.pl-audio-lab { font-size: var(--fs-xs); }
.pl-step { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; gap: 14px; padding: 12px 0; }
.pl-step-name { display: inline-flex; align-items: center; gap: 8px; font-size: var(--fs-lg); font-weight: 600; color: var(--text-2); flex-wrap: wrap; justify-content: center; }
.pl-step-left { font-size: 72px; font-weight: 600; letter-spacing: -0.03em; line-height: 1; font-variant-numeric: tabular-nums; }
.pl-lead { font-size: 96px; color: var(--accent); }
.pl-rep { font-size: var(--fs-xs); font-weight: 600; color: var(--text); background: var(--surface-3); border-radius: 999px; padding: 2px 8px; }
.pl-bar { width: 100%; max-width: 360px; height: 6px; border-radius: 3px; background: var(--surface-3); overflow: hidden; }
.pl-bar > i { display: block; height: 100%; background: var(--seg, var(--text)); transition: width 0.25s linear; }
.pl-detail { font-size: var(--fs-sm); color: var(--text-2); line-height: 1.55; max-width: 44ch; margin: 0; }
.pl-note { font-size: var(--fs-xs); color: var(--text-3); display: inline-flex; align-items: center; gap: 6px; margin: 0; }
.pl-paused { font-size: var(--fs-sm); color: var(--warning); display: inline-flex; align-items: center; gap: 8px; background: var(--warning-soft); padding: 8px 12px; border-radius: var(--r-md); }
.pl-controls { display: grid; grid-template-columns: 56px 1fr 1fr; gap: 8px; }
.pl-controls-2 { grid-template-columns: 1fr 1fr; }
.pl-controls .btn { min-height: 52px; font-size: var(--fs-md); }
.pl-foot { display: flex; justify-content: space-between; gap: 12px; font-size: var(--fs-xs); color: var(--text-3); }
.pl-foot strong { color: var(--text); font-variant-numeric: tabular-nums; }
.pl-next { font-size: var(--fs-sm); color: var(--text-2); display: flex; align-items: center; gap: 8px; justify-content: center; border-top: 1px solid var(--border); padding-top: 12px; }
.pl-next strong { color: var(--text); }
.pl-next-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg); padding: 14px 16px; max-width: 420px; display: flex; flex-direction: column; gap: 6px; }
.pl-next-lab { font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-3); font-weight: 600; }
.pl-next-name { font-size: var(--fs-md); font-weight: 600; display: inline-flex; align-items: center; gap: 8px; justify-content: center; }

/* Ligne de temps : un segment = un bloc, largeur proportionnelle à sa
   durée, cliquable pour sauter directement au bloc voulu. */
.pl-timeline { display: flex; gap: 2px; height: 14px; }
.pl-tl-seg { position: relative; min-width: 4px; padding: 0; border: none; border-radius: 3px; background: var(--surface-3); overflow: hidden; cursor: pointer; opacity: 0.55; transition: opacity 0.2s, transform 0.2s; }
.pl-tl-seg > i { display: block; height: 100%; width: 0; background: var(--seg, var(--text-2)); }
.pl-tl-seg.is-warm { --seg: var(--zone-2); }
.pl-tl-seg.is-work { --seg: var(--zone-4); }
.pl-tl-seg.is-rest { --seg: var(--zone-1); }
.pl-tl-seg.is-steady { --seg: var(--zone-3); }
.pl-tl-seg.is-cool { --seg: var(--zone-1); }
.pl-tl-seg.done { opacity: 0.85; }
.pl-tl-seg.now { opacity: 1; transform: scaleY(1.45); }
.pl-kind-warm { --seg: var(--zone-2); }
.pl-kind-work { --seg: var(--zone-4); }
.pl-kind-rest, .pl-kind-cool { --seg: var(--zone-1); }
.pl-kind-steady { --seg: var(--zone-3); }
/* Les classes ci-dessus sont le repli : un bloc qui annonce une zone
   reçoit sa couleur en ligne (`--seg`, cf. segColor dans js/player.js,
   recap.js et designer.js) — la palette des zones du Guide. */
.pl-kind-work .pl-step-left { color: var(--seg, var(--zone-4)); }
.pl-kind-rest .pl-step-left, .pl-kind-cool .pl-step-left { color: var(--text-2); }

/* Bandeau GPS : trois chiffres lisibles d'un coup d'œil, en course.
   L'allure se colore quand elle sort de la cible du bloc. */
/* Quatre chiffres, deux par ligne sur téléphone : à 375 px, quatre
   colonnes couperaient « En mouvement » en deux. */
/* Le nombre de tuiles varie : quatre d'ordinaire, cinq quand la cadence
   est mesurée (cf. js/cadence.js). `auto-fit` évite d'avoir à compter. */
.pl-gps { display: grid; grid-template-columns: repeat(auto-fit, minmax(92px, 1fr)); gap: 8px; text-align: center; }
@media (max-width: 520px) { .pl-gps { grid-template-columns: repeat(2, 1fr); gap: 10px 8px; } }

/* État détecté (arrêt, marche) — discret, sous les chiffres. */
.pl-phase {
  display: flex; align-items: center; justify-content: center; gap: 7px;
  margin-top: 8px; padding: 6px 12px; border-radius: var(--r-sm);
  font-size: var(--fs-xs); font-weight: 600;
  background: color-mix(in srgb, var(--warning) 12%, transparent);
  color: var(--warning); border: 1px solid color-mix(in srgb, var(--warning) 30%, transparent);
}
.pl-phase.is-walk { background: color-mix(in srgb, var(--accent) 12%, transparent); color: var(--accent); border-color: color-mix(in srgb, var(--accent) 30%, transparent); }
/* Angle mort : l'app est passée en arrière-plan et le relevé s'est tu (cf.
   BLIND_MIN dans js/gps.js). Plus grave qu'un arrêt détecté — là, de la
   donnée manque VRAIMENT — d'où la teinte d'alerte. La phrase nomme une
   cause et une conséquence : elle a le droit de tenir sur deux lignes,
   et `align-items: flex-start` garde alors l'icône en tête de texte au
   lieu de la centrer sur la hauteur du bloc. */
.pl-phase.is-blind {
  background: color-mix(in srgb, var(--danger) 12%, transparent);
  color: var(--danger); border-color: color-mix(in srgb, var(--danger) 30%, transparent);
  align-items: flex-start; text-align: left; line-height: 1.35; font-weight: 500;
}
.pl-phase.is-blind svg { flex: none; margin-top: 2px; }
.pl-phase svg { width: 14px; height: 14px; }
.pl-gps > div { background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-md); padding: 8px 6px; display: flex; flex-direction: column; gap: 2px; }
.pl-gps-lab { font-size: var(--fs-xs); color: var(--text-3); }
.pl-gps-val { font-size: var(--fs-lg); font-weight: 600; font-variant-numeric: tabular-nums; }
.pl-gps-pace.is-ok { color: var(--success); }
.pl-gps-pace.is-fast { color: var(--warning); }
.pl-gps-pace.is-slow { color: var(--accent); }
/* Choix de l'accompagnement, sur l'écran de préparation */
.pl-mode { display: flex; flex-direction: column; align-items: center; gap: 6px; width: 100%; max-width: 420px; }
.pl-mode-lab { display: inline-flex; align-items: center; gap: 6px; font-size: var(--fs-xs); font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-3); }
.pl-mode-seg { margin-bottom: 0; width: 100%; }
.pl-mode-seg .segmented-btn { flex: 1 1 0; min-width: 0; padding-left: 4px; padding-right: 4px; }
.pl-mode-hint { margin: 0; font-size: var(--fs-xs); color: var(--text-2); line-height: 1.5; text-align: center; min-height: 2.6em; }
/* Choix de la voix : discret, mais à portée de pouce — c'est ce qui décide
   qu'on entend un coach plutôt qu'un synthétiseur. */
.pl-voice-box { display: flex; flex-direction: column; gap: 6px; width: 100%; }
.pl-voice { display: flex; align-items: center; gap: 8px; width: 100%; font-size: var(--fs-xs); color: var(--text-3); }
.pl-voice > span { flex: none; width: 46px; text-transform: uppercase; letter-spacing: 0.06em; font-weight: 600; }
.pl-voice > select { flex: 1 1 auto; min-width: 0; background: var(--surface); color: var(--text); border: 1px solid var(--border); border-radius: var(--r-sm); padding: 6px 8px; font-size: var(--fs-xs); font-family: inherit; }
.pl-rate-seg { flex: 1 1 auto; min-width: 0; margin-bottom: 0; }
.pl-rate-seg .segmented-btn { flex: 1 1 0; min-width: 0; padding: 5px 4px; font-size: var(--fs-xs); }
/* Voix mécanique : le dire ne suffit pas, il faut donner la sortie — la
   marche à suivre de l'appareil, comme pour un refus de localisation. */
.pl-voice-hint { width: 100%; margin: 0; font-size: var(--fs-xs); color: var(--text-2); line-height: 1.5; text-align: left; background: var(--accent-soft); border-radius: var(--r-sm); padding: 8px 10px; }
.pl-voice-hint strong { color: var(--text); }
.pl-voice-help { width: 100%; font-size: var(--fs-xs); background: var(--warning-soft); border-radius: var(--r-sm); padding: 8px 10px; text-align: left; }
.pl-voice-help > summary { cursor: pointer; color: var(--warning); font-weight: 600; list-style: none; display: flex; align-items: center; gap: 6px; }
.pl-voice-help > summary::-webkit-details-marker { display: none; }
.pl-voice-help p { margin: 8px 0 0; color: var(--text-2); line-height: 1.5; }
.pl-voice-help ol { margin: 8px 0 0; padding-left: 18px; color: var(--text-2); line-height: 1.5; }
.pl-voice-help li + li { margin-top: 6px; }

/* Aide GPS : le message d'erreur porte toujours de quoi agir — la marche à
   suivre de l'appareil et un bouton pour relancer une fois le réglage changé. */
.pl-gps-help { display: flex; flex-direction: column; align-items: center; gap: 8px; text-align: center; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-md); padding: 10px 12px; }
.pl-gps-msg { display: inline-flex; align-items: center; gap: 8px; font-size: var(--fs-sm); color: var(--text-2); }
.pl-gps-steps { width: 100%; font-size: var(--fs-sm); }
.pl-gps-steps > summary { cursor: pointer; color: var(--accent); font-weight: 600; list-style: none; }
.pl-gps-steps > summary::-webkit-details-marker { display: none; }
.pl-gps-steps ol { margin: 8px 0 0; padding-left: 20px; text-align: left; color: var(--text-2); line-height: 1.5; }
.pl-gps-steps li + li { margin-top: 6px; }

/* Splits : les derniers kilomètres annoncés restent affichés, du plus
   ancien au plus récent, pour l'athlète qui jette un œil à l'écran. */
.pl-splits { display: flex; gap: 6px; justify-content: center; flex-wrap: wrap; }
.pl-split { display: inline-flex; align-items: baseline; gap: 6px; background: var(--surface); border: 1px solid var(--border); border-radius: 999px; padding: 4px 10px; font-size: var(--fs-xs); color: var(--text-3); }
.pl-split > strong { color: var(--text); font-variant-numeric: tabular-nums; }

/* ------------------------------------------------------------
   Carte du parcours (trace GPS) — fond de tuiles Esri, la même carte
   claire dans les deux thèmes (cf. TILES dans js/map.js), tracé en SVG
   par-dessus. Hors-ligne le fond ne charge pas, et le tracé seul reste
   parfaitement lisible.
   ------------------------------------------------------------ */
.tmap-card { display: flex; flex-direction: column; gap: 8px; }

/* Conteneur Leaflet. `z-index: 0` n'est pas décoratif : il crée un contexte
   d'empilement qui ENFERME les z-index de Leaflet (ses panneaux montent à
   800, ses contrôles au-dessus). Sans lui, les boutons de zoom d'une carte
   posée dans le journal passeraient par-dessus l'en-tête collant et les
   feuilles plein écran. */
.trace-map { position: relative; z-index: 0; width: 100%; min-height: 140px; border-radius: var(--r-md); overflow: hidden; background: var(--surface-2); border: 1px solid var(--border); }
.leaflet-container { background: var(--surface-2); font: inherit; outline: none; }
/* Vignette tactile : un appui ouvre le plein écran (cf. map.js). Le
   curseur et le halo au survol disent que c'est cliquable. */
.trace-map.tmap-tap { cursor: zoom-in; }
.trace-map.tmap-tap .leaflet-container { cursor: zoom-in; }

/* Fond de carte : LA MÊME CARTE CLAIRE dans les deux thèmes (cf. BASES
   dans js/map.js). Le filtre ne l'inverse pas — ça retournait les teintes
   et virait les forêts au vert fluo — et ne l'assombrit pas : une carte
   assombrie est une carte moins lisible, ce qu'on cherche justement à
   éviter. Il désature juste assez pour qu'aucune route ne vienne
   rivaliser avec le bleu du tracé.

   EN THÈME SOMBRE, on ne change donc pas la carte : on lui retire son
   ÉCLAT. `brightness` reste à 1 — baisser la luminosité rabattrait les
   gris de la carte les uns sur les autres — et c'est un voile posé
   par-dessus (cf. .trace-map::after) qui calme le rectangle blanc au
   milieu d'une page sombre, sans rien retirer au contraste dessous.

   Le filtre porte sur les TUILES seules : appliqué au conteneur, il
   emporterait aussi le tracé, les repères et les info-bulles. */
.leaflet-tile { filter: saturate(0.85) contrast(1.04); }

/* Le voile de thème sombre. `pointer-events: none` n'est pas négociable :
   il est posé au-dessus des tuiles, il ne doit intercepter ni le geste de
   déplacement, ni le clic sur un bloc du tracé. Il se range sous les
   panneaux Leaflet (z-index 400+) : ni le tracé, ni les repères, ni les
   contrôles ne passent dessous. */
:root:not([data-theme="light"]) .trace-map::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 350;
  pointer-events: none;
  background: color-mix(in srgb, var(--bg) 16%, transparent);
}

/* Contrôles et attribution au thème de l'app — le blanc par défaut de
   Leaflet jure avec tout le reste. */
.leaflet-bar a, .leaflet-bar a:hover {
  background: var(--surface-2); color: var(--text); border-bottom-color: var(--border);
}
.leaflet-bar a:hover { background: var(--surface-3); }
.leaflet-bar { border: 1px solid var(--border); box-shadow: var(--shadow-sm); }
.leaflet-control-attribution {
  background: color-mix(in srgb, var(--bg) 78%, transparent) !important;
  color: var(--text-3); font-size: 10px; padding: 1px 6px; border-radius: 4px 0 0 0;
}
.leaflet-control-attribution a { color: var(--text-3); }

/*  Info-bulle du bloc mis en évidence.

    ELLE N'AVAIT PAS DE FOND. Ces deux propriétés désignaient
    `--surface-1` et `--text-1`, qui n'existent pas : les tokens
    s'appellent `--surface` et `--text` (cf. styles.css et ui.css). Une
    variable non définie rend la déclaration INVALIDE — pas « ignorée au
    profit de celle d'avant », invalide — et la bulle se retrouvait sans
    aucun fond, son texte posé à même la carte, illisible dès que le
    tracé ou une rue passait dessous.

    C'est le défaut typique d'un token fantôme : rien ne casse, rien ne
    prévient, et le style manquant ne se voit que sur un fond chargé. Sept
    autres déclarations de ce fichier étaient dans le même cas.

    La flèche prend la couleur du FOND, pas de la bordure : c'est la
    pointe de la bulle, elle en fait partie. */
.leaflet-tooltip.tmap-tip {
  background: var(--surface); color: var(--text); border: 1px solid var(--border);
  box-shadow: var(--shadow-md); border-radius: var(--r-sm); font-size: var(--fs-xs);
  line-height: 1.35; padding: 5px 8px; text-align: center; white-space: nowrap;
}
.leaflet-tooltip.tmap-tip.leaflet-tooltip-top::before { border-top-color: var(--surface); }
.leaflet-tooltip.tmap-tip.leaflet-tooltip-bottom::before { border-bottom-color: var(--surface); }
.leaflet-tooltip.tmap-tip.leaflet-tooltip-left::before { border-left-color: var(--surface); }
.leaflet-tooltip.tmap-tip.leaflet-tooltip-right::before { border-right-color: var(--surface); }

/* Barre de blocs sous la carte plein écran : la même liste que le récap,
   mais à portée de pouce pendant qu'on regarde la carte. Défilement
   horizontal — sur un téléphone, huit blocs ne tiennent pas en largeur. */
.tmap-blocks { display: flex; gap: 8px; overflow-x: auto; padding: 2px 0 6px; scrollbar-width: thin; }
.tmap-block {
  flex: 0 0 auto; display: flex; flex-direction: column; gap: 2px; align-items: flex-start;
  padding: 7px 11px; border-radius: var(--r-sm); border: 1px solid var(--border);
  background: var(--surface-2); color: var(--text-2); cursor: pointer; text-align: left;
  border-left-width: 3px; transition: background .15s, border-color .15s, color .15s;
}
.tmap-block:hover { background: var(--surface-3); color: var(--text); }
.tmap-block.is-work { border-left-color: var(--danger); }
.tmap-block.is-steady { border-left-color: var(--accent); }
.tmap-block.is-warm { border-left-color: var(--warning); }
.tmap-block.is-cool { border-left-color: var(--success); }
.tmap-block.is-rest { border-left-color: var(--text-3); }
.tmap-block-lab { font-weight: 600; font-size: var(--fs-xs); color: var(--text); }
.tmap-block-sub { font-size: 11px; color: var(--text-3); font-variant-numeric: tabular-nums; }
.tmap-block.is-focused { background: var(--surface-3); border-color: var(--accent); color: var(--text); }

/* ------------------------------------------------------------
   RÉPARTITION DE L'EFFORT — course / marche / arrêt
   Une barre empilée plutôt que trois chiffres : la proportion se lit
   avant même les durées, et c'est elle qui explique une séance.
   ------------------------------------------------------------ */
.eff-bar { display: flex; height: 12px; border-radius: 6px; overflow: hidden; background: var(--surface-3); }
.eff-seg { display: block; height: 100%; }
.eff-seg.is-run { background: var(--accent); }
.eff-seg.is-walk { background: var(--warning); }
.eff-seg.is-stop { background: var(--text-3); opacity: 0.5; }
.eff-keys { display: flex; flex-wrap: wrap; gap: 6px 18px; margin-top: 10px; }
.eff-key { display: flex; align-items: baseline; gap: 6px; font-size: var(--fs-xs); }
.eff-dot { width: 9px; height: 9px; border-radius: 3px; flex: none; align-self: center; }
.eff-dot.is-run { background: var(--accent); }
.eff-dot.is-walk { background: var(--warning); }
.eff-dot.is-stop { background: var(--text-3); opacity: 0.5; }
.eff-lab { color: var(--text-2); }
.eff-val { font-variant-numeric: tabular-nums; }
.eff-sub { color: var(--text-3); }
/* Allure de l’état : elle ne se lit qu’avec sa légende, d’où la puce
   plutôt qu’une colonne — la ligne reste lisible quand la marche ou
   l’arrêt n’en ont pas. */
.eff-pace {
  font-variant-numeric: tabular-nums; color: var(--text);
  background: var(--surface-3); border-radius: 999px; padding: 1px 7px;
  font-size: calc(var(--fs-xs) - 1px);
}

/* Split : le temps arrêts déduits, en second rang sous le chrono */
.tmap-split-move { display: block; font-style: normal; font-size: 10px; font-weight: 500; color: var(--text-3); }

/* ------------------------------------------------------------
   COURBE D'ALLURE (js/paceplot.js)
   Le SVG s'étire en largeur (preserveAspectRatio="none") : les épaisseurs
   de trait sont donc données en unités du repère interne, pas en pixels.
   ------------------------------------------------------------ */
.pp-wrap { display: flex; flex-direction: column; gap: 8px; }
.pp-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.pp-title { display: inline-flex; align-items: center; gap: 8px; font-size: var(--fs-sm); font-weight: 600; }
.pp-title svg { width: 15px; height: 15px; }
.pp-legend { display: inline-flex; align-items: center; gap: 6px; font-size: var(--fs-xs); color: var(--text-3); }
.pp-key { width: 10px; height: 3px; border-radius: 2px; display: inline-block; margin-left: 6px; }
.pp-key.is-run { background: var(--accent); }
.pp-key.is-walk { background: var(--warning); }
.pp-key.is-stop { background: var(--text-3); opacity: 0.6; }
.pp-svg {
  width: 100%; height: 220px; display: block;
  background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--r-md);
}
.pp-grid { stroke: var(--border); stroke-width: 1; vector-effect: non-scaling-stroke; }
.pp-line { fill: none; stroke-width: 2.5; stroke-linecap: round; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.pp-line.is-run { stroke: var(--accent); }
.pp-line.is-walk { stroke: var(--warning); }
.pp-stop { fill: var(--text-3); opacity: 0.45; }
.pp-ylab, .pp-xlab, .pp-unit { fill: var(--text-3); font-size: 11px; font-variant-numeric: tabular-nums; }
.pp-unit { font-size: 10px; }
.pp-band:hover .pp-band-top { opacity: 1; }
.pp-band.is-focused rect:first-child { opacity: 0.18; }
.pp-band.is-focused .pp-band-top { opacity: 1; }

/* Deux tuiles côte à côte sous la courbe (régularité, dérive) */
.rcp-tiles-2 { grid-template-columns: repeat(2, 1fr) !important; margin-top: 10px; }

/* ------------------------------------------------------------
   ANCIENS ESPACES DE DONNÉES (Profil → Mes données)
   Volontairement mis en avant : quelqu'un qui croit avoir tout perdu
   doit tomber dessus, pas le chercher.
   ------------------------------------------------------------ */
.own-box {
  margin: 14px 0; padding: 14px; border-radius: var(--r-md);
  border: 1px solid color-mix(in srgb, var(--warning) 35%, var(--border));
  background: color-mix(in srgb, var(--warning) 7%, transparent);
}
.own-box .card-title { display: flex; align-items: center; gap: 8px; margin: 0 0 6px; }
.own-box .card-title svg { width: 16px; height: 16px; color: var(--warning); }
.own-list { display: flex; flex-direction: column; gap: 8px; margin-top: 12px; }
.own-row {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 10px 12px; border-radius: var(--r-sm);
  background: var(--surface-2); border: 1px solid var(--border);
}
.own-icon { display: inline-flex; color: var(--text-3); flex: none; }
.own-icon svg { width: 18px; height: 18px; }
.own-id { flex: 1; min-width: 160px; }
.own-name { font-size: var(--fs-sm); font-weight: 600; }
.own-sub { font-size: var(--fs-xs); color: var(--text-3); font-variant-numeric: tabular-nums; }
.own-done {
  display: flex; align-items: flex-start; gap: 8px; margin-bottom: 12px;
  font-size: var(--fs-xs); color: var(--success); line-height: 1.45;
}
.own-done svg { width: 15px; height: 15px; flex: none; margin-top: 1px; }
.own-done-chip { display: inline-flex; align-items: center; gap: 5px; font-size: var(--fs-xs); color: var(--success); }
.own-done-chip svg { width: 13px; height: 13px; }

/* Splits du journal : une barre par kilomètre, la plus rapide en repère */
.tmap-splits { display: flex; flex-direction: column; gap: 4px; }
.tmap-splits-lab { font-size: var(--fs-xs); color: var(--text-3); text-transform: uppercase; letter-spacing: 0.06em; font-weight: 600; margin-bottom: 2px; }
.tmap-split { display: grid; grid-template-columns: 52px 1fr 54px; align-items: center; gap: 10px; font-size: var(--fs-xs); font-variant-numeric: tabular-nums; }
.tmap-split-n { color: var(--text-3); }
.tmap-split-t { text-align: right; font-weight: 600; }
.tmap-split-bar { height: 8px; border-radius: 4px; background: var(--surface-3); overflow: hidden; }
.tmap-split-bar > i { display: block; height: 100%; background: var(--accent); opacity: 0.8; }
.tmap-split.is-best .tmap-split-bar > i { background: var(--success); opacity: 1; }
.tmap-split.is-best .tmap-split-t { color: var(--success); }

/* ------------------------------------------------------------
   Récap de séance — même coque plein écran que le mode séance, mais
   pensée pour être LUE, pas regardée à bout de bras : on peut donc
   redescendre en taille et empiler l'information.
   ------------------------------------------------------------ */
/*  DÉTAIL D'ACTIVITÉ EN MODE FOCUS (cf. js/recap.js) : il occupe la zone
    de contenu à la place de l'onglet courant, masqué mais pas repeint.
    Menu de gauche, barre du haut et fil d'Ariane restent. Sa largeur est
    celle de la zone de contenu : les colonnes se règlent donc sur ELLE
    (requêtes de conteneur), pas sur l'écran — à 1440 px d'écran, le menu
    en prend déjà 232. */
body.focus-open .container > .tab-content.active { display: none; }
.focus-view { container-type: inline-size; padding-bottom: 24px; }
.rcp-sheet { display: flex; flex-direction: column; gap: 18px; }
.focus-bar { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin: 0 0 -8px; }
.focus-bar .sess-back { margin-left: -10px; }
.focus-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-bottom: 0; }
.focus-head .page-title { min-width: 0; }

/* Trois à quatre chiffres en tête : ce qu'on veut savoir avant tout. */
.rcp-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 8px; }
.rcp-tile { background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-md); padding: 10px 12px; display: flex; flex-direction: column; gap: 2px; }
.rcp-tile-lab { font-size: var(--fs-xs); color: var(--text-3); text-transform: uppercase; letter-spacing: 0.06em; font-weight: 600; }
.rcp-tile-val { font-size: var(--fs-xl); font-weight: 600; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.rcp-tile-sub { font-size: var(--fs-xs); color: var(--text-3); }
/* Puissance estimée (js/power.js) : hypothèses du calcul, en une ligne. */
.pw-basis { margin: 8px 0 0; font-size: var(--fs-xs); line-height: 1.5; color: var(--text-3); }
.pw-basis .link-btn { font-size: inherit; }

.rcp-section { display: flex; flex-direction: column; gap: 10px; }
.rcp-section-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.06em; font-weight: 600; color: var(--text-3); }
.rcp-section-head > span:first-child { display: inline-flex; align-items: center; gap: 6px; color: var(--text-2); }
.rcp-map { display: flex; flex-direction: column; gap: 8px; }

/* Une ligne par bloc : nom et chiffres réels à gauche, réalisé face au
   prévu à droite. Le rail coloré reprend la teinte du type de bloc, comme
   la ligne de temps du mode séance. */
.rcp-rows { display: flex; flex-direction: column; }
.rcp-row { display: flex; align-items: flex-start; gap: 10px; padding: 10px 0; border-top: 1px solid var(--border); }
.rcp-row:first-child { border-top: none; padding-top: 0; }
.rcp-rail { flex: none; width: 3px; align-self: stretch; min-height: 34px; border-radius: 2px; background: var(--seg, var(--text-3)); }
.rcp-row.is-warm { --seg: var(--zone-2); }
.rcp-row.is-work { --seg: var(--zone-4); }
.rcp-row.is-rest { --seg: var(--zone-1); }
.rcp-row.is-steady { --seg: var(--zone-3); }
.rcp-row.is-cool { --seg: var(--zone-1); }
/* Une ligne de bloc devient un <button> dès qu'un tracé permet de la
   situer (cf. recap.js) : il faut donc défaire l'apparence de bouton du
   navigateur, et rendre l'affordance par autre chose — un picto discret
   qui n'apparaît que si le clic mène quelque part. */
.rcp-row.is-clickable {
  width: 100%; font: inherit; color: inherit; text-align: left;
  background: none; border-left: none; border-right: none; border-bottom: none;
  cursor: pointer; border-radius: var(--r-sm); transition: background .15s;
}
.rcp-row.is-clickable:hover { background: var(--surface-2); }
.rcp-row.is-clickable:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.rcp-row.is-focused { background: color-mix(in srgb, var(--accent) 12%, transparent); }
.rcp-row.is-focused .rcp-rail { box-shadow: 0 0 0 1px var(--accent); }
.rcp-row-pin { display: inline-flex; margin-left: 6px; color: var(--text-3); vertical-align: -1px; }
.rcp-row-pin svg { width: 13px; height: 13px; }
.rcp-row.is-focused .rcp-row-pin { color: var(--accent); }
.rcp-row-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.rcp-row-name { font-size: var(--fs-sm); font-weight: 600; }
.rcp-row-sub { font-size: var(--fs-xs); color: var(--text-2); font-variant-numeric: tabular-nums; }
.rcp-vs { align-self: flex-start; font-size: 11px; font-weight: 600; border-radius: 999px; padding: 1px 7px; margin-top: 2px; }
.rcp-vs.is-ok { color: var(--success); background: color-mix(in srgb, var(--success) 14%, transparent); }
.rcp-vs.is-fast { color: var(--warning); background: var(--warning-soft); }
.rcp-vs.is-slow { color: var(--accent); background: var(--accent-soft); }
.rcp-row-times { flex: none; display: flex; flex-direction: column; align-items: flex-end; gap: 2px; }
.rcp-real { font-size: var(--fs-md); font-weight: 600; font-variant-numeric: tabular-nums; }
.rcp-plan { font-size: var(--fs-xs); color: var(--text-3); font-variant-numeric: tabular-nums; }
.rcp-plan.is-ok { color: var(--success); }
.rcp-plan.is-warn { color: var(--warning); }
.rcp-plan.is-off { color: var(--danger); }

.rcp-note { display: flex; align-items: flex-start; gap: 8px; margin: 0; font-size: var(--fs-sm); color: var(--text-2); line-height: 1.5; background: var(--surface); border-radius: var(--r-md); padding: 12px; }

/* ------------------------------------------------------------
   Concepteur de séance — un formulaire, mais pensé pour le pouce :
   un bloc = une carte, ses champs sur une grille qui se replie sur
   téléphone, les commandes de structure regroupées dans l'en-tête.
   ------------------------------------------------------------ */
/* ------------------------------------------------------------
   Compte connecté (panneau Données). Affiché au-dessus des actions
   d'export / d'effacement : on doit toujours savoir de quel compte
   on parle avant de toucher à ses données.
   ------------------------------------------------------------ */
.acct { display: flex; align-items: center; gap: 12px; padding: 10px 12px; margin-bottom: 12px; background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--r-md); }
.acct-pic { width: 36px; height: 36px; border-radius: 50%; flex: none; object-fit: cover; background: var(--surface-3); }
.acct-pic-ph { display: inline-flex; align-items: center; justify-content: center; color: var(--text-3); }
.acct-pic-ph svg { width: 18px; height: 18px; }
.acct-id { min-width: 0; flex: 1 1 auto; }
.acct-name { font-weight: 600; font-size: var(--fs-sm); color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.acct-mail { font-size: var(--fs-xs); color: var(--text-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.acct-out { flex: none; text-decoration: none; }
@media (max-width: 420px) {
  .acct { flex-wrap: wrap; }
  .acct-out { width: 100%; justify-content: center; }
}

#designer { position: fixed; inset: 0; z-index: 510; background: var(--bg); display: flex; align-items: flex-start; justify-content: center; overflow-y: auto; }
.dg-sheet { gap: 16px; }
.dg-section { display: flex; flex-direction: column; gap: 10px; }
.dg-section-head { display: flex; align-items: center; justify-content: space-between; font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.06em; font-weight: 600; color: var(--text-3); }
.dg-section-head > span:first-child { display: inline-flex; align-items: center; gap: 6px; color: var(--text-2); }
.dg-sport { margin-bottom: 0; }
.dg-sport .segmented-btn { flex: 1 1 0; min-width: 0; display: inline-flex; align-items: center; justify-content: center; gap: 6px; }

/* Champ étiqueté : étiquette à gauche, contrôle à droite */
.dg-f { display: flex; align-items: center; gap: 8px; min-width: 0; font-size: var(--fs-xs); color: var(--text-3); }
/* L'étiquette est le PREMIER span : le sélecteur ne doit pas attraper le
   groupe valeur + unité, lui aussi un span. */
.dg-f > span:first-child { flex: none; width: 74px; text-transform: uppercase; letter-spacing: 0.05em; font-weight: 600; font-size: 10.5px; }
.dg-f > input, .dg-f > select, .dg-f > textarea { flex: 1 1 auto; min-width: 0; background: var(--surface); color: var(--text); border: 1px solid var(--border); border-radius: var(--r-sm); padding: 7px 8px; font-size: var(--fs-sm); font-family: inherit; }
.dg-f > input[type=number] { font-variant-numeric: tabular-nums; }
.dg-f-wide { grid-column: 1 / -1; }
.dg-f-col { flex-direction: column; align-items: stretch; }
.dg-f-col > span:first-child { width: auto; }
.dg-f > textarea { resize: vertical; line-height: 1.45; }

/* Valeur + unité côte à côte */
.dg-amount { flex: 1 1 auto; display: flex; gap: 4px; min-width: 0; }
.dg-amount > input { flex: 1 1 60px; min-width: 0; width: 60px; background: var(--surface); color: var(--text); border: 1px solid var(--border); border-radius: var(--r-sm); padding: 7px 8px; font-size: var(--fs-sm); font-family: inherit; font-variant-numeric: tabular-nums; }
.dg-amount > select { flex: none; width: 58px; background: var(--surface); color: var(--text-2); border: 1px solid var(--border); border-radius: var(--r-sm); padding: 7px 4px; font-size: var(--fs-xs); font-family: inherit; }

/* Un bloc = une carte, avec un rail de la couleur du type */
.dg-blocks { display: flex; flex-direction: column; gap: 8px; }
.dg-block { position: relative; background: var(--surface); border: 1px solid var(--border); border-left: 3px solid var(--seg, var(--text-3)); border-radius: var(--r-md); padding: 10px 12px; display: flex; flex-direction: column; gap: 8px; }
.dg-block.is-warm { --seg: var(--zone-2); }
.dg-block.is-set { --seg: var(--zone-4); }
.dg-block.is-steady { --seg: var(--zone-3); }
.dg-block.is-cool { --seg: var(--zone-1); }
.dg-block-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.dg-kind { background: transparent; color: var(--text); border: none; font-weight: 600; font-size: var(--fs-sm); font-family: inherit; padding: 2px 0; }
.dg-tools { display: inline-flex; gap: 2px; }
.dg-tool { width: 30px; height: 30px; display: inline-flex; align-items: center; justify-content: center; border: none; background: transparent; color: var(--text-3); border-radius: var(--r-sm); cursor: pointer; }
.dg-tool:hover:not(:disabled) { background: var(--surface-3); color: var(--text); }
.dg-tool:disabled { opacity: 0.3; cursor: default; }
.dg-tool-del:hover { color: var(--danger); }
.dg-block-body { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px 12px; }
@media (max-width: 420px) { .dg-block-body { grid-template-columns: 1fr; } }

.dg-add { display: flex; flex-wrap: wrap; gap: 6px; }
.dg-hint { display: flex; align-items: center; gap: 8px; margin: 0; font-size: var(--fs-sm); color: var(--text-2); }

/* Aperçu : exactement ce que le mode séance déroulera */
.dg-preview { background: var(--surface-2); border-radius: var(--r-md); padding: 10px 12px; }
.dg-preview-head { display: flex; align-items: center; justify-content: space-between; font-size: var(--fs-xs); color: var(--text-3); text-transform: uppercase; letter-spacing: 0.06em; font-weight: 600; }
.dg-preview-head > span { display: inline-flex; align-items: center; gap: 6px; }
.dg-preview-head > strong { color: var(--text); text-transform: none; letter-spacing: 0; font-size: var(--fs-sm); font-variant-numeric: tabular-nums; }
.dg-preview-rows { display: flex; flex-direction: column; margin-top: 6px; }
.dg-preview-row { display: grid; grid-template-columns: 20px 1fr auto 52px; gap: 8px; align-items: center; padding: 5px 0; border-top: 1px solid var(--border); font-size: var(--fs-xs); }
.dg-preview-row:first-child { border-top: none; }
.dg-pv-ic { color: var(--text-3); display: inline-flex; }
.dg-pv-lab { color: var(--text); font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dg-pv-zone { color: var(--text-3); }
.dg-pv-dur { text-align: right; font-variant-numeric: tabular-nums; color: var(--text-2); }

/* Modèles */
.dg-tpl { gap: 8px; }
.dg-tpl-row { display: flex; gap: 8px; }
.dg-tpl-row > input { flex: 1 1 auto; min-width: 0; }
.dg-tpl-list { display: flex; flex-wrap: wrap; gap: 6px; }
.dg-tpl-list .chip { display: inline-flex; align-items: center; gap: 6px; }
.dg-tpl-del { border: none; background: transparent; color: var(--text-3); padding: 0; display: inline-flex; cursor: pointer; font-size: 12px; }
.dg-tpl-del:hover { color: var(--danger); }

#tmap-full { position: fixed; inset: 0; z-index: 520; background: var(--bg); display: flex; flex-direction: column; padding: 12px 12px calc(12px + env(safe-area-inset-bottom)); gap: 10px; }
.tmap-full-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; font-size: var(--fs-md); font-weight: 600; }
.tmap-full-head > span { display: inline-flex; align-items: center; gap: 8px; }
.tmap-big { flex: 1; min-height: 0; }
/* La barre de blocs ne doit ni pousser la carte hors de l'écran, ni se
   faire écraser : hauteur libre, mais jamais plus du tiers de la vue. */
#tmap-full .tmap-blocks { flex: none; max-height: 33vh; }

/* Mode conseil de course */
.rc-brief { display: flex; flex-direction: column; gap: 14px; align-items: center; }
.rc-target { text-align: center; }
.rc-target-lab { font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-3); font-weight: 600; }
.rc-target-val { font-size: 56px; font-weight: 600; letter-spacing: -0.03em; line-height: 1.05; font-variant-numeric: tabular-nums; }
.rc-target-sub { font-size: var(--fs-sm); color: var(--text-2); margin-top: 4px; }
.rc-rows { width: 100%; display: flex; flex-direction: column; }
.rc-rows-live { border-top: 1px solid var(--border); padding-top: 8px; }
.rc-row { display: grid; grid-template-columns: 24px 1fr auto auto; gap: 10px; align-items: center; padding: 9px 0; border-top: 1px solid var(--border); font-size: var(--fs-sm); }
.rc-row:first-child { border-top: none; }
.rc-row-head { font-size: var(--fs-xs); color: var(--text-3); text-transform: uppercase; letter-spacing: 0.05em; font-weight: 600; }
.rc-row-ic { color: var(--sport, var(--text-3)); display: inline-flex; font-size: 16px; }
.rc-row-lab { font-weight: 600; min-width: 0; }
.rc-row-plan { color: var(--text-3); font-variant-numeric: tabular-nums; min-width: 56px; text-align: right; }
.rc-row-real { font-weight: 600; font-variant-numeric: tabular-nums; min-width: 64px; text-align: right; }
.rc-row.todo { opacity: 0.55; }
.rc-row.now { background: var(--accent-soft); border-radius: var(--r-sm); padding-left: 6px; padding-right: 6px; }
.rc-nutri { display: flex; flex-wrap: wrap; gap: 6px; justify-content: center; }
.rc-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; text-align: center; }
.rc-stats > div { background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-md); padding: 10px 6px; display: flex; flex-direction: column; gap: 2px; }
.rc-stat-lab { font-size: var(--fs-xs); color: var(--text-3); }
.rc-stats strong { font-size: var(--fs-lg); font-variant-numeric: tabular-nums; }
.rc-delta.ok { color: var(--success); }
.rc-delta.late { color: var(--warning); }
.rc-delta.early { color: var(--accent); }
.rc-cue { font-size: var(--fs-md); color: var(--text); }
.race-coach-card { border-color: var(--border-strong); }

@media (max-width: 420px) {
  .pl-step-left { font-size: 60px; }
  .pl-lead { font-size: 78px; }
  .rc-target-val { font-size: 44px; }
  .pl-audio-lab { display: none; }
  .rc-stats strong { font-size: var(--fs-md); }
}

.pmc-chart { width: 100%; height: 200px; display: block; margin-top: 4px; }
.pmc-chart path { fill: none; stroke-width: 2; stroke-linejoin: round; }
.pmc-ctl { stroke: var(--accent); }
.pmc-atl { stroke: var(--warning); }
.pmc-tsb { stroke: var(--success); stroke-width: 1.5; }
.pmc-proj { stroke-dasharray: 4 4; opacity: 0.7; }
.pmc-zero { stroke: var(--border-strong); stroke-width: 1; }
.pmc-today { stroke: var(--text); stroke-width: 1; stroke-dasharray: 2 3; }
.pmc-race { stroke: var(--danger); stroke-width: 1; }
.pmc-tick { font-size: 10px; fill: var(--text-3); text-anchor: middle; }
.review-card .log-label { margin-top: 4px; }
.coach-table { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); }
.coach-table th { text-align: left; font-size: var(--fs-xs); color: var(--text-3); font-weight: 600; padding: 6px 8px; border-bottom: 1px solid var(--border); white-space: nowrap; }
.coach-table td { padding: 9px 8px; border-bottom: 1px solid var(--border); white-space: nowrap; }
.coach-table tr:hover td { background: var(--surface-2); }
.today-session-actions .btn { flex: 0 1 auto; }

/* ============================================================
   ADMINISTRATION (js/admin.js)
   L'onglet a été écrit avec son propre vocabulaire de classes
   (`adm-*`) mais sans sa feuille : aucune des quarante n'existait
   en CSS. Tout s'empilait verticalement, sans gouttière ni
   alignement, et les pastilles de rôle — qui ne reçoivent du JS
   qu'une couleur en style inline — sortaient en texte teinté,
   faute de bordure, de rayon et d'espacement à porter.

   Le parti pris suit le reste de l'app : des LIGNES, pas un
   tableau. Un tableau impose des colonnes de largeur égale à des
   contenus qui n'en ont pas besoin (une adresse longue, un rôle
   court) et ne survit pas à un écran de téléphone. Ici chaque
   ligne est un flex : identité extensible, rôle et actions à
   droite, et sur mobile les actions passent dessous plutôt que de
   comprimer le nom.
   ============================================================ */

/* Barre de sections : jusqu'à cinq onglets pour un admin global,
   donc elle défile horizontalement plutôt que de se casser en deux
   rangs — une navigation qui change de hauteur déplace la page. */
.adm-nav { display: flex; width: 100%; }

.adm-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 14px; }
.adm-head .card-title { margin: 0; }
.adm-count { font-size: var(--fs-xs); color: var(--text-3); font-variant-numeric: tabular-nums; white-space: nowrap; }

/* Filtres : la recherche prend la place restante, les listes
   déroulantes gardent la leur. */
.adm-filters { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 14px; }
.adm-filters .form-input { flex: 1 1 220px; min-width: 0; }
.adm-filters .schedule-select { flex: 0 1 auto; }

/* --- Une ligne : membre, club, entrée de configuration --------- */
.adm-list { display: flex; flex-direction: column; }
.adm-row {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 0; border-top: 1px solid var(--border);
}
.adm-list > .adm-row:first-child { border-top: none; }

.adm-avatar {
  flex: none; width: 34px; height: 34px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--surface-2); border: 1px solid var(--border); font-size: 16px;
}
.adm-avatar svg { width: 17px; height: 17px; }

/* `min-width: 0` n'est pas décoratif : sans lui, une adresse longue
   refuse de se tronquer et pousse le rôle et les actions hors du
   cadre — le défaut le plus visible de l'écran non stylé. */
.adm-id { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.adm-name { font-size: var(--fs-sm); font-weight: 600; color: var(--text); }
.adm-mail { font-size: var(--fs-xs); color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.adm-self {
  font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
  color: var(--accent); background: color-mix(in srgb, var(--accent) 15%, transparent);
  border-radius: 999px; padding: 1px 6px; margin-left: 4px; vertical-align: 1px;
}
.adm-alert {
  font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
  color: var(--danger); background: color-mix(in srgb, var(--danger) 15%, transparent);
  border-radius: 999px; padding: 1px 6px; margin-left: 6px; vertical-align: 1px;
}

/* Pastille de rôle : js/admin.js pose la COULEUR en style inline
   (elle vient de AppStore.ROLES, donc du modèle de droits, pas de
   la feuille). Ce qui manquait ici, c'est la forme — sans bordure
   ni rayon ni espacement, la couleur seule donnait du texte teinté.
   `currentColor` reprend la couleur inline pour la bordure, ce qui
   évite de redire ici une palette qui vit ailleurs. */
.adm-role {
  flex: none; display: inline-flex; align-items: center; gap: 5px;
  font-size: var(--fs-xs); font-weight: 600; white-space: nowrap;
  border: 1px solid currentColor; border-radius: 999px; padding: 3px 9px;
}

.adm-actions { flex: none; display: flex; align-items: center; gap: 6px; }
.adm-select { padding: 5px 8px; font-size: var(--fs-xs); max-width: 150px; }

/* Retirer un membre : destructif, donc discret au repos et franc au
   survol. Un bouton rouge en permanence dans chaque ligne d'une
   liste de trente personnes fait un écran qui crie. */
.adm-x {
  flex: none; width: 28px; height: 28px; border-radius: var(--r-sm);
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent; border: 1px solid var(--border);
  color: var(--text-3); font-size: 13px; line-height: 1; cursor: pointer;
  /* On ne transitionne PAS `border-color` : elle vaut var(--border), qui
     change quand le thème bascule. Une transition en cours sur une
     propriété pilotée par un token fige l’élément sur la valeur de
     l’ancien thème — le bouton gardait sa bordure sombre sur fond clair,
     alors qu’un clone neuf du même bouton prenait la bonne. Le survol
     change quand même la bordure, il la change juste sans fondu. */
  transition: color .15s, background .15s;
}
.adm-x:hover { color: var(--danger); border-color: var(--danger); background: color-mix(in srgb, var(--danger) 12%, transparent); }
.adm-x:focus-visible { outline: 2px solid var(--danger); outline-offset: 1px; }

/* --- Invitation ------------------------------------------------ */
.adm-invite { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--border); }
.adm-invite .form-input { flex: 1 1 180px; min-width: 0; }
.adm-invite .schedule-select { flex: 0 1 auto; }
.adm-invite .btn { flex: none; }

/* --- Notes et états vides -------------------------------------- */
/* Le texte est enveloppé dans un <span> : sans lui, un <strong> au
   milieu de la phrase deviendrait un élément flex à part entière et
   sortirait du fil du texte. */
.adm-note {
  display: flex; align-items: flex-start; gap: 7px; margin: 12px 0 0;
  font-size: var(--fs-xs); color: var(--text-2); line-height: 1.45;
}
.adm-note > span { flex: 1; min-width: 0; }
.adm-note svg { width: 14px; height: 14px; flex: none; margin-top: 1px; }
.adm-note code { font-size: 11px; padding: 1px 5px; border-radius: 4px; background: var(--surface-2); border: 1px solid var(--border); }

.adm-empty {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  padding: 22px 16px; font-size: var(--fs-sm); color: var(--text-3); text-align: center;
}
.adm-empty svg { width: 15px; height: 15px; flex: none; }

/* --- Chiffres clés --------------------------------------------- */
.adm-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); gap: 8px; margin-bottom: 16px; }
.adm-stat {
  display: flex; flex-direction: column; gap: 2px;
  padding: 11px 13px; border-radius: var(--r-md);
  background: var(--surface-2); border: 1px solid var(--border);
}
.adm-stat-lab { font-size: var(--fs-xs); color: var(--text-3); text-transform: uppercase; letter-spacing: .04em; }
.adm-stat-val { font-size: var(--fs-xl); font-weight: 700; font-variant-numeric: tabular-nums; line-height: 1.15; }
.adm-stat-sub { font-size: var(--fs-xs); color: var(--text-3); }

/* --- Champs et actions en ligne --------------------------------- */
.adm-field { margin-top: 14px; }
.adm-field > label { display: block; font-size: var(--fs-xs); color: var(--text-3); margin-bottom: 5px; }
.adm-inline { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.adm-inline .form-input { flex: 1 1 180px; min-width: 0; }

.adm-code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: var(--fs-sm); letter-spacing: .06em; font-weight: 600;
  padding: 6px 11px; border-radius: var(--r-sm);
  background: var(--surface-2); border: 1px dashed var(--border-strong);
}

/* --- Club dépliable --------------------------------------------- */
.adm-club { border-top: 1px solid var(--border); }
.adm-club:first-child { border-top: none; }
.adm-club > .adm-row { border-top: none; }
.adm-club > .adm-row:hover { background: var(--surface-2); }
/* Le chevron dit dans quel sens ça va s'ouvrir, et l'a déjà tourné
   quand c'est ouvert : c'est la seule affordance de la ligne. */
.adm-club > .adm-row .adm-actions svg { width: 16px; height: 16px; color: var(--text-3); transition: transform .18s; }
.adm-club.is-open > .adm-row .adm-actions svg { transform: rotate(180deg); }
.adm-club-body {
  padding: 4px 0 14px 44px;   /* 44px = avatar + gouttière : le détail s'aligne sous le nom */
  display: flex; flex-direction: column; gap: 10px;
}

/* --- Journal ----------------------------------------------------- */
/* Deux colonnes : l'horodatage à largeur fixe pour que les lignes
   s'alignent, le texte prend le reste. */
.adm-log { display: flex; flex-direction: column; }
.adm-log-row {
  display: flex; align-items: baseline; gap: 12px;
  padding: 9px 0; border-top: 1px solid var(--border);
  font-size: var(--fs-xs); line-height: 1.5;
}
.adm-log-row:first-child { border-top: none; }
.adm-log-when { flex: none; width: 108px; color: var(--text-3); font-variant-numeric: tabular-nums; }
.adm-log-txt { flex: 1; min-width: 0; color: var(--text-2); }
.adm-log-txt strong { color: var(--text); font-weight: 600; }
.adm-log-sub { color: var(--text-3); }

/* --- Système : état de la configuration -------------------------- */
/* Un rail coloré à gauche, plutôt qu'une ligne entière teintée :
   quatre lignes rouges côte à côte se lisent comme une panne
   générale, alors qu'il s'agit de quatre réglages indépendants. */
.adm-cfg { align-items: flex-start; padding-left: 11px; border-left: 3px solid transparent; }
.adm-cfg.is-ok { border-left-color: var(--success); }
.adm-cfg.is-bad { border-left-color: var(--danger); }
.adm-cfg.is-opt { border-left-color: var(--warning); }
.adm-cfg .adm-avatar { width: 26px; height: 26px; background: transparent; border: none; }
.adm-cfg.is-ok .adm-avatar { color: var(--success); }
.adm-cfg.is-bad .adm-avatar { color: var(--danger); }
.adm-cfg.is-opt .adm-avatar { color: var(--warning); }
.adm-cfg .adm-name { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.adm-cfg .adm-mail { white-space: normal; overflow: visible; }

.adm-key {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 11px; font-weight: 600; padding: 1px 6px; border-radius: 4px;
  background: var(--surface-2); border: 1px solid var(--border); color: var(--text-2);
}
/* La commande à copier : sélectionnable d'un geste, et elle défile
   plutôt que de casser la mise en page sur téléphone. */
.adm-fix { margin-top: 6px; }
.adm-fix code {
  display: block; overflow-x: auto; white-space: pre;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 11px; padding: 7px 10px; border-radius: var(--r-sm);
  background: var(--bg-deep, var(--surface-2)); border: 1px solid var(--border); color: var(--text-2);
  user-select: all;
}

/* Carte d'alerte : un liseré, pas un aplat — le contenu doit rester
   lisible, c'est l'encadré qui signale. */
.adm-warn { border-color: color-mix(in srgb, var(--danger) 45%, var(--border)); }
.adm-warn .card-title { color: var(--danger); }
.adm-warn .card-title svg { color: var(--danger); }

/* --- Écrans étroits ----------------------------------------------- */
/* Une ligne de membre porte jusqu’à deux listes déroulantes et un
   bouton. En dessous de ~860 px, tout tenir sur un rang ne comprime pas
   les actions — elles ont une largeur mini — mais l’IDENTITÉ : l’adresse
   se réduisait à « benjamin.deloi… » sur un écran de portable pourtant
   large. Les actions passent donc sous le nom, alignées sur lui. */
@media (max-width: 860px) {
  .adm-row { flex-wrap: wrap; }
  .adm-id { flex: 1 1 auto; }
  .adm-role { order: 3; }
  .adm-actions { order: 4; width: 100%; flex-wrap: wrap; padding-left: 44px; }
  .adm-select { flex: 1 1 auto; max-width: none; }
}

/* Téléphone : plus de place pour un retrait, et le journal passe en
   deux lignes plutôt qu’en deux colonnes. */
@media (max-width: 560px) {
  .adm-actions { padding-left: 0; }
  /* Les deux listes remplissent déjà leur rang : le retrait se retrouve
     seul sur un troisième. Collé à droite, il se lit comme la fin de la
     ligne plutôt que comme un bouton égaré. */
  .adm-x { margin-left: auto; }
  .adm-log-row { flex-direction: column; gap: 2px; }
  .adm-log-when { width: auto; }
  .adm-club-body { padding-left: 0; }
}

/* ------------------------------------------------------------
   Ici vivait tout ce qu'il fallait pour rendre supportable une barre
   d'onglets trop courte : fondus de bord en `mask-image`, onglets
   resserrés au pixel, gouttière réduite à 1 px, et du JS pour ramener
   l'onglet actif dans le champ. Onze destinations ne tiennent pas sur
   une ligne de 880 px — aucun réglage n'y changeait rien, et on lisait
   « c'est cassé » là où il fallait lire « ça défile ».

   Elles tiennent dans une colonne. Voir la section suivante.
   ------------------------------------------------------------ */

/* ============================================================
   COLONNE DE NAVIGATION (ordinateur / tablette)
   Onze destinations ne tiennent pas sur une ligne de 880 px — la barre
   d'onglets défilait horizontalement, ce que personne ne devine et que
   rien ne rend agréable. Une colonne en accueille trente sans effort,
   et permet ce qu'une ligne interdisait : les GROUPER. « Aujourd'hui,
   Plan, Activités, Progression » ne sont pas de même nature que « Guide »
   ou « Administration », et l'oeil le voit maintenant sans lire.

   Trois largeurs, une seule logique :
     · ≥ 1024 px — colonne complète, intitulés de groupe visibles ;
     · 769–1023 px — colonne réduite aux icônes (68 px). C'est la plage
       où la barre horizontale souffrait le plus ; on préfère une colonne
       muette mais entière à une ligne tronquée ;
     · < 769 px — la colonne disparaît, la barre basse prend le relais.
       Elle marche très bien, elle ne bouge pas.

   Le décalage du contenu se fait par `padding-left` sur `body` : la
   topbar est collante à l'intérieur de `body`, elle suit donc toute
   seule, et les plein-écrans (mode séance, récap, carte) restent en
   `position: fixed` par rapport au VIEWPORT — ils recouvrent la colonne,
   ce qui est exactement ce qu'on veut d'un écran qu'on lit en courant.
   cf. js/ui.js (clics, groupes vides) et index.html (#sidenav)
   ============================================================ */

:root { --nav-w: 232px; }

.sidenav { display: none; }

@media (min-width: 769px) {
  body { padding-left: var(--nav-w); }

  .sidenav {
    position: fixed;
    top: 0; left: 0; bottom: 0;
    width: var(--nav-w);
    z-index: 120;
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 14px 12px calc(14px + env(safe-area-inset-bottom));
    background: var(--surface);
    border-right: 1px solid var(--border);
    overflow-y: auto;
    overscroll-behavior: contain;
  }

  /* La marque ramène à « Aujourd'hui » : c'est ce qu'on attend d'un
     logo dans une app, et ça évite un onglet de plus. */
  .sidenav-brand {
    display: flex; align-items: center; gap: 10px;
    padding: 6px 10px 18px;
    background: none; border: none; cursor: pointer;
    color: var(--text); font: inherit; font-size: var(--fs-lg); font-weight: 600;
    letter-spacing: -0.01em;
  }
  .sidenav-nav { display: flex; flex-direction: column; }

  .sidenav-group { display: flex; flex-direction: column; gap: 1px; margin-bottom: 16px; }
  .sidenav-group-lab {
    padding: 0 10px 6px;
    font-size: 10.5px; font-weight: 600; letter-spacing: 0.07em;
    text-transform: uppercase; color: var(--text-3);
  }

  /* Le pied porte le profil : une destination comme les autres, mais
     qu'on ne cherche pas au milieu des séances. */
  .sidenav-foot {
    margin-top: auto;
    padding-top: 12px;
    border-top: 1px solid var(--border);
  }

  /*  LE BADGE DE PROFIL — descendu de la barre du haut (cf. index.html).
      Il garde son avatar et son identité, mais prend la forme d'une
      entrée de menu : c'est ce qu'il est devenu. */
  .sidenav-foot .nav-me {
    display: flex; align-items: center; gap: 10px;
    width: 100%; padding: 7px 8px;
    border: none; border-radius: var(--r-md);
    background: transparent; color: var(--text);
    font: inherit; text-align: left; cursor: pointer;
    transition: background 0.15s ease;
  }
  .sidenav-foot .nav-me:hover { background: var(--surface-2); }
  .sidenav-foot .nav-me.active { background: var(--surface-2); }
  .sidenav-foot .nav-me .topbar-avatar { width: 30px; height: 30px; font-size: 15px; }
  .sidenav-foot .nav-me .topbar-id { flex: 1; min-width: 0; }
  .sidenav-foot .nav-me .topbar-name,
  .sidenav-foot .nav-me .topbar-sub { max-width: 100%; }
  /*  La pastille garde sa taille : `align-self` l'empêche de s'étirer
      sur toute la colonne d'identité, qui est un conteneur flex. */
  .sidenav-foot .nav-me .role-chip-header { align-self: flex-start; margin-top: 3px; }

  /* --- Les entrées ---------------------------------------------------
     `.tab-btn` vient de styles.css, taillé pour un onglet horizontal
     (rayon en haut, soulignement du bas). On reprend tout à zéro plutôt
     que de corriger propriété par propriété. */
  .sidenav .tab-btn {
    display: flex; align-items: center; gap: 10px;
    width: 100%; min-height: 36px;
    padding: 7px 10px;
    border: none; border-radius: var(--r-md);
    background: transparent; color: var(--text-2);
    font-size: var(--fs-sm); font-weight: 500; text-align: left;
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease;
  }
  .sidenav .tab-btn:hover { background: var(--surface-2); color: var(--text); }
  .sidenav .tab-btn [data-icon] { color: var(--text-3); font-size: 16px; display: inline-flex; flex-shrink: 0; }

  /*  L'ENTRÉE ACTIVE — une touche enfoncée, un texte plein. Le texte reste
      à l'encre : la couleur, dans cette app, dit une discipline ou un état
      (zone, réussite, alerte). Seule l'icône prend le bleu d'accent, celui
      de « sélectionné » partout ailleurs (décision du 07/10/2026). */
  .sidenav .tab-btn.active,
  [data-theme="light"] .sidenav .tab-btn.active {
    position: relative;
    background: var(--sunk);
    box-shadow: var(--elev-pressed);
    color: var(--text);
    font-weight: 600;
    border: none;
  }
  .sidenav .tab-btn.active [data-icon] { color: var(--accent); }

  .sidenav-lab { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

  /* L'écran de chargement masque déjà topbar et contenu : la colonne
     ne doit pas apparaître seule avant que les données soient là. */
  body.is-loading .sidenav { visibility: hidden; }
}

/* --- Colonne réduite aux icônes ------------------------------------
   UNE CLASSE, PAS UNE PLAGE DE LARGEURS. C'était une règle de
   tablette : sous 1024 px, pas le choix. C'est resté vrai, mais ça ne
   suffisait plus — sur un grand écran aussi on veut parfois rendre ces
   232 px au contenu, et ce choix-là se garde d'une visite à l'autre.
   La décision est donc prise en JavaScript (cf. js/ui.js : largeur
   disponible OU volonté de l'athlète), posée sur <html>, et appliquée
   ici une seule fois pour les deux cas. Le script d'avant-peinture
   d'index.html pose la même classe avant le premier pixel.         */
@media (min-width: 769px) {
  :root.nav-mini { --nav-w: 68px; }

  .nav-mini .sidenav { padding-left: 10px; padding-right: 10px; align-items: stretch; }
  .nav-mini .sidenav-lab { display: none; }
  /* Sans libellé, l'intitulé de groupe n'a plus rien à intituler : il
     devient un simple filet de séparation. */
  .nav-mini .sidenav-group-lab {
    padding: 0; height: 1px; margin: 0 6px 8px;
    background: var(--border); overflow: hidden; text-indent: -999px;
  }
  .nav-mini .sidenav-group:first-child .sidenav-group-lab { display: none; }
  .nav-mini .sidenav-brand { justify-content: center; padding: 6px 0 16px; }
  .nav-mini .sidenav .tab-btn { justify-content: center; padding: 9px 0; gap: 0; }
  .nav-mini .sidenav .tab-btn [data-icon] { font-size: 18px; }
  .nav-mini .sidenav .tab-btn.active { background: var(--sunk); }

  /* Le badge se réduit à son avatar : le nom, l'objectif et le rôle
     n'entrent pas dans 68 px, et les tronquer ne dirait rien. */
  .nav-mini .sidenav-foot .nav-me { justify-content: center; padding: 8px 0; gap: 0; }
  .nav-mini .sidenav-foot .nav-me .topbar-id { display: none; }
}

/* ============================================================
   BARRE DU HAUT — bouton de repli, fil d'Ariane, actions

   Elle portait l'identité de l'athlète dans son coin le plus visible,
   pour répéter une chose qu'il sait déjà. Elle porte maintenant
   l'endroit où il se trouve, qui n'était écrit nulle part : la colonne
   marque bien l'onglet actif, mais elle est hors du regard quand on lit
   le contenu, et repliée elle ne montre qu'une icône.
   cf. index.html (#crumbs, #nav-toggle) et js/ui.js (syncCrumbs)
   ============================================================ */
.topbar-inner { justify-content: flex-start; gap: 10px; }
.topbar-actions { margin-left: auto; }

/*  LE BOUTON DE REPLI N'EXISTE QU'AU-DESSUS DE 1024 px. En dessous, la
    colonne est déjà réduite aux icônes et il ne pourrait rien changer ;
    sous 769 px, il n'y a plus de colonne du tout. */
.nav-toggle { display: none; }
@media (min-width: 1024px) { .nav-toggle { display: inline-flex; } }

/*  LE FIL D'ARIANE EST UNE AFFAIRE D'ORDINATEUR, comme la colonne qu'il
    accompagne. Sur téléphone, la barre basse marque déjà l'onglet actif
    et le détail d'une séance a son propre bouton de retour : un fil de
    plus prendrait de la hauteur à un en-tête collant, pour redire ce
    qui est déjà dit. */
.crumbs { display: none; }
@media (min-width: 769px) {
  .crumbs {
    display: flex; align-items: center; gap: 6px;
    min-width: 0; overflow: hidden;
    font-size: var(--fs-sm);
  }
  .crumb {
    max-width: 22ch;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    font: inherit;
  }
  .crumb-dim { color: var(--text-3); }
  .crumb-link {
    padding: 2px 6px; margin: 0 -2px;
    border: none; border-radius: var(--r-sm);
    background: transparent; color: var(--text-2);
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease;
  }
  .crumb-link:hover { background: var(--surface-2); color: var(--text); }
  .crumb-now { color: var(--text); font-weight: 600; }
  .crumb-sep { display: inline-flex; color: var(--text-3); font-size: 12px; flex-shrink: 0; }
}

/*  LE NOM DE L'APP AU CENTRE DE LA BARRE, sous 769 px seulement (au-dessus,
    la colonne porte déjà le logo). Centré sur la barre et non sur l'espace
    restant : à gauche il n'y a rien, à droite l'icône de synchro — un
    centrage « flex » le décalerait. Hauteur de barre tenue par un minimum,
    puisque le logo, sorti du flux, ne la donne plus. */
.topbar-logo { display: none; }
@media (max-width: 768px) {
  .topbar-inner { position: relative; min-height: 50px; }
  .topbar-logo {
    position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
    display: inline-flex; align-items: center; gap: 8px;
    padding: 4px 6px; border: none; border-radius: var(--r-md);
    background: transparent; cursor: pointer;
  }
  .topbar-logo .brand-mark { width: 26px; height: 26px; }
  .topbar-logo .brand-word { height: 18px; }
}

/* ============================================================
   SUIVI EN DIRECT — bandeau dans l'écran de séance (js/live.js)
   Le bouton n'est pas mis en avant : partager sa position est un
   geste qu'on fait quand on le décide, pas une action principale
   de l'écran. Il reste donc discret tant qu'il dort, et devient
   visible — point vert, cadre teinté — une fois actif, parce que
   là il faut qu'on n'oublie pas qu'on émet.
   ============================================================ */
.pl-live { margin-top: 12px; }

.lv-start {
  width: 100%; display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 10px 14px; border-radius: var(--r-md);
  background: transparent; border: 1px dashed var(--border-strong);
  color: var(--text-2); font: inherit; font-size: var(--fs-sm); font-weight: 600;
  cursor: pointer; transition: color .15s, background .15s;
}
.lv-start:hover { color: var(--text); background: var(--surface-2); }
.lv-start:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.lv-start svg { width: 15px; height: 15px; }

.lv-on {
  border-radius: var(--r-md); padding: 11px 13px;
  background: color-mix(in srgb, var(--success) 9%, transparent);
  border: 1px solid color-mix(in srgb, var(--success) 38%, var(--border));
}
.lv-head { display: flex; align-items: center; gap: 8px; font-size: var(--fs-sm); }
.lv-head strong { font-weight: 700; }
.lv-left { margin-left: auto; font-size: var(--fs-xs); color: var(--text-3); font-variant-numeric: tabular-nums; }

/* Le point dit l'état de l'émission, et lui seul : vert qui bat = ça
   part ; orange fixe = ça ne part plus. On ne l'anime pas quand c'est
   perdu — une pastille qui clignote joyeusement pendant une coupure
   réseau raconterait l'inverse de ce qui se passe. */
.lv-dot {
  width: 9px; height: 9px; border-radius: 50%; flex: none;
  background: var(--success); animation: lv-pulse 1.8s ease-in-out infinite;
}
.lv-dot.is-lost { background: var(--warning); animation: none; }
@keyframes lv-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .3; } }
@media (prefers-reduced-motion: reduce) { .lv-dot { animation: none; } }

.lv-sub { margin: 5px 0 0; font-size: var(--fs-xs); color: var(--text-2); line-height: 1.45; }
.lv-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.lv-actions .btn { flex: 1 1 auto; }

/* ------------------------------------------------------------
   ACTIVITÉ LIBRE & FLUX D'ACTIVITÉS
   Deux écrans, un même geste : choisir un sport et partir.
     · l'ENREGISTREUR (#freerec) réutilise la feuille du mode séance
       (.pl-*) — c'est le même plein écran, tenu en main, lu en courant.
       Il n'ajoute que ce qui lui est propre : le sélecteur de sport et
       un chrono qui prend toute la largeur, faute de blocs à afficher ;
     · le FLUX (.feed-*) est la page d'atterrissage d'après-sortie : le
       lanceur en haut, le bilan du mois, puis la ligne de temps.
   cf. js/free-activity.js et js/feed.js
   ------------------------------------------------------------ */

/* --- Sélecteur de sport (écran de préparation) --- */
.fa-picker { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }
@media (max-width: 520px) { .fa-picker { grid-template-columns: repeat(3, 1fr); } }
.fa-sport {
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  padding: 12px 6px; cursor: pointer;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-md);
  color: var(--text-2); font: inherit; font-size: var(--fs-xs); font-weight: 600;
  transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease;
}
.fa-sport:hover { border-color: var(--border-strong); color: var(--text); }
.fa-sport-ico { font-size: 22px; display: inline-flex; color: var(--sport, var(--text-3)); }
.fa-sport-lab { line-height: 1.2; text-align: center; }
/* Le sport choisi prend sa teinte de discipline : c'est le seul endroit
   de cet écran où la couleur porte une information. */
.fa-sport.active {
  color: var(--text);
  border-color: color-mix(in srgb, var(--sport) 55%, transparent);
  background: color-mix(in srgb, var(--sport) 12%, transparent);
}

.fa-prep { display: flex; flex-direction: column; align-items: center; gap: 12px; flex: 1; justify-content: center; }
.fa-nogps {
  display: inline-flex; align-items: center; gap: 8px; text-align: left;
  font-size: var(--fs-xs); color: var(--text-2);
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-md); padding: 9px 12px;
}
.fa-nogps svg { flex: none; color: var(--text-3); }

/* --- Enregistrement en cours ---
   Le chrono remplace le compte à rebours du mode séance : c'est le seul
   chiffre qu'on cherche d'un coup d'oeil, bras ballant, en plein effort. */
.fa-clock { display: flex; flex-direction: column; align-items: center; gap: 2px; padding: 8px 0 2px; }
.fa-clock-lab { font-size: var(--fs-xs); color: var(--text-3); text-transform: uppercase; letter-spacing: 0.06em; font-weight: 600; }
.fa-clock-val { font-size: 68px; font-weight: 600; letter-spacing: -0.03em; line-height: 1; font-variant-numeric: tabular-nums; }
@media (max-width: 420px) { .fa-clock-val { font-size: 56px; } }
.fa-rec.is-paused .fa-clock-val { color: var(--text-2); }
.fa-rec .pl-kicker { display: inline-flex; align-items: center; gap: 7px; text-transform: none; letter-spacing: 0; color: var(--sport); }
.fa-rec .pl-kicker svg { width: 15px; height: 15px; }
.fa-gps { margin-top: 2px; }
/* Tour / pause / terminer : le bouton de tour est étroit, c'est un
   repère qu'on pose, pas une décision. */
.fa-controls { grid-template-columns: 56px 1fr 1fr; margin-top: auto; }
.fa-sheet .pl-controls .btn { min-height: 56px; }
.fa-sheet .pl-paused { align-self: center; }

/* --- Page « Mes activités » : le lanceur --- */
.feed-hero {
  margin-top: 4px; padding: 18px 20px 20px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg);
}
.feed-hero-title { display: flex; align-items: center; gap: 9px; margin: 0; font-size: var(--fs-lg); font-weight: 600; }
.feed-hero-title svg { color: var(--text-3); }
.feed-hero-sub { margin: 6px 0 0; font-size: var(--fs-sm); color: var(--text-2); line-height: 1.55; max-width: 60ch; }
.feed-sports { display: grid; grid-template-columns: repeat(7, 1fr); gap: 8px; margin-top: 16px; }
@media (max-width: 720px) { .feed-sports { grid-template-columns: repeat(4, 1fr); } }
@media (max-width: 420px) { .feed-sports { grid-template-columns: repeat(3, 1fr); } }
.feed-sport {
  display: flex; flex-direction: column; align-items: center; gap: 7px;
  padding: 13px 4px; cursor: pointer; font: inherit;
  font-size: var(--fs-xs); font-weight: 600; color: var(--text-2); text-align: center;
  background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--r-md);
  transition: border-color 0.15s ease, color 0.15s ease, transform 0.1s ease, background 0.15s ease;
}
.feed-sport:hover {
  color: var(--text); background: color-mix(in srgb, var(--sport) 10%, var(--surface-2));
  border-color: color-mix(in srgb, var(--sport) 45%, transparent);
}
.feed-sport:active { transform: translateY(1px); }
.feed-sport-ico { font-size: 21px; display: inline-flex; color: var(--sport); }
.feed-sport-lab { line-height: 1.25; }

/* Enregistrement déjà lancé : la page ne propose plus d'en démarrer un
   second, elle ramène à celui qui tourne. */
.feed-hero-live {
  display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
  border-color: color-mix(in srgb, var(--success) 40%, var(--border));
  background: color-mix(in srgb, var(--success) 7%, var(--surface));
}
.feed-hero-live .feed-hero-txt { flex: 1 1 260px; }
.feed-hero-live .feed-hero-title svg { color: var(--success); }

/* --- En-tête : titre à gauche, période à droite ---
   La période règle toute la page (bilan compris) : elle se pose à côté
   du titre, pas dans une barre de filtres. Centrée verticalement sur le
   titre ; sous 560 px, elle passe dessous, sur toute la largeur. */
.feed-head { align-items: center; }
.feed-head .segmented { margin: 0; }
.feed-seg-period .segmented-btn { padding-left: 12px; padding-right: 12px; }
@media (max-width: 560px) {
  .feed-head .feed-seg-period { width: 100%; }
  .feed-head .feed-seg-period .segmented-btn { flex: 1 1 0; padding-left: 4px; padding-right: 4px; }
}

/* --- Bilan par sport ---
   Des cartes, pas un tableau : chaque sport se lit d'un bloc, et le bloc
   est cliquable — il filtre le flux sur ce sport. La première carte,
   « Tous les sports », porte le total et remet le filtre à zéro.
   `auto-fit` les met côte à côte quand la place existe et les range en
   2 × 2 sur un téléphone, sans point de rupture à maintenir. */
.feed-bysport {
  display: grid; gap: 10px; margin-top: 4px;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 150px), 1fr));
}
.feed-sportcard {
  display: flex; flex-direction: column; gap: 8px;
  padding: 12px 14px; text-align: left; font: inherit; color: inherit; cursor: pointer;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg);
  border-left: 3px solid var(--sport, var(--border));
  transition: border-color 0.15s ease, background 0.15s ease;
}
.feed-sportcard:hover { background: var(--surface-2); }
.feed-sportcard.is-active {
  background: color-mix(in srgb, var(--sport) 9%, var(--surface));
  border-color: color-mix(in srgb, var(--sport) 45%, var(--border));
  border-left-color: var(--sport);
}
.feed-sportcard-head {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: var(--fs-sm); font-weight: 600; color: var(--sport, var(--text));
}
.feed-sportcard-head svg { width: 16px; height: 16px; }
.feed-sportcard-nums { display: flex; gap: 6px 18px; flex-wrap: wrap; }
.feed-sportcard-nums > span { display: flex; flex-direction: column; gap: 1px; }
.feed-sportcard-nums strong { font-size: var(--fs-lg); font-weight: 600; font-variant-numeric: tabular-nums; letter-spacing: -0.01em; }
.feed-sportcard-nums span span { font-size: var(--fs-xs); color: var(--text-3); }
/*  Téléphone : deux cartes par rangée, 150 px chacune. Trois chiffres
    empilés sur leur étiquette y prenaient quatre lignes ; en ligne
    (« 4 sorties · 4h · 37,4 km »), deux suffisent. « de sport » et
    « parcourus » tombent : l'unité (h, km, m) dit déjà ce que c'est. */
@media (max-width: 480px) {
  .feed-sportcard { padding: 10px 12px; gap: 6px; }
  .feed-sportcard-nums { gap: 2px 10px; }
  .feed-sportcard-nums > span { flex-direction: row; align-items: baseline; gap: 4px; }
  .feed-sportcard-nums strong { font-size: var(--fs-md); }
  .feed-sportcard-nums .feed-sportcard-sec { display: none; }
}

.feed-toolbar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 18px 0 6px; }
.feed-toolbar .segmented { margin: 0; }
.segmented-count { margin-left: 6px; color: var(--text-3); font-variant-numeric: tabular-nums; }

/* --- Ligne de temps --- */
.feed-day {
  margin: 18px 0 8px; font-size: var(--fs-xs); font-weight: 600;
  color: var(--text-3); text-transform: uppercase; letter-spacing: 0.06em;
}
.feed-list > .feed-day:first-child { margin-top: 4px; }
.feed-row {
  display: flex; align-items: flex-start; gap: 13px;
  padding: 13px 15px; margin-bottom: 8px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-md);
  transition: border-color 0.15s ease, background 0.15s ease;
}
.feed-row.is-openable { cursor: pointer; }
.feed-row.is-openable:hover { border-color: var(--border-strong); background: var(--surface-2); }
.feed-row .sport-glyph { margin-top: 1px; }
.feed-main { flex: 1; min-width: 0; }
.feed-title { font-size: var(--fs-md); font-weight: 600; line-height: 1.3; overflow-wrap: anywhere; }
/* Durée, distance, allure, RPE : les points médians sont posés en CSS,
   la liste reste une liste et ne finit jamais par un séparateur seul. */
.feed-stats { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 3px; font-size: var(--fs-sm); color: var(--text-2); font-variant-numeric: tabular-nums; }
.feed-stats > span + span::before { content: "\00b7"; margin-right: 6px; color: var(--text-3); }
.feed-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.feed-actions { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; justify-content: flex-end; flex-shrink: 0; }
.feed-actions .btn-icon { padding-left: 8px; padding-right: 8px; }
/* Bouton fantôme qui tient la place de « Détail » (cf. row dans
   js/feed.js) : utile seulement quand les actions sont en colonne. */
.feed-act-ghost { display: none; visibility: hidden; pointer-events: none; }
@media (max-width: 620px) {
  .feed-row { flex-wrap: wrap; }
  .feed-actions { width: 100%; justify-content: flex-start; margin-top: 4px; }
}

/*  CE QUE LA CARTE MONTRE EN PLUS SUR UN GRAND ÉCRAN (cf. js/feed.js)
    Masqués par défaut, révélés par paliers plus bas. Les déclarer ici
    plutôt que dans la media query garde leur APPARENCE au même endroit
    que le reste du flux ; seule leur apparition dépend de la largeur. */
.feed-tiles, .feed-graph, .feed-thumb { display: none; }

/*  Les chiffres en BLOC, pas en rangée. Six tuiles à la file font 490 px
    et poussent le titre de la sortie à se replier sur quatre lignes : la
    carte passait de 101 px à 234 px de haut, ce qui est l'inverse du but.
    En 3 × 2, elles tiennent dans 250 px, se calent sur la hauteur de la
    vignette de parcours, et la rangée reste une rangée. */
/*  Colonnes à LARGEUR FIXE, pas `auto` : chaque carte est sa propre
    grille, et des colonnes calées sur leur contenu décalaient les
    chiffres d'une carte à l'autre (« 1:02:54 » plus large que « 1h35 »). */
.feed-tiles { grid-template-columns: repeat(3, var(--feed-tile-w, 84px)); column-gap: 14px; row-gap: 5px; flex-shrink: 0; }
.feed-tile { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.feed-tile > strong {
  font-size: var(--fs-md); font-weight: 600; line-height: 1.2;
  font-variant-numeric: tabular-nums; letter-spacing: -0.01em;
}
.feed-tile > span { font-size: 10.5px; color: var(--text-3); white-space: nowrap; }

.feed-graph { flex-direction: column; gap: 3px; flex-shrink: 0; }
.feed-graph-lab { font-size: 10.5px; color: var(--text-3); }
.feed-spark { width: 118px; height: 30px; display: block; }

/*  La vignette de parcours porte un fond et un cadre : sans eux, un tracé
    posé à même la carte flotte. Elle n'est pas cliquable à part — c'est
    la ligne entière qui ouvre le détail. */
.feed-thumb {
  flex-shrink: 0; padding: 3px;
  background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--r-sm);
}
.feed-route { width: 132px; height: 62px; display: block; }

/* La boîte de réception Strava vit sous le flux : un filet la sépare,
   elle ne se confond pas avec le carnet. */
#strava-inbox:not(:empty) { margin-top: 30px; padding-top: 22px; border-top: 1px solid var(--border); }
.feed-section-head .page-title { font-size: var(--fs-lg); }

/* ============================================================
   DENSITÉ EN GRAND ÉCRAN
   Dernière section du fichier, et c'est voulu : elle ne fait que
   RETOUCHER des composants définis plus haut, elle doit donc primer.

   LE PROBLÈME QU'ELLE RÉSOUT. Élargir `.container` (cf. --page-w) rend
   la place disponible, mais ne dit pas quoi en faire. Une colonne unique
   qu'on étire donne des lignes de 1300 px où le contenu tient à gauche
   et les boutons partent à droite, séparés par un désert — c'est pire
   que la colonne étroite d'avant.

   LA RÈGLE, donc : la largeur gagnée sert à montrer PLUS DE CHOSES, pas
   des choses plus larges. Concrètement : une carte de sortie en dit plus
   (parcours, chiffres, courbe d'allure), une grille de questions se range
   sur deux rangs, ce qui n'a rien à gagner à s'élargir est borné, et ce
   qui se lit comme du texte garde une mesure lisible.

   TOUT EST SOUS `min-width` : en dessous du palier, pas une déclaration
   ne s'applique, et le rendu mobile reste exactement celui d'avant.
   ============================================================ */

/* ------------------------------------------------------------
   DÉTAIL DE SÉANCE EN ONGLETS (cf. js/recap.js)

   Le détail empilait tout sur trois colonnes : chiffres, analyse, carte,
   profil, segments, courbe, blocs, splits. Il se range maintenant en
   rubriques (UITabs) : Synthèse · Splits · Carte · Résumé. Sous le
   titre, une ligne factuelle (distance · durée · allure · D+) reste en
   vue quel que soit l'onglet.

   Dans chaque rubrique, deux colonnes au plus (`.rcp-duo`), réglées sur
   la LARGEUR DU DÉTAIL (requête de conteneur sur .focus-view), pas sur
   l'écran — à 1440 px, le menu en prend déjà 232. Sous 820 px, une
   colonne, dans l'ordre du HTML.
   ------------------------------------------------------------ */
.focus-head-main { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.rcp-sub { font-variant-numeric: tabular-nums; }
.rcp-tabs .ptabs { margin-bottom: 16px; }
/*  Cinq onglets en 375 px : sans leurs icônes, ils tiennent sur la
    ligne au lieu de cacher « Résumé » hors de l'écran. */
@container (max-width: 440px) {
  .rcp-tabs .ptab { flex: 1 1 auto; justify-content: center; padding-left: 6px; padding-right: 6px; }
  .rcp-tabs .ptab svg { display: none; }
}
.rcp-panel { display: flex; flex-direction: column; gap: 18px; }
.rcp-duo { display: flex; flex-direction: column; gap: 18px; }
.rcp-duo-col { display: flex; flex-direction: column; gap: 18px; min-width: 0; }
.rcp-duo-col .pt-card, .rcp-panel > .pt-card { margin: 0; }

/* ------------------------------------------------------------
   SYNTHÈSE — le tableau d'affichage (cf. paint dans js/recap.js)
   Un bandeau à la teinte du sport (--sport, posée sur .rcp-panel) :
   trois chiffres qu'on lit de loin, la forme du parcours à côté, le
   reste en petit dessous. Les tailles suivent la LARGEUR DU DÉTAIL
   (cqw), comme les colonnes.
   ------------------------------------------------------------ */
.rcp-hero {
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas: "head route" "nums nums" "more more";
  gap: 14px 14px; padding: 16px;
  border-radius: var(--r-lg);
  border: 1px solid color-mix(in srgb, var(--sport) 34%, var(--border));
  background:
    radial-gradient(120% 140% at 0% 0%, color-mix(in srgb, var(--sport) 20%, transparent), transparent 62%),
    var(--surface);
}
.rcp-hero-head { grid-area: head; display: flex; align-items: center; flex-wrap: wrap; gap: 8px 10px; min-width: 0; }
.rcp-hero-date { font-size: var(--fs-sm); font-weight: 600; color: var(--text-2); }
.rcp-hero-badges { display: flex; flex-wrap: wrap; gap: 6px; }
.rcp-badge {
  --b: var(--text-3);
  display: inline-flex; align-items: center; gap: 6px; padding: 3px 10px; border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--b) 50%, transparent);
  background: color-mix(in srgb, var(--b) 14%, transparent);
  font-size: var(--fs-xs); font-weight: 600; color: var(--text); white-space: nowrap;
}
.rcp-badge i { width: 8px; height: 8px; border-radius: 50%; background: var(--b); flex: none; }
.rcp-badge.is-ok { --b: var(--success); }
.rcp-badge.is-warn { --b: var(--warning); }
.rcp-badge.is-off { --b: var(--danger); }

.rcp-hero-nums { grid-area: nums; display: grid; grid-template-columns: repeat(var(--n, 3), minmax(0, 1fr)); gap: 10px 12px; align-items: start; }
.rcp-big { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.rcp-big-lab, .rcp-mini-lab { font-size: var(--fs-xs); font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-3); }
.rcp-big-val {
  font-size: clamp(22px, 7cqw, 56px); font-weight: 700; line-height: 1; letter-spacing: -0.035em;
  font-variant-numeric: tabular-nums; white-space: nowrap; color: var(--text);
}
.rcp-big-val small { margin-left: 0.22em; font-size: 0.4em; font-weight: 600; letter-spacing: 0; color: var(--text-2); }
.rcp-big-sub, .rcp-mini-sub { font-size: var(--fs-xs); color: var(--text-3); }

/* La forme du parcours : un bouton vers l'onglet Carte quand il existe. */
.rcp-hero-route { grid-area: route; align-self: start; display: block; width: clamp(84px, 22cqw, 150px); height: clamp(48px, 12.5cqw, 86px); padding: 0; border: 0; border-radius: var(--r-md); background: none; color: var(--sport); }
button.rcp-hero-route { cursor: pointer; transition: transform .15s ease; }
button.rcp-hero-route:hover { transform: scale(1.04); }
button.rcp-hero-route:focus-visible { outline: 2px solid var(--brand-green); outline-offset: 3px; }
.rcp-hero-route svg { display: block; width: 100%; height: 100%; overflow: visible; }
.rcp-route-glow, .rcp-route-line { fill: none; stroke: currentColor; stroke-linecap: round; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.rcp-route-glow { stroke-width: 9; opacity: 0.2; }
.rcp-route-line { stroke-width: 3; }
.rcp-route-a { fill: var(--success); stroke: var(--surface); stroke-width: 2; }
.rcp-route-z { fill: var(--text); stroke: var(--surface); stroke-width: 2; }

.rcp-hero-more {
  grid-area: more; display: grid; grid-template-columns: repeat(auto-fit, minmax(112px, 1fr)); gap: 12px 16px;
  padding-top: 14px; border-top: 1px solid color-mix(in srgb, var(--sport) 20%, var(--border));
}
.rcp-mini { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.rcp-mini strong { font-size: var(--fs-lg); font-weight: 600; letter-spacing: -0.01em; font-variant-numeric: tabular-nums; }

@container (min-width: 700px) {
  .rcp-hero { grid-template-areas: "head route" "nums route" "more more"; gap: 20px 32px; padding: 22px 26px; }
  .rcp-hero-nums { gap: 12px 28px; }
  .rcp-big { gap: 8px; }
  .rcp-hero-route { align-self: center; width: clamp(190px, 26cqw, 320px); height: clamp(110px, 15cqw, 180px); }
  .rcp-hero-more { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
}

/* Ce dont on a été capable : les trois tuiles à la teinte du sport. */
.rcp-tab-summary .rcp-s-best .rcp-tile {
  border-color: color-mix(in srgb, var(--sport) 30%, var(--border));
  background: color-mix(in srgb, var(--sport) 7%, var(--surface));
  box-shadow: inset 3px 0 0 var(--sport);
  padding-left: 14px;
}
.rcp-tab-summary .rcp-s-best .rcp-tile-val { font-size: clamp(17px, 2.5cqw, 26px); font-weight: 700; white-space: nowrap; }
.rcp-tab-summary .eff-bar { height: 16px; border-radius: 8px; }

/*  La carte ne prend pas toute la hauteur que lui donnerait sa largeur
    (62 % de 1 300 px = 800 px : plus d'un écran). Bornée à la fenêtre,
    elle laisse voir la barre des blocs et le profil juste dessous.
    `!important` : la hauteur de départ est posée en ligne au montage
    (cf. mount dans js/map.js). */
/*  La distance du parcours est déjà sous le titre. */
.rcp-tab-map .rcp-map > .log-label { display: none; }
.rcp-tab-map .rcp-map .trace-map { height: clamp(240px, min(56vh, 85cqw), 560px) !important; }

@container (min-width: 820px) {
  .rcp-duo { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 18px 24px; align-items: start; }
  .rcp-duo.is-single { grid-template-columns: minmax(0, 1fr); }
  /*  Synthèse : deux rangées de deux colonnes égales (effort / ressenti,
      meilleures allures / puissance) sous le bandeau de tête. */
  .rcp-tab-summary .rcp-duo { gap: 22px 28px; }
  /*  Carte : le profil (graphique) prend la place, les montées une liste. */
  .rcp-tab-map .rcp-duo:not(.is-single) { grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); }
}

/*  LA CARTE DE SORTIE S'ENRICHIT PAR PALIERS.
    Trois blocs, trois seuils, et l'ordre n'est pas arbitraire : on ajoute
    d'abord ce qui se lit (les chiffres), puis ce qui se reconnaît (la
    forme du parcours), enfin ce qui se devine (la courbe d'allure). À
    chaque palier, la ligne est pleine sans être serrée.
    `align-items: center` accompagne le premier palier : une ligne haute
    de 62 px n'a plus de raison d'aligner ses blocs sur le haut.

    LA CARTE PASSE EN GRILLE À COLONNES NOMMÉES, de largeur fixe à droite
    du titre. En flex, un bloc absent (pas de tracé en natation, pas de
    « Détail ») faisait glisser tous les autres : les chiffres et les
    boutons ne tombaient plus les uns sous les autres. Ici, un bloc
    absent laisse sa colonne vide, et tout reste aligné d'une carte à
    l'autre ; seul le titre (1fr) absorbe la largeur restante. */
@media (min-width: 1240px) {
  .feed-row {
    display: grid; align-items: center; column-gap: 18px;
    grid-template-columns: 36px minmax(0, 1fr) auto var(--feed-act-w);
    grid-template-areas: "glyph main tiles actions";
    --feed-act-w: 180px;
  }
  .feed-row > .sport-glyph { grid-area: glyph; margin-top: 0; }
  .feed-row > .feed-main { grid-area: main; }
  .feed-row > .feed-tiles { grid-area: tiles; display: grid; }
  .feed-row > .feed-graph { grid-area: graph; }
  .feed-row > .feed-thumb { grid-area: thumb; }
  .feed-row > .feed-actions { grid-area: actions; flex-wrap: nowrap; justify-content: flex-start; }
  .feed-act-ghost { display: inline-flex; }
}
@media (min-width: 1460px) {
  .feed-row {
    grid-template-columns: 36px minmax(0, 1fr) auto 140px var(--feed-act-w);
    grid-template-areas: "glyph main tiles thumb actions";
  }
  .feed-thumb { display: block; }
}
@media (min-width: 1680px) {
  .feed-row {
    grid-template-columns: 36px minmax(0, 1fr) auto 118px 140px var(--feed-act-w);
    grid-template-areas: "glyph main tiles graph thumb actions";
  }
  .feed-graph { display: flex; }
}

@media (min-width: 1360px) {
  /*  LE CHECK-IN EN DEUX COLONNES.
      Quatre questions, une échelle de 1 à 5 chacune. Étirées sur toute la
      largeur, ces échelles donnaient des boutons de 162 px : on ne vise
      pas une note sur cinq comme on vise un bouton « Enregistrer », et un
      bouton large ne rend pas le geste plus facile — il rend seulement la
      rangée plus longue à parcourir des yeux. Deux par ligne rend aux
      boutons une taille de bouton, et met les quatre questions dans un
      seul regard.
      Le champ « FC de repos » et les actions restent sur toute la largeur :
      ce sont les conclusions de la carte, pas des questions. */
  .ci-form { display: grid; grid-template-columns: 1fr 1fr; gap: 12px 36px; }
  .ci-form > .ci-extra, .ci-form > .log-actions { grid-column: 1 / -1; }

  /*  LA SEMAINE DU PLAN prend TOUTE la largeur, comme la carte de semaine
      au-dessus d'elle : deux cartes empilées de largeurs différentes
      donnaient une page mal alignée (demande de Benjamin, 24/09/2026).
      Elle était bornée à 1080 px. */

  /*  LA MESURE DU TEXTE.
      Une carte peut faire 1300 px de large ; une ligne de texte, non. Au
      delà d'environ 70 caractères, l'œil rate le retour à la ligne
      suivante — c'est mesuré, et ça se sent. Ces quatre blocs sont des
      explications, pas des étiquettes : ils atteignaient 180 à 210
      caractères par ligne une fois la page élargie.
      Les autres textes de l'app portent déjà leur propre mesure
      (`.page-sub` 62ch, `.feed-hero-sub` 60ch) ou sont contraints par la
      grille qui les contient. */
  .week-focus-text, .load-footnote, .data-meta, .strava-note { max-width: 70ch; }
}

/* ------------------------------------------------------------
   PROFIL VITESSE-DURÉE (cf. js/speedprofile.js)
   Trois repères chiffrés, une courbe, le détail par durée. La courbe
   est en SVG inline : pas de dépendance, et elle suit les tokens de
   thème comme le reste.
   ------------------------------------------------------------ */
.sp-kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; margin-bottom: 12px; }
.sp-kpi { display: flex; flex-direction: column; gap: 2px; background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--r-md); padding: 10px 12px; }
.sp-kpi > strong { font-size: var(--fs-xl); font-weight: 600; letter-spacing: -0.01em; font-variant-numeric: tabular-nums; }
.sp-kpi > span { font-size: var(--fs-xs); color: var(--text-3); line-height: 1.35; }

/*  Tableau des records : durée · allure · distance · séance d'origine (un
    lien qui ouvre le détail — c'est ce qui permet de VÉRIFIER un record). */
.sp-rows { display: flex; flex-direction: column; margin-top: 14px; }
.sp-row {
  display: grid; grid-template-columns: 64px minmax(0, 1fr) minmax(0, 1fr) auto; align-items: center; gap: 12px;
  padding: 7px 0; border-top: 1px solid var(--border);
  font-size: var(--fs-sm); font-variant-numeric: tabular-nums;
}
.sp-row-head { border-top: none; padding-top: 0; font-size: 10.5px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-3); }
.sp-row-head > span:last-child { text-align: right; }
.sp-row-d { color: var(--text-3); }
.sp-row-m { color: var(--text-2); }
.sp-row-v { font-weight: 600; }
.sp-row-src { justify-self: end; font-size: var(--fs-xs); color: var(--text-3); white-space: nowrap; }
.sp-legend { display: flex; gap: 16px; flex-wrap: wrap; margin-top: 8px; font-size: var(--fs-xs); color: var(--text-3); }
.sp-legend span { display: inline-flex; align-items: center; gap: 6px; }
.sp-legend i { display: inline-block; width: 16px; height: 0; border-top: 2px solid var(--sport-run); }
.sp-legend i.sp-l-model { border-top: 2px dashed var(--text-3); }

/* Deux niveaux de commentaire : `note` explique ce qu'on regarde,
   `foot` dit ce que la mesure ne vaut pas. Le second est plus discret
   mais ne doit pas disparaître — c'est lui qui empêche de prendre une
   courbe basse pour un plafond. */
.sp-note { margin: 0 0 12px; font-size: var(--fs-sm); color: var(--text-2); line-height: 1.55; max-width: 70ch; }
.sp-note svg { width: 14px; height: 14px; vertical-align: -0.15em; color: var(--text-3); }
.sp-foot { margin: 12px 0 0; font-size: var(--fs-xs); color: var(--text-3); line-height: 1.5; max-width: 70ch; }

/* Repères tirés du profil vitesse-durée (cf. Targets.fromCritical) : ils
   SITUENT l'effort demandé, ils ne le chiffrent pas une fois de plus. La
   teinte d'accent les distingue des cibles de zone sans les rendre plus
   bruyants. */
.target-chip-cs { border-color: color-mix(in srgb, var(--accent) 35%, var(--border)); }
.target-chip-cs > span { color: var(--accent); }

/* ============================================================
   PROFIL EN RUBRIQUES — onglets (cf. index.html .ptabs, js/ui.js)
   Le soulignement est le VERT DU LOGO (--brand-green) : c'est la
   marque qui dit « tu es ici », pas une couleur sémantique. Sur
   téléphone, la barre défile horizontalement plutôt que de passer
   sur deux lignes — cinq intitulés ne tiennent pas en 375 px.
   ============================================================ */
.ptabs {
  display: flex; gap: 2px;
  margin: 0 0 18px;
  border-bottom: 1px solid var(--border);
  overflow-x: auto; overscroll-behavior-x: contain;
  scrollbar-width: none;
}
.ptabs::-webkit-scrollbar { display: none; }
.ptab {
  position: relative; flex: none;
  display: inline-flex; align-items: center; gap: 7px;
  padding: 10px 14px 12px;
  border: none; background: none; cursor: pointer;
  color: var(--text-2); font: inherit; font-size: var(--fs-md); font-weight: 600;
  white-space: nowrap;
  transition: color 0.15s ease;
}
.ptab svg { width: 16px; height: 16px; opacity: 0.8; }
.ptab::after {
  content: ""; position: absolute; left: 10px; right: 10px; bottom: -1px;
  height: 3px; border-radius: 3px 3px 0 0;
  background: var(--brand-green);
  transform: scaleX(0); transform-origin: center;
  transition: transform 0.2s ease;
}
.ptab:hover { color: var(--text); }
.ptab:hover::after { transform: scaleX(0.35); opacity: 0.5; }
.ptab[aria-selected="true"] { color: var(--text); }
.ptab[aria-selected="true"] svg { color: var(--brand-green); opacity: 1; }
.ptab[aria-selected="true"]::after { transform: scaleX(1); opacity: 1; }
.ptab:focus-visible { outline: 2px solid var(--brand-green); outline-offset: -3px; border-radius: var(--r-sm); }
@media (prefers-reduced-motion: reduce) { .ptab::after { transition: none; } }
@media (max-width: 480px) { .ptab { padding: 10px 11px 12px; font-size: var(--fs-sm); } }

.ptab-panel[hidden] { display: none; }
.ptab-panel:focus { outline: none; }
.ptab-panel > .card + .card, .ptab-panel > .card + div { margin-top: 0; }
.ptab-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 4px; }

/* ============================================================
   RENFO / PPG (cf. js/ppg.js)
   ============================================================ */
/* Mode séance : une série comptée affiche ses répétitions, pas un
   compte à rebours (cf. js/player.js, segments `manual`). */
.pl-step-left.pl-reps { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.pl-step-left.pl-reps > span { font-size: var(--fs-md); font-weight: 600; letter-spacing: 0; color: var(--text-2); text-transform: uppercase; }

/* Concepteur : exercices et circuits */
.dg-block.is-ex, .dg-block.is-circuit { --seg: var(--sport-renfo); }
.dg-ex { flex: 1 1 auto; min-width: 0; background: var(--surface); color: var(--text); border: 1px solid var(--border); border-radius: var(--r-sm); padding: 7px 8px; font-size: var(--fs-sm); font-family: inherit; }
.is-ex .dg-amount > select, .dg-item .dg-amount > select { width: auto; }
.dg-cue { margin: 0; font-size: var(--fs-xs); line-height: 1.45; color: var(--text-3); }
.dg-items { display: flex; flex-direction: column; gap: 6px; }
.dg-item { display: grid; grid-template-columns: 20px minmax(0, 1fr) minmax(0, 150px) 30px; gap: 6px; align-items: center; }
.dg-item-n { font-size: var(--fs-xs); font-weight: 700; color: var(--text-3); text-align: center; font-variant-numeric: tabular-nums; }
.dg-item-add { align-self: flex-start; }
@media (max-width: 480px) {
  .dg-item { grid-template-columns: 18px minmax(0, 1fr) 30px; }
  .dg-item .dg-amount { grid-column: 2 / 3; }
}
/* Cartes du profil : même rythme vertical que l'ancienne colonne
   (.profile-card-inner, styles.css), boutons à leur largeur. */
.ptab-panel .profile-card-inner > .card-title { margin-bottom: 0; }
.ptab-panel .profile-card-inner > .btn { align-self: flex-start; }
.adm-dev { margin: -6px 0 14px; }

/* ============================================================
   COHÉRENCE DES PAGES (revue du 24/09/2026)
   Chaque page s'ouvre sur le même titre (.page-head) ; la navigation
   interne passe par les onglets (.ptabs), les filtres par .segmented.
   ============================================================ */
/* Plan : le titre s'efface sur la page d'une séance, qui a son retour. */
#tab-week.session-open .plan-page-head { display: none; }
/* Titre accompagné d'une action à droite (club : code d'invitation). */
.page-head-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.prog-hero-text:empty { display: none; }


/* ============================================================
   PETITS GRAPHIQUES (cf. js/minichart.js)
   Lignes en SVG étiré (épaisseur fixe), points et graduations en HTML
   placés en % : rien ne se déforme, quelle que soit la largeur. Hauteur
   fixe (--mc-h) : un graphique ne grandit pas avec l'écran.
   ============================================================ */
.mc {
  display: grid; grid-template-columns: auto minmax(0, 1fr); grid-template-rows: var(--mc-h, 160px) auto;
  column-gap: 8px; margin: 10px 0 0;
}
.mc-y { position: relative; min-width: 34px; }
.mc-y-lab {
  position: absolute; right: 0; transform: translateY(-50%);
  font-size: 10.5px; color: var(--text-3); font-variant-numeric: tabular-nums; white-space: nowrap;
}
.mc-plot { position: relative; border-left: 1px solid var(--border); border-bottom: 1px solid var(--border); }
.mc-grid-line { position: absolute; left: 0; right: 0; height: 0; border-top: 1px dashed color-mix(in srgb, var(--border) 70%, transparent); }
.mc-svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.mc-dot {
  position: absolute; width: 8px; height: 8px; margin: -4px 0 0 -4px; border-radius: 50%;
  background: var(--mc-c, var(--accent)); box-shadow: 0 0 0 2px var(--surface);
}
.mc-dot.is-strong { width: 11px; height: 11px; margin: -5.5px 0 0 -5.5px; }
/* GRAPHIQUES D3 (js/d3charts.js) — un SVG à la taille réelle de la
   figure : courbes lissées, aire en dégradé, grille discrète, bulle au
   survol. La hauteur du tracé reste `--mc-h` ; la figure ajoute la bande
   des graduations. */
.mc.d3c { display: block; position: relative; height: calc(var(--mc-h, 160px) + 26px); margin: 10px 0 0; }
.mc.d3c.d3c-pmc { height: calc(var(--mc-h, 236px) + 24px); }
.d3c-svg { display: block; overflow: visible; }
.d3c-grid line, .d3c-gridline { stroke: color-mix(in srgb, var(--text) 9%, transparent); stroke-width: 1; shape-rendering: crispEdges; }
.d3c-base { stroke: color-mix(in srgb, var(--text) 22%, transparent); stroke-width: 1; shape-rendering: crispEdges; }
.d3c-lab { font-size: 10.5px; fill: var(--text-3); font-variant-numeric: tabular-nums; }
.d3c-line { fill: none; stroke-linecap: round; stroke-linejoin: round; }
.d3c-line.is-dashed { stroke-dasharray: 5 5; opacity: .7; }
.d3c-area { opacity: var(--o, 1); pointer-events: none; }
.d3c-area.is-flat { --o: .4; }
.d3c-dot { stroke: var(--surface); stroke-width: 2; }
.d3c-dot.is-ring { fill: var(--surface); stroke-width: 2.25; }
.d3c-dot.is-strong { stroke: var(--surface); stroke-width: 2.5; }
.d3c-halo { opacity: .22; }
.d3c-cross { stroke: color-mix(in srgb, var(--text) 38%, transparent); stroke-width: 1; stroke-dasharray: 3 3; pointer-events: none; shape-rendering: crispEdges; }
.d3c-mark { fill: none; stroke-width: 2.5; pointer-events: none; }
.d3c-mark.is-solid { stroke: var(--surface); stroke-width: 2; }
.d3c-hit { fill: transparent; cursor: crosshair; touch-action: pan-y; }
.d3c-flag { stroke-width: 1; shape-rendering: crispEdges; }
.d3c-flag.is-today { stroke: var(--text-2); stroke-dasharray: 2 3; }
.d3c-flag.is-race { stroke: var(--brand-green); }
.d3c-flag-lab { font-size: 10px; font-weight: 600; fill: var(--text-2); }
.d3c-flag-lab.is-race { fill: var(--brand-green); }
/* Le tracé se dessine, l'aire monte, les points apparaissent — une fois. */
.d3c-line.is-in { stroke-dasharray: 1; stroke-dashoffset: 1; animation: d3c-draw .9s cubic-bezier(.3, .7, .2, 1) forwards; }
.d3c-area.is-in { opacity: 0; animation: d3c-fade .7s ease-out .25s forwards; }
.d3c-dot.is-in { opacity: 0; transform-box: fill-box; transform-origin: center; animation: d3c-pop .35s ease-out forwards; }
@keyframes d3c-draw { to { stroke-dashoffset: 0; } }
@keyframes d3c-fade { to { opacity: var(--o, 1); } }
@keyframes d3c-pop { from { opacity: 0; transform: scale(.4); } to { opacity: 1; transform: scale(1); } }
@media (prefers-reduced-motion: reduce) {
  .d3c-line.is-in, .d3c-area.is-in, .d3c-dot.is-in { animation: none; opacity: var(--o, 1); stroke-dashoffset: 0; }
}
/* Bulle du survol */
.d3c-tip {
  position: absolute; top: 0; left: 0; z-index: 3; pointer-events: none;
  display: flex; flex-direction: column; gap: 1px; min-width: 76px; padding: 7px 10px; border-radius: 10px;
  background: var(--surface-2); border: 1px solid var(--border-strong); box-shadow: 0 8px 24px rgba(0, 0, 0, .28);
  font-size: var(--fs-xs); color: var(--text-2); font-variant-numeric: tabular-nums; white-space: nowrap;
}
.d3c-tip[hidden] { display: none; }
.d3c-tip strong { font-size: var(--fs-md); font-weight: 700; color: var(--text); line-height: 1.25; }
.d3c-tip-cap { display: flex; align-items: center; gap: 6px; color: var(--text-3); }
.d3c-tip-more { color: var(--text-3); }
.d3c-tip-row { display: flex; align-items: center; gap: 6px; }
.d3c-tip-row b { margin-left: auto; padding-left: 14px; color: var(--text); font-weight: 700; }
.d3c-tip-cap i, .d3c-tip-row i { flex: none; width: 8px; height: 8px; border-radius: 50%; }
.mc-x { grid-column: 2; position: relative; height: 20px; }
.mc-x-lab {
  position: absolute; top: 5px; transform: translateX(-50%);
  font-size: 10.5px; color: var(--text-3); white-space: nowrap; font-variant-numeric: tabular-nums;
}

/* Évolution des performances : trois repères chiffrés au-dessus du graphe
   (remplacent la liste de pastilles, qui s'allongeait sans fin). */
.perf-stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; margin-top: 8px; }
.perf-stats > div { display: flex; flex-direction: column; gap: 1px; background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--r-md); padding: 8px 10px; min-width: 0; }
.perf-stats span { font-size: 10.5px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-3); }
.perf-stats strong { font-size: var(--fs-md); font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.perf-stats em { font-style: normal; font-size: var(--fs-xs); color: var(--text-3); }
.perf-block + .perf-block { margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--border); }
@media (min-width: 1100px) {
  /*  Profils course et vélo côte à côte quand la place le permet. */
  .sp-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; align-items: start; }
  .sp-pair > .card { margin: 0; }
}
/* Repères du profil vitesse-durée : toujours sur une ligne, comme ceux de
   l'évolution des performances — empilés, ils prenaient un écran de téléphone. */
.sp-kpis { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 560px) {
  .sp-kpi { padding: 8px 10px; }
  .sp-kpi > strong { font-size: var(--fs-md); white-space: nowrap; }
}

/* ============================================================
   SENS DE PARCOURS (cf. js/map.js, drawArrows)
   Une pastille à la couleur du tracé, un chevron blanc, un liseré
   blanc : lisible sur le tracé comme sur n'importe quel fond de carte.
   Les flèches du reste du parcours s'effacent quand un bloc est mis
   en évidence — celui-ci garde les siennes, à sa couleur.
   ============================================================ */
.leaflet-marker-icon.tmap-arrow { background: none; border: 0; }
.tmap-arrow > span {
  display: flex; align-items: center; justify-content: center;
  width: 16px; height: 16px; border-radius: 50%;
  background: var(--c, #3b82f6); box-shadow: 0 0 0 1.5px #fff, 0 1px 3px rgba(0, 0, 0, 0.35);
}
.tmap-arrow svg { width: 12px; height: 12px; fill: none; stroke: #fff; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
.tmap-focusing .tmap-arrow:not(.is-focus) { opacity: 0.25; }


/* ============================================================
   CARTES À TA FAÇON (cf. js/map.js : BASES, resolveColor, Calques)
   ============================================================ */
/* Satellite : pas de désaturation — une photo désaturée perd ce qui la
   rend reconnaissable (l'eau, les champs, les forêts). */
.trace-map[data-base="imagery"] .leaflet-tile { filter: none; }

/* Légende du tracé. Toujours CLAIRE, comme la carte qu'elle décrit (la
   carte ne suit pas le thème, cf. BASES) : la rampe d'allure a été validée
   sur fond blanc, et son bleu nuit disparaîtrait sur une surface sombre. */
.tmap-legend {
  min-width: 170px; max-width: 240px; padding: 7px 9px 6px; border-radius: 8px;
  background: rgba(255, 255, 255, 0.94); color: #1f2937; box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
  font-size: 11px; line-height: 1.3;
}
.tmap-legend-title { font-weight: 700; margin-bottom: 5px; }
.tmap-legend-title span { font-weight: 500; color: #4b5563; }
.tmap-legend-bar { display: flex; gap: 2px; height: 8px; }
.tmap-legend-bar i { flex: 1; border-radius: 2px; }
.tmap-legend-ticks { position: relative; height: 14px; margin-top: 2px; font-variant-numeric: tabular-nums; }
.tmap-legend-ticks span { position: absolute; top: 0; transform: translateX(-50%); color: #374151; }
.tmap-legend-ends { display: flex; justify-content: space-between; gap: 8px; color: #6b7280; font-size: 10px; }
.tmap-legend-stop, .tmap-legend-kinds span { display: inline-flex; align-items: center; gap: 5px; }
.tmap-legend-stop { margin-top: 4px; color: #4b5563; }
.tmap-legend-stop i, .tmap-legend-kinds i { width: 14px; height: 4px; border-radius: 2px; display: inline-block; }
.tmap-legend-kinds { display: flex; flex-wrap: wrap; gap: 4px 10px; color: #1f2937; }
.tmap-legend-why { color: #4b5563; }

/* Bouton « Calques » du plein écran et son panneau. */
.tmap-layers { display: flex; flex-direction: column; align-items: flex-end; gap: 6px; }
.tmap-layers-btn {
  display: inline-flex; align-items: center; gap: 6px; padding: 6px 10px;
  border: 1px solid var(--border); border-radius: var(--r-md); cursor: pointer;
  background: var(--surface-2); color: var(--text); font: inherit; font-size: var(--fs-xs); font-weight: 600;
  box-shadow: var(--shadow-sm);
}
.tmap-layers-btn svg { width: 15px; height: 15px; }
.tmap-layers-btn[aria-expanded="true"] { border-color: var(--brand-green); }
.tmap-layers-panel {
  width: 250px; padding: 10px; border-radius: var(--r-md);
  background: var(--surface); border: 1px solid var(--border); box-shadow: var(--shadow-md);
}
.tmap-layers-panel[hidden] { display: none; }
.tmap-layers-lab { font-size: 10.5px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-3); margin: 0 0 5px; }
.tmap-layers-lab + .tmap-layers-row + .tmap-layers-lab { margin-top: 10px; }
.tmap-layers-row { display: flex; flex-wrap: wrap; gap: 4px; }
.tmap-layers-row button {
  flex: 1 1 auto; padding: 5px 8px; border-radius: var(--r-sm); cursor: pointer;
  border: 1px solid var(--border); background: var(--surface-2); color: var(--text-2);
  font: inherit; font-size: var(--fs-xs); font-weight: 600;
}
.tmap-layers-row button.is-on { background: var(--text); color: var(--bg); border-color: var(--text); }
.tmap-layers-save {
  width: 100%; margin-top: 10px; padding: 6px 8px; border-radius: var(--r-sm); cursor: pointer;
  border: 1px dashed var(--border-strong); background: transparent; color: var(--text); font: inherit; font-size: var(--fs-xs); font-weight: 600;
}
.tmap-layers-save:hover { background: var(--surface-2); }
.map-pref { margin-bottom: 10px; }

/* Attribution sur UNE ligne, dépliée au survol ou au toucher : complète,
   elle faisait deux lignes sur un téléphone et recouvrait la légende. Elle
   reste présente et lisible en entier — c'est une condition d'usage. */
.trace-map .leaflet-control-attribution {
  max-width: 46%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; cursor: help;
}
.trace-map .leaflet-control-attribution:hover,
.trace-map .leaflet-control-attribution:focus-within {
  max-width: calc(100% - 16px); white-space: normal;
}
/* Vignette : légende réduite à l'essentiel (les valeurs sont dans le plein écran). */
.trace-map:not(.tmap-big) .tmap-legend { min-width: 0; padding: 5px 7px; }
.trace-map:not(.tmap-big) .tmap-legend-ticks { display: none; }

/* Vie réelle (js/reallife.js) : semaine chargée, temps disponible, arrêts. */
.busy-panel { margin-top: 10px; padding: 12px; border-radius: var(--r-md); background: var(--surface-2); }
.busy-panel-title { margin: 0 0 10px; font-size: var(--fs-sm); color: var(--text-2); }
.busy-options { display: flex; flex-wrap: wrap; gap: 8px; }
.busy-options .btn { flex-direction: column; align-items: flex-start; gap: 2px; height: auto; padding-top: 8px; padding-bottom: 8px; }
.busy-sub { font-size: var(--fs-xs); font-weight: 400; color: var(--text-3); }
.limits-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); gap: 8px; margin-bottom: 8px; }
.limits-day { display: flex; flex-direction: column; gap: 4px; font-size: var(--fs-xs); color: var(--text-3); font-weight: 600; }
.rl-card .segmented { margin-bottom: 12px; }
.rl-check { display: flex; align-items: center; gap: 8px; font-size: var(--fs-sm); color: var(--text-2); align-self: end; padding-bottom: 12px; }
.rl-row + .rl-row { margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--border); }
.rl-what { margin: 0 0 10px; font-size: var(--fs-sm); line-height: 1.5; }
.rl-sub { margin: 0 0 8px; font-size: var(--fs-xs); color: var(--text-3); font-weight: 600; }
.rl-row .advice-line { margin-bottom: 10px; }
.rl-link-row { margin-top: 10px; }
.rl-link { font-size: var(--fs-xs); display: inline-flex; align-items: center; gap: 6px; }
.log-skip-reasons .rl-link { flex-basis: 100%; margin-top: 4px; }

/* Cardio et impact (Progression) : deux barres par semaine. */
.dual { display: grid; gap: 6px; }
.dual-row { display: grid; grid-template-columns: minmax(84px, auto) 1fr 1fr; gap: 10px; align-items: center; font-size: var(--fs-xs); }
.dual-head { color: var(--text-3); font-weight: 600; }
.dual-lab { color: var(--text-2); white-space: nowrap; }
.dual-cell { display: flex; align-items: center; gap: 6px; min-width: 0; }
.dual-bar { flex: 1; height: 8px; border-radius: 4px; background: var(--surface-2); overflow: hidden; }
.dual-bar i { display: block; height: 100%; border-radius: 4px; }
.dual-val { min-width: 34px; text-align: right; font-variant-numeric: tabular-nums; color: var(--text); }

/* Parcours trail (Jour J) : secteurs entre ravitaillements. */
.sectors { display: grid; gap: 2px; margin-top: 12px; }
.sector-row { display: grid; grid-template-columns: minmax(0, 2.4fr) repeat(4, minmax(0, 1fr)); gap: 8px; align-items: center; padding: 8px 0; border-bottom: 1px solid var(--border); font-size: var(--fs-sm); }
.sector-head { font-size: var(--fs-xs); color: var(--text-3); font-weight: 600; padding-top: 0; }
.sector-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sector-num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.sector-head span:not(:first-child) { text-align: right; }
.sector-at { color: var(--text-2); }
@media (max-width: 560px) {
  .sector-row { grid-template-columns: minmax(0, 1fr) auto auto; row-gap: 2px; }
  /* Sur téléphone : le D+ et l'heure de passage, ce qu'on regarde en course. */
  .sector-row > :nth-child(2), .sector-row > :nth-child(4) { display: none; }
}

/* ------------------------------------------------------------
   SEGMENTS (cf. js/segments.js) — dans le détail d'une sortie, juste
   sous la carte : toucher une ligne allume sa portion. Même grammaire
   que les lignes de bloc (rail coloré, chiffres à droite).
   ------------------------------------------------------------ */
.seg-list { display: flex; flex-direction: column; }
.seg-item { border-top: 1px solid var(--border); }
.seg-list > .seg-item:first-child { border-top: none; }
.seg-line { display: flex; align-items: center; gap: 8px; }
.seg-line > .seg-row { flex: 1; min-width: 0; }
.seg-row {
  display: flex; align-items: flex-start; gap: 10px; width: 100%; padding: 9px 4px;
  font: inherit; color: inherit; text-align: left; background: none; border: none;
  cursor: pointer; border-radius: var(--r-sm); transition: background .15s;
}
.seg-row:hover { background: var(--surface-2); }
.seg-row:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.seg-row.is-focused { background: color-mix(in srgb, var(--warning) 12%, transparent); }
.seg-rail { flex: none; width: 3px; align-self: stretch; min-height: 32px; border-radius: 2px; background: var(--accent); }
.seg-rail.is-climb { background: var(--warning); }
.seg-rail.is-idea { opacity: 0.45; }
.rcp-s-seg .rcp-section-head .link-btn { display: inline-flex; align-items: center; gap: 4px; text-transform: none; letter-spacing: 0; font-size: var(--fs-sm); }
.rcp-s-seg .rcp-section-head .link-btn svg { width: 13px; height: 13px; }
.seg-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.seg-name { font-size: var(--fs-sm); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.seg-name svg { width: 14px; height: 14px; vertical-align: -0.15em; color: var(--text-3); }
.seg-sub { font-size: var(--fs-xs); color: var(--text-2); font-variant-numeric: tabular-nums; }
.seg-times { flex: none; display: flex; flex-direction: column; align-items: flex-end; gap: 3px; }
.seg-time { font-size: var(--fs-md); font-weight: 600; font-variant-numeric: tabular-nums; }
.seg-delta { font-size: var(--fs-xs); color: var(--text-3); font-variant-numeric: tabular-nums; white-space: nowrap; }
.seg-badge { display: inline-flex; align-items: center; gap: 4px; font-size: 11px; font-weight: 600; border-radius: 999px; padding: 1px 7px; color: var(--text-2); background: var(--surface-2); }
.seg-badge svg { width: 11px; height: 11px; }
.seg-badge.is-pr { color: var(--success); background: var(--success-soft); }
.seg-follow { flex: none; }
.seg-sub-head { display: flex; align-items: center; gap: 6px; margin-top: 4px; font-size: var(--fs-xs); font-weight: 600; color: var(--text-3); }
.seg-sub-head svg { width: 14px; height: 14px; }
.seg-empty { margin: 0; font-size: var(--fs-sm); color: var(--text-2); }

/* Historique déplié sous une ligne : les cinq meilleurs passages. */
.seg-hist { display: flex; flex-direction: column; gap: 2px; padding: 0 4px 10px 17px; }
.seg-hist-row { display: grid; grid-template-columns: 18px 1fr auto minmax(64px, auto); gap: 10px; align-items: baseline; font-size: var(--fs-xs); font-variant-numeric: tabular-nums; padding: 3px 6px; border-radius: var(--r-sm); }
.seg-hist-row.is-me { background: color-mix(in srgb, var(--warning) 12%, transparent); }
.seg-hist-n { color: var(--text-3); }
.seg-hist-d { color: var(--text-2); }
.seg-hist-v { color: var(--text-3); text-align: right; }
.seg-hist-more { font-size: var(--fs-xs); color: var(--text-3); padding: 4px 6px 0; }

/* Éditeur : deux curseurs, un nom, deux boutons. */
.seg-edit { display: flex; flex-direction: column; gap: 10px; padding: 12px; border-radius: var(--r-md); background: var(--surface-2); border: 1px solid var(--border); }
.seg-edit-f { display: grid; grid-template-columns: 62px 1fr 70px; align-items: center; gap: 10px; font-size: var(--fs-xs); color: var(--text-3); }
.seg-edit-f > span { text-transform: uppercase; letter-spacing: 0.05em; font-weight: 600; font-size: 10.5px; }
.seg-edit-f input[type=range] { width: 100%; accent-color: var(--accent); }
.seg-edit-f output { text-align: right; color: var(--text); font-variant-numeric: tabular-nums; }
.seg-edit-name { grid-template-columns: 62px 1fr; }
.seg-edit-name input { min-width: 0; background: var(--surface); color: var(--text); border: 1px solid var(--border); border-radius: var(--r-sm); padding: 7px 8px; font-size: var(--fs-sm); font-family: inherit; }
.seg-edit-stats { font-size: var(--fs-sm); font-weight: 600; font-variant-numeric: tabular-nums; }
.seg-edit-actions { display: flex; justify-content: flex-end; gap: 8px; flex-wrap: wrap; }

/* Progression › Performances : un segment par ligne, dépliable. */
.seg-card-item { border-top: 1px solid var(--border); }
.seg-card-item:first-of-type { border-top: none; }
.seg-card-item > summary { display: flex; align-items: flex-start; gap: 10px; padding: 10px 0; cursor: pointer; list-style: none; }
.seg-card-item > summary::-webkit-details-marker { display: none; }
.seg-card-item > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--r-sm); }
.seg-card-body { display: flex; flex-direction: column; gap: 10px; padding: 0 0 12px 13px; }
.seg-h-rows { display: flex; flex-direction: column; }
.seg-h-row { display: grid; grid-template-columns: minmax(64px, auto) auto 1fr auto; gap: 10px; align-items: baseline; padding: 5px 0; border-top: 1px solid var(--border); font-size: var(--fs-xs); font-variant-numeric: tabular-nums; }
.seg-h-row:first-child { border-top: none; }
.seg-h-d { color: var(--text-2); text-align: left; }
.seg-h-t { font-size: var(--fs-sm); }
.seg-h-v { color: var(--text-3); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.seg-h-x { color: var(--text-3); text-align: right; white-space: nowrap; }
.seg-h-x svg { width: 11px; height: 11px; vertical-align: -0.1em; }
.seg-h-row.is-best .seg-h-x { color: var(--success); font-weight: 600; }
.seg-card-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.seg-del:hover { color: var(--danger); }

/* ------------------------------------------------------------
   PROFIL & REPLAY (cf. js/replay.js) — le profil d'altitude sert de
   barre de temps. Pente : rampe divergente bleu ↔ rouge, gris au plat,
   validée (outil dataviz) sur chaque fond. En sombre, la pente forte est
   la plus LUMINEUSE : c'est elle qui doit ressortir du fond.
   ------------------------------------------------------------ */
:root {
  --grade-0: #9ec5f4; --grade-1: #3987e5; --grade-2: #184f95; --grade-3: #5c5b56;
  --grade-4: #9e1f1f; --grade-5: #e66767; --grade-6: #f6b6a6;
}
[data-theme="light"] {
  --grade-0: #104281; --grade-1: #2a78d6; --grade-2: #86b6ef; --grade-3: #a9a8a1;
  --grade-4: #f2a08a; --grade-5: #e34948; --grade-6: #9e1f1f;
}

.rp-read { font-variant-numeric: tabular-nums; text-transform: none; letter-spacing: 0; font-weight: 600; color: var(--text); font-size: var(--fs-xs); text-align: right; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rp-chart { position: relative; display: grid; grid-template-columns: 40px 1fr; grid-template-rows: 120px auto; gap: 4px 6px; outline: none; }
.rp-chart.is-flat { grid-template-columns: 1fr; grid-template-rows: 26px auto; }
.rp-chart.is-compact { grid-template-rows: 64px auto; }
.rp-chart.is-compact.is-flat { grid-template-rows: 22px auto; }
.rp-chart:focus-visible .rp-plot { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 2px; }
.rp-y { position: relative; }
.rp-y-lab { position: absolute; right: 0; transform: translateY(-50%); font-size: 10.5px; color: var(--text-3); font-variant-numeric: tabular-nums; white-space: nowrap; }
.rp-plot { position: relative; cursor: crosshair; touch-action: pan-y; user-select: none; -webkit-user-select: none; }
.rp-svg { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.rp-grid { position: absolute; left: 0; right: 0; border-top: 1px solid color-mix(in srgb, var(--text) 9%, transparent); }
.rp-track { position: absolute; left: 0; right: 0; top: 50%; height: 6px; margin-top: -3px; border-radius: 3px; background: var(--surface-3); }
.rp-done { position: absolute; left: 0; bottom: 0; height: 3px; border-radius: 2px; background: var(--accent); pointer-events: none; }
.rp-chart.is-flat .rp-done { top: 50%; bottom: auto; height: 6px; margin-top: -3px; border-radius: 3px; }
.rp-cur, .rp-hover { position: absolute; top: 0; bottom: 0; width: 0; border-left: 2px solid var(--accent); transform: translateX(-1px); pointer-events: none; }
.rp-hover { border-left: 1px solid var(--text-2); }
.rp-dot { position: absolute; width: 12px; height: 12px; margin: -6px 0 0 -6px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 2px var(--surface), 0 0 0 6px color-mix(in srgb, var(--accent) 28%, transparent); pointer-events: none; }
.rp-tip {
  position: absolute; top: 4px; margin-left: 8px; z-index: 2; pointer-events: none;
  display: flex; flex-direction: column; gap: 1px; padding: 7px 10px; border-radius: 10px;
  background: var(--surface-2); border: 1px solid var(--border-strong); color: var(--text-2);
  font-size: 11.5px; font-variant-numeric: tabular-nums; white-space: nowrap; box-shadow: 0 8px 24px rgba(0, 0, 0, .28);
}
.rp-tip.is-left { transform: translateX(calc(-100% - 16px)); }
.rp-tip[hidden] { display: none; }
.rp-tip b { color: var(--text); font-weight: 600; }
.rp-tip span { color: var(--text-3); }
.rp-x { grid-column: -2; position: relative; height: 14px; }
.rp-x-lab { position: absolute; top: 0; transform: translateX(-50%); font-size: 10.5px; color: var(--text-3); font-variant-numeric: tabular-nums; white-space: nowrap; }
.rp-x-lab:first-child { transform: none; }
.rp-x-lab:last-child { transform: translateX(-100%); }
.rp-ctrl { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.rp-ctrl [data-rp-play] { display: inline-flex; align-items: center; gap: 6px; }
.rp-speed { font-variant-numeric: tabular-nums; min-width: 52px; }
.rp-legend { margin-left: auto; display: inline-flex; align-items: center; gap: 6px; font-size: 10.5px; color: var(--text-3); }
.rp-leg-bar { position: relative; display: inline-flex; gap: 2px; padding-bottom: 12px; }
.rp-leg-bar > i { width: 20px; height: 8px; border-radius: 2px; }
.rp-leg-ticks { position: absolute; left: 0; right: 0; bottom: 0; height: 11px; }
.rp-leg-ticks em { position: absolute; transform: translateX(-50%); font-style: normal; font-variant-numeric: tabular-nums; }
.rp-leg-end { padding-bottom: 12px; }

/* Barre compacte sous la carte plein écran. */
.rp-bar { flex: none; display: flex; align-items: center; gap: 10px; }
.rp-bar-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.rp-bar .rp-read { text-align: left; min-height: 1.2em; }
.rp-bar .rp-chart { grid-template-columns: 34px 1fr; }
/* Téléphone : le profil prend toute la largeur, les boutons passent dessous. */
@media (max-width: 640px) {
  .rp-bar { flex-wrap: wrap; justify-content: space-between; }
  .rp-bar-main { flex-basis: 100%; order: -1; }
}

/* Courbe d'allure : repère du même instant. */
.pp-box { position: relative; }
.pp-cursor { position: absolute; width: 0; border-left: 2px solid var(--accent); transform: translateX(-1px); pointer-events: none; }
/* Courbe d'allure dessinée par D3 (js/d3charts.js) : pas de cadre, la
   figure fait toute la largeur ; agrandie, elle prend la hauteur donnée. */
.pp-box.is-d3 .mc.d3c { margin: 0; }
.cz-body .pp-box.is-d3 { max-width: none; }
.d3c-pace .pp-band.is-focused rect:first-child { opacity: .2; }

.tmap-card-acts { display: inline-flex; gap: 14px; }

/* Commandes posées SUR la vignette de carte (cf. TraceMap.card) : en haut
   à droite — le zoom est à gauche, la légende et l'attribution en bas.
   Pastilles claires, comme la légende : la carte est claire dans les deux
   thèmes. `z-index: 1` suffit : `.trace-map` enferme les z-index de
   Leaflet dans son propre contexte (z-index: 0). Cible tactile ≥ 36 px. */
.tmap-frame { position: relative; }
.tmap-over { position: absolute; top: 10px; right: 10px; z-index: 1; display: flex; gap: 6px; }
.tmap-over-btn {
  display: inline-flex; align-items: center; gap: 6px; min-height: 36px; padding: 0 12px;
  border: 0; border-radius: 999px; cursor: pointer;
  background: rgba(255, 255, 255, 0.95); color: #111827;
  font: inherit; font-size: var(--fs-xs); font-weight: 700; letter-spacing: 0.01em;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.28);
  transition: transform 0.12s ease, box-shadow 0.12s ease;
}
.tmap-over-btn svg { width: 16px; height: 16px; flex: none; }
.tmap-over-btn:hover { box-shadow: 0 2px 8px rgba(0, 0, 0, 0.32); transform: translateY(-1px); }
.tmap-over-btn:focus-visible { outline: 2px solid var(--brand-green); outline-offset: 2px; }
/* Vignette étroite : icônes seules, libellé en infobulle (title). */
@container (max-width: 360px) { .tmap-over-btn span { display: none; } .tmap-over-btn { width: 36px; padding: 0; justify-content: center; } }
@media (max-width: 380px) { .tmap-over-btn span { display: none; } .tmap-over-btn { width: 36px; padding: 0; justify-content: center; } }
.tmap-full-acts { display: inline-flex; align-items: center; gap: 8px; }

/* ------------------------------------------------------------
   SURVOL 3D (cf. js/fly3d.js) — plein écran, comme la carte agrandie.
   La scène (relief + satellite) est sombre et chargée : le HUD est une
   carte opaque, lisible sur n'importe quelle image.
   ------------------------------------------------------------ */
#fly3d { position: fixed; inset: 0; z-index: 530; background: var(--bg); display: flex; flex-direction: column; gap: 10px; padding: 12px 12px calc(12px + env(safe-area-inset-bottom)); }
.f3-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.f3-title { display: inline-flex; align-items: center; gap: 8px; font-size: var(--fs-md); font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.f3-stage { position: relative; flex: 1; min-height: 0; border-radius: var(--r-md); overflow: hidden; background: #0b0f14; }
/* Sélecteur renforcé : maplibre-gl.css, chargé après, pose `position: relative` sur le conteneur. */
#fly3d .f3-map { position: absolute; inset: 0; }
/* Panneaux posés sur la carte : verre dépoli sombre — le fond transparaît,
   flouté, et le texte reste lisible sur n'importe quelle image. Sans
   `backdrop-filter`, le fond plus opaque suffit. */
.f3-hud, .f3-wait, .f3-hint, .f3-mark > span, #fly3d .maplibregl-ctrl-group {
  background: rgba(13, 17, 23, .78); border: 1px solid rgba(255, 255, 255, .14);
  box-shadow: 0 6px 24px rgba(0, 0, 0, .28);
}
@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .f3-hud, .f3-wait, .f3-hint, .f3-mark > span, #fly3d .maplibregl-ctrl-group {
    background: rgba(13, 17, 23, .52); -webkit-backdrop-filter: blur(14px) saturate(1.5); backdrop-filter: blur(14px) saturate(1.5);
  }
}
.f3-hud {
  position: absolute; top: 12px; left: 12px; z-index: 2; pointer-events: none;
  display: flex; flex-direction: column; gap: 2px; padding: 10px 14px; border-radius: 16px;
  color: #eef1f5; font-variant-numeric: tabular-nums; max-width: calc(100% - 84px);
}
.f3-km { font-size: var(--fs-2xl, 26px); font-weight: 700; letter-spacing: -0.02em; line-height: 1.1; }
.f3-alt { font-size: var(--fs-sm); font-weight: 600; color: #ffffff; }
.f3-row { font-size: var(--fs-xs); color: #c3cad5; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.f3-wait { position: absolute; left: 50%; bottom: 14px; transform: translateX(-50%); z-index: 2; display: inline-flex; align-items: center; gap: 8px; padding: 6px 12px; border-radius: 999px; color: #e8eaee; font-size: var(--fs-xs); }
.f3-wait[hidden] { display: none; }
.f3-foot { flex: none; display: flex; flex-direction: column; gap: 8px; }
.f3-ctrl { display: flex; align-items: center; gap: 8px; }
.f3-ctrl [data-f3-play] { display: inline-flex; align-items: center; gap: 6px; }
.f3-opt { display: inline-flex; align-items: center; gap: 6px; }
.f3-opt[aria-pressed="true"] { color: var(--brand-green); border-color: color-mix(in srgb, var(--brand-green) 45%, var(--border)); }
/* Téléphone : Tour et Vue libre en icônes seules, la ligne tient sans déborder. */
@media (max-width: 480px) { .f3-opt > span { display: none; } }
.f3-hint { position: absolute; left: 50%; bottom: 14px; transform: translateX(-50%); z-index: 2; max-width: calc(100% - 28px); padding: 6px 12px; border-radius: var(--r-md); color: #e8eaee; font-size: var(--fs-xs); text-align: center; pointer-events: none; }
.f3-hint[hidden] { display: none; }
.f3-sum { margin-left: auto; font-size: var(--fs-xs); color: var(--text-3); font-variant-numeric: tabular-nums; }
/* Repères : l'étiquette flotte au-dessus des toits, une tige la relie au
   point posé sur le sol. */
.f3-mark { --mk: #1fb57a; display: flex; flex-direction: column; align-items: center; pointer-events: none; }
.f3-mark > span { padding: 3px 9px; border-radius: 999px; color: #fff; font-size: 11.5px; font-weight: 600; white-space: nowrap; }
.f3-mark > b { width: 2px; height: 22px; background: linear-gradient(rgba(255, 255, 255, .95), rgba(255, 255, 255, .25)); }
.f3-mark > i { width: 12px; height: 12px; margin-top: -2px; border-radius: 50%; border: 2px solid #fff; background: var(--mk); box-shadow: 0 0 0 3px color-mix(in srgb, var(--mk) 35%, transparent), 0 1px 4px rgba(0, 0, 0, .5); }
.f3-mark.is-end { --mk: #f0a82d; }
.f3-mark.is-cp { --mk: #4f8cff; }
/* Le coureur : une pastille cerclée de blanc, dont l'onde bat. */
.f3-pos { width: 20px; height: 20px; pointer-events: none; }
.f3-pos > i {
  position: absolute; inset: 0; border-radius: 50%; background: #ff7a1a; border: 3px solid #fff;
  box-shadow: 0 2px 8px rgba(0, 0, 0, .45);
}
.f3-pos::before {
  content: ""; position: absolute; inset: -8px; border-radius: 50%; background: rgba(255, 122, 26, .45);
  animation: f3-pulse 1.8s ease-out infinite;
}
@keyframes f3-pulse { from { transform: scale(.45); opacity: .9; } to { transform: scale(1.35); opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .f3-pos::before { animation: none; transform: scale(.9); opacity: .5; } }
/* Boutons de la carte (zoom, boussole) : même verre que le reste. */
#fly3d .maplibregl-ctrl-group { border-radius: 14px; overflow: hidden; }
#fly3d .maplibregl-ctrl-group button { width: 36px; height: 36px; background-color: transparent; }
#fly3d .maplibregl-ctrl-group button + button { border-top: 1px solid rgba(255, 255, 255, .12); }
#fly3d .maplibregl-ctrl-group button:hover { background-color: rgba(255, 255, 255, .1); }
#fly3d .maplibregl-ctrl-group .maplibregl-ctrl-icon { filter: invert(1) brightness(1.6); }
#fly3d .maplibregl-ctrl-top-right { top: 2px; right: 2px; }
#fly3d .maplibregl-ctrl-attrib { font-size: 10px; }

/* ------------------------------------------------------------
   AGRANDIR UN GRAPHIQUE (js/chartzoom.js)
   Bouton discret posé sur chaque graphique ; feuille plein écran.
   ------------------------------------------------------------ */
.chart-zoom-btn {
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  width: 32px; height: 32px; border-radius: var(--r-sm); cursor: pointer;
  border: 1px solid var(--border); background: var(--surface); color: var(--text-2); font-size: 15px;
}
.chart-zoom-btn:hover { color: var(--text); border-color: var(--border-strong); }
.chart-zoom-btn:focus-visible { outline: 2px solid var(--brand-green); outline-offset: 2px; }
/* MiniChart : en haut à droite, au-dessus du tracé (hors de la figure). */
.mc-wrap { position: relative; }
.mc-wrap > .chart-zoom-btn { position: absolute; top: -2px; right: 0; z-index: 1; width: 28px; height: 28px; opacity: 0.85; }
.mc-wrap > .chart-zoom-btn:hover { opacity: 1; }
.pp-head .pp-legend { margin-left: auto; }
.rcp-s-prof .rcp-section-head { gap: 8px; }
.rcp-s-prof .rp-read { margin-left: auto; }

.chart-zoom {
  position: fixed; inset: 0; z-index: 540; background: color-mix(in srgb, var(--bg) 70%, transparent);
  display: flex; align-items: center; justify-content: center; padding: 16px;
}
.cz-sheet {
  width: min(1200px, 100%); max-height: 100%; overflow: auto; display: flex; flex-direction: column; gap: 12px;
  background: var(--bg); border: 1px solid var(--border); border-radius: var(--r-lg); box-shadow: var(--shadow-md);
  padding: 14px 16px calc(16px + env(safe-area-inset-bottom));
}
.cz-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.cz-title { display: inline-flex; align-items: center; gap: 8px; font-size: var(--fs-md); font-weight: 600; }
.cz-body .rcp-section { margin: 0; border: 0; padding: 0; background: transparent; }
.cz-body .rcp-section-head > span:first-child { display: none; } /* le titre est déjà dans l'en-tête */
/* Courbe d'allure : agrandie SANS être déformée (texte dans le SVG). */
.cz-body .pp-box { max-width: calc((100vh - 220px) * 700 / 240); margin: 0 auto; width: 100%; }
.cz-body .pp-svg { height: auto; aspect-ratio: 700 / 240; }
.cz-body .pp-title { display: none; }
@media (max-width: 640px) { .chart-zoom { padding: 0; } .cz-sheet { border-radius: 0; height: 100%; border: 0; } }

/* ------------------------------------------------------------
   SPLITS DÉTAILLÉS (js/splits.js, TraceMap.card)
   ------------------------------------------------------------ */
.spl { display: flex; flex-direction: column; gap: 6px; }
.spl-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.spl-table { width: 100%; border-collapse: collapse; font-size: var(--fs-xs); font-variant-numeric: tabular-nums; }
.spl-table th, .spl-table td { padding: 6px 6px; text-align: right; white-space: nowrap; border-bottom: 1px solid var(--border); vertical-align: middle; }
.spl-table thead th { font-weight: 600; color: var(--text-3); text-transform: uppercase; letter-spacing: 0.04em; font-size: 10.5px; border-bottom-color: var(--border-strong); }
.spl-table thead th small { text-transform: none; letter-spacing: 0; font-weight: 500; }
.spl-table th:first-child, .spl-table td:first-child { text-align: left; padding-left: 0; }
.spl-table tbody th { font-weight: 600; color: var(--text-2); }
.spl-table td small { display: block; font-size: 10px; color: var(--text-3); font-weight: 500; }
.spl-avg { position: relative; min-width: 64px; font-weight: 700; }
.spl-avg > i { position: absolute; right: 6px; bottom: 3px; height: 3px; border-radius: 2px; background: var(--accent); opacity: 0.55; max-width: calc(100% - 12px); }
.spl-avg > span { position: relative; }
/* Allure ajustée à la pente (cf. js/gradepace.js) : secondaire, sous l'allure réelle. */
.spl-gap { color: var(--text-2); }
.spl-table tr.is-best .spl-avg { color: var(--success); }
.spl-table tr.is-best .spl-avg > i { background: var(--success); opacity: 0.9; }
.spl-table tr.is-partial td, .spl-table tr.is-partial th { color: var(--text-3); }
.spl-elev span { display: block; line-height: 1.25; }
.spl-elev .is-up { color: var(--text); font-weight: 600; }
.spl-elev .is-down { color: var(--text-3); font-size: 10px; }

/* ---------------------------------------------------------------------
   Météo et vent — carte de l'accueil (js/weather.js, homeCard)
   Maintenant en tête, puis les prochaines heures en bande défilante
   (jamais de débordement de page : la bande défile seule), puis le
   meilleur créneau et les conseils sous forme de lignes .advice-line.
   --------------------------------------------------------------------- */
.wx-card .today-week-head { margin-bottom: 8px; }
.wx-now { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.wx-now-icon { font-size: 34px; color: var(--warning); display: inline-flex; flex: none; }
.wx-now-main { min-width: 0; }
.wx-now-temp { font-size: var(--fs-3xl); font-weight: 600; letter-spacing: -0.02em; line-height: 1; }
.wx-now-temp small { font-size: var(--fs-md); font-weight: 500; color: var(--text-2); margin-left: 2px; }
.wx-now-sub { font-size: var(--fs-sm); color: var(--text-2); margin-top: 4px; }
.wx-now-facts { display: flex; flex-direction: column; gap: 4px; margin-left: auto; font-size: var(--fs-sm); color: var(--text-2); }
.wx-now-facts span { display: inline-flex; align-items: center; gap: 6px; }
.wx-now-facts strong { color: var(--text); font-weight: 600; }
.wx-arrow { display: inline-flex; color: var(--accent); transition: transform .2s; }
.wx-strip {
  list-style: none; margin: 14px 0 0; padding: 0 0 4px; display: flex; gap: 6px;
  overflow-x: auto; scrollbar-width: thin; -webkit-overflow-scrolling: touch;
}
.wx-hour {
  flex: 0 0 auto; min-width: 54px; display: flex; flex-direction: column; align-items: center; gap: 4px;
  padding: 8px 6px; border-radius: var(--r-md); background: var(--surface-2); border: 1px solid transparent;
  font-size: var(--fs-xs); color: var(--text-2);
}
.wx-hour.is-now { border-color: var(--border-strong); color: var(--text); }
.wx-h { font-weight: 600; }
.wx-i { font-size: 18px; color: var(--text); display: inline-flex; }
.wx-t { font-size: var(--fs-md); font-weight: 600; color: var(--text); }
.wx-w { display: inline-flex; align-items: center; gap: 2px; }
.wx-r { min-height: 14px; color: var(--accent); }
.wx-advice { display: flex; flex-direction: column; gap: 8px; margin-top: 14px; }
.wx-foot { margin-top: 10px; }
@media (max-width: 480px) {
  .wx-now-facts { margin-left: 0; width: 100%; flex-direction: row; flex-wrap: wrap; gap: 4px 14px; }
}
.wx-hour.is-next-day { margin-left: 10px; position: relative; }
.wx-hour.is-next-day::before { content: ""; position: absolute; left: -9px; top: 8px; bottom: 8px; border-left: 1px dashed var(--border-strong); }

/* Écart d'effort (js/effort.js) : ligne sous le RPE, dans le journal de séance. */
.effort-hint { display: flex; gap: 6px; align-items: flex-start; margin-top: 10px; }
.effort-hint svg { flex: none; margin-top: 2px; }

/* Qualité de l'air (js/weather.js) : la couleur suit l'indice européen. */
.wx-air-0, .wx-air-1 { color: var(--success); }
.wx-air-3 { color: var(--warning); }
.wx-air-4, .wx-air-5 { color: var(--danger); }
#weather-panel .check-row { margin: 10px 0 12px; }

/* ------------------------------------------------------------
   CONFIRMATION (UIConfirm, js/ui.js) — geste à ne pas faire par erreur.
   ------------------------------------------------------------ */
.uic {
  position: fixed; inset: 0; z-index: 600; display: flex; align-items: center; justify-content: center; padding: 16px;
  background: color-mix(in srgb, var(--bg) 70%, transparent);
}
.uic-box {
  width: min(420px, 100%); display: flex; flex-direction: column; gap: 10px; padding: 18px 18px 16px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg); box-shadow: var(--shadow-md);
}
.uic-title { margin: 0; font-size: var(--fs-lg); font-weight: 600; }
.uic-text { margin: 0; color: var(--text-2); font-size: var(--fs-sm); line-height: 1.5; }
.uic-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 6px; flex-wrap: wrap; }

/* Météo de la semaine dans le calendrier du plan (Weather.planDay) :
   température mini / maxi, pluie seulement quand il en tombe. Discret :
   c'est un repère, pas le sujet de la ligne. Colonne de largeur fixe pour
   que les températures s'alignent d'un jour à l'autre ; masquée tant
   qu'aucun jour n'a de prévision (pas de ville, semaine lointaine). */
.sess-wx-cell { width: 62px; display: flex; justify-content: flex-end; }
.sess-list:not(.has-wx) .sess-wx-cell { display: none; }
.sess-list:not(.has-wx) .sess-row { grid-template-columns: 46px 40px 1fr auto; }
.sess-wx { display: inline-flex; flex-direction: column; align-items: flex-end; gap: 1px; font-size: var(--fs-xs); color: var(--text-2); font-variant-numeric: tabular-nums; white-space: nowrap; }
.sess-wx-t { font-weight: 600; color: var(--text); }
.sess-wx-min { color: var(--text-3); font-weight: 500; }
.sess-wx-r { display: inline-flex; align-items: center; gap: 3px; color: var(--text-2); font-weight: 600; }
.sess-wx-r svg { font-size: 12px; }
@media (max-width: 520px) {
  .sess-wx-cell { width: 40px; }
  .sess-list:not(.has-wx) .sess-row { grid-template-columns: 40px 34px 1fr auto; }
}

/* ------------------------------------------------------------
   SUIVI DU PLAN (js/tracking.js) — objectif face au réalisé.
   Prévu = piste claire, réalisé = plein (même code que le graphique de
   charge de Progression) ; le trait vertical marque le prévu À DATE.
   ------------------------------------------------------------ */
#plan-tabs .ptabs { margin-bottom: 14px; }
#plan-track-root { display: flex; flex-direction: column; gap: 16px; }
#plan-track-root[hidden], #plan-week-view[hidden] { display: none; }
#plan-track-root .card { margin: 0; }
#weekly-progress-wrapper:has(.pt-week) { display: block; }
.pt-week { width: 100%; }
.pt-chart .load-bar-planned { box-shadow: inset 0 0 0 1px var(--border-strong); }

.pt-row {
  display: grid; grid-template-columns: 110px minmax(60px, 1fr) auto 64px; align-items: center; gap: 10px;
  padding: 5px 0; font-size: var(--fs-sm);
}
.pt-row-text { grid-template-columns: 110px 1fr; }
.pt-lab { display: inline-flex; align-items: center; gap: 6px; font-weight: 600; min-width: 0; color: var(--text-2); }
.pt-lab > span { color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pt-val { color: var(--text-2); font-variant-numeric: tabular-nums; white-space: nowrap; text-align: right; }
.pt-val strong { color: var(--text); }
.pt-chip { display: flex; justify-content: flex-end; }
.pt-note { font-size: var(--fs-xs); color: var(--text-2); justify-content: flex-start; grid-column: span 1; white-space: nowrap; }
.pt-row:has(.pt-note) { grid-template-columns: 110px minmax(60px, 1fr) auto minmax(64px, auto); }

.pt-bar { position: relative; height: 10px; border-radius: 5px; background: transparent; }
.pt-bar > i { position: absolute; top: 0; bottom: 0; left: 0; border-radius: 5px; }
.pt-bar-plan { background: var(--surface-3); box-shadow: inset 0 0 0 1px var(--border-strong); }
.pt-bar-real { background: var(--success); top: 2px !important; bottom: 2px !important; left: 2px !important; max-width: calc(100% - 4px); }
.pt-bar-mark { width: 2px; top: -3px !important; bottom: -3px !important; margin-left: -1px; border-radius: 1px; background: var(--text); }

/* Séance : échelle RPE 1–10, attendu en contour, ressenti en plein. */
.pt-rpe { display: grid; grid-template-columns: repeat(10, 1fr); gap: 2px; height: 12px; }
.pt-rpe > i { border-radius: 3px; background: var(--surface-3); }
.pt-rpe > i.is-real { background: var(--rpe, var(--success)); }
.pt-rpe > i.is-exp { box-shadow: 0 0 0 2px var(--text); }

.pt-card { margin: 14px 0; padding: 12px 14px; border: 1px solid var(--border); border-radius: var(--r-md); background: var(--surface-2); }
.pt-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; flex-wrap: wrap; margin-bottom: 4px; }
.pt-title { display: inline-flex; align-items: center; gap: 6px; font-weight: 600; }
.pt-hint { font-size: var(--fs-xs); color: var(--text-3); }

/* Semaine : barre d'état des séances + légende. */
.pt-week { display: flex; flex-direction: column; gap: 4px; margin-top: 12px; }
.pt-week-top { display: flex; flex-direction: column; gap: 6px; margin-bottom: 6px; }
.pt-status { display: flex; gap: 2px; height: 10px; border-radius: 5px; overflow: hidden; }
.pt-status > i { min-width: 6px; }
.pt-s-done { background: var(--success); }
.pt-s-skipped { background: var(--text-3); }
.pt-s-missed { background: var(--warning); }
.pt-s-upcoming { background: var(--surface-3); box-shadow: inset 0 0 0 1px var(--border-strong); }
.pt-legend { display: flex; flex-wrap: wrap; gap: 4px 14px; font-size: var(--fs-xs); color: var(--text-2); }
.pt-legend i { display: inline-block; width: 10px; height: 10px; border-radius: 3px; margin-right: 5px; vertical-align: -1px; }
.pt-foot { margin: 4px 0 0; font-size: var(--fs-xs); color: var(--text-3); }

/* Plan : indicateurs, graphique par semaine cliquable. */
.pt-kpis { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; margin-bottom: 14px; }
.pt-kpi { display: flex; flex-direction: column; gap: 4px; align-items: flex-start; padding: 10px 12px; border-radius: var(--r-md); background: var(--surface-2); }
.pt-kpi-val { font-size: var(--fs-xl); font-weight: 600; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.pt-kpi-val small { font-size: var(--fs-sm); color: var(--text-2); font-weight: 500; }
.pt-kpi-lab { font-size: var(--fs-xs); color: var(--text-2); }
.pt-col { border: 0; background: transparent; font: inherit; color: inherit; cursor: pointer; }
.pt-col:hover { background: var(--surface-2); }
.pt-col:focus-visible { outline: 2px solid var(--brand-green); outline-offset: 1px; }
.pt-col.is-future .load-bar-planned { opacity: 0.6; }
.pt-l-plan { background: transparent !important; border-top: 2px dashed var(--text-3); height: 0 !important; width: 14px !important; vertical-align: 3px !important; border-radius: 0 !important; }

@media (max-width: 720px) { .pt-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
/* Téléphone : libellé, valeur et pourcentage sur une ligne, la barre dessous. */
@media (max-width: 520px) {
  .pt-row, .pt-row:has(.pt-note) {
    grid-template-columns: minmax(0, 1fr) auto auto; grid-template-areas: "lab val chip" "bar bar bar"; row-gap: 5px; padding: 6px 0;
  }
  .pt-row:has(.pt-note) { grid-template-areas: "lab val val" "bar bar bar" "chip chip chip"; }
  .pt-row > .pt-lab { grid-area: lab; }
  .pt-row > .pt-val { grid-area: val; }
  .pt-row > .pt-chip { grid-area: chip; }
  .pt-row > .pt-bar, .pt-row > .pt-rpe { grid-area: bar; }
  .pt-row > .pt-chip:empty { display: none; }
  .pt-row-text { grid-template-areas: "lab val"; grid-template-columns: minmax(0, 1fr) auto; }
}

/* ------------------------------------------------------------
   RÉSUMÉ À PARTAGER (onglet « Résumé » du détail, cf. js/recapshare.js)
   L'aperçu montre le texte EXACT qui partira : texte brut, retours à la
   ligne gardés, police de l'app (pas de chasse fixe : dans une
   messagerie, le texte ne sera pas en chasse fixe non plus).
   ------------------------------------------------------------ */
.rcp-s-share { max-width: 1080px; }
/* Le texte et l'image côte à côte dès que le détail est assez large. */
.rs-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 24px; align-items: start; }
.rs-text, .rs-image { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.rs-card {
  display: block; width: 100%; max-width: 340px; height: auto; aspect-ratio: 4 / 5;
  border-radius: var(--r-lg); border: 1px solid var(--border); background: #0b101a;
  box-shadow: 0 14px 40px rgba(0, 0, 0, 0.28);
}
@container (min-width: 820px) {
  .rs-grid { grid-template-columns: minmax(0, 1fr) 340px; gap: 32px; }
}
.rs-controls { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; }
.rs-controls .segmented { margin: 0; }
.rs-opts { display: flex; flex-wrap: wrap; gap: 6px; }
.rs-opt {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 10px; border-radius: 999px;
  border: 1px solid var(--border); background: var(--surface);
  color: var(--text-2); font: inherit; font-size: var(--fs-sm); cursor: pointer;
}
.rs-opt svg { width: 15px; height: 15px; }
.rs-opt.is-on { color: var(--text); border-color: color-mix(in srgb, var(--brand-green) 55%, var(--border)); }
.rs-opt.is-on svg { color: var(--brand-green); }
.rs-opt:hover:not(:disabled) { background: var(--surface-2); }
.rs-opt:disabled { opacity: 0.45; cursor: default; }
.rs-opt:focus-visible { outline: 2px solid var(--brand-green); outline-offset: 2px; }
.rs-preview {
  margin: 0; padding: 14px 16px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-md);
  font-family: inherit; font-size: var(--fs-sm); line-height: 1.6; color: var(--text);
  white-space: pre-wrap; overflow-wrap: anywhere;
  max-height: 60vh; overflow-y: auto;
  user-select: text;
}
.rs-actions { display: flex; flex-wrap: wrap; gap: 8px; }

/* ------------------------------------------------------------
   PAGE D'UN ÉVÉNEMENT (cf. js/events.js) — Infos · Coureurs
   ------------------------------------------------------------ */
.ev-page-ctx { color: var(--ev-accent, var(--text-3)); display: inline-flex; align-items: center; gap: 6px; font-size: var(--fs-xs); font-weight: 600; }
.ev-page-head .page-sub { margin-top: 4px; }
.ev-page-manage { display: inline-flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }
.ev-page-body { padding: 0; }
.ev-page-body.ev-sheet-body { padding: 0 0 8px; }

/* ------------------------------------------------------------
   SUIVI DES COUREURS (cf. js/racefollow.js)
   Le dossard est le repère : gros chiffres à gauche de chaque fiche,
   lisibles à bout de bras, au soleil.
   ------------------------------------------------------------ */
.rf-empty .rf-empty-act { margin-top: 14px; }
.rf-import { cursor: pointer; }
/* Barre de recherche COLLÉE sous l'en-tête de l'app (--rf-top, mesuré par
   js/racefollow.js) : on fait défiler les fiches sans perdre le champ. */
.rf-bar {
  display: flex; gap: 8px; align-items: stretch;
  position: sticky; top: var(--rf-top, 0); z-index: 6;
  margin: 0 calc(-1 * var(--page-pad, 16px)); padding: 8px var(--page-pad, 16px);
  background: var(--bg);
}
.rf-q { flex: 1 1 auto; min-width: 0; font-size: 16px; }   /* 16 px : pas de zoom automatique sur iPhone */
.rf-scan { display: inline-flex; align-items: center; gap: 6px; flex-shrink: 0; }
.rf-filters { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-top: 10px; }
.rf-filters:empty { display: none; }
.rf-filters .segmented { margin: 0; }
.rf-race { width: auto; max-width: 100%; }
.rf-sum { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 16px; margin-top: 6px; font-size: var(--fs-sm); color: var(--text-2); }
.rf-active {
  display: inline-flex; align-items: center; gap: 4px; min-height: 30px; padding: 3px 10px;
  border: 1px solid var(--accent); border-radius: 999px; background: var(--accent-soft); color: var(--text);
  font: inherit; font-size: var(--fs-xs); font-weight: 600; cursor: pointer;
}
.rf-active svg { width: 12px; height: 12px; }
/* Listing PDF de la sélection : à droite du résumé, avec son effectif. */
.rf-export { display: inline-flex; align-items: center; gap: 6px; margin-left: auto; }
.rf-export svg { width: 15px; height: 15px; }
.rf-export span { color: var(--text-3); font-weight: 500; font-variant-numeric: tabular-nums; }
/* Filtres repliables : fermés par défaut au téléphone. */
.rf-filt { margin-top: 10px; }
.rf-filt > summary {
  display: inline-flex; align-items: center; gap: 8px; min-height: 36px; padding: 0 12px;
  border: 1px solid var(--border); border-radius: var(--r-md); background: var(--surface);
  font-size: var(--fs-sm); font-weight: 600; color: var(--text-2); cursor: pointer; list-style: none;
}
.rf-filt > summary::-webkit-details-marker { display: none; }
.rf-filt > summary svg { width: 15px; height: 15px; }
.rf-filt[open] > summary { color: var(--text); }
.rf-filt-n { min-width: 20px; height: 20px; padding: 0 6px; border-radius: 999px; background: var(--accent); color: #fff; font-size: 12px; line-height: 20px; text-align: center; }
.rf-filt-n[hidden] { display: none; }
.rf-filt-hint { font-weight: 500; color: var(--text-3); }
.rf-sum strong { color: var(--text); font-variant-numeric: tabular-nums; }
.rf-cats { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.rf-cat {
  display: inline-flex; align-items: center; gap: 6px; padding: 6px 11px; min-height: 32px;
  border: 1px solid var(--border); border-radius: 999px; background: var(--surface); color: var(--text-2);
  font: inherit; font-size: var(--fs-sm); font-weight: 600; cursor: pointer;
}
.rf-cat span { color: var(--text-3); font-weight: 500; font-variant-numeric: tabular-nums; }
.rf-cat.is-on { border-color: var(--accent); color: var(--text); background: var(--accent-soft); }
.rf-cat.is-empty { opacity: .45; cursor: default; }
.rf-results { margin-top: 12px; display: flex; flex-direction: column; gap: 8px; scroll-margin-top: calc(var(--rf-top, 0px) + 72px); }
/* Le numéro tapé : sa fiche en tête, bien visible. */
.rf-card.is-hit { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.rf-card.is-hit .rf-name { font-size: var(--fs-lg, 18px); }
.rf-when { display: inline-flex; align-items: center; gap: 2px; }
.rf-when .rf-unmark { min-height: 30px; }
.rf-sec { margin: 10px 0 0; font-size: var(--fs-xs); font-weight: 600; color: var(--text-3); text-transform: uppercase; letter-spacing: 0.06em; }
.rf-card {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 14px;
  padding: 12px 14px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-md);
}
.rf-card.is-passed { border-left: 3px solid var(--success); }
.rf-bib {
  min-width: 64px; padding: 8px 10px; text-align: center; border-radius: var(--r-sm);
  background: var(--surface-2); border: 1px solid var(--border-strong);
  font-size: 24px; font-weight: 700; line-height: 1; letter-spacing: -0.02em; font-variant-numeric: tabular-nums;
}
.rf-name { font-size: var(--fs-md); font-weight: 600; line-height: 1.3; overflow-wrap: anywhere; }
/* Chaque info porte son « · » devant ; celui d'un début de ligne tombe
   dans la marge rognée — sur un téléphone étroit, la ligne qui passe à la
   ligne ne commence plus par un point orphelin. */
.rf-meta { display: flex; flex-wrap: wrap; gap: 4px 0; margin: 3px 0 0 -14px; clip-path: inset(0 0 0 14px); font-size: var(--fs-sm); color: var(--text-2); }
.rf-meta > span::before { content: "\00b7"; display: inline-block; width: 14px; text-align: center; color: var(--text-3); }
.rf-extra { display: flex; flex-wrap: wrap; gap: 2px 12px; margin-top: 4px; font-size: var(--fs-xs); color: var(--text-2); }
.rf-extra em { font-style: normal; color: var(--text-3); }
.rf-side { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }
.rf-side .btn-icon { padding-left: 8px; padding-right: 8px; }
.rf-passed { display: inline-flex; align-items: center; gap: 4px; font-size: var(--fs-xs); font-weight: 600; color: var(--success); font-variant-numeric: tabular-nums; }
.rf-missing, .rf-more, .rf-note { margin: 4px 0 0; font-size: var(--fs-sm); color: var(--text-3); }
.rf-missing { display: flex; align-items: center; gap: 6px; color: var(--warning); }
.rf-foot { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px; margin-top: 18px; padding-top: 12px; border-top: 1px solid var(--border); font-size: var(--fs-xs); color: var(--text-3); }
.rf-foot-acts { display: flex; flex-wrap: wrap; gap: 6px; }
/* Téléphone : fiche compacte, le bouton reste à droite (avant, il
   prenait une ligne à lui seul et une fiche faisait 115 px de haut). */
@media (max-width: 520px) {
  .rf-card { gap: 10px; padding: 10px 12px; }
  .rf-side { flex-direction: column; align-items: flex-end; flex-wrap: nowrap; gap: 4px; }
  .rf-side:empty { display: none; }
  .rf-bib { min-width: 54px; padding: 7px 8px; font-size: 22px; }
  .rf-meta { font-size: var(--fs-xs); }
  .rf-scan { padding-left: 12px; padding-right: 12px; }
  .rf-scan span, .rf-filt-hint { display: none; }
}
/* Saisie en cours au téléphone (pavé ouvert, ou clavier sur le champ) :
   les filtres s'effacent, la fiche monte sous la barre. */
@media (max-width: 768px) {
  body.bp-on .rf-filt, .rf-bar:focus-within ~ .rf-filt { display: none; }
}
/* Vérification de l'import */
.rf-preview-sum { margin: 0 0 10px; font-size: var(--fs-sm); color: var(--text-2); }
.rf-cols { display: flex; flex-wrap: wrap; gap: 6px; }
.rf-cols em { font-style: normal; opacity: 0.7; font-weight: 500; }
.rf-warn { list-style: none; margin: 12px 0 0; padding: 0; display: grid; gap: 6px; font-size: var(--fs-sm); color: var(--warning); }
.rf-warn li { display: flex; gap: 6px; align-items: flex-start; }
.rf-table-wrap { margin-top: 12px; overflow-x: auto; border: 1px solid var(--border); border-radius: var(--r-sm); }
.rf-table { width: 100%; border-collapse: collapse; font-size: var(--fs-xs); }
.rf-table th, .rf-table td { padding: 6px 10px; text-align: left; white-space: nowrap; border-bottom: 1px solid var(--border); }
.rf-table th { color: var(--text-3); font-weight: 600; background: var(--surface-2); }
.rf-table tr:last-child td { border-bottom: 0; }
.rf-acts { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }

/* ------------------------------------------------------------
   LECTEUR DE DOSSARDS (cf. js/bibscan.js) — plein écran.
   Téléphone : la vidéo en haut, les coureurs reconnus dessous (le
   pouce atteint la saisie). Grand écran : côte à côte.
   ------------------------------------------------------------ */
.bs {
  position: fixed; inset: 0; z-index: 1300; display: flex; flex-direction: column;
  background: #05070a; color: #fff;
}
.bs-stage { position: relative; flex: 0 0 52vh; min-height: 240px; overflow: hidden; background: #000; }
.bs-video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/*  Ce que le lecteur voit : cadres et numéros lus, tracés sur la vidéo. */
.bs-overlay { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
/*  Viseur : la bande que l'OCR lit vraiment (cf. grab() : 4 % de marge
    à gauche et à droite, 18 % en haut et en bas de l'image). Placé ici
    à titre d'attente : dès la première image lue, overlay() le pose sur
    la zone réelle, en tenant compte du recadrage de la vidéo. */
.bs-frame {
  position: absolute; left: 4%; right: 4%; top: 18%; bottom: 18%;
  border: 2px solid rgba(255, 255, 255, 0.85); border-radius: 14px;
  box-shadow: 0 0 0 100vmax rgba(0, 0, 0, 0.35);
  pointer-events: none;
}
.bs-top {
  position: absolute; left: 0; right: 0; top: 0; display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: calc(10px + env(safe-area-inset-top)) 12px 10px;
  background: linear-gradient(rgba(0, 0, 0, 0.6), transparent);
}
.bs-title { display: inline-flex; align-items: center; gap: 8px; min-width: 0; font-size: var(--fs-sm); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bs-top-acts { display: inline-flex; gap: 6px; flex-shrink: 0; }
.bs-btn {
  display: inline-flex; align-items: center; gap: 6px; min-height: 40px; padding: 8px 12px;
  border: 1px solid rgba(255, 255, 255, 0.35); border-radius: 999px; background: rgba(0, 0, 0, 0.45);
  color: #fff; font: inherit; font-size: var(--fs-sm); font-weight: 600; cursor: pointer;
}
.bs-btn[hidden] { display: none; }
.bs-btn.is-on { background: #ffd23f; color: #111; border-color: #ffd23f; }
.bs-status {
  position: absolute; left: 12px; right: 12px; bottom: 10px; padding: 8px 12px; border-radius: var(--r-md);
  background: rgba(0, 0, 0, 0.6); font-size: var(--fs-sm); text-align: center;
}
.bs-status[data-kind="err"] { background: rgba(160, 40, 40, 0.85); }
.bs-panel {
  flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; gap: 10px;
  padding: 12px 12px calc(12px + env(safe-area-inset-bottom));
  background: var(--bg); color: var(--text);
}
.bs-manual { display: flex; gap: 8px; }
.bs-manual .form-input { flex: 1 1 auto; min-width: 0; font-size: 16px; }
.bs-hits { flex: 1 1 auto; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 8px; }
.bs-hit { display: flex; flex-direction: column; gap: 4px; }
.bs-hit-time { font-size: var(--fs-xs); color: var(--text-3); font-variant-numeric: tabular-nums; }
.bs-hit.is-new .rf-card { border-color: var(--success); box-shadow: 0 0 0 2px color-mix(in srgb, var(--success) 35%, transparent); animation: bs-in .25s ease-out; }
@keyframes bs-in { from { transform: translateY(-6px); opacity: 0.4; } to { transform: none; opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .bs-hit.is-new .rf-card { animation: none; } }
.bs-empty { margin: 8px 0; font-size: var(--fs-sm); color: var(--text-3); }
@media (min-width: 900px) {
  .bs { flex-direction: row; }
  .bs-stage { flex: 1 1 auto; height: 100%; }
  .bs-panel { flex: 0 0 400px; border-left: 1px solid var(--border); }
}
.rf-sec-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.rf-sec-row .link-btn { text-transform: none; letter-spacing: 0; font-size: var(--fs-xs); }

/* ------------------------------------------------------------
   PAGE D'UN ÉVÉNEMENT : documents (images en liseuse, cf. js/reader.js)
   et lien public en lecture seule (cf. functions/api/share).
   ------------------------------------------------------------ */
.ev-docs-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 10px; }
.ev-doc { position: relative; margin: 0; }
.ev-doc-open { display: block; width: 100%; aspect-ratio: 4 / 3; padding: 0; border: 1px solid var(--border); border-radius: var(--r-md); overflow: hidden; background: var(--surface-2); cursor: zoom-in; }
.ev-doc-open img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ev-doc figcaption { margin-top: 5px; font-size: var(--fs-xs); color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ev-doc-del {
  position: absolute; top: 6px; right: 6px; width: 30px; height: 30px; display: grid; place-items: center;
  border: 0; border-radius: 50%; background: rgba(0, 0, 0, 0.6); color: #fff; cursor: pointer;
}
.ev-doc-del svg { width: 14px; height: 14px; }
.ev-doc-add { margin-top: 10px; cursor: pointer; display: inline-flex; align-items: center; gap: 6px; }
.ev-publink-note { margin: 0 0 10px; font-size: var(--fs-sm); color: var(--text-2); line-height: 1.5; }
.ev-publink-body .ev-publink-note { margin: 10px 0 0; font-size: var(--fs-xs); color: var(--text-3); }
.ev-publink-wait { font-size: var(--fs-sm); color: var(--text-3); }
.ev-publink-url { width: 100%; font-size: var(--fs-sm); font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
.ev-publink-acts { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.ev-publink-acts .btn { display: inline-flex; align-items: center; gap: 6px; }
/* État du lien, en toutes lettres : actif (vert) ou aucun (neutre). */
.ev-publink-state { display: flex; align-items: flex-start; gap: 10px; margin-bottom: 10px; padding: 10px 12px; border-radius: var(--r-md); border: 1px solid var(--border); background: var(--surface-2); font-size: var(--fs-sm); color: var(--text-2); line-height: 1.45; }
.ev-publink-state svg { width: 18px; height: 18px; flex: none; margin-top: 1px; }
.ev-publink-state strong { display: block; color: var(--text); }
.ev-publink-state.is-on { border-color: color-mix(in srgb, var(--success) 45%, transparent); background: color-mix(in srgb, var(--success) 8%, transparent); }
.ev-publink-state.is-on svg { color: var(--success); }
.ev-publink-state.is-off svg { color: var(--text-3); }
.ev-publink-manage { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--border); }
.ev-publink-manage .btn { display: inline-flex; align-items: center; gap: 6px; }
.ev-publink-manage .btn:disabled, .ev-publink-acts .btn:disabled { opacity: .5; cursor: progress; }

/* Rubriques et liens d'un événement (cf. infoBlocksHtml dans js/events.js) */
.ev-info-body { font-size: var(--fs-sm); color: var(--text-2); line-height: 1.6; white-space: pre-wrap; overflow-wrap: anywhere; }
.ev-info-body .ev-link { color: var(--accent); }
.ev-links { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 8px; }
.ev-linkcard {
  display: flex; align-items: center; gap: 10px; min-height: 48px; padding: 8px 12px;
  border: 1px solid var(--border); border-radius: var(--r-md); background: var(--surface); color: var(--text); text-decoration: none;
}
.ev-linkcard:hover { border-color: var(--accent); }
.ev-linkcard svg { width: 16px; height: 16px; flex: none; color: var(--accent); }
.ev-linkcard span { display: flex; flex-direction: column; min-width: 0; }
.ev-linkcard strong { font-size: var(--fs-sm); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ev-linkcard small { font-size: var(--fs-xs); color: var(--text-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ev-sec-editor, .ev-link-editor { display: flex; flex-direction: column; gap: 8px; }
.ev-sec-editor .form-hint { margin: -4px 0 2px; }
.ev-sec-row { display: flex; flex-direction: column; gap: 6px; padding: 10px; border: 1px solid var(--border); border-radius: var(--r-md); background: var(--surface-2); }
.ev-sec-head { display: flex; gap: 6px; align-items: center; }
.ev-sec-head .form-input { flex: 1; min-width: 0; font-weight: 600; }
.ev-sec-head .ev-icon-btn:disabled { opacity: .35; cursor: default; }
.ev-sec-add { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.ev-sec-presets { display: flex; flex-wrap: wrap; gap: 6px; }
.ev-sec-preset { cursor: pointer; font: inherit; font-size: var(--fs-xs); }
.ev-link-row { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr) auto; gap: 6px; align-items: center; }
.ev-link-editor > .ev-btn { align-self: flex-start; }

/* Organisation d'un événement : membres désignés (cf. organizersEditorHtml). */
.ev-org-editor { display: flex; flex-direction: column; gap: 8px; }
.ev-org-editor .form-hint, .ev-org-editor .ev-no-part { margin: 0; }
.ev-org-list { display: flex; flex-wrap: wrap; gap: 6px; }
.ev-org-chip { font-size: var(--fs-sm); padding: 4px 4px 4px 10px; }
.ev-org-chip svg { width: 13px; height: 13px; }
.ev-org-del { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; border: 0; border-radius: 50%; background: transparent; color: var(--text-3); cursor: pointer; }
.ev-org-del:hover { color: var(--danger); background: var(--danger-soft); }
.ev-org-add { max-width: 360px; }
.ev-org-badge { color: var(--success); border-color: color-mix(in srgb, var(--success) 45%, transparent); }

/* Formulaire en onglets : « Général » puis une rubrique par onglet (les
   mêmes que sur la page de l'événement). « + Rubrique » au bout de la
   barre, hors du défilement des onglets. */
.ev-ftabs { display: flex; align-items: flex-end; gap: 8px; margin: 4px 0 16px; border-bottom: 1px solid var(--border); }
.ev-ftabs .ptabs { flex: 1 1 auto; min-width: 0; margin: 0; border-bottom: 0; }
.ev-ftab-add { flex: none; display: inline-flex; align-items: center; gap: 6px; margin-bottom: 6px; }
.ev-ftab-add svg { width: 14px; height: 14px; }
.ev-fpanel[hidden] { display: none; }
.ev-sec-list { display: flex; flex-wrap: wrap; gap: 6px; }
.ev-sec-jump, .ev-blk-kind { cursor: pointer; font: inherit; font-size: var(--fs-xs); }
.ev-sec-jump svg, .ev-blk-kind svg { width: 13px; height: 13px; }
.ev-sec-editor > .ev-sec-presets { align-items: center; }
.ev-sec-editor > .ev-sec-presets .form-hint { margin: 0; }
/* Un composant d'une rubrique : en-tête (genre + déplacer/retirer), puis sa saisie. */
.ev-blk { display: flex; flex-direction: column; gap: 8px; padding: 10px 12px; border: 1px solid var(--border); border-radius: var(--r-md); background: var(--surface-2); }
.ev-blk-head { display: flex; align-items: center; gap: 8px; min-width: 0; }
.ev-blk-head strong { flex: 1; min-width: 0; font-size: var(--fs-sm); }
.ev-blk-ico { flex: none; display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: 8px; color: var(--accent); background: var(--accent-soft); }
.ev-blk-ico svg { width: 15px; height: 15px; }
.ev-blk-acts { display: inline-flex; gap: 4px; }
.ev-blk-acts .ev-icon-btn:disabled { opacity: .35; cursor: default; }
.ev-blk > .ev-btn { align-self: flex-start; }
.ev-blk .form-hint { margin: 0; }
.ev-blk-add { display: flex; flex-direction: column; gap: 6px; padding: 10px 12px; border: 1px dashed var(--border); border-radius: var(--r-md); }
.ev-blk-add .form-label { margin: 0; }
.ev-blk-kinds { display: flex; flex-wrap: wrap; gap: 6px; }
@media (max-width: 520px) {
  .ev-link-row { grid-template-columns: minmax(0, 1fr) auto; }
  .ev-link-row input[type=url] { grid-column: 1; grid-row: 2; }
}

/* Parcours d'un événement (cf. js/eventtraces.js) : une carte de séance
   (TraceMap.card) par trace, sous un en-tête discipline · distance · D+.
   Le libellé « Parcours · km » de la carte ferait doublon : masqué. */
.ev-traces { display: flex; flex-direction: column; gap: 14px; }
.ev-traces .ev-sheet-parts-title { margin-bottom: 0; }
.ev-trace { container-type: inline-size; display: flex; flex-direction: column; gap: 8px; }
.ev-trace-head { display: flex; align-items: center; gap: 10px; min-width: 0; }
.ev-trace-ico { flex: none; display: inline-flex; align-items: center; justify-content: center; width: 34px; height: 34px; border-radius: 10px; color: var(--ev-trace); background: color-mix(in srgb, var(--ev-trace) 14%, transparent); }
.ev-trace-ico svg { width: 18px; height: 18px; }
.ev-trace-title { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.ev-trace-title strong { font-size: var(--fs-sm); font-weight: 700; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ev-trace-title span { font-size: var(--fs-xs); color: var(--text-2); }
.ev-trace-acts { flex: none; display: inline-flex; gap: 4px; }
.ev-trace-acts .btn { display: inline-flex; align-items: center; gap: 6px; }
.ev-trace-acts svg { width: 15px; height: 15px; }
.ev-trace-del:hover { color: var(--danger); }
.ev-trace-map .log-label { display: none; }
.ev-trace-form { display: flex; flex-direction: column; gap: 10px; padding: 12px; border: 1px solid var(--border); border-radius: var(--r-md); background: var(--surface-2); }
.ev-trace-form-grid { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); gap: 10px; }
.ev-trace-form-grid .form-group { margin: 0; }
.ev-trace-src { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.ev-trace-file { cursor: pointer; display: inline-flex; align-items: center; gap: 6px; }
.ev-trace-act { width: auto; max-width: 100%; min-height: 34px; font-size: var(--fs-sm); }
.ev-trace-form .form-hint { margin: 0; }
@media (max-width: 520px) { .ev-trace-form-grid { grid-template-columns: 1fr; } }

/* ------------------------------------------------------------
   APP INSTALLÉE — ZONES SÛRES DU HAUT (encoche, barre d'état)
   L'app déclare `viewport-fit=cover` (index.html) : installée, elle se
   dessine sous la barre d'état et l'appareil photo. La barre du haut en
   tient compte (css/ui.css) ; les plein-écrans aussi, sinon leur en-tête
   — et son bouton Quitter — passerait sous l'encoche. Dans un navigateur
   ordinaire, env(safe-area-inset-*) vaut 0 : rien ne bouge.
   ------------------------------------------------------------ */
#player, #race-coach, #freerec, #designer {
  padding-top: env(safe-area-inset-top, 0px);
  padding-left: env(safe-area-inset-left, 0px);
  padding-right: env(safe-area-inset-right, 0px);
}
#tmap-full, #fly3d { padding-top: calc(12px + env(safe-area-inset-top, 0px)); }
.chart-zoom, .uic { padding-top: calc(16px + env(safe-area-inset-top, 0px)); }
.ev-sheet-backdrop { padding-top: env(safe-area-inset-top, 0px); }
.landing { padding-top: calc(40px + env(safe-area-inset-top, 0px)); }
.landing-close { top: calc(16px + env(safe-area-inset-top, 0px)); }
@media (min-width: 769px) {
  .sidenav { padding-top: calc(14px + env(safe-area-inset-top, 0px)); }
}

/* ------------------------------------------------------------
   PROJET D'UN ÉVÉNEMENT (js/eventproject.js) — kanban des tâches.
   Trois colonnes côte à côte ; au téléphone, une seule, choisie par
   le sélecteur .pj-colsw (qui porte les compteurs).
   ------------------------------------------------------------ */
.pj-head { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 10px; margin: 4px 0 14px; }
.pj-dl, .pj-prog {
  display: flex; align-items: center; gap: 12px; min-width: 0;
  padding: 12px 14px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-md);
}
.pj-prog { flex-direction: column; align-items: stretch; justify-content: center; gap: 6px; }
.pj-dl-ico { display: inline-flex; color: var(--brand-green); flex-shrink: 0; }
.pj-dl-ico svg { width: 20px; height: 20px; }
.pj-dl-txt { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1; }
.pj-dl-txt strong { font-size: var(--fs-md); font-weight: 600; }
.pj-lbl { font-size: 10.5px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-3); }
.pj-dl-sub { font-size: var(--fs-xs); color: var(--text-2); }
.pj-prog-bar { height: 8px; border-radius: 999px; background: var(--surface-3); overflow: hidden; }
.pj-prog-bar > span { display: block; height: 100%; border-radius: inherit; background: var(--brand-green); transition: width .3s ease; }
.pj-prog-txt { font-size: var(--fs-sm); color: var(--text-2); font-variant-numeric: tabular-nums; }
.pj-prog-txt strong { color: var(--text); }
.pj-late { color: var(--danger); font-weight: 600; }

.pj-bar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 12px; }
.pj-bar .segmented { margin: 0; }
.pj-n {
  display: inline-block; min-width: 18px; padding: 0 5px; border-radius: 999px; margin-left: 2px;
  background: var(--surface-3); color: var(--text-2); font-size: 11px; line-height: 18px; text-align: center; font-variant-numeric: tabular-nums;
}
.pj-colsw { display: none; }

.pj-board { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; align-items: start; }
/* Une couleur par colonne : bleu « À faire », ambre « En cours », vert
   « Fait » — liseré en tête, fond teinté, pastille du compteur. Les
   jetons suivent le thème (assombris en clair, cf. css/ui.css). */
.pj-col[data-status="todo"], .pj-colsw [data-col="todo"] { --pj-col: var(--accent); }
.pj-col[data-status="doing"], .pj-colsw [data-col="doing"] { --pj-col: var(--warning); }
.pj-col[data-status="done"], .pj-colsw [data-col="done"] { --pj-col: var(--success); }
.pj-col {
  display: flex; flex-direction: column; gap: 8px; min-width: 0; min-height: 140px; padding: 10px;
  background: color-mix(in srgb, var(--pj-col) 7%, var(--surface-2));
  border: 1px solid var(--border); border-top: 3px solid var(--pj-col); border-radius: var(--r-lg);
  transition: border-color .15s ease, background .15s ease;
}
.pj-col.is-over { border-color: var(--pj-col); background: color-mix(in srgb, var(--pj-col) 16%, var(--surface-2)); }
.pj-col-head { display: flex; align-items: center; gap: 6px; padding: 0 2px; }
.pj-col-head h3 { margin: 0; font-size: var(--fs-sm); font-weight: 600; display: inline-flex; align-items: center; gap: 7px; }
.pj-col-head h3::before, .pj-colsw .segmented-btn::before {
  content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--pj-col); flex-shrink: 0;
}
.pj-col .pj-col-head .pj-n, .pj-colsw .pj-n { background: color-mix(in srgb, var(--pj-col) 20%, transparent); color: var(--text); }
.pj-add {
  margin-left: auto; display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px;
  border: 1px solid transparent; border-radius: var(--r-sm); background: transparent; color: var(--text-2); cursor: pointer;
}
.pj-add:hover { color: var(--text); border-color: var(--border-strong); background: var(--surface); }
.pj-add svg { width: 16px; height: 16px; }
.pj-list { display: flex; flex-direction: column; gap: 8px; min-height: 40px; }
.pj-none { margin: 6px 2px; font-size: var(--fs-sm); color: var(--text-3); }

.pj-card {
  display: flex; align-items: stretch; min-width: 0;
  background: var(--surface); border: 1px solid var(--border); border-left: 3px solid var(--pj-prio, var(--border-strong));
  border-radius: var(--r-md); box-shadow: var(--shadow-sm);
}
.pj-card.prio-high { --pj-prio: var(--danger); }
.pj-card.prio-normal { --pj-prio: var(--text-3); }
.pj-card.prio-low { --pj-prio: var(--border-strong); }
.pj-card.is-drag { opacity: .45; }
.pj-card[draggable="true"] { cursor: grab; }
.pj-card-main {
  flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: flex-start; gap: 5px;
  padding: 10px 6px 10px 12px; background: none; border: 0; color: inherit; font: inherit; text-align: left; cursor: pointer;
  border-radius: var(--r-md) 0 0 var(--r-md);
}
.pj-card-top { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; }
.pj-card-top { width: 100%; justify-content: space-between; }
.pj-rel-tag { font-size: 10.5px; font-weight: 600; color: var(--text-3); font-variant-numeric: tabular-nums; }
.pj-card-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px; margin-top: 1px; }
.pj-head:has(> :only-child) { grid-template-columns: minmax(0, 1fr); }
.pj-prio { font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; color: var(--pj-prio); }
.pj-card.prio-normal .pj-prio { color: var(--text-2); }
.pj-card.prio-low .pj-prio { color: var(--text-3); }
.pj-title { font-size: var(--fs-sm); font-weight: 600; line-height: 1.35; overflow-wrap: anywhere; }
.pj-card.due-done .pj-title { color: var(--text-2); }
.pj-note { font-size: var(--fs-xs); color: var(--text-3); line-height: 1.4; overflow-wrap: anywhere; }
.pj-due { display: inline-flex; align-items: center; gap: 4px; font-size: var(--fs-xs); color: var(--text-2); font-variant-numeric: tabular-nums; }
.pj-due svg { width: 12px; height: 12px; flex-shrink: 0; }
.pj-due.is-late { color: var(--danger); font-weight: 600; }
.pj-due.is-today, .pj-due.is-soon { color: var(--warning); font-weight: 600; }
.pj-due.is-done, .pj-due.is-unset { color: var(--text-3); }
.pj-who { display: inline-flex; align-items: center; gap: 6px; font-size: var(--fs-xs); color: var(--text-2); min-width: 0; }
.pj-who.is-none { color: var(--text-3); }
.pj-who.is-me { color: var(--text); font-weight: 600; }
.pj-who svg { width: 13px; height: 13px; }
.pj-av {
  width: 20px; height: 20px; flex-shrink: 0; border-radius: 50%; overflow: hidden; display: inline-flex; align-items: center; justify-content: center;
  background: var(--surface-2); font-size: 12px; line-height: 1;
}
.pj-av .pj-av-img { width: 100%; height: 100%; object-fit: cover; }
.pj-move { display: flex; flex-direction: column; justify-content: center; gap: 2px; padding: 4px; }
.pj-mv {
  display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px;
  border: 1px solid transparent; border-radius: var(--r-sm); background: transparent; color: var(--text-3); cursor: pointer;
}
.pj-mv:hover { color: var(--text); background: var(--surface-2); border-color: var(--border); }
.pj-mv svg { width: 16px; height: 16px; }

.pj-empty { padding: 26px 18px; text-align: center; background: var(--surface); border: 1px dashed var(--border-strong); border-radius: var(--r-lg); }
.pj-empty p { margin: 0 0 14px; color: var(--text-2); }
.pj-empty-acts { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; }
.pj-io { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 16px; padding-top: 12px; border-top: 1px solid var(--border); }
.pj-empty .pj-io { justify-content: center; border-top-style: dashed; }
.pj-io-hint { font-size: var(--fs-xs); color: var(--text-3); margin-left: 4px; }
.pj-live { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; margin: 0; }

/* Fenêtre d'une tâche */
.pj-dlg .uic-box { width: min(520px, 100%); max-height: calc(100dvh - 32px); overflow-y: auto; }
.pj-form { gap: 12px; }
.pj-field { display: flex; flex-direction: column; gap: 5px; }
.pj-fs { border: 0; margin: 0; padding: 0; min-width: 0; display: flex; flex-direction: column; gap: 5px; }
.pj-fs legend { padding: 0; margin-bottom: 5px; }
.pj-f-row { display: flex; flex-wrap: wrap; gap: 12px 16px; }
.pj-seg { margin: 0; align-self: flex-start; overflow: visible; }   /* largeur fractionnaire : pas de barre de défilement fantôme */
.pj-seg .segmented-btn { position: relative; display: inline-flex; align-items: center; }
.pj-radio { position: absolute; inset: 0; opacity: 0; margin: 0; cursor: pointer; }
.pj-seg .segmented-btn:has(.pj-radio:focus-visible) { outline: 2px solid var(--accent); outline-offset: 1px; }
.pj-rel { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; font-size: var(--fs-sm); color: var(--text-2); }
.pj-days { width: 84px; }
.pj-side { width: auto; }
.pj-due-in .form-hint { margin-top: 6px; }
.pj-notes { resize: vertical; min-height: 64px; }
.pj-err { color: var(--danger); margin: 0; }
.pj-f-meta { margin: 0; font-size: var(--fs-xs); color: var(--text-3); }
.pj-f-acts .pj-f-del { margin-right: auto; }
.pj-linkbtn { padding: 0; border: 0; background: none; color: var(--accent); font: inherit; text-decoration: underline; cursor: pointer; }

@media (max-width: 768px) {
  .pj-head { grid-template-columns: minmax(0, 1fr); }
  .pj-colsw { display: flex; width: 100%; margin: 0 0 10px; }
  .pj-colsw .segmented-btn { flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 6px; }
  .pj-colsw .segmented-btn.active { box-shadow: inset 0 -2px 0 var(--pj-col), var(--shadow-sm); }
  .pj-board { grid-template-columns: minmax(0, 1fr); }
  .pj-col:not(.is-cur) { display: none; }
  .pj-col { min-height: 0; }
  /* Le sélecteur porte déjà le nom et le compteur. */
  .pj-col-head h3, .pj-col-head .pj-n { display: none; }
  .pj-col-head { justify-content: flex-end; margin: -4px 0 -6px; }
}


/* Sous-onglets Tableau · Planning, jalon et documents sur la carte */
.pj-head + .ptabs { margin-top: 16px; margin-bottom: 14px; }
.pj-card-tags { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; }
.pj-ms { display: inline-flex; align-items: center; gap: 5px; min-width: 0; font-size: var(--fs-xs); font-weight: 600; color: var(--text-2); }
.pj-ms i { width: 8px; height: 8px; border-radius: 2px; background: var(--ms); flex-shrink: 0; }
.pj-clip { display: inline-flex; align-items: center; gap: 3px; font-size: var(--fs-xs); color: var(--text-2); font-variant-numeric: tabular-nums; }
.pj-clip svg { width: 13px; height: 13px; }
.pj-bar-r { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.pj-bar-r .segmented { margin: 0; }
.pj-hint { margin: 0 0 10px; font-size: var(--fs-sm); color: var(--text-3); }

/* Fenêtre d'une tâche : jalon, dates, documents */
.pj-f-2 > .pj-field { flex: 1 1 180px; min-width: 0; }
.pj-when { display: flex; flex-direction: column; gap: 8px; }
.pj-flist { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.pj-flist:empty { display: none; }
.pj-frow {
  display: flex; align-items: center; gap: 2px; min-width: 0; padding-right: 4px;
  background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--r-md);
}
.pj-fopen {
  flex: 1; min-width: 0; display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: 10px; align-items: center;
  padding: 7px 8px 7px 10px; background: none; border: 0; color: inherit; font: inherit; text-align: left; cursor: pointer;
  border-radius: var(--r-md) 0 0 var(--r-md);
}
.pj-fopen:hover .pj-fname { text-decoration: underline; }
.pj-fkind {
  grid-row: span 2; min-width: 46px; padding: 4px 6px; border-radius: 6px; text-align: center;
  font-size: 10px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  color: var(--k); background: color-mix(in srgb, var(--k) 13%, transparent); border: 1px solid color-mix(in srgb, var(--k) 35%, transparent);
}
.k-pdf { --k: var(--danger); }
.k-docx { --k: var(--accent); }
.k-xlsx { --k: var(--success); }
.k-image { --k: var(--sport-bike); }
.pj-fname { font-size: var(--fs-sm); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pj-fmeta { font-size: var(--fs-xs); color: var(--text-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pj-ficon {
  flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; width: 34px; height: 34px;
  border: 1px solid transparent; border-radius: var(--r-sm); background: transparent; color: var(--text-2); cursor: pointer;
}
.pj-ficon:hover { color: var(--text); background: var(--surface); border-color: var(--border); }
.pj-ficon.is-danger:hover { color: var(--danger); }
.pj-ficon:disabled { opacity: .4; cursor: default; }
.pj-ficon svg { width: 16px; height: 16px; }
.pj-docs-acts { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; }
.pj-docs-acts .form-hint { margin: 0; }
.pj-fbusy { display: flex; align-items: center; gap: 8px; margin: 0; font-size: var(--fs-sm); color: var(--text-2); }
.pj-fbusy[hidden] { display: none; }
.pj-spin {
  width: 16px; height: 16px; flex-shrink: 0; border: 2px solid var(--border-strong); border-top-color: var(--accent);
  border-radius: 50%; animation: pj-spin .8s linear infinite;
}
@keyframes pj-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .pj-spin, .dv-spin { animation-duration: 2.4s; } }
.pj-swatches { display: flex; flex-wrap: wrap; gap: 8px; }
.pj-swatch {
  position: relative; width: 30px; height: 30px; border-radius: 50%; cursor: pointer;
  background: var(--ms); border: 2px solid transparent; box-shadow: inset 0 0 0 2px var(--surface);
}
.pj-swatch.active { border-color: var(--text); }
.pj-swatch:has(.pj-radio:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Planning (Gantt) : libellés collés à gauche, frise qui défile.
   L'échelle (`--ppd`, pixels par jour) et la largeur de la frise
   (`--gt-w`) sont posées par js/eventproject.js. Le premier jour est
   toujours un lundi : les traits de semaine tombent sur les lundis. */
.gt {
  --gt-label: 240px; --gt-row: 36px;
  overflow-x: auto; overscroll-behavior-x: contain;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg);
}
/* `clip` (pas `hidden`) : rien ne dépasse de la frise, et les libellés restent collés à gauche. */
.gt-inner { position: relative; width: calc(var(--gt-label) + var(--gt-w)); overflow-x: clip; }
.gt-head { display: flex; background: var(--surface-2); border-bottom: 1px solid var(--border); }
.gt-label {
  position: sticky; left: 0; z-index: 2; flex: 0 0 var(--gt-label); width: var(--gt-label); min-width: 0;
  background: var(--surface); border-right: 1px solid var(--border);
}
.gt-head .gt-label {
  display: flex; align-items: flex-end; padding: 6px 12px; background: var(--surface-2);
  font-size: var(--fs-xs); font-weight: 600; color: var(--text-3);
}
.gt-scale { position: relative; flex: 0 0 var(--gt-w); width: var(--gt-w); }
.gt-months { position: relative; height: 24px; }
.gt-month {
  position: absolute; top: 0; height: 24px; padding: 0 6px; line-height: 24px; overflow: hidden; white-space: nowrap;
  font-size: var(--fs-xs); font-weight: 600; color: var(--text-2); border-left: 1px solid var(--border);
}
.gt-ticks { position: relative; height: 20px; border-top: 1px solid var(--border); }
.gt-tick {
  position: absolute; top: 0; height: 20px; line-height: 20px; overflow: hidden; text-align: center;
  font-size: 10.5px; color: var(--text-3); font-variant-numeric: tabular-nums;
  border-left: 1px solid color-mix(in srgb, var(--border) 60%, transparent);
}
.gt-z-week .gt-tick { text-align: left; padding-left: 4px; }
.gt-tick.is-we { background: color-mix(in srgb, var(--text) 5%, transparent); }
.gt-tick.is-today { color: var(--danger); font-weight: 700; }
.gt-body { position: relative; }
.gt-row { display: flex; min-height: var(--gt-row); border-bottom: 1px solid color-mix(in srgb, var(--border) 70%, transparent); }
.gt-track {
  position: relative; flex: 0 0 var(--gt-w); width: var(--gt-w);
  background-image: linear-gradient(to right, color-mix(in srgb, var(--border) 70%, transparent) 1px, transparent 1px);
  background-size: calc(var(--ppd) * 7) 100%;
}
/* Échelle « jours » : le week-end grisé, en plus des lundis. */
.gt-z-day .gt-track {
  background-image:
    linear-gradient(to right, color-mix(in srgb, var(--border) 70%, transparent) 1px, transparent 1px),
    linear-gradient(to right, transparent calc(var(--ppd) * 5), color-mix(in srgb, var(--text) 4%, transparent) calc(var(--ppd) * 5));
  background-size: calc(var(--ppd) * 7) 100%, calc(var(--ppd) * 7) 100%;
}
button.gt-label {
  display: flex; align-items: center; gap: 8px; padding: 4px 12px; border: 0; border-right: 1px solid var(--border);
  color: inherit; font: inherit; text-align: left; cursor: pointer;
}
button.gt-label:hover .gt-ttl { text-decoration: underline; }
div.gt-label { display: flex; align-items: center; gap: 8px; padding: 4px 12px; }
/* Tâche : une poignée (glisser vers un jalon) puis le titre, qui ouvre la fiche. */
div.gt-task-label { gap: 2px; padding: 0 12px 0 4px; }
.gt-grip {
  flex: none; display: inline-flex; align-items: center; justify-content: center; width: 20px; align-self: stretch;
  color: var(--text-3); cursor: grab; opacity: .55; touch-action: none;
}
.gt-grip svg { width: 14px; height: 14px; pointer-events: none; }
.gt-task:hover .gt-grip { opacity: 1; color: var(--text-2); }
.gt:not(.can-drag) .gt-grip { visibility: hidden; }
.gt-open {
  flex: 1; min-width: 0; align-self: stretch; display: flex; align-items: center; gap: 8px; padding: 4px 0;
  border: 0; background: none; color: inherit; font: inherit; text-align: left; cursor: pointer;
}
.gt-open:hover .gt-ttl { text-decoration: underline; }
.gt-open:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; border-radius: 4px; }
.gt.can-drag .gt-task .gt-track { cursor: grab; }
.gt-task.is-drag { opacity: .4; }
/* Jalon survolé pendant un glisser : tout le groupe s'éclaire. */
.gt-group { position: relative; }
.gt-group.is-over { background: color-mix(in srgb, var(--ms) 12%, transparent); }
.gt-group.is-over::after {
  content: ""; position: absolute; inset: 0; z-index: 3; pointer-events: none;
  border: 2px solid var(--ms); border-radius: 4px;
}
.gt-group.is-over .gt-label { background: color-mix(in srgb, var(--ms) 16%, var(--surface)); }
.gt-group-drop { display: none; }
.gt.is-dragging .gt-group-drop { display: block; }
.gt.is-dragging .gt-group-drop .gt-ms-row { border-top: 1px dashed var(--border-strong); }
.gt-task.is-dropped .gt-label { animation: gt-dropped 1.4s ease-out; }
@keyframes gt-dropped { from { background: color-mix(in srgb, var(--brand-green) 30%, var(--surface)); } to { background: var(--surface); } }
@media (prefers-reduced-motion: reduce) { .gt-task.is-dropped .gt-label { animation: none; } }
.gt-ttl { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--fs-sm); }
.gt-ttl.is-late { color: var(--danger); }
.gt-who, .gt-sub { flex-shrink: 0; font-size: var(--fs-xs); color: var(--text-3); white-space: nowrap; }
.gt-who { max-width: 72px; overflow: hidden; text-overflow: ellipsis; }
.st-todo { --st: var(--accent); }
.st-doing { --st: var(--warning); }
.st-done { --st: var(--success); }
.gt-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; background: var(--st); }
.gt-ms-row { background: color-mix(in srgb, var(--ms) 7%, transparent); }
.gt-ms-row.is-none { --ms: var(--text-3); }
.gt-ms-row .gt-label { background: color-mix(in srgb, var(--ms) 9%, var(--surface)); }
.gt-ms-label i { width: 10px; height: 10px; border-radius: 3px; flex-shrink: 0; background: var(--ms); }
.gt-ms-txt { flex: 1; min-width: 0; display: flex; flex-direction: column; line-height: 1.25; }
.gt-ms-txt .gt-sub { overflow: hidden; text-overflow: ellipsis; }
.gt-ms-label .gt-ttl { font-weight: 700; }
.gt-span { position: absolute; top: 50%; height: 8px; transform: translateY(-50%); border-radius: 4px; background: var(--ms); }
.gt-diamond {
  position: absolute; top: 50%; width: 12px; height: 12px; border-radius: 2px;
  background: var(--ms); transform: translate(-50%, -50%) rotate(45deg);
}
.gt-bar {
  position: absolute; top: 6px; height: calc(var(--gt-row) - 12px); min-width: 10px;
  display: flex; align-items: center; gap: 4px; padding: 0 6px;
  border: 1px solid var(--ms); border-radius: 6px; background: color-mix(in srgb, var(--ms) 22%, var(--surface));
  color: var(--text); font: inherit; font-size: var(--fs-xs); font-weight: 600; text-align: left; cursor: pointer;
}
.gt-bar.st-doing { background: color-mix(in srgb, var(--ms) 55%, var(--surface)); }
.gt-bar.st-done { background: var(--ms); color: var(--surface); }
.gt-bar.is-derived { background: transparent; border-style: dashed; }
.gt-bar.is-late { border: 2px solid var(--danger); }
.gt-bar:hover, .gt-bar:focus-visible { outline: none; box-shadow: 0 0 0 3px color-mix(in srgb, var(--ms) 35%, transparent); }
.gt-bar svg { width: 12px; height: 12px; flex-shrink: 0; }
.gt-bar-txt { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gt-bar-txt.is-out {
  position: absolute; left: calc(100% + 6px); top: 50%; transform: translateY(-50%); overflow: visible;
  color: var(--text-2); font-weight: 500; pointer-events: none;
}
.gt-bar-txt.is-out.is-left { left: auto; right: calc(100% + 6px); }
.gt-nodate {
  position: sticky; left: calc(var(--gt-label) + 10px); display: inline-block; line-height: var(--gt-row);
  font-size: var(--fs-xs); font-style: italic; color: var(--text-3);
}
.gt-lines { position: absolute; top: 0; bottom: 0; left: var(--gt-label); width: var(--gt-w); z-index: 1; pointer-events: none; }
.gt-line { position: absolute; top: 0; bottom: 0; width: 0; }
.gt-line.is-today { border-left: 2px solid var(--danger); }
.gt-line.is-dl { border-left: 2px dashed var(--brand-green); }
.gt-line b { position: absolute; top: 0; left: 3px; display: inline-flex; padding: 0 4px; border-radius: 3px; font-size: 10px; line-height: 16px; white-space: nowrap; }
.gt-line.is-today b { color: #fff; background: var(--danger); }
.gt-line.is-dl b { color: var(--brand-green); background: var(--surface); padding: 1px; }
.gt-line.is-dl b svg { width: 14px; height: 14px; }
.pj-legend { display: flex; flex-wrap: wrap; gap: 6px 14px; margin: 10px 0 0; font-size: var(--fs-xs); color: var(--text-3); }
.pj-legend span { display: inline-flex; align-items: center; gap: 6px; }
.pj-legend .lg { --ms: var(--accent); width: 18px; height: 10px; border-radius: 3px; border: 1px solid var(--ms); background: color-mix(in srgb, var(--ms) 22%, var(--surface)); }
.pj-legend .lg.st-doing { background: color-mix(in srgb, var(--ms) 55%, var(--surface)); }
.pj-legend .lg.st-done { background: var(--ms); }
.pj-legend .lg.is-derived { background: transparent; border-style: dashed; }
.pj-legend .lg.is-late { background: transparent; border: 2px solid var(--danger); }
.pj-legend .pj-legend-tip { margin-left: auto; }
.pj-legend-tip svg { width: 13px; height: 13px; }
.pj-bar .segmented-btn:disabled { opacity: .4; cursor: default; }

@media (max-width: 768px) {
  .gt { --gt-label: 136px; }
  .gt-who { display: none; }
  div.gt-task-label { padding-right: 8px; }
  .pj-bar-r { width: 100%; }
  .pj-legend .pj-legend-tip { margin-left: 0; }
}

/* =====================================================================
   VISIONNEUSE DE DOCUMENTS (js/docviewer.js) — PDF, Word, Excel, images
   Les pages gardent un fond BLANC dans les deux thèmes : ce sont des
   documents pensés pour le papier (couleurs, tableaux, logos).
   ===================================================================== */
.dv { position: fixed; inset: 0; z-index: 1300; display: flex; flex-direction: column; background: var(--bg); color: var(--text); }
.dv-top {
  display: flex; align-items: center; gap: 10px; padding: calc(8px + env(safe-area-inset-top, 0px)) 12px 8px;
  background: var(--surface); border-bottom: 1px solid var(--border);
}
.dv-close {
  flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; width: 40px; height: 40px;
  border: 1px solid var(--border); border-radius: 50%; background: transparent; color: var(--text); cursor: pointer;
}
.dv-close:hover { background: var(--surface-2); }
.dv-close svg { width: 18px; height: 18px; }
.dv-name { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.dv-name strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--fs-md); font-weight: 600; }
.dv-name > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--fs-xs); color: var(--text-3); }
.dv-kind { font-weight: 700; }
.dv-kind-pdf { color: var(--danger); }
.dv-kind-docx { color: var(--accent); }
.dv-kind-xlsx { color: var(--success); }
.dv-kind-image { color: var(--sport-bike); }
.dv-acts { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
.dv-zoom { display: inline-flex; align-items: center; border: 1px solid var(--border); border-radius: 999px; overflow: hidden; }
.dv-zbtn {
  display: inline-flex; align-items: center; justify-content: center; min-width: 36px; height: 34px; padding: 0 6px;
  border: 0; background: transparent; color: var(--text); font: inherit; font-size: var(--fs-xs); font-variant-numeric: tabular-nums; cursor: pointer;
}
.dv-zbtn:hover { background: var(--surface-2); }
.dv-zbtn svg { width: 16px; height: 16px; }
.dv-body { flex: 1; min-height: 0; overflow: auto; padding: 16px 12px calc(28px + env(safe-area-inset-bottom, 0px)); background: var(--surface-2); outline: none; }
.dv-wait { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px; min-height: 60%; padding: 24px; text-align: center; color: var(--text-2); }
.dv-fail p { max-width: 420px; margin: 0; }
.dv-spin { width: 28px; height: 28px; border: 3px solid var(--border-strong); border-top-color: var(--accent); border-radius: 50%; animation: pj-spin .8s linear infinite; }
.dv-muted { color: var(--text-3); }
.dv-pad { margin: 0; padding: 16px; }

/* PDF : une page = un canevas ; la largeur suit le zoom. Bloc (pas
   flex centré) : agrandie, la page déborde vers la droite et reste
   atteignable en faisant défiler. */
.dv-page {
  width: calc(min(900px, 100%) * var(--dv-zoom, 1)); margin: 0 auto 12px;
  background: #fff; box-shadow: var(--shadow-md);
}
.dv-page canvas { display: block; width: 100%; height: 100%; }
.dv-page .dv-muted { color: #6b7280; }

/* Image */
.dv-photo { display: block; width: calc(min(1200px, 100%) * var(--dv-zoom, 1)); max-width: none; height: auto; margin: 0 auto; background: #fff; }

/* Word */
.dv-paper {
  width: min(820px, 100%); margin: 0 auto; padding: 56px 64px; box-shadow: var(--shadow-md);
  background: #fff; color: #1b1b1b; color-scheme: light;
  font-family: Calibri, Carlito, "Segoe UI", Arial, sans-serif; font-size: 15px; line-height: 1.5; overflow-wrap: anywhere;
}
.dv-paper p { margin: 0 0 .6em; }
.dv-paper p.is-empty { min-height: 1em; margin: 0 0 .3em; }
.dv-paper h2, .dv-paper h3, .dv-paper h4, .dv-paper h5, .dv-paper h6, .dv-paper h7 { margin: 1.1em 0 .45em; line-height: 1.25; font-weight: 600; color: #1f3864; }
.dv-paper h2 { font-size: 1.55em; }
.dv-paper h3 { font-size: 1.3em; }
.dv-paper h4 { font-size: 1.12em; }
.dv-paper h5, .dv-paper h6 { font-size: 1em; }
.dv-paper .dv-title { font-size: 2em; font-weight: 500; color: #1b1b1b; }
.dv-paper a { color: #1d4ed8; text-decoration: underline; }
.dv-paper .dv-muted { color: #6b7280; }
.dv-li { display: flex; gap: .5em; margin-bottom: .3em; }
.dv-li-mark { flex-shrink: 0; min-width: 1.2em; }
.dv-li-body { flex: 1; min-width: 0; }
.dv-tab { display: inline-block; width: 2em; }
.dv-pgbreak { display: block; height: 0; margin: 1.4em -64px; border-top: 1px dashed #c8c8c8; }
.dv-img { max-width: 100%; height: auto; vertical-align: middle; }
.dv-table-wrap { overflow-x: auto; margin: .4em 0 .9em; }
.dv-table { width: 100%; border-collapse: collapse; }
.dv-table td { padding: 4px 7px; border: 1px solid #c9c9c9; vertical-align: top; }
.dv-table td p { margin: 0 0 .25em; }

/* Excel */
.dv-k-xlsx .dv-body { display: flex; flex-direction: column; padding: 0; }
.dv-xlsx { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.dv-xlsx-stage { flex: 1; min-height: 0; overflow: auto; background: #fff; color: #1b1b1b; color-scheme: light; }
.dv-sheet .dv-muted { color: #6b7280; }
.dv-grid { table-layout: fixed; border-collapse: separate; border-spacing: 0; font: 13px/1.35 Calibri, Carlito, "Segoe UI", Arial, sans-serif; }
.dv-grid th, .dv-grid td {
  height: 22px; padding: 3px 6px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  border-right: 1px solid #e1e1e1; border-bottom: 1px solid #e1e1e1;
}
.dv-grid td.is-num { text-align: right; font-variant-numeric: tabular-nums; }
.dv-grid td.is-wrap { white-space: normal; }
.dv-grid thead th { position: sticky; top: 0; z-index: 2; background: #f3f4f6; color: #4b5563; font-size: 12px; font-weight: 600; text-align: center; }
.dv-grid th.dv-rn { position: sticky; left: 0; z-index: 1; background: #f3f4f6; color: #4b5563; font-size: 12px; font-weight: 500; text-align: center; }
.dv-grid thead th.dv-corner { left: 0; z-index: 3; }
.dv-rn-col { width: 44px; }
.dv-sheets {
  display: flex; gap: 4px; overflow-x: auto; padding: 6px 10px calc(6px + env(safe-area-inset-bottom, 0px));
  background: var(--surface); border-top: 1px solid var(--border);
}
.dv-sheet-tab {
  flex-shrink: 0; padding: 6px 12px; border: 1px solid var(--border); border-radius: 999px; background: transparent;
  color: var(--text-2); font: inherit; font-size: var(--fs-sm); white-space: nowrap; cursor: pointer;
}
.dv-sheet-tab.is-on { color: var(--text); font-weight: 600; border-color: var(--brand-green); background: color-mix(in srgb, var(--brand-green) 14%, transparent); }

@media (max-width: 768px) {
  .dv-paper { padding: 22px 18px; font-size: 14.5px; }
  .dv-pgbreak { margin: 1em -18px; }
  .dv-act span { display: none; }
  .dv-acts .dv-act { padding-left: 9px; padding-right: 9px; }
  .dv-zoom .dv-zoom-val { display: none; }
}


/* Modèles d'événement (js/eventtemplates.js, liste « Modèles » de js/events.js) */
.ev-tpls { display: flex; flex-direction: column; gap: 10px; margin-top: 16px; }
.ev-tpl {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px 16px; padding: 14px 16px;
  background: var(--surface); border: 1px solid var(--border); border-left: 3px solid var(--ev-accent, var(--border-strong)); border-radius: var(--r-lg);
}
.ev-tpl-main { display: flex; flex-direction: column; gap: 3px; min-width: 0; flex: 1 1 260px; }
.ev-tpl-main strong { font-size: var(--fs-md); font-weight: 600; overflow-wrap: anywhere; }
.ev-tpl-main small { font-size: var(--fs-xs); color: var(--text-3); }
.ev-tpl-acts { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.ev-tpl-del:hover { color: var(--danger); }
.ev-tpl-banner {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; margin-bottom: 14px; padding: 12px 14px;
  border: 1px dashed color-mix(in srgb, var(--brand-green) 55%, var(--border)); border-radius: var(--r-md);
  background: color-mix(in srgb, var(--brand-green) 7%, var(--surface));
}
.ev-tpl-banner > span { display: inline-flex; color: var(--brand-green); }
.ev-tpl-banner > span svg { width: 20px; height: 20px; }
.ev-tpl-banner p { flex: 1 1 260px; margin: 0; font-size: var(--fs-sm); color: var(--text-2); }
.ev-tpl-banner strong { color: var(--text); }
.et-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; font-size: var(--fs-sm); }
.et-list li { display: flex; align-items: flex-start; gap: 8px; color: var(--text-2); }
.et-list svg { width: 15px; height: 15px; flex-shrink: 0; margin-top: 2px; }
.et-list .is-keep svg { color: var(--success); }
.et-list .is-drop svg { color: var(--danger); }
.et-busy { display: flex; align-items: center; gap: 8px; margin: 0; font-size: var(--fs-sm); color: var(--text-2); }
.et-busy[hidden] { display: none; }

/* =====================================================================
   BÉNÉVOLES D'UN ÉVÉNEMENT (js/eventvolunteers.js) — équipe organisatrice
   Fenêtres et zone d'import : celles du kanban (.pj-dlg, .pj-io…).
   ===================================================================== */
.vo-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 4px 12px; }
.vo-head .ptabs { flex: 1 1 auto; min-width: 0; margin-bottom: 0; }
.vo-sync { display: inline-flex; align-items: center; gap: 5px; font-size: var(--fs-xs); color: var(--text-3); }
.vo-sync:empty { display: none; }
.vo-sync svg { width: 14px; height: 14px; }
.vo-sync.is-ok { color: var(--success); }
.vo-sync.is-off { color: var(--warning); }
.vo-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 14px 0 12px; }
.vo-bar-txt { flex: 1 1 auto; font-size: var(--fs-sm); color: var(--text-2); }
.vo-bar-txt strong { color: var(--text); }
.vo-q { flex: 1 1 200px; min-width: 0; font-size: 16px; }
.vo-filter { flex: 0 1 220px; width: auto; min-width: 0; }
.vo-low { color: var(--danger); font-weight: 600; }
.vo-none { margin: 10px 0; font-size: var(--fs-sm); color: var(--text-3); }

/* Liste des bénévoles */
.vo-list { display: flex; flex-direction: column; gap: 6px; }
.vo-row {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(170px, 240px); gap: 8px 14px; align-items: center;
  padding: 10px 12px; background: var(--surface); border: 1px solid var(--border); border-left: 3px solid var(--vo-c, var(--border));
  border-radius: var(--r-md);
}
.vo-row-main { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.vo-name { align-self: flex-start; padding: 0; border: 0; background: none; color: var(--text); font: inherit; font-weight: 600; text-align: left; cursor: pointer; overflow-wrap: anywhere; }
.vo-name:hover { color: var(--accent); }
.vo-contact { display: flex; flex-wrap: wrap; gap: 2px 12px; font-size: var(--fs-sm); color: var(--text-2); min-width: 0; }
.vo-contact span { overflow-wrap: anywhere; }
.vo-contact a { color: inherit; font-variant-numeric: tabular-nums; }
.vo-row-tags { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; }
.vo-apt { padding: 2px 7px; border-radius: 999px; background: var(--surface-2); border: 1px solid var(--border); font-size: 11px; font-weight: 600; color: var(--text-2); }
.vo-apt.is-req { color: var(--accent); background: var(--accent-soft); border-color: transparent; }
.vo-apt.is-minor { color: var(--warning); background: var(--warning-soft); border-color: transparent; }
.vo-prefs { font-size: var(--fs-xs); color: var(--text-3); }
.vo-avoid { color: var(--danger); }
.vo-row-side { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.vo-assign { width: 100%; min-width: 0; }
.vo-assign.is-compact { min-height: 32px; padding-top: 4px; padding-bottom: 4px; font-size: var(--fs-sm); }
.vo-issues { display: flex; flex-wrap: wrap; gap: 3px 8px; }
.vo-issue { display: inline-flex; align-items: center; gap: 3px; font-size: 11.5px; font-weight: 600; }
.vo-issue svg { width: 12px; height: 12px; flex: none; }
.vo-issue.is-no { color: var(--danger); }
.vo-issue.is-check { color: var(--warning); }
.vo-purge { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; margin-top: 14px; font-size: var(--fs-xs); color: var(--text-3); }
.vo-danger { color: var(--danger); font-size: var(--fs-sm); }

/* Pôles */
.vo-poles { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 10px; }
.vo-pole {
  display: flex; flex-direction: column; gap: 8px; padding: 12px 14px; text-align: left; font: inherit; color: inherit; cursor: pointer;
  background: var(--surface); border: 1px solid var(--border); border-top: 3px solid var(--vo-c); border-radius: var(--r-md);
}
.vo-pole:hover { border-color: var(--border-strong); border-top-color: var(--vo-c); }
.vo-pole-head { display: flex; align-items: center; gap: 8px; }
.vo-dot { width: 10px; height: 10px; border-radius: 50%; background: var(--vo-c); flex: none; }
.vo-pole-meta { display: flex; flex-direction: column; gap: 3px; font-size: var(--fs-xs); color: var(--text-2); }
.vo-pole-meta span { display: inline-flex; align-items: center; gap: 5px; }
.vo-pole-meta svg { width: 13px; height: 13px; flex: none; color: var(--text-3); }
.vo-pole-meta .is-none { color: var(--text-3); }

/* Jauge besoin / affectés : trait = minimum */
.vo-gauge { display: flex; align-items: center; gap: 8px; min-width: 0; }
.vo-gauge-bar { position: relative; flex: 1 1 auto; height: 6px; min-width: 50px; border-radius: 999px; background: var(--surface-3, var(--surface-2)); }
.vo-gauge-bar > span { display: block; height: 100%; border-radius: inherit; background: var(--success); }
.vo-gauge-bar > i { position: absolute; top: -3px; bottom: -3px; width: 2px; margin-left: -1px; background: var(--text-2); border-radius: 1px; }
.vo-gauge.is-short .vo-gauge-bar > span { background: var(--warning); }
.vo-gauge.is-low .vo-gauge-bar > span { background: var(--danger); }
.vo-gauge-txt { flex: none; font-size: var(--fs-xs); color: var(--text-2); font-variant-numeric: tabular-nums; }
.vo-gauge-txt strong { color: var(--text); font-size: var(--fs-sm); }
.vo-gauge.is-low .vo-gauge-txt strong { color: var(--danger); }

/* Répartition : une colonne par pôle */
.vo-board { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 10px; align-items: start; }
.vo-col { background: var(--surface); border: 1px solid var(--border); border-top: 3px solid var(--vo-c); border-radius: var(--r-md); padding: 10px 12px; min-width: 0; }
.vo-col-head { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; margin-bottom: 8px; }
.vo-col-head h3 { margin: 0; font-size: var(--fs-sm); font-weight: 700; flex: 1 1 auto; min-width: 0; }
.vo-col-head .vo-gauge { flex: 1 1 100%; }
.vo-split-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.vo-split-item { display: flex; flex-direction: column; gap: 4px; padding-top: 8px; border-top: 1px solid var(--border); }
.vo-split-item:first-child { padding-top: 0; border-top: 0; }
.vo-split-who { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 8px; }
.vo-rank { font-size: 11px; font-weight: 600; color: var(--text-3); }
.vo-rank.is-1 { color: var(--success); }
.vo-rank.is-2, .vo-rank.is-3 { color: var(--accent); }
.vo-rank.is-0 { color: var(--warning); }

/* Créneaux */
.vo-slots { display: flex; flex-wrap: wrap; width: fit-content; max-width: 100%; margin: 0 0 12px; }
.vo-slots .segmented-btn { white-space: nowrap; }
.vo-slotcard { margin: 14px 0 4px; padding: 12px 14px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-md); }
.vo-slotcard-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.vo-slotcard-head h3 { margin: 0; font-size: var(--fs-sm); font-weight: 700; }
.vo-slotlist { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.vo-slotchip { display: inline-flex; align-items: center; gap: 6px; padding: 6px 11px; border: 1px solid var(--border); border-radius: 999px; background: var(--surface-2); color: var(--text); font: inherit; font-size: var(--fs-sm); cursor: pointer; }
.vo-slotchip svg { width: 13px; height: 13px; color: var(--text-3); }
.vo-slotchip:hover { border-color: var(--border-strong); }
.vo-slot-none { margin: 6px 0 0; font-size: var(--fs-sm); color: var(--text-2); }
.vo-pole.is-closed { opacity: .55; }
.vo-pole-closed { font-size: var(--fs-xs); color: var(--text-3); }
.vo-row.is-away { opacity: .6; }
/* Absent (désistement) : la ligne reste, le nom barré ; ce qu'il laisse
   vacant et le bouton de retour restent bien lisibles. */
.vo-row.is-absent { opacity: 1; }
.vo-row.is-absent .vo-row-main { opacity: .6; }
.vo-row.is-absent .vo-name, .vo-split-item.is-absent .vo-name { text-decoration: line-through; }
.vo-apt.is-absent { color: var(--danger); background: color-mix(in srgb, var(--danger) 12%, transparent); border-color: transparent; text-decoration: none; }
.vo-abs-txt { font-size: var(--fs-xs); font-weight: 600; color: var(--danger); }
.vo-abs-btn { align-self: flex-start; }
.vo-abs-link { align-self: flex-end; font-size: var(--fs-xs); color: var(--text-3); }
.vo-abs-link:hover { color: var(--danger); }
.vo-split-item.is-absent { flex-direction: row; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 2px 8px; }
.vo-split-item.is-absent .vo-name { color: var(--text-3); }
.vo-gone { display: inline-flex; align-items: center; gap: 5px; font-size: var(--fs-xs); font-weight: 600; color: var(--danger); }
.vo-gone svg { width: 13px; height: 13px; flex: none; }
.vo-f-absent { align-items: flex-start; padding: 8px 10px; border: 1px solid var(--border); border-radius: var(--r-md); }
.vo-f-absent:has(input:checked) { border-color: var(--danger); background: color-mix(in srgb, var(--danger) 8%, transparent); }
.vo-f-absent span { font-size: var(--fs-sm); color: var(--text-2); }
.vo-f-absent strong { color: var(--text); }
.vo-others { font-size: var(--fs-xs); color: var(--text-3); }
.vo-shift { display: flex; flex-direction: column; gap: 4px; font-size: var(--fs-xs); color: var(--text-2); }

/* Épingle : affectation posée à la main */
.vo-assign-row { display: flex; align-items: center; gap: 6px; min-width: 0; }
.vo-assign-row .vo-assign { flex: 1 1 auto; }
.vo-pin { flex: none; min-height: 30px; padding: 0 9px; border: 1px dashed var(--border-strong); border-radius: 999px; background: transparent; color: var(--text-3); font: inherit; font-size: 11px; font-weight: 600; cursor: pointer; }
.vo-pin.is-on { border-style: solid; border-color: transparent; background: var(--accent-soft); color: var(--accent); }

/* Répartition automatique */
.vo-auto { display: flex; flex-direction: column; gap: 8px; }
.vo-auto-sum { margin: 0; font-weight: 600; }
.vo-auto-slot { padding: 8px 10px; border: 1px solid var(--border); border-radius: var(--r-md); background: var(--surface-2); font-size: var(--fs-sm); }
.vo-auto-slot p { margin: 2px 0; }
.vo-ok { color: var(--success); }
.vo-left { color: var(--text-2); font-size: var(--fs-xs); }
.vo-left em { color: var(--text-3); font-style: normal; }

/* Diffusion */
.vo-share-docs { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 8px; margin: 14px 0 4px; }
.vo-doc { display: flex; align-items: center; gap: 10px; padding: 12px 14px; text-align: left; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-md); color: var(--text); font: inherit; cursor: pointer; }
.vo-doc:hover { border-color: var(--border-strong); }
.vo-doc svg { width: 20px; height: 20px; flex: none; color: var(--accent); }
.vo-doc span { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.vo-doc small { font-size: var(--fs-xs); color: var(--text-3); }
.vo-share { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 10px; align-items: start; }
.vo-sharecard { padding: 10px 12px; background: var(--surface); border: 1px solid var(--border); border-top: 3px solid var(--vo-c); border-radius: var(--r-md); min-width: 0; }
.vo-share-meta { margin: 0 0 8px; font-size: var(--fs-xs); color: var(--text-2); }
.vo-share-acts { display: flex; flex-wrap: wrap; gap: 6px; }
.vo-share-acts a.btn { text-decoration: none; }
.vo-msg { margin-top: 8px; font-size: var(--fs-sm); }
.vo-msg summary { cursor: pointer; color: var(--text-2); }
.vo-msg pre { margin: 6px 0 0; padding: 8px 10px; white-space: pre-wrap; overflow-wrap: anywhere; font: inherit; font-size: var(--fs-xs); background: var(--surface-2); border-radius: var(--r-sm, 8px); color: var(--text); }

/* Fenêtres */
.vo-f-2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px 12px; }
.vo-f-tri { display: flex; flex-wrap: wrap; gap: 10px 16px; }
.vo-tri .segmented-btn { min-width: 40px; justify-content: center; }
.vo-checks { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px 12px; }
.vo-check { display: inline-flex; align-items: center; gap: 8px; font-size: var(--fs-sm); color: var(--text); cursor: pointer; }
.vo-check input { width: 18px; height: 18px; accent-color: var(--accent); }
#vo-f-warn { color: var(--warning); margin: -4px 0 0; }

/* Liste : nom, bouton « Modifier », étiquette « Formulaire » */
.vo-name-row { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; }
.vo-edit {
  display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; padding: 0;
  border: 1px solid transparent; border-radius: var(--r-sm); background: transparent; color: var(--text-3); cursor: pointer;
}
.vo-edit:hover { color: var(--text); border-color: var(--border); background: var(--surface-2); }
.vo-edit svg { width: 14px; height: 14px; }
.vo-apt.is-form { color: var(--brand-green); border-color: color-mix(in srgb, var(--brand-green) 40%, transparent); background: color-mix(in srgb, var(--brand-green) 10%, transparent); }
.vo-mode { margin: 0; }
.vo-mode .segmented-btn { display: inline-flex; align-items: center; gap: 6px; }
.vo-mode svg { width: 14px; height: 14px; }
.vo-tpl-note { margin: 12px 0 0; padding: 10px 12px; border: 1px dashed var(--border-strong); border-radius: var(--r-md); font-size: var(--fs-sm); color: var(--text-2); }

/* Tableau éditable (comme un tableur) : en-tête et numéro de ligne
   collés, une cellule = un champ sans cadre, cadre bleu au focus. */
.vo-list.is-grid { display: block; }
.vg-wrap {
  max-height: min(70vh, 720px); overflow: auto; overscroll-behavior: contain;
  border: 1px solid var(--border); border-radius: var(--r-md); background: var(--surface);
}
.vg { border-collapse: separate; border-spacing: 0; table-layout: fixed; width: max-content; font-size: var(--fs-sm); }
.vg th, .vg td { border-right: 1px solid var(--border); border-bottom: 1px solid var(--border); padding: 0; height: 34px; }
.vg thead th {
  position: sticky; top: 0; z-index: 2; padding: 0; background: var(--surface-2); color: var(--text-2);
  font-size: var(--fs-xs); font-weight: 600; text-align: left; white-space: nowrap; overflow: hidden;
}
/* En-tête de colonne : un bouton qui ouvre « trier / filtrer ». Flèche =
   colonne triée, entonnoir = colonne filtrée. */
.vg-h {
  display: flex; align-items: center; gap: 4px; width: 100%; height: 33px; padding: 0 4px 0 8px; border: 0;
  background: none; color: inherit; font: inherit; font-weight: 600; text-align: left; cursor: pointer;
}
.vg-h:hover { background: color-mix(in srgb, var(--text) 6%, transparent); color: var(--text); }
.vg-h:focus-visible { outline: none; box-shadow: inset 0 0 0 2px var(--accent); }
.vg-h-l { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.vg-h-s, .vg-h-f { flex: none; display: inline-flex; }
.vg-h svg { width: 12px; height: 12px; }
.vg-h-f { opacity: .45; }
.vg-h:hover .vg-h-f { opacity: 1; }
.vg-h-s { color: var(--accent); }
.vg-h-s.is-desc svg, .vg-menu-btn.is-desc svg { transform: rotate(180deg); }
.vg-h.is-filtered .vg-h-f { opacity: 1; color: var(--accent); }
.vg-h.is-sorted, .vg-h.is-filtered { color: var(--text); }
/* Tri et filtres en place, au-dessus du tableau */
.vg-state { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; margin: 0 0 8px; font-size: var(--fs-xs); color: var(--text-2); }
.vg-chip {
  display: inline-flex; align-items: center; gap: 6px; min-height: 28px; padding: 2px 8px 2px 10px; max-width: 100%;
  border: 1px solid var(--border); border-radius: 999px; background: var(--surface); color: var(--text-2);
  font: inherit; font-weight: 600; cursor: pointer;
}
.vg-chip.is-flt { border-color: var(--accent); background: var(--accent-soft); color: var(--text); }
.vg-chip:hover { border-color: var(--border-strong); color: var(--text); }
.vg-chip svg { width: 12px; height: 12px; flex: none; }
.vg-state-n { font-variant-numeric: tabular-nums; }
/* Menu d'une colonne */
.vg-menu {
  position: fixed; z-index: 120; width: 264px; max-width: calc(100vw - 16px); overflow: auto; overscroll-behavior: contain;
  display: flex; flex-direction: column; gap: 10px; padding: 8px;
  background: var(--surface); border: 1px solid var(--border-strong); border-radius: var(--r-md); box-shadow: var(--shadow-lg, 0 12px 32px rgba(0, 0, 0, .28));
  font-size: var(--fs-sm); color: var(--text);
}
.vg-menu-sort { display: flex; flex-direction: column; gap: 2px; padding-bottom: 8px; border-bottom: 1px solid var(--border); }
.vg-menu-btn {
  display: flex; align-items: center; gap: 8px; min-height: 34px; padding: 0 8px; border: 0; border-radius: var(--r-sm);
  background: none; color: var(--text); font: inherit; text-align: left; cursor: pointer;
}
.vg-menu-btn:hover { background: var(--surface-2); }
.vg-menu-btn.is-on { background: var(--accent-soft); color: var(--accent); font-weight: 600; }
.vg-menu-btn svg { width: 14px; height: 14px; flex: none; }
.vg-menu-flt { display: flex; flex-direction: column; gap: 8px; }
.vg-menu-flt .form-label { margin: 0; }
.vg-menu-q { font-size: 16px; }
.vg-menu-blank { margin: 0; display: flex; }
.vg-menu-blank .segmented-btn { flex: 1 1 0; padding-left: 4px; padding-right: 4px; font-size: var(--fs-xs); }
.vg-menu-vals { display: flex; flex-direction: column; gap: 2px; max-height: 232px; overflow: auto; padding: 2px; border: 1px solid var(--border); border-radius: var(--r-sm); }
.vg-menu-vals .vo-check { padding: 4px 6px; border-radius: 6px; }
.vg-menu-vals .vo-check:hover { background: var(--surface-2); }
.vg-menu-v { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vg-menu-v em { color: var(--text-3); }
.vg-menu-n { flex: none; font-size: var(--fs-xs); color: var(--text-3); font-variant-numeric: tabular-nums; }
.vg-menu-row { display: flex; justify-content: space-between; gap: 8px; font-size: var(--fs-xs); }
.vg-menu-clear { align-self: flex-start; }
.vg-menu-clear svg { width: 13px; height: 13px; }
/* Cellules : lecture seule, case à cocher, nombre */
.vg-t {
  display: block; height: 33px; padding: 0 8px; line-height: 33px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: var(--text-2);
}
.vg td.vg-ro { background: color-mix(in srgb, var(--text) 3%, var(--surface)); }
.vg td.vg-ro.vg-fix { color: var(--text); }
.vg td.vg-fix .vg-t { color: var(--text); font-weight: 600; }
button.vg-multi { width: 100%; border: 0; background: none; font: inherit; font-size: var(--fs-sm); text-align: left; cursor: pointer; }
button.vg-multi:hover { color: var(--accent); }
.vg-t.is-low, .vg-t.is-no { color: var(--danger); font-weight: 600; }
.vg-t.is-short, .vg-t.is-check, .vg-t.is-rank0 { color: var(--warning); font-weight: 600; }
.vg-t.is-ok, .vg-t.is-rank1 { color: var(--success); font-weight: 600; }
.vg-t.is-rank2, .vg-t.is-rank3 { color: var(--accent); font-weight: 600; }
.vg td.vg-chk { text-align: center; }
input.vg-chk { display: inline-block; width: 18px; height: 18px; margin: 7px 0 0; padding: 0; accent-color: var(--accent); cursor: pointer; }
input.vg-chk:focus { box-shadow: none; outline: 2px solid var(--accent); outline-offset: 2px; background: none; }
input.vg-chk:disabled { opacity: .35; cursor: default; }
.vg td.vg-num .vg-in { text-align: right; font-variant-numeric: tabular-nums; }
.vg-none td { padding: 0 12px; color: var(--text-3); font-style: italic; }
.vg .vg-rn { position: sticky; left: 0; z-index: 1; width: 44px; background: var(--surface-2); color: var(--text-3); font-size: var(--fs-xs); font-weight: 500; text-align: center; }
.vg thead .vg-rn { z-index: 3; }
.vg .vg-fix { position: sticky; z-index: 1; background: var(--surface); }
.vg thead .vg-fix { z-index: 3; background: var(--surface-2); }
.vg td.vg-fix + td:not(.vg-fix), .vg th.vg-fix + th:not(.vg-fix) { box-shadow: inset 1px 0 0 var(--border-strong); }
.vg-rn svg { width: 14px; height: 14px; vertical-align: middle; }
.vg-open { width: 100%; height: 34px; padding: 0; border: 0; background: none; color: inherit; font: inherit; font-variant-numeric: tabular-nums; cursor: pointer; }
.vg-open:hover { color: var(--accent); text-decoration: underline; }
.vg-in {
  display: block; width: 100%; height: 33px; margin: 0; padding: 0 8px; border: 0; border-radius: 0;
  background: transparent; color: var(--text); font: inherit; font-size: var(--fs-sm); outline: none;
}
select.vg-in { padding-right: 4px; cursor: pointer; }
.vg-in:focus { box-shadow: inset 0 0 0 2px var(--accent); background: var(--surface); }
.vg td:has(.vg-in:focus) { position: relative; z-index: 0; }
.vg tr.is-away td { opacity: .6; }
.vg tr:hover td { background: color-mix(in srgb, var(--accent) 4%, transparent); }
.vg-new td, .vg-new th { background: color-mix(in srgb, var(--brand-green) 5%, var(--surface)); }
.vg-new .vg-in::placeholder { color: var(--text-3); }
.vg-hint { margin: 8px 2px 0; font-size: var(--fs-xs); color: var(--text-3); }

/* Diffusion : document à deux sorties (tableur, PDF) */
.vo-doc.is-split { cursor: default; flex-wrap: wrap; }
.vo-doc.is-split:hover { border-color: var(--border); }
.vo-doc .vo-doc-acts { flex-direction: row; gap: 6px; margin-left: auto; }

/* Fiches : images à insérer */
.vo-print .uic-box, .vo-dlg .vo-print { width: min(620px, 100%); }
.vo-imgs { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; max-height: 46vh; overflow: auto; }
.vo-img { display: grid; grid-template-columns: 56px minmax(0, 1fr) minmax(150px, 210px); align-items: center; gap: 10px; padding: 6px; border: 1px solid var(--border); border-radius: var(--r-md); background: var(--surface-2); }
.vo-img-thumb { width: 56px; height: 42px; display: inline-flex; align-items: center; justify-content: center; border-radius: 6px; overflow: hidden; background: var(--surface-3); color: var(--text-3); }
.vo-img-thumb img { width: 100%; height: 100%; object-fit: cover; }
.vo-img-thumb svg { width: 18px; height: 18px; }
.vo-img-txt { display: flex; flex-direction: column; min-width: 0; }
.vo-img-txt strong { font-size: var(--fs-sm); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vo-img-txt small { font-size: var(--fs-xs); color: var(--text-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vo-print-busy { display: flex; align-items: center; gap: 8px; margin: 0; font-size: var(--fs-sm); color: var(--text-2); }
.vo-print-busy[hidden] { display: none; }

/* Lien d'inscription */
.vo-link-body { display: flex; flex-direction: column; gap: 10px; }
.vo-link-body .uic-text, .vo-link-body .form-hint { margin: 0; }
.vo-link-row .form-input { font-size: var(--fs-sm); }
.vo-link-acts { display: flex; flex-wrap: wrap; gap: 6px; }
.vo-link-acts a.btn { text-decoration: none; }

@media (max-width: 640px) {
  .vo-img { grid-template-columns: 48px minmax(0, 1fr); }
  .vo-img .vo-img-to { grid-column: 1 / -1; }
  .vo-doc .vo-doc-acts { margin-left: 0; width: 100%; }
}

@media (max-width: 640px) {
  .vo-row { grid-template-columns: minmax(0, 1fr); }
  .vo-filter { flex: 1 1 100%; }
  .vo-f-2, .vo-checks { grid-template-columns: minmax(0, 1fr); }
  .vo-f-tri { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px 12px; }
  .vo-head .vo-sync { order: -1; width: 100%; justify-content: flex-end; }
}

/* ============================================================
   ANALYSE D'UNE SORTIE (détail d'activité, onglets Analyse et Splits)
   Ligne de temps (js/timeline.js), conditions neutres (js/neutral.js),
   exécution face au plan (js/execution.js).
   ============================================================ */

/* --- Ligne de temps : pistes empilées, un seul repère ------------- */
.rcp-s-tl .mc.d3c { margin: 0; }
.mc.d3c.d3c-tl { height: calc(var(--mc-h, 300px) + 24px); outline: none; border-radius: var(--r-sm); }
.mc.d3c.d3c-tl:focus-visible { outline: 2px solid var(--brand-green); outline-offset: 4px; }
.d3c-track { font-size: 10px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; fill: var(--text-3); }
.tl-selrect { fill: var(--accent); opacity: 0.14; pointer-events: none; }
.tl-seledge { stroke: var(--accent); stroke-width: 1.5; pointer-events: none; shape-rendering: crispEdges; }
.d3c-tl .d3c-tip { min-width: 148px; }
.d3c-tl .d3c-tip-row b:empty { display: none; }
/* Repères numérotés : encre pleine, chiffre en réserve — ils nomment un
   endroit, ils ne portent pas de donnée. */
.tl-note-span { fill: none; stroke: var(--text-2); stroke-width: 1.5; }
.tl-note-drop { stroke: var(--text-2); stroke-width: 1; stroke-dasharray: 2 3; pointer-events: none; }
.tl-note-dot { fill: var(--text); }
.tl-note-num { fill: var(--bg); font-size: 10.5px; font-weight: 700; pointer-events: none; }
.tl-note:hover .tl-note-dot { fill: var(--brand-green); }

.tl-legend { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 14px; font-size: var(--fs-xs); color: var(--text-3); }
.tl-legend > span { display: inline-flex; align-items: center; gap: 6px; }
.tl-k { width: 12px; height: 3px; border-radius: 2px; display: inline-block; }
.tl-k.is-run { background: var(--accent); }
.tl-k.is-walk { background: var(--warning); }
.tl-k.is-gap { background: var(--text); height: 2px; opacity: 0.75; }
.tl-k.is-stop { background: var(--text-3); opacity: 0.5; height: 5px; }
.tl-legend > .tl-hint { margin-left: auto; }

.tl-sel { display: flex; flex-direction: column; gap: 10px; padding: 12px; border: 1px solid color-mix(in srgb, var(--accent) 40%, var(--border)); border-radius: var(--r-md); background: var(--accent-soft); }
.tl-sel[hidden] { display: none; }
.tl-sel-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; font-size: var(--fs-sm); font-variant-numeric: tabular-nums; }
.tl-sel-head .link-btn { display: inline-flex; align-items: center; gap: 4px; }
.tl-sel-head .link-btn svg { width: 13px; height: 13px; }
.tl-sel-actions { display: flex; flex-wrap: wrap; gap: 8px; }

.tl-notes { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.tl-notes li + li { border-top: 1px solid var(--border); }
.tl-note-row {
  width: 100%; display: grid; grid-template-columns: 22px minmax(0, 1fr) auto; align-items: center; gap: 10px;
  padding: 9px 4px; background: none; border: 0; border-radius: var(--r-sm); color: inherit; font: inherit; text-align: left; cursor: pointer;
}
.tl-note-row:hover { background: var(--surface-2); }
.tl-note-row:focus-visible { outline: 2px solid var(--brand-green); outline-offset: -2px; }
.tl-note-row > b { width: 20px; height: 20px; border-radius: 50%; background: var(--text); color: var(--bg); font-size: 11px; font-weight: 700; display: grid; place-items: center; }
.tl-note-main { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.tl-note-lab { font-size: var(--fs-sm); font-weight: 600; }
.tl-note-sub { font-size: var(--fs-xs); color: var(--text-2); font-variant-numeric: tabular-nums; }
.tl-note-at { font-size: var(--fs-xs); color: var(--text-3); font-variant-numeric: tabular-nums; }

/* --- Ce que les conditions ont pesé ------------------------------- */
.nt-top { display: flex; flex-wrap: wrap; gap: 8px; }
.nt-fig { flex: 1 1 150px; display: flex; flex-direction: column; gap: 2px; padding: 10px 12px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-md); }
.nt-fig > span { font-size: var(--fs-xs); color: var(--text-3); text-transform: uppercase; letter-spacing: 0.06em; font-weight: 600; }
.nt-fig > strong { font-size: var(--fs-xl); font-weight: 600; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.nt-fig > em { font-style: normal; font-size: var(--fs-xs); color: var(--text-3); font-variant-numeric: tabular-nums; }
.nt-fig.is-raw > strong { color: var(--text-2); }
.nt-none { margin: 0; font-size: var(--fs-sm); color: var(--text-2); line-height: 1.5; }
.nt-rows { display: flex; flex-direction: column; }
.nt-row {
  display: grid; grid-template-columns: 64px minmax(40px, 1fr) minmax(74px, auto); grid-template-areas: "lab bar val" ". sub sub";
  align-items: center; gap: 2px 10px; padding: 8px 0; border-top: 1px solid var(--border);
}
.nt-row:first-child { border-top: 0; padding-top: 0; }
.nt-lab { grid-area: lab; font-size: var(--fs-sm); font-weight: 600; }
.nt-bar { grid-area: bar; display: block; height: 8px; border-radius: 4px; background: var(--surface-3); overflow: hidden; }
.nt-bar > i { display: block; height: 100%; border-radius: 4px; }
.nt-bar > i.is-cost, .nt-key i.is-cost { background: var(--grade-5); }
.nt-bar > i.is-gain, .nt-key i.is-gain { background: var(--grade-1); }
.nt-val { grid-area: val; text-align: right; font-size: var(--fs-sm); font-variant-numeric: tabular-nums; white-space: nowrap; }
.nt-sub { grid-area: sub; font-size: var(--fs-xs); color: var(--text-3); font-variant-numeric: tabular-nums; }
.nt-row.is-unknown .nt-val, .nt-row.is-unknown .nt-lab { color: var(--text-3); }
.nt-key { display: flex; gap: 14px; font-size: var(--fs-xs); color: var(--text-3); }
.nt-key > span { display: inline-flex; align-items: center; gap: 6px; }
.nt-key i { width: 10px; height: 8px; border-radius: 3px; display: inline-block; }

/* --- Exécution : dans la cible, répétitions, la dernière fois ------ */
.ex-bar { display: flex; gap: 2px; height: 8px; border-radius: 4px; overflow: hidden; }
.ex-bar > i { display: block; height: 100%; min-width: 2px; }
.ex-bar > i.is-slow, .ex-keys i.is-slow { background: var(--accent); }
.ex-bar > i.is-in, .ex-keys i.is-in { background: var(--success); }
.ex-bar > i.is-fast, .ex-keys i.is-fast { background: var(--warning); }
.rcp-row-main > .ex-bar { max-width: 220px; height: 6px; margin-top: 3px; }
.ex-keys { display: flex; flex-wrap: wrap; gap: 4px 14px; font-size: var(--fs-xs); color: var(--text-3); font-variant-numeric: tabular-nums; }
.ex-keys > span { display: inline-flex; align-items: center; gap: 6px; }
.ex-keys i { width: 10px; height: 8px; border-radius: 3px; display: inline-block; }
.rcp-s-reps .mc.d3c { margin: 0; }
.rcp-s-reps .rcp-section-head { min-height: 28px; }
.ex-band { fill: var(--success); opacity: 0.12; }
.ex-rep-lab { font-size: 10.5px; font-weight: 700; fill: var(--text-2); }
.ex-ramp { display: flex; align-items: center; gap: 6px; font-size: var(--fs-xs); color: var(--text-3); }
.ex-ramp > i { width: 64px; height: 4px; border-radius: 2px; background: linear-gradient(90deg, color-mix(in srgb, var(--accent) 30%, var(--surface-3)), var(--accent)); }
.ex-ramp sup { font-size: 0.7em; }
.ex-ramp-band { margin-left: auto; display: inline-flex; align-items: center; gap: 6px; }
.ex-ramp-band > b { width: 14px; height: 8px; border-radius: 2px; background: color-mix(in srgb, var(--success) 26%, transparent); }
.ex-sum { margin: 0; font-size: var(--fs-xs); color: var(--text-2); line-height: 1.5; font-variant-numeric: tabular-nums; }
.rcp-s-last .rcp-section-head .link-btn { text-transform: none; letter-spacing: 0; font-size: var(--fs-sm); }
.ex-last { display: flex; flex-direction: column; }
.ex-last-row {
  display: grid; grid-template-columns: auto 16px auto minmax(0, 1fr); grid-template-areas: "lab lab lab lab" "then arrow now note";
  align-items: baseline; gap: 2px 8px; padding: 9px 0; border-top: 1px solid var(--border); font-variant-numeric: tabular-nums;
}
.ex-last-row:first-child { border-top: 0; padding-top: 0; }
.ex-last-lab { grid-area: lab; font-size: var(--fs-xs); color: var(--text-3); }
.ex-last-then { grid-area: then; font-size: var(--fs-md); color: var(--text-2); }
.ex-last-arrow { grid-area: arrow; color: var(--text-3); align-self: center; display: inline-flex; }
.ex-last-arrow svg { width: 14px; height: 14px; }
.ex-last-now { grid-area: now; font-size: var(--fs-md); font-weight: 600; }
.ex-last-note { grid-area: note; justify-self: end; font-size: var(--fs-xs); color: var(--text-2); }
.ex-last-note.is-up { color: var(--success); font-weight: 600; }

/* --- Jour J : fourchette de la prédiction (js/confidence.js) ------- */
.race-range { display: flex; flex-direction: column; gap: 8px; margin: 0 0 16px; padding: 12px; border: 1px solid var(--border); border-radius: var(--r-md); }
.race-range-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.race-range-head > span { font-size: var(--fs-xs); color: var(--text-3); text-transform: uppercase; letter-spacing: 0.06em; font-weight: 600; }
.race-range-head > strong { font-size: var(--fs-lg); font-weight: 600; font-variant-numeric: tabular-nums; }
.race-range-bar { position: relative; height: 12px; margin: 4px 0 0; border-radius: 6px; background: var(--surface-3); }
.race-range-band { position: absolute; top: 0; bottom: 0; border-radius: 6px; background: color-mix(in srgb, var(--accent) 55%, transparent); }
.race-range-mark { position: absolute; top: -4px; width: 2px; height: 20px; border-radius: 1px; background: var(--text-3); transform: translateX(-1px); }
.race-range-mark.is-on { width: 4px; border-radius: 2px; background: var(--text); transform: translateX(-2px); }
.race-range-ends { display: flex; justify-content: space-between; font-size: var(--fs-xs); color: var(--text-3); }
.race-range-tip { display: flex; align-items: flex-start; gap: 8px; margin: 0; font-size: var(--fs-xs); line-height: 1.5; color: var(--text-2); }
.race-range-tip svg { flex: none; width: 14px; height: 14px; margin-top: 2px; color: var(--text-3); }
.race-range-why { font-size: var(--fs-xs); color: var(--text-2); }
.race-range-why > summary { cursor: pointer; color: var(--text-3); font-weight: 600; }
.race-range-why > summary:focus-visible { outline: 2px solid var(--brand-green); outline-offset: 2px; border-radius: var(--r-sm); }
.race-range-why ul { margin: 8px 0 0; padding-left: 18px; display: flex; flex-direction: column; gap: 4px; line-height: 1.5; }

/* ------------------------------------------------------------
   NAVIGATION — suivre un parcours, guidé à la voix (js/nav.js)
   Greffée sur l'enregistreur d'activité libre (#freerec, .pl-*) :
     · à la préparation, l'emplacement #fa-route — choisir un parcours ;
     · pendant la sortie, le bandeau #fa-nav — la flèche et la distance
       du prochain virage, lisibles bras tendu ;
     · la CARTE À LA DEMANDE (#nav-map), montée le temps d'un coup d'œil ;
     · l'ÉCRAN NOIR (#nav-dark) : un noir pur, sur lequel un écran OLED
       n'allume aucun pixel. Il n'a volontairement rien d'un thème — ni
       surface, ni bordure, ni couleur : chaque pixel allumé y coûte.
   ------------------------------------------------------------ */

/* « Suivre », posé sur la carte d'un parcours (cf. card dans js/map.js) :
   il garde son libellé même sur une vignette étroite, où ses voisins se
   réduisent à leur icône — une boussole seule ne dit pas ce qu'elle lance. */
.tmap-over-btn.tmap-over-nav { width: auto; padding: 0 12px; }
.tmap-over-btn.tmap-over-nav span { display: inline; }

/* --- Préparation : le parcours à suivre --- */
.fa-route:empty { display: none; }
.nv-add { width: 100%; min-height: 48px; border-style: dashed; color: var(--text-2); }
.nv-add svg { color: var(--brand-green); }

.nv-plan, .nv-pick {
  display: flex; flex-direction: column; gap: 10px; padding: 12px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-md);
}
.nv-plan { border-color: color-mix(in srgb, var(--brand-green) 45%, var(--border)); }
.nv-plan-head { display: flex; align-items: center; gap: 10px; }
.nv-plan-ico { flex: none; width: 36px; height: 36px; display: grid; place-items: center; border-radius: var(--r-sm); background: color-mix(in srgb, var(--brand-green) 14%, transparent); color: var(--brand-green); }
.nv-plan-ico svg { width: 20px; height: 20px; }
.nv-plan-txt { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.nv-plan-txt strong { font-size: var(--fs-md); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nv-plan-txt span { font-size: var(--fs-xs); color: var(--text-2); font-variant-numeric: tabular-nums; }
.nv-plan-status { font-size: var(--fs-sm); color: var(--text); font-weight: 600; }
.nv-plan-status:empty { display: none; }
.nv-plan-warn { display: flex; align-items: flex-start; gap: 8px; font-size: var(--fs-xs); color: var(--warning); }
.nv-plan-warn svg { flex: none; width: 14px; height: 14px; margin-top: 2px; }
.nv-plan-acts { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.nv-switch { display: inline-flex; align-items: center; gap: 8px; min-height: 32px; font-size: var(--fs-xs); color: var(--text-2); cursor: pointer; }
.nv-switch input { width: 18px; height: 18px; accent-color: var(--brand-green); }
.nv-switch span { display: inline-flex; align-items: center; gap: 6px; }
.nv-switch svg { width: 14px; height: 14px; }

.nv-pick-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: var(--fs-md); }
.nv-pick-row {
  display: flex; align-items: center; gap: 10px; width: 100%; min-height: 48px; padding: 8px 10px; text-align: left; cursor: pointer;
  background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--r-sm); color: var(--text); font: inherit;
}
.nv-pick-row:hover { border-color: var(--border-strong); }
.nv-pick-row:focus-visible, .nv-switch input:focus-visible { outline: 2px solid var(--brand-green); outline-offset: 2px; }
.nv-pick-ico { flex: none; display: inline-flex; color: var(--text-3); }
.nv-pick-ico svg { width: 18px; height: 18px; }
.nv-pick-txt { min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.nv-pick-txt strong { font-size: var(--fs-sm); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nv-pick-txt span { font-size: var(--fs-xs); color: var(--text-2); font-variant-numeric: tabular-nums; }
.nv-pick-empty { margin: 0; font-size: var(--fs-sm); color: var(--text-2); }
.nv-pick-file { align-self: flex-start; cursor: pointer; }

/* --- Pendant la sortie : le bandeau de guidage ---
   La flèche et la distance d'abord : ce sont les deux seules choses qu'on
   vient chercher, et elles doivent se lire sans s'arrêter. */
.nv { display: flex; flex-direction: column; gap: 10px; padding: 14px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-md); }
.nv-main { display: flex; align-items: center; gap: 14px; }
.nv-arrow {
  flex: none; width: 72px; height: 72px; display: grid; place-items: center; border-radius: var(--r-md);
  background: color-mix(in srgb, var(--brand-green) 14%, transparent); color: var(--brand-green);
}
.nv-arrow svg { width: 52px; height: 52px; }
.nv-txt { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.nv-dist { font-size: 44px; font-weight: 600; line-height: 1; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.nv-what { font-size: var(--fs-md); color: var(--text-2); font-weight: 600; }
/* Le virage est là : la pastille se remplit. */
.nv.is-near .nv-arrow { background: var(--brand-green); color: #fff; }
.nv.is-off { border-color: color-mix(in srgb, var(--danger) 50%, var(--border)); }
.nv.is-off .nv-arrow { background: var(--danger-soft); color: var(--danger); }
.nv.is-off .nv-what { color: var(--danger); }
.nv.is-pre .nv-arrow, .nv.is-done .nv-arrow { background: var(--surface-3); color: var(--text-2); }
.nv.is-done .nv-dist { font-size: 32px; }
.nv-bar { height: 4px; border-radius: 2px; background: var(--surface-3); overflow: hidden; }
.nv-bar > i { display: block; height: 100%; background: var(--brand-green); }
.nv-meta { display: flex; justify-content: space-between; gap: 12px; font-size: var(--fs-xs); color: var(--text-2); font-variant-numeric: tabular-nums; }
.nv-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-3); }
.nv-acts { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.nv-acts .btn { min-height: 44px; justify-content: center; padding: 0 6px; gap: 6px; white-space: nowrap; }
.nv-acts .btn svg { flex: none; }
/* Guidé, le chrono n'est plus le chiffre principal : il cède la place. */
.fa-rec.has-nav .fa-clock { padding: 0; }
.fa-rec.has-nav .fa-clock-val { font-size: 40px; }

/* --- Carte à la demande --- */
#nav-map {
  position: fixed; inset: 0; z-index: 530; background: var(--bg); display: flex; flex-direction: column; gap: 10px;
  padding: calc(12px + env(safe-area-inset-top, 0px)) 12px calc(12px + env(safe-area-inset-bottom, 0px));
}
.nvm-head, .nvm-foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.nvm-title { min-width: 0; display: inline-flex; align-items: center; gap: 8px; font-size: var(--fs-md); font-weight: 600; }
.nvm-title span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nvm-title svg { flex: none; }
.nvm-count { color: var(--text-3); font-variant-numeric: tabular-nums; }
.nvm-map { flex: 1; min-height: 0; }
.nvm-foot { flex-wrap: wrap; }
.nvm-next { font-size: var(--fs-md); font-weight: 600; font-variant-numeric: tabular-nums; }
.nvm-acts { display: inline-flex; gap: 8px; margin-left: auto; }

/* --- Écran noir --- */
#nav-dark {
  position: fixed; inset: 0; z-index: 9000; background: #000; color: #000;
  display: grid; place-items: center; touch-action: none; user-select: none; -webkit-user-select: none;
  -webkit-touch-callout: none; cursor: pointer;
}
.nvd-in { display: flex; flex-direction: column; align-items: center; gap: 14px; padding: 24px; text-align: center; }
.nvd-ring { width: 56px; height: 56px; border-radius: 50%; border: 3px solid #000; transition: border-color 0.2s linear; }
.nvd-next { font-size: 28px; font-weight: 600; font-variant-numeric: tabular-nums; }
.nvd-hint { font-size: 13px; }
/* Un appui : la consigne se montre, en gris sombre, puis s'efface. */
#nav-dark.is-peek { color: #6b6b6b; }
#nav-dark.is-peek .nvd-ring { border-color: #2a2a2a; }
/* Appui maintenu : l'anneau se colore le temps qu'il faut pour rallumer. */
#nav-dark.is-holding .nvd-ring { border-color: #1fb57a; transition-duration: 0.9s; }
/* Sous l'écran noir, plus rien ne se dessine. */
body.nav-dark #freerec { visibility: hidden; }

/* ============================================================
   RELIEF DOUX — AUJOURD'HUI (07/10/2026)
   Chiffres clés et semaine en barres (js/today.js : kpisCard,
   weekCard). Les tokens (--elev-*, --raised, --sunk, --fs-kpi,
   --fs-hero) vivent dans styles.css et ui.css.
   ============================================================ */
/* UN bouton coloré sur l'accueil : celui de la séance. Les « Enregistrer »
   des autres cartes (check-in, douleur, bilan…) valident un formulaire,
   pas l'écran : ils restent à l'encre, comme les petits boutons. */
#tab-today .card:not(.today-session) .btn-primary { background: var(--text); color: var(--bg); border-color: var(--text); box-shadow: none; }
#tab-today .card:not(.today-session) .btn-primary:hover { background: color-mix(in srgb, var(--text) 88%, var(--bg)); }

/* --- Chiffres clés ------------------------------------------------------ */
.today-kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 16px; min-width: 0; }
.today-kpis .kpi-card {
  margin: 0; padding: 16px; min-width: 0;
  display: flex; flex-direction: column; align-items: flex-start; gap: 4px;
  font: inherit; color: var(--text); text-align: left; cursor: pointer;
  transition: box-shadow 0.15s ease, background 0.15s ease, border-color 0.15s ease;
}
.today-kpis .kpi-card:hover { border-color: var(--border-strong); }
.today-kpis .kpi-card:active { background: var(--sunk); box-shadow: var(--elev-pressed); }
.kpi-card-lab { font-size: var(--fs-xs); font-weight: 500; color: var(--text-2); }
.kpi-card-val { font-size: var(--fs-kpi); font-weight: 700; letter-spacing: -0.02em; line-height: 1.15; font-variant-numeric: tabular-nums; white-space: nowrap; }
/* L'unité à demi-taille, à côté de la valeur. */
.kpi-card-val small { font-size: var(--fs-md); font-weight: 500; letter-spacing: 0; color: var(--text-2); margin-left: 4px; }
.kpi-card-sub { display: inline-flex; align-items: center; gap: 4px; font-size: var(--fs-xs); color: var(--text-3); line-height: 1.35; }
.kpi-card-sub svg { width: 13px; height: 13px; flex: none; }
.kpi-spark { display: block; width: 100%; height: 26px; margin-top: 4px; color: var(--accent); }
.kpi-bar { display: block; width: 100%; height: 8px; margin-top: 8px; border-radius: 999px; background: var(--sunk); box-shadow: var(--elev-pressed); overflow: hidden; }
.kpi-bar > i { display: block; height: 100%; border-radius: 999px; background: var(--accent); }
/* Téléphone : la rangée défile, une tuile et demie visible pour le dire.
   Marges négatives = la rangée va d'un bord à l'autre de l'écran ; le
   remplissage laisse la place des ombres, que le défilement rognerait. */
@media (max-width: 640px) {
  .today-kpis {
    display: flex; gap: 12px; overflow-x: auto; scroll-snap-type: x mandatory; scroll-padding-inline: var(--page-pad);
    margin: -8px calc(-1 * var(--page-pad)) -10px; padding: 8px var(--page-pad) 18px; scrollbar-width: none;
  }
  .today-kpis::-webkit-scrollbar { display: none; }
  .today-kpis .kpi-card { flex: 0 0 158px; scroll-snap-align: start; }
}

/* --- Semaine en barres -------------------------------------------------- */
.wk-chart { display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: 8px; }
/* 9 px = le haut des barres dans chaque colonne (remplissage 8 + bordure 1). */
.wk-axis { height: var(--wk-h); margin-top: 9px; display: flex; flex-direction: column; justify-content: space-between; align-items: flex-end; font-size: 10.5px; color: var(--text-3); font-variant-numeric: tabular-nums; }
.wk-axis span { height: 0; display: flex; align-items: center; white-space: nowrap; }
.wk-chart .week-dots {
  background:
    linear-gradient(var(--border), var(--border)) 0 9px / 100% 1px no-repeat,
    linear-gradient(var(--border), var(--border)) 0 calc(9px + var(--wk-h) / 2) / 100% 1px no-repeat,
    linear-gradient(var(--border), var(--border)) 0 calc(9px + var(--wk-h)) / 100% 1px no-repeat;
}
.wk-chart .week-dot:hover { background: var(--accent-soft); }
/* Aujourd'hui : le libellé et le contour de la barre, plus un aplat qui
   masquerait la grille. */
.wk-chart .week-dot.is-today { background: transparent; border-color: transparent; }
.wk-chart .week-dot.is-today:hover { background: var(--accent-soft); }
.wk-chart .week-dot.is-today .week-dot-dow { color: var(--accent); font-weight: 700; }
.wk-chart .week-dot.is-today .wk-plan { outline: 2px solid var(--accent); outline-offset: 1px; }
.wk-bars { width: 100%; height: var(--wk-h); display: flex; align-items: flex-end; justify-content: center; gap: 3px; }
.wk-bars i { display: block; width: 9px; border-radius: 5px 5px 0 0; }
.wk-plan { background: color-mix(in srgb, var(--accent) 28%, var(--surface)); }
.wk-real { background: var(--accent); }
.wk-legend { display: flex; gap: 14px; margin-top: 10px; font-size: var(--fs-xs); color: var(--text-2); }
.wk-legend span { display: inline-flex; align-items: center; gap: 6px; }
.wk-legend i { display: block; width: 9px; height: 9px; border-radius: 3px; }

/* ============================================================
   RELIEF DOUX — DÉTAIL D'ACTIVITÉ (07/10/2026)
   Synthèse avec tracé (cf. paint dans js/recap.js) : la carte et le
   profil à gauche, les chiffres et l'action à droite. Colonnes réglées
   sur la LARGEUR DU DÉTAIL (requête de conteneur sur .focus-view),
   comme le reste de la page.
   ============================================================ */
.rcp-hero { box-shadow: var(--elev-raised); }
.rcp-top { display: grid; grid-template-columns: minmax(0, 1fr); gap: 0; }
/* `isolation` : les calques de Leaflet (z-index 400 et plus) restent
   SOUS la feuille des chiffres, qui mord sur le bas de la carte. */
.rcp-top-map { position: relative; isolation: isolate; min-width: 0; }
/* La distance du parcours est déjà sous le titre. */
.rcp-top .rcp-map > .log-label { display: none; }
/* `!important` : la hauteur de départ est posée en ligne au montage. */
.rcp-top .rcp-map .trace-map { height: clamp(220px, 44vh, 360px) !important; }
/* Téléphone : une feuille arrondie posée sur le bas de la carte. Les
   mentions du fond de carte remontent d'autant — elles doivent rester
   lisibles, c'est la condition d'usage des fonds. */
.rcp-hero.is-side {
  position: relative; z-index: 1; margin-top: -16px;
  grid-template-columns: minmax(0, 1fr); grid-template-areas: "head" "nums" "more" "acts";
  border-radius: 22px 22px var(--r-lg) var(--r-lg);
}
.rcp-top .leaflet-bottom { bottom: 16px; }
.rcp-hero.is-side .rcp-big-val { font-size: clamp(22px, 7cqw, 34px); }
.rcp-hero-acts { grid-area: acts; display: flex; flex-direction: column; gap: 10px; }
.rcp-top-prof { margin-top: 18px; min-width: 0; padding: 16px; border: 1px solid var(--border); border-radius: var(--r-lg); background: var(--surface); box-shadow: var(--elev-raised); }
@container (min-width: 820px) {
  .rcp-top { grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); grid-template-areas: "map side" "prof side"; gap: 18px 24px; align-items: start; }
  .rcp-top-map { grid-area: map; }
  .rcp-top-prof { grid-area: prof; margin-top: 0; }
  .rcp-top .rcp-map .trace-map { height: clamp(280px, 46vh, 440px) !important; }
  .rcp-top .tmap-frame { border-radius: var(--r-lg); box-shadow: var(--elev-raised); }
  .rcp-top .leaflet-bottom { bottom: 0; }
  .rcp-hero.is-side { grid-area: side; margin-top: 0; border-radius: var(--r-lg); padding: 20px 22px; gap: 18px; }
}
