/* MyTrailPredict — système de design.
 *
 * Direction : la lumière du sentier, pas la salle de contrôle. Fond sable,
 * cuivre pour agir, vert sauge pour le relief. Une application qui parle de
 * montagne n'a pas de raison d'être froide.
 *
 * Quatre partis pris.
 *
 * **Le sable est le fond, pas les cartes.** La page porte la chaleur ; les
 * surfaces de données restent claires et calmes. Un tableau de quinze colonnes
 * se lit vingt minutes, il ne doit pas fatiguer.
 *
 * **Une seule famille, Inter, sur toute l'application.** Son axe optique fait
 * le travail qu'une seconde police ferait moins bien : aux grandes tailles les
 * formes se resserrent et l'interlettrage se sert, un titre y gagne la présence
 * d'un caractère d'affiche sans rien perdre en lisibilité. Une serif grasse
 * avait été essayée : belle sur trois mots, illisible sur « 10h28 ».
 *
 * **Le cuivre agit, le rouge alerte.** Deux teintes chaudes voisines, mais
 * l'une est claire et invite, l'autre est sombre et arrête. Le vert sauge
 * n'appartient qu'au relief : montagnes, profil altimétrique, tronçon plus
 * rapide que prévu.
 *
 * **Pas de police monospace.** Inter avec chiffres tabulaires suffit à aligner
 * les colonnes, sans l'air d'outil de développeur.
 *
 * Aucune dépendance externe pour la mise en forme : l'application doit
 * s'afficher sans connexion.
 */

/* ==========================================================================
   Jetons
   ========================================================================== */

:root {
  /* Surfaces et encre.
   *
   * Le fond porte une teinte verte à peine perceptible, empruntée à l'accent.
   * Elle ne se voit pas seule ; elle sert à faire ressortir les surfaces
   * blanches, qui n'ont alors plus besoin d'ombres marquées pour exister. */
  /* Une échelle entièrement chaude, du sable à l'ivoire. Aucun blanc pur :
   * une carte blanche sur du sable troue la page au lieu de s'y poser. */
  --paper: #f2e3cd;
  --paper-warm: #f6ead8;
  --surface: #fdf7ec;
  --surface-sunken: #f4e9d6;
  --ink: #24190f;
  --ink-soft: #57493a;
  --muted: #85735f;
  --faint: #ab9a85;
  --line: #e5d5bb;
  --line-strong: #d2bd9c;

  /* Cuivre : la couleur de l'action. Claire, chaude, elle invite. */
  --accent: #c0703a;
  --accent-hover: #a4592a;
  --accent-soft: #f7e3cd;
  --accent-line: #e0bd97;

  /* Sienne : la seconde voix du titre, et l'encre des grands chiffres. */
  --sienna: #7e4420;

  /* Signaux */
  /* Le rouge de la balise GR. Sombre et saturé, il arrête là où le cuivre
   * invite : deux teintes chaudes voisines, mais de clarté très différente. */
  --danger: #9d2f22;
  --danger-soft: #f7ddd4;
  --warn: #8a6524;
  --warn-soft: #f4e7cc;

  /* La nuit est un fait de course, pas une alerte : elle a sa propre teinte,
   * un indigo froid qui se distingue du vert sans lui disputer l'attention. */
  /* Même la nuit se réchauffe : un indigo tirant sur la prune, qui tient sur
   * du sable là où un bleu franc paraîtrait rapporté. */
  --night: #46406a;
  --night-soft: #ece5ea;
  --night-line: #d3c8d4;

  /* Scénarios : trois teintes harmonisées, désaturées */
  /* Le vert sauge n'appartient qu'au relief et à ce qui va mieux que prévu. */
  /* Le vert du dehors. Il marque le relief, et ce qui est acquis : une étape
   * franchie, un tronçon plus rapide que prévu. C'est le rappel outdoor qui
   * traverse toute l'application sans jamais réclamer d'action. */
  --sage: #8ba46a;
  --sage-deep: #5f7d46;
  --sage-soft: #e6edd4;

  --scenario-fast: #5f7d46;
  --scenario-mid: #c0703a;
  --scenario-slow: #8a6524;
  --bronze-soft: #f4e9d2;

  /* Typographie */
  /* Inter, du libellé de douze pixels au slogan de soixante-quatre.
   *
   * L'axe optique porte toute la hiérarchie : `opsz 14` pour le texte courant,
   * `opsz 32` pour les grands chiffres et les titres. Les formes se resserrent
   * à mesure que la taille monte, ce qui donne l'impact d'un caractère
   * d'affiche là où une seconde police aurait ajouté du chargement et un
   * risque de désaccord. */
  --sans: "Inter", -apple-system, "Segoe UI", system-ui, sans-serif;

  /* Échelle d'espacement, base 4 */
  --s1: 4px;
  --s2: 8px;
  --s3: 12px;
  --s4: 16px;
  --s5: 24px;
  --s6: 32px;
  --s7: 48px;
  --s8: 64px;

  /* Rayons */
  --r-sm: 6px;
  --r: 10px;
  --r-lg: 14px;
  --r-pill: 999px;

  /* Élévation : une seule, discrète */
  /* Ombres teintées de brun : sur du sable, une ombre grise vire au sale. */
  --shadow: 0 1px 2px rgba(60, 40, 20, .04), 0 2px 8px rgba(60, 40, 20, .05);
  --shadow-raised: 0 2px 4px rgba(60, 40, 20, .06), 0 8px 20px rgba(60, 40, 20, .08);
  --shadow-lift: 0 4px 8px rgba(60, 40, 20, .07), 0 20px 48px rgba(60, 40, 20, .16);

  /* Deux durées seulement : le retour immédiat d'un appui, et le glissement
   * d'un élément qui apparaît. Au-delà, le mouvement se remarque. */
  --tap: 90ms;
  --ease: cubic-bezier(.2, .8, .3, 1);

  --rail: 236px;
  --content: 1120px;
}

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

html {
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.55;
  font-feature-settings: "cv05" 1, "ss01" 1;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

a {
  color: var(--accent);
  text-decoration: none;
}

a:hover {
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}

/* ==========================================================================
   Structure
   ========================================================================== */

.shell {
  display: grid;
  grid-template-columns: var(--rail) minmax(0, 1fr);
  min-height: 100vh;
}

.rail {
  background: var(--paper-warm);
  border-right: 1px solid var(--line);
  padding: var(--s5) var(--s3) var(--s5);
  position: sticky;
  top: 0;
  height: 100vh;
  display: flex;
  flex-direction: column;
}

.wordmark,
a.wordmark {
  display: flex;
  align-items: center;
  gap: var(--s2);
  font-variation-settings: "opsz" 24;
  font-weight: 720;
  font-size: 18px;
  letter-spacing: -0.028em;
  color: var(--ink);
  text-decoration: none;
  padding: 0 var(--s3);
  margin-bottom: var(--s6);
}

a.wordmark:hover {
  color: var(--accent);
  text-decoration: none;
}

/* Balise GR : la marque du sentier, réduite à un trait. */
.balise {
  display: inline-block;
  width: 6px;
  height: 20px;
  flex: none;
  border-radius: 2px;
  background: linear-gradient(
    to bottom,
    var(--danger) 0 38%,
    var(--surface) 38% 62%,
    var(--danger) 62% 100%
  );
  box-shadow: inset 0 0 0 1px var(--line-strong);
}

.rail nav {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.rail nav a {
  display: flex;
  align-items: center;
  gap: var(--s3);
  font-size: 14px;
  font-weight: 460;
  color: var(--ink-soft);
  padding: 9px var(--s3);
  border-radius: var(--r-sm);
  transition: background .12s ease, color .12s ease;
}

.rail nav a:hover {
  background: var(--surface-sunken);
  color: var(--ink);
  text-decoration: none;
}

.rail nav a[aria-current="page"] {
  background: var(--accent-soft);
  color: var(--accent);
  font-weight: 560;
}

.rail nav a svg {
  width: 17px;
  height: 17px;
  flex: none;
  stroke-width: 1.5;
}

.rail nav .optional {
  margin-left: auto;
  font-size: 10px;
  font-weight: 500;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--faint);
}

.rail footer {
  margin-top: auto;
  padding: var(--s4) var(--s3) 0;
  border-top: 1px solid var(--line);
  font-size: 12px;
  color: var(--faint);
}

.rail footer a {
  color: var(--muted);
}

.rail footer a:hover {
  color: var(--accent);
}

/* Portée limitée à l'ossature applicative : la page d'accueil est elle aussi
   un `<main>`, et un sélecteur de type l'aurait bridée à la largeur de contenu.
   C'est le genre de collision qui ne se voit qu'à la mesure. */
.shell main {
  padding: var(--s7) var(--s7) var(--s8);
  max-width: var(--content);
}

/* ==========================================================================
   Typographie
   ========================================================================== */

.eyebrow {
  font-size: 12px;
  font-weight: 500;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 var(--s2);
}

h1 {
  font-variation-settings: "opsz" 32;
  font-weight: 780;
  font-size: clamp(32px, 3.8vw, 42px);
  line-height: 1.08;
  letter-spacing: -0.032em;
  margin: 0 0 var(--s3);
}

h2 {
  display: flex;
  align-items: center;
  gap: var(--s2);
  font-variation-settings: "opsz" 28;
  font-weight: 680;
  font-size: 21px;
  letter-spacing: -0.018em;
  line-height: 1.2;
  margin: var(--s8) 0 var(--s4);
}

h2 svg {
  width: 19px;
  height: 19px;
  stroke-width: 1.5;
  color: var(--accent);
}

h3 {
  font-size: 15px;
  font-weight: 580;
  letter-spacing: -0.005em;
  margin: 0 0 var(--s1);
}

.lede {
  color: var(--ink-soft);
  font-size: 15px;
  max-width: 62ch;
  margin: 0 0 var(--s5);
}

/* ==========================================================================
   Rangée de chiffres — remplace les jauges circulaires
   ========================================================================== */

.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow);
  overflow: hidden;
  margin-bottom: var(--s5);
}

.stat {
  padding: var(--s5) var(--s5) var(--s4);
  border-right: 1px solid var(--line);
}

.stat:last-child {
  border-right: none;
}

.stat dt,
.stat .stat-label {
  font-size: 12px;
  font-weight: 500;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 var(--s2);
}

.stat dd,
.stat .stat-value {
  font-variation-settings: "opsz" 32;
  font-weight: 700;
  font-size: 33px;
  line-height: 1;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  margin: 0;
  color: var(--ink);
}

.stat .stat-caption {
  display: block;
  font-family: var(--sans);
  font-size: 12px;
  color: var(--faint);
  margin-top: var(--s2);
}

/* Barre de progression : seulement là où un rapport a du sens. */
.stat .meter {
  display: block;
  height: 3px;
  border-radius: var(--r-pill);
  background: var(--line);
  margin-top: var(--s3);
  overflow: hidden;
}

.stat .meter span {
  display: block;
  height: 100%;
  border-radius: var(--r-pill);
  background: var(--accent);
}

/* Une jauge pleine dit un acquis, pas une action : elle passe au sauge. */
.stat .meter span[style*="width: 100%"] {
  background: var(--sage-deep);
}

.stat.warn .meter span { background: var(--warn); }
.stat.danger .meter span { background: var(--danger); }
.stat.danger .stat-value { color: var(--danger); }

/* ==========================================================================
   Cartes
   ========================================================================== */

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: var(--s4);
}

.cards.two {
  grid-template-columns: repeat(auto-fit, minmax(280px, 400px));
}

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow);
  padding: var(--s5);
  transition: transform var(--tap) var(--ease), box-shadow var(--tap) var(--ease);
}

.card h3 {
  font-size: 16px;
  font-weight: 620;
  letter-spacing: -0.005em;
  margin: 0 0 var(--s1);
}

.card .meta {
  font-size: 12px;
  letter-spacing: .03em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0;
}

/* Texte courant dans une carte, sous le titre et l'intitulé. */
.card-text {
  color: var(--ink-soft);
  font-size: 13.5px;
  line-height: 1.55;
  margin: var(--s3) 0 var(--s4);
}

.card dl {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s5);
  margin: var(--s4) 0 0;
}

.card dt {
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--muted);
}

.card dd {
  margin: 2px 0 0;
  font-variation-settings: "opsz" 28;
  font-size: 21px;
  font-weight: 680;
  letter-spacing: -0.025em;
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}

.card dd small {
  font-family: var(--sans);
  font-size: 12px;
  color: var(--muted);
  margin-left: 3px;
}

/* ==========================================================================
   Tableaux
   ========================================================================== */

table {
  width: 100%;
  border-collapse: collapse;
  font-variant-numeric: tabular-nums;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow);
  overflow: hidden;
  font-size: 14px;
}

th {
  font-size: 11px;
  font-weight: 550;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--muted);
  text-align: right;
  padding: var(--s3) var(--s4);
  background: var(--surface-sunken);
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}

th:first-child,
td:first-child {
  text-align: left;
  padding-left: var(--s5);
}

th:last-child,
td:last-child {
  padding-right: var(--s5);
}

td {
  padding: var(--s4);
  text-align: right;
  border-bottom: 1px solid var(--line);
  color: var(--ink-soft);
}

tbody tr:last-child td {
  border-bottom: none;
}

tbody tr {
  transition: background .1s ease;
}

tbody tr:hover {
  background: var(--surface-sunken);
}

td.name {
  font-size: 15px;
  font-weight: 520;
  color: var(--ink);
}

td .sub {
  display: block;
  font-size: 12px;
  font-weight: 400;
  color: var(--faint);
  margin-top: 1px;
}

.num {
  font-variant-numeric: tabular-nums;
}

td.soft {
  color: var(--faint);
  font-size: 13px;
}

/* En-tête sur deux niveaux */
thead th[colspan] {
  text-align: center;
  border-bottom: none;
  padding-bottom: var(--s1);
  color: var(--ink-soft);
}

thead .sub-head th {
  font-size: 10px;
  letter-spacing: .04em;
  color: var(--faint);
  padding-top: 0;
  font-weight: 450;
}

td.group-end,
th.group-end {
  border-right: 1px solid var(--line);
}

.plan-table {
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow);
  overflow-x: auto;
  /* Un dégradé au bord droit signale qu'il reste des colonnes à droite. Il
     disparaît dès qu'on atteint la fin du défilement. */
  background:
    linear-gradient(to right, var(--surface) 30%, rgba(255, 255, 255, 0)) left / 40px 100% no-repeat,
    linear-gradient(to left, var(--surface) 30%, rgba(255, 255, 255, 0)) right / 40px 100% no-repeat,
    radial-gradient(farthest-side at 0 50%, rgba(22, 24, 29, .08), transparent) left / 14px 100% no-repeat,
    radial-gradient(farthest-side at 100% 50%, rgba(22, 24, 29, .08), transparent) right / 14px 100% no-repeat,
    var(--surface);
  background-attachment: local, local, scroll, scroll, local;
}

.plan-table table {
  border-radius: 0;
  border: none;
  background: none;
  font-size: 13px;
}

/* Quinze colonnes : la densité est assumée, la lisibilité vient de
   l'alignement et des filets de groupe, pas de l'espacement. */
.plan-table th {
  padding: var(--s2) 10px;
  background: var(--surface-sunken);
}

.plan-table td {
  padding: var(--s3) 10px;
}

.plan-table th:first-child,
.plan-table td:first-child {
  padding-left: var(--s4);
  position: sticky;
  left: 0;
  background: var(--surface);
  z-index: 1;
}

/* Le titre de la page porte deux voix : l'encre pour le constat, la sienne
   pour ce que l'application propose. Le contraste dit qui parle. */
h1 .said {
  color: var(--sienna);
}

.plan-table thead th:first-child {
  background: var(--surface-sunken);
}

.plan-table tbody tr:hover td:first-child {
  background: var(--surface-sunken);
}

.plan-table tbody tr:nth-child(4n + 1),
.plan-table tbody tr:nth-child(4n + 2) {
  background: transparent;
}

/* Un ravitaillement assisté ouvre un bloc d'autonomie : c'est là que le sac se
   recharge. Le repère est un trait, pas une couleur de fond. */
.plan-table tr.assisted td {
  border-bottom-color: var(--line-strong);
}

.plan-table tr.assisted td.name {
  box-shadow: inset 3px 0 0 var(--danger);
}

/* Une section nocturne change la manière de courir : frontale, froid, allure
   plus prudente. Elle mérite d'être vue sans crier comme une alerte. */
.plan-table td.night {
  color: var(--night);
  font-weight: 550;
  background: var(--night-soft);
  box-shadow: inset 0 -1px 0 var(--night-line);
}

.plan-table tbody tr:hover td.night {
  background: var(--night-soft);
}

.table-hint {
  font-size: 13px;
  color: var(--muted);
  margin: calc(-1 * var(--s2)) 0 var(--s3);
}

/* ==========================================================================
   Boutons
   ========================================================================== */

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s2);
  font-family: var(--sans);
  font-size: 14px;
  font-weight: 520;
  line-height: 1;
  padding: 11px var(--s4);
  border-radius: var(--r-sm);
  border: 1px solid var(--accent);
  background: var(--accent);
  /* Ivoire plutôt que blanc pur : sur du cuivre, le blanc franc vibre. */
  color: var(--surface);
  cursor: pointer;
  transition: background .12s ease, border-color .12s ease, box-shadow .12s ease;
  white-space: nowrap;
}

.button:hover {
  background: var(--accent-hover);
  border-color: var(--accent-hover);
  text-decoration: none;
}

.button:active {
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, .16);
}

.button:disabled,
.button[aria-disabled="true"] {
  background: var(--line);
  border-color: var(--line);
  color: var(--faint);
  cursor: not-allowed;
}

.button.ghost {
  background: var(--surface);
  border-color: var(--line-strong);
  color: var(--ink);
}

.button.ghost:hover {
  background: var(--surface-sunken);
  border-color: var(--muted);
}

.button.ghost.danger {
  color: var(--danger);
}

.button.ghost.danger:hover {
  border-color: var(--danger);
  background: var(--danger-soft);
}

.button.large {
  font-variation-settings: "opsz" 24;
  font-weight: 640;
  font-size: 16px;
  letter-spacing: -0.008em;
  padding: 15px var(--s6);
  border-radius: var(--r-pill);
}

.button svg {
  width: 16px;
  height: 16px;
  stroke-width: 1.6;
}

.button.run {
  padding: 7px var(--s3);
  font-size: 13px;
}

.icon-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  background: none;
  color: var(--faint);
  cursor: pointer;
  transition: color .12s ease, background .12s ease, border-color .12s ease;
}

a.icon-button:hover {
  text-decoration: none;
}

.icon-button svg {
  width: 16px;
  height: 16px;
  stroke-width: 1.5;
}

.icon-button:hover {
  color: var(--ink);
  background: var(--surface-sunken);
  border-color: var(--line);
}

/* Une action destructrice ne doit pas attirer l'œil en permanence. */
.actions-cell .icon-button:last-child:hover,
form .icon-button:hover {
  color: var(--danger);
  background: var(--danger-soft);
  border-color: transparent;
}

.icon-button.open {
  color: var(--accent);
  background: var(--accent-soft);
}

.link-button {
  background: none;
  border: none;
  padding: 0;
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 500;
  color: var(--accent);
  cursor: pointer;
}

.link-button:hover {
  text-decoration: underline;
  text-underline-offset: 3px;
}

.actions {
  display: flex;
  align-items: center;
  gap: var(--s3);
  flex-wrap: wrap;
}

.actions form {
  display: inline-flex;
}

/* Une cellule de tableau ne doit pas devenir un conteneur flex : elle sort
   alors du modèle de tableau, et la bordure de la ligne s'arrête avant elle.
   L'alignement se fait donc en ligne, comme du texte. */
.actions-cell {
  text-align: right;
  white-space: nowrap;
}

.actions-cell > *,
.actions-cell form {
  vertical-align: middle;
}

.actions-cell form {
  display: inline-flex;
  margin-left: var(--s1);
}

.actions-cell .icon-button + .icon-button,
.actions-cell .button + .icon-button {
  margin-left: var(--s1);
}

/* ==========================================================================
   Formulaires
   ========================================================================== */

form .fieldset {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow);
  padding: var(--s5) var(--s5) var(--s6);
  margin-bottom: var(--s4);
}

form .fieldset > h3 {
  display: flex;
  align-items: center;
  gap: var(--s2);
  font-size: 16px;
  font-weight: 620;
  letter-spacing: -0.005em;
  margin: 0 0 var(--s2);
}

form .fieldset > h3 svg {
  width: 18px;
  height: 18px;
  stroke-width: 1.5;
  color: var(--accent);
}

form .fieldset > .hint {
  color: var(--muted);
  font-size: 13.5px;
  line-height: 1.5;
  margin: 0 0 var(--s5);
  max-width: 66ch;
}

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--s4) var(--s5);
}

.field label {
  display: block;
  font-size: 13px;
  font-weight: 520;
  color: var(--ink-soft);
  margin-bottom: var(--s2);
}

.field label .opt {
  font-weight: 400;
  color: var(--faint);
}

/* Tous les champs de saisie, sauf ceux qui ont leur propre apparence.
   Énumérer les types acceptés finissait par en oublier : `email` et `password`
   restaient à leur largeur par défaut, soit un tiers de la carte. */
.field input:not([type="checkbox"]):not([type="radio"]):not([type="file"]),
.field select,
.field textarea {
  width: 100%;
  font-family: var(--sans);
  font-size: 14px;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  padding: 10px var(--s3);
  transition: border-color .12s ease, box-shadow .12s ease;
}

.field textarea {
  line-height: 1.6;
  resize: vertical;
  min-height: 120px;
}

.field input::placeholder,
.field textarea::placeholder {
  color: var(--faint);
}

.field input:not([type="checkbox"]):not([type="radio"]):hover,
.field select:hover,
.field textarea:hover {
  border-color: var(--muted);
}

.field input:not([type="checkbox"]):not([type="radio"]):focus,
.field select:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

.field .error {
  display: block;
  color: var(--danger);
  font-size: 12.5px;
  margin-top: var(--s2);
}

.field.invalid input,
.field.invalid select,
.field.invalid textarea {
  border-color: var(--danger);
}

.field.invalid input:focus,
.field.invalid textarea:focus {
  box-shadow: 0 0 0 3px var(--danger-soft);
}

.field input[type="file"] {
  width: 100%;
  font-size: 13px;
  color: var(--muted);
  padding: var(--s2) 0;
}

.field input[type="file"]::file-selector-button {
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 520;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  padding: 8px var(--s3);
  margin-right: var(--s3);
  cursor: pointer;
}

.field input[type="file"]::file-selector-button:hover {
  background: var(--surface-sunken);
  border-color: var(--muted);
}

.check {
  display: flex;
  align-items: center;
  gap: var(--s3);
  padding-top: 26px;
}

.check input {
  width: 17px;
  height: 17px;
  accent-color: var(--accent);
  flex: none;
}

.check label {
  font-size: 14px;
  font-weight: 400;
  color: var(--ink);
  margin: 0;
}

.portion-box {
  border-left: 2px solid var(--accent);
}

.portion-note {
  display: block;
  font-size: 12.5px;
  color: var(--accent);
  margin-top: var(--s2);
  min-height: 1.1em;
}

/* ==========================================================================
   Messages
   ========================================================================== */

/* Une confirmation dit un acquis : elle emprunte le vert, pas le cuivre. */
.flash {
  display: flex;
  align-items: flex-start;
  gap: var(--s3);
  background: var(--sage-soft);
  border: 1px solid #c3d3a8;
  border-radius: var(--r);
  padding: var(--s3) var(--s4);
  margin-bottom: var(--s5);
  font-size: 14px;
  color: var(--ink);
}

.flash svg {
  width: 17px;
  height: 17px;
  flex: none;
  margin-top: 1px;
  stroke-width: 1.6;
  color: var(--sage-deep);
}

.flash.error {
  background: var(--danger-soft);
  border-color: #e6bdb0;
}

.flash.error svg {
  color: var(--danger);
}

.alert {
  display: flex;
  align-items: flex-start;
  gap: var(--s3);
  background: var(--surface);
  border: 1px solid var(--line);
  border-left: 2px solid var(--danger);
  border-radius: var(--r);
  padding: var(--s3) var(--s4);
  margin-bottom: var(--s2);
  font-size: 14px;
  color: var(--ink-soft);
}

.alert svg {
  width: 16px;
  height: 16px;
  flex: none;
  margin-top: 2px;
  stroke-width: 1.6;
  color: var(--danger);
}

.alert strong {
  color: var(--ink);
  font-weight: 550;
}

.notice {
  background: var(--surface);
  border: 1px solid var(--line);
  border-left: 2px solid var(--accent-line);
  border-radius: var(--r);
  padding: var(--s4) var(--s5);
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--muted);
}

.notice p {
  margin: 0 0 var(--s2);
}

.notice p:last-child {
  margin-bottom: 0;
}

.notice strong {
  color: var(--ink-soft);
  font-weight: 550;
}

/* ==========================================================================
   États vides
   ========================================================================== */

.empty {
  background: var(--surface);
  border: 1px dashed var(--line-strong);
  border-radius: var(--r-lg);
  padding: var(--s8) var(--s5);
  text-align: center;
}

.empty svg {
  width: 28px;
  height: 28px;
  stroke-width: 1.3;
  color: var(--faint);
  margin-bottom: var(--s3);
}

.empty p {
  color: var(--muted);
  font-size: 14px;
  max-width: 48ch;
  margin: 0 auto var(--s5);
}

/* ==========================================================================
   Étiquettes
   ========================================================================== */

.tag {
  display: inline-flex;
  align-items: center;
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: .02em;
  padding: 3px 9px;
  border-radius: var(--r-pill);
  background: var(--surface-sunken);
  color: var(--muted);
  border: 1px solid var(--line);
  white-space: nowrap;
}

.tag.assisted {
  background: var(--danger-soft);
  border-color: transparent;
  color: var(--danger);
}

tr.past-due td.name::after {
  content: "date passée";
  display: inline-block;
  font-size: 11px;
  font-weight: 500;
  color: var(--accent);
  background: var(--accent-soft);
  border-radius: var(--r-pill);
  padding: 2px 8px;
  margin-left: var(--s2);
  vertical-align: 1px;
}

/* ==========================================================================
   Sous-onglets et scénarios
   ========================================================================== */

.subtabs {
  display: flex;
  gap: var(--s1);
  border-bottom: 1px solid var(--line);
  margin: var(--s5) 0 var(--s6);
}

.subtabs a {
  font-size: 14px;
  font-weight: 500;
  color: var(--muted);
  padding: var(--s3) var(--s3);
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}

.subtabs a:hover {
  color: var(--ink);
  text-decoration: none;
}

.subtabs a[aria-current="page"] {
  color: var(--ink);
  border-bottom-color: var(--accent);
  font-weight: 550;
}

.scenarios {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--s3);
  margin: var(--s5) 0 var(--s5);
}

.scenarios a {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--s1);
  padding: var(--s4) var(--s4) var(--s5);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface);
  color: var(--muted);
  transition: border-color .12s ease, box-shadow .12s ease;
}

.scenarios a:hover {
  border-color: var(--line-strong);
  text-decoration: none;
}

.scenarios a.optimiste { --tone: var(--scenario-fast); }
.scenarios a.realiste { --tone: var(--scenario-mid); }
.scenarios a.prudent { --tone: var(--scenario-slow); }

.scenarios a[aria-selected="true"] {
  border-color: var(--tone);
  box-shadow: inset 0 0 0 1px var(--tone);
  background: var(--surface);
}

.scenarios .label {
  font-size: 12px;
  font-weight: 550;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--tone);
}

.scenarios .time {
  font-variation-settings: "opsz" 32;
  font-weight: 700;
  letter-spacing: -0.03em;
  font-size: 31px;
  line-height: 1.05;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

.scenarios .hint {
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--faint);
  margin-top: var(--s1);
}

/* ==========================================================================
   Choix de mode
   ========================================================================== */

.mode-choice {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: var(--s4);
}

.mode {
  position: relative;
  display: block;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface);
  padding: var(--s5);
  cursor: pointer;
  transition: border-color .12s ease, box-shadow .12s ease;
}

.mode:hover:not(.disabled) {
  border-color: var(--line-strong);
}

.mode input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.mode:has(input:checked) {
  border-color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent);
}

.mode.disabled {
  opacity: .55;
  cursor: default;
  background: var(--surface-sunken);
}

.mode-body {
  display: block;
}

.mode-body > span {
  display: block;
}

.mode-title {
  display: flex;
  align-items: center;
  gap: var(--s2);
  font-size: 17px;
  font-weight: 620;
  letter-spacing: -0.005em;
  color: var(--ink);
  margin-bottom: var(--s3);
  padding-right: var(--s6);
}

.mode-title svg {
  width: 18px;
  height: 18px;
  stroke-width: 1.5;
  color: var(--accent);
}

.mode-text {
  color: var(--ink-soft);
  font-size: 14px;
  line-height: 1.55;
  margin-bottom: var(--s3);
}

.mode-note {
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--faint);
}

.mode-check {
  position: absolute;
  top: var(--s5);
  right: var(--s5);
  width: 18px;
  height: 18px;
  border: 1.5px solid var(--line-strong);
  border-radius: 50%;
  background: var(--surface);
}

.mode:has(input:checked) .mode-check {
  border-color: var(--accent);
  border-width: 5.5px;
}

/* ==========================================================================
   Tolérance
   ========================================================================== */

.tolerance {
  display: inline-flex;
  gap: 3px;
}

.pip {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--line-strong);
}

.pip.on {
  background: var(--sage-deep);
}

.tolerance-scale {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
  gap: var(--s2);
}

.tolerance-option {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s1);
  padding: var(--s4) var(--s2);
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--surface);
  cursor: pointer;
  text-align: center;
  transition: border-color .12s ease, box-shadow .12s ease;
}

.tolerance-option:hover {
  border-color: var(--line-strong);
}

.tolerance-option input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.tolerance-option .value {
  font-variation-settings: "opsz" 28;
  font-size: 23px;
  font-weight: 680;
  letter-spacing: -0.02em;
  line-height: 1;
  color: var(--muted);
}

.tolerance-option .caption {
  font-size: 12px;
  line-height: 1.35;
  color: var(--faint);
}

.tolerance-option:has(input:checked) {
  border-color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent);
}

.tolerance-option:has(input:checked) .value {
  color: var(--accent);
}

/* ==========================================================================
   Questionnaire post-course
   ========================================================================== */

.checklist {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: var(--s2);
}

.situation {
  display: flex;
  align-items: flex-start;
  gap: var(--s3);
  padding: var(--s3) var(--s4);
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--surface);
  font-size: 14px;
  color: var(--ink-soft);
  cursor: pointer;
  transition: border-color .12s ease, background .12s ease;
}

.situation:hover {
  border-color: var(--line-strong);
}

.situation input {
  width: 17px;
  height: 17px;
  margin-top: 1px;
  flex: none;
  accent-color: var(--accent);
}

.situation:has(input:checked) {
  border-color: var(--accent);
  background: var(--accent-soft);
  color: var(--ink);
}

/* ==========================================================================
   Comparaison prédit / réalisé
   ========================================================================== */

td.faster {
  color: var(--sage-deep);
  font-weight: 550;
}

td.slower {
  color: var(--danger);
  font-weight: 550;
}

.deviation {
  width: 88px;
}

.bar {
  display: block;
  height: 4px;
  width: var(--width, 0%);
  border-radius: var(--r-pill);
  margin-left: auto;
}

.bar.faster { background: var(--sage-deep); }
.bar.slower { background: var(--danger); }

/* ==========================================================================
   Détail de consommation
   ========================================================================== */

tr.consumption td {
  background: var(--surface-sunken);
  padding: var(--s4) var(--s5);
  text-align: left;
  border-bottom: 1px solid var(--line-strong);
}

.conso-label {
  display: block;
  font-size: 11px;
  font-weight: 550;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: var(--s3);
}

.conso-list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2);
  list-style: none;
  margin: 0;
  padding: 0;
}

.conso-list li {
  font-size: 13.5px;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-pill);
  padding: 4px 12px;
  color: var(--ink-soft);
}

.inventory {
  list-style: none;
  margin: var(--s4) 0 0;
  padding: 0;
  font-size: 14px;
  color: var(--ink-soft);
}

.inventory li {
  display: flex;
  gap: var(--s2);
  padding: 3px 0;
}

.inventory strong {
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  font-weight: 550;
  min-width: 1.5em;
}

/* ==========================================================================
   Profil altimétrique
   ========================================================================== */

.profile {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: var(--s4) var(--s4) var(--s2);
}

.profile svg.altimetry {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1000 / 180;
}

/* Le relief prend l'accent : c'est le terrain sur lequel tout se calcule. */
.altimetry .relief {
  fill: var(--sage);
  opacity: .3;
}

.altimetry .crest {
  fill: none;
  stroke: var(--sage-deep);
  stroke-width: 1.6;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}

.altimetry .night-band {
  fill: var(--night);
  opacity: .08;
}

/* Un ravitaillement assisté est le seul point rouge : c'est là que le sac se
   recharge, et c'est la seule information du profil qui appelle une décision. */
.altimetry .tick {
  stroke: var(--muted);
  stroke-width: 1;
  opacity: .3;
  vector-effect: non-scaling-stroke;
}

.altimetry .tick.assisted {
  stroke: var(--danger);
  opacity: .55;
}

.altimetry .dot {
  fill: var(--surface);
  stroke: var(--sage-deep);
  stroke-width: 1.6;
  vector-effect: non-scaling-stroke;
}

.altimetry .dot.assisted {
  fill: var(--danger);
  stroke: var(--surface);
}

.profile-scale {
  display: flex;
  justify-content: space-between;
  font-size: 12px;
  color: var(--faint);
  padding: var(--s2) var(--s1) var(--s2);
}

/* ==========================================================================
   Guide de démarrage
   ========================================================================== */

.steps {
  list-style: none;
  margin: 0;
  padding: 0;
}

.step {
  display: flex;
  gap: var(--s4);
  padding: var(--s5) 0;
  border-bottom: 1px solid var(--line);
}

.step:last-child {
  border-bottom: none;
}

.marker {
  flex: none;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  border: 1px solid var(--line-strong);
  display: flex;
  align-items: center;
  justify-content: center;
  font-variation-settings: "opsz" 28;
  font-size: 14px;
  color: var(--muted);
  background: var(--surface);
}

/* Une étape franchie est un acquis, pas une action : elle passe au vert. */
.step.done .marker {
  border-color: var(--sage-deep);
  background: var(--sage-deep);
  color: var(--surface);
}

.step.done .marker svg {
  width: 14px;
  height: 14px;
  stroke-width: 2;
}

.step .body {
  flex: 1;
}

.step h3 {
  font-size: 17px;
  font-weight: 620;
  margin: 2px 0 var(--s2);
}

.step p {
  color: var(--muted);
  font-size: 14px;
  margin: 0 0 var(--s4);
  max-width: 60ch;
}

.step .state {
  font-size: 12.5px;
  font-weight: 520;
  color: var(--sage-deep);
  margin: 0;
}

.step.done h3 {
  color: var(--muted);
}

/* ==========================================================================
   Boîtes de dialogue
   ========================================================================== */

dialog {
  border: none;
  border-radius: var(--r-lg);
  padding: var(--s6);
  max-width: 560px;
  width: calc(100% - var(--s6));
  background: var(--surface);
  color: var(--ink);
  box-shadow: var(--shadow-lift);
}

dialog::backdrop {
  background: rgba(22, 24, 29, .32);
  backdrop-filter: blur(2px);
}

dialog h3 {
  font-variation-settings: "opsz" 28;
  font-size: 19px;
  font-weight: 680;
  letter-spacing: -0.018em;
  margin: 0 0 var(--s5);
}

dialog .grid {
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
}

dialog.tour {
  position: relative;
  max-width: 460px;
  padding: var(--s7) var(--s6) var(--s5);
  text-align: center;
}

.tour-close {
  position: absolute;
  top: var(--s3);
  right: var(--s4);
  background: none;
  border: none;
  font-size: 24px;
  line-height: 1;
  color: var(--faint);
  cursor: pointer;
  padding: var(--s1) var(--s2);
  border-radius: var(--r-sm);
}

.tour-close:hover {
  color: var(--ink);
  background: var(--surface-sunken);
}

.tour-icon {
  width: 44px;
  height: 44px;
  margin: 0 auto var(--s4);
  border-radius: 50%;
  background: var(--accent-soft);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--accent);
}

.tour-icon svg {
  width: 20px;
  height: 20px;
  stroke-width: 1.5;
}

dialog.tour h2 {
  display: block;
  font-variation-settings: "opsz" 28;
  font-weight: 720;
  font-size: 23px;
  letter-spacing: -0.025em;
  margin: 0 0 var(--s3);
}

dialog.tour p {
  color: var(--muted);
  font-size: 14.5px;
  line-height: 1.6;
  margin: 0 auto;
  max-width: 34ch;
}

.tour-detail {
  margin-top: var(--s3) !important;
  font-size: 13px !important;
  color: var(--faint) !important;
}

.tour-dots {
  display: flex;
  gap: var(--s1);
  justify-content: center;
  margin: var(--s6) 0 var(--s5);
}

.tour-dots span {
  width: 5px;
  height: 5px;
  border-radius: var(--r-pill);
  background: var(--line-strong);
  transition: width .2s ease, background .2s ease;
}

.tour-dots span.active {
  background: var(--accent);
  width: 18px;
}

.tour-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s4);
  padding-top: var(--s4);
  border-top: 1px solid var(--line);
}

.tour-counter {
  font-size: 12px;
  color: var(--faint);
  font-variant-numeric: tabular-nums;
}

.tour-buttons {
  display: flex;
  gap: var(--s2);
}

table.compact {
  font-size: 13.5px;
}

table.compact th {
  padding: var(--s2) var(--s3);
}

table.compact td {
  padding: var(--s3);
}

td.muted {
  color: var(--faint);
  text-align: center;
  font-size: 13.5px;
}

.row-actions {
  white-space: nowrap;
}

/* ==========================================================================
   Page d'accueil
   ========================================================================== */

body.welcome {
  margin: 0;
  min-height: 100vh;
  color: var(--ink);
  display: flex;
  /* Le sable dérive vers un vert pâle en haut à droite : la lumière vient de
     là, et les montagnes montent à sa rencontre. */
  background:
    radial-gradient(110% 80% at 84% 6%, #f9ecd2 0%, rgba(249, 236, 210, 0) 55%),
    radial-gradient(90% 70% at 12% 92%, #ecead0 0%, rgba(236, 234, 208, 0) 50%),
    var(--paper);
}

/* La page tient sur un écran, sans défilement : `100dvh` tient compte des
   barres d'outils mobiles, que `100vh` ignore. */
.splash {
  position: relative;
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--s5);
  height: 100dvh;
  max-height: 100dvh;
  overflow: hidden;
}

body.welcome {
  height: 100dvh;
  overflow: hidden;
}

/* La scène : trois lignes de pics en perspective atmosphérique, un tracé qui
   les traverse, une lumière d'avant-aube. C'est le seul endroit de
   l'application où l'on se permet une image. */
.skyline {
  position: absolute;
  inset: auto 0 0 0;
  width: 100%;
  height: 34%;
  min-height: 230px;
  pointer-events: none;
  z-index: 0;
}

.skyline .ridge {
  stroke: none;
}

/* Plus une ligne de pics est loin, plus l'air la délave. */
.skyline .far { fill: #cbdcb4; opacity: .55; }
.skyline .mid { fill: #aecb92; opacity: .6; }
.skyline .near { fill: var(--sage-deep); opacity: .35; }

.skyline .route {
  fill: none;
  stroke: var(--accent);
  stroke-width: 3;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}

.skyline .waypoint {
  fill: var(--accent);
  stroke: none;
}

@keyframes ridge-rise {
  from {
    opacity: 0;
    transform: translateY(26px);
  }
}

@keyframes draw {
  from { stroke-dashoffset: 2400; }
  to { stroke-dashoffset: 0; }
}

@keyframes waypoint-in {
  from {
    opacity: 0;
    transform: scale(.3);
  }
}

@keyframes glow {
  from { opacity: 0; }
}

.skyline .dawn { animation: glow 1500ms var(--ease) both; }
.skyline .far { animation: ridge-rise 900ms var(--ease) both; }
.skyline .mid { animation: ridge-rise 900ms 150ms var(--ease) both; }
.skyline .near { animation: ridge-rise 900ms 300ms var(--ease) both; }

.skyline .route {
  stroke-dasharray: 2400;
  animation: draw 1800ms 480ms var(--ease) both;
}

.skyline .waypoint {
  transform-box: fill-box;
  transform-origin: center;
  animation: waypoint-in 340ms 2100ms var(--ease) both;
}

@keyframes content-rise {
  from {
    opacity: 0;
    transform: translateY(14px);
  }
}

.splash-inner {
  position: relative;
  z-index: 1;
  max-width: 640px;
  text-align: center;
  /* Le contenu remonte pour dégager la scène, qui occupe le bas de l'écran. */
  margin-bottom: 22vh;
  animation: content-rise 700ms 120ms var(--ease) both;
}

.mark {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  margin-bottom: var(--s6);
}

.mark .name {
  font-variation-settings: "opsz" 24;
  font-weight: 720;
  font-size: 18px;
  letter-spacing: -0.028em;
}

body.welcome h1 {
  font-variation-settings: "opsz" 32;
  font-weight: 800;
  font-size: clamp(40px, 5.8vw, 64px);
  line-height: 1.06;
  letter-spacing: -0.038em;
  margin: 0 0 var(--s5);
}

.promise {
  font-size: 16px;
  line-height: 1.6;
  color: var(--ink-soft);
  max-width: 46ch;
  margin: 0 auto var(--s6);
  text-wrap: balance;
}

.promise strong {
  color: var(--ink);
  font-weight: 550;
}

.splash-actions {
  display: flex;
  gap: var(--s3);
  justify-content: center;
  flex-wrap: wrap;
}

.footnote {
  margin-top: var(--s7);
  font-size: 12.5px;
  color: var(--faint);
}

/* ==========================================================================
   Accessibilité et adaptation
   ========================================================================== */

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}

svg[viewBox="0 0 24 24"]:not([class]) {
  width: 1em;
  height: 1em;
}

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

@media (max-width: 900px) {
  .shell main {
    padding: var(--s5) var(--s5) var(--s7);
  }

  .scenarios {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 780px) {
  .shell {
    grid-template-columns: 1fr;
  }

  .rail {
    position: static;
    height: auto;
    border-right: none;
    border-bottom: 1px solid var(--line);
    padding: var(--s4);
  }

  .wordmark,
  a.wordmark {
    margin-bottom: var(--s4);
  }

  .rail nav {
    flex-direction: row;
    flex-wrap: wrap;
  }

  .rail footer {
    margin-top: var(--s4);
    border-top: none;
    padding-top: 0;
  }

  .stats {
    grid-template-columns: repeat(2, 1fr);
  }

  .stat {
    border-bottom: 1px solid var(--line);
  }
}

/* ==========================================================================
   Mouvement
   --------------------------------------------------------------------------
   Deux usages seulement : confirmer un appui, et faire entrer ce qui arrive.
   Rien ne bouge en continu, rien ne bouge sans raison. Tout est coupé par
   `prefers-reduced-motion`, déclaré plus haut.
   ========================================================================== */

/* L'appui s'enfonce. C'est le retour tactile le plus court possible — 90 ms,
   sous le seuil où le mouvement se remarque comme animation. */
.button:active {
  transform: translateY(1px);
  box-shadow: inset 0 1px 3px rgba(0, 0, 0, .18);
}

.button.ghost:active {
  box-shadow: inset 0 1px 3px rgba(22, 24, 29, .08);
}

.button {
  transition:
    background var(--tap) var(--ease),
    border-color var(--tap) var(--ease),
    box-shadow var(--tap) var(--ease),
    transform var(--tap) var(--ease);
}

.button:hover {
  box-shadow: var(--shadow-raised);
}

.icon-button {
  transition:
    color var(--tap) var(--ease),
    background var(--tap) var(--ease),
    border-color var(--tap) var(--ease),
    transform var(--tap) var(--ease);
}

.icon-button:active {
  transform: scale(.92);
}

.link-button:active {
  opacity: .6;
}

/* Une carte cliquable se soulève ; une carte informative reste posée. */
.scenarios a,
.mode,
.tolerance-option,
.situation {
  transition:
    border-color var(--tap) var(--ease),
    background var(--tap) var(--ease),
    box-shadow var(--tap) var(--ease),
    transform var(--tap) var(--ease);
}

.scenarios a:hover,
.mode:hover:not(.disabled) {
  transform: translateY(-2px);
  box-shadow: var(--shadow-raised);
}

.scenarios a:active,
.mode:active:not(.disabled),
.tolerance-option:active,
.situation:active {
  transform: translateY(0);
  box-shadow: var(--shadow);
}

.scenarios a[aria-selected="true"]:hover {
  transform: none;
}

/* Le rail : l'élément survolé avance d'un cheveu vers le contenu. */
.rail nav a {
  transition:
    background var(--tap) var(--ease),
    color var(--tap) var(--ease),
    padding-left var(--tap) var(--ease);
}

.rail nav a:hover {
  padding-left: 15px;
}

/* Ce qui arrive glisse depuis le haut : un message, une confirmation. */
@keyframes settle {
  from {
    opacity: 0;
    transform: translateY(-6px);
  }
}

.flash,
.alert:first-of-type {
  animation: settle 220ms var(--ease) both;
}

@keyframes dialog-in {
  from {
    opacity: 0;
    transform: translateY(8px) scale(.985);
  }
}

dialog[open] {
  animation: dialog-in 180ms var(--ease) both;
}

@keyframes backdrop-in {
  from { opacity: 0; }
}

dialog[open]::backdrop {
  animation: backdrop-in 180ms var(--ease) both;
}

/* Le détail de consommation se déroule sous son tronçon. */
tr.consumption:not([hidden]) td {
  animation: settle 180ms var(--ease) both;
}

/* Les cinq index UTMB forment une échelle — général, 20K, 50K, 100K, 100M.
   Les répartir sur une seule ligne dit cet ordre ; une grille souple laissait
   le dernier orphelin sur sa rangée. */
.grid.scale {
  grid-template-columns: repeat(5, 1fr);
  gap: var(--s3);
}

@media (max-width: 1000px) {
  .grid.scale {
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  }
}

/* Un champ court ne s'étire pas sur toute la largeur : la longueur d'un champ
   annonce la longueur de la réponse attendue. Une liste déroulante ou un
   nombre d'heures n'ont pas besoin de neuf cents pixels.

   Les zones de texte et les sélecteurs de fichier gardent leur pleine largeur :
   là, l'espace sert vraiment. */
form .fieldset > .field:not(:has(textarea)):not(:has(input[type="file"])),
.grid > .field:only-child {
  max-width: 22rem;
}

/* ==========================================================================
   Micro-interactions
   --------------------------------------------------------------------------
   Trois moments seulement : la page qui se pose, la ligne qu'on survole, la
   valeur qui se remplit. Chacun dit quelque chose de vrai sur le contenu.
   Tout est coupé par `prefers-reduced-motion`.
   ========================================================================== */

/* Les jauges se remplissent au chargement : elles mesurent une progression,
   autant la montrer progresser. Le décalage suit l'ordre de lecture. */
@keyframes fill {
  from { transform: scaleX(0); }
}

.stat .meter span {
  transform-origin: left;
  animation: fill 700ms 200ms var(--ease) both;
}

.stat:nth-child(2) .meter span { animation-delay: 290ms; }
.stat:nth-child(3) .meter span { animation-delay: 380ms; }
.stat:nth-child(4) .meter span { animation-delay: 470ms; }

/* Survoler une ligne de tableau la marque d'un trait au bord gauche : le
   repère suit l'œil sans déplacer quoi que ce soit. */
tbody tr td:first-child {
  box-shadow: inset 0 0 0 0 var(--accent);
  transition: box-shadow 120ms var(--ease);
}

tbody tr:hover td:first-child {
  box-shadow: inset 2px 0 0 0 var(--accent);
}

/* Le repère d'un ravitaillement assisté prime : il ne s'efface pas au survol. */
.plan-table tr.assisted td.name,
.plan-table tr.assisted:hover td.name {
  box-shadow: inset 3px 0 0 var(--danger);
}

/* Une étiquette de catégorie se réchauffe au survol de sa ligne. */
tbody tr:hover .tag {
  border-color: var(--line-strong);
}

/* L'icône d'une action de suppression recule d'un cheveu avant de partir. */
.actions-cell form:active .icon-button {
  transform: scale(.9);
}

/* Le libellé d'un champ suit son état : au focus, il prend la couleur de
   l'accent. C'est le seul repère qui dit où l'on écrit sans déplacer le texte. */
.field:focus-within label {
  color: var(--accent);
}

.field label {
  transition: color var(--tap) var(--ease);
}

/* Une carte de produit ou de bloc se soulève à peine : assez pour qu'on sente
   qu'elle est là, pas assez pour qu'elle bouge. */
.card:hover {
  box-shadow: var(--shadow-raised);
}

/* Le passage d'un sous-onglet à l'autre glisse. */
.subtabs a {
  transition: color var(--tap) var(--ease), border-color 160ms var(--ease);
}

/* Les pastilles de tolérance s'allument une à une. */
@keyframes pip-in {
  from {
    opacity: 0;
    transform: scale(.4);
  }
}

.tolerance .pip.on {
  animation: pip-in 240ms var(--ease) both;
}

.tolerance .pip.on:nth-child(2) { animation-delay: 40ms; }
.tolerance .pip.on:nth-child(3) { animation-delay: 80ms; }
.tolerance .pip.on:nth-child(4) { animation-delay: 120ms; }
.tolerance .pip.on:nth-child(5) { animation-delay: 160ms; }

/* Un seuil franchi est un acquis : la jauge passe au vert du dehors. */
.stat.sage .meter span { background: var(--sage-deep); }

/* Ce qui se boit, ce qui se mâche, ce qui s'avale sec : trois gestes
   différents en course. Les teintes les séparent sans qu'on ait à lire —
   très légères, elles n'entrent pas en concurrence avec les alertes. */
.conso-list li.liquide {
  background: #e8eff5;
  border-color: #c6d8e5;
  color: #2f4a5c;
}

.conso-list li.solide {
  background: var(--sage-soft);
  border-color: #c3d3a8;
  color: #47582f;
}

.conso-list li.electrolyte {
  background: var(--surface);
  border-color: var(--line-strong);
  color: var(--muted);
}

/* --- Connexion et inscription ------------------------------------------ */

.splash.account {
  align-items: flex-start;
  padding-top: 10vh;
}

.splash.account .splash-inner {
  margin-bottom: 0;
  max-width: 400px;
  width: 100%;
  /* Un formulaire se lit aligné à gauche : centrer les libellés obligerait
     l'œil à repartir d'un point différent à chaque ligne. */
  text-align: left;
}

.splash.account .mark,
.splash.account .promise,
.splash.account .footnote {
  margin-left: 0;
  margin-right: 0;
}

.account-title {
  font-variation-settings: "opsz" 32;
  font-weight: 780;
  font-size: 34px;
  letter-spacing: -0.03em;
  line-height: 1.1;
  margin: var(--s6) 0 var(--s3);
}

.splash.account .promise {
  font-size: 15px;
  margin-bottom: var(--s5);
}

.account-form {
  display: flex;
  flex-direction: column;
  gap: var(--s4);
  text-align: left;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow);
  padding: var(--s5);
}

.account-form .button {
  margin-top: var(--s2);
  width: 100%;
}

.hint-inline {
  display: block;
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--muted);
  margin-top: var(--s2);
}

.account-switch {
  font-size: 14px;
  color: var(--muted);
  margin: var(--s5) 0 0;
}

.splash.account .footnote {
  margin-top: var(--s5);
}

/* Sur cette page le défilement est permis : un clavier virtuel réduit la
   fenêtre de moitié, et le champ actif doit rester atteignable. */
body.welcome:has(.account) {
  height: auto;
  min-height: 100dvh;
  overflow: auto;
}

body.welcome:has(.account) .splash {
  height: auto;
  max-height: none;
  overflow: visible;
}

/* --- Rappel de confirmation d'adresse -----------------------------------
 *
 * Visible sans être bloquant. Il emprunte l'ambre des avertissements plutôt
 * que le rouge des alertes : rien n'est cassé, il y a seulement quelque chose
 * à finir. Le rouge, réservé à ce qui appelle une correction immédiate,
 * perdrait de sa force à servir ici.
 */

.verify-bar {
  display: flex;
  align-items: center;
  gap: var(--s3);
  flex-wrap: wrap;
  background: var(--warn-soft);
  border: 1px solid #e0cda3;
  border-radius: var(--r);
  padding: var(--s3) var(--s4);
  margin-bottom: var(--s5);
  font-size: 14px;
  line-height: 1.5;
  color: var(--ink-soft);
}

.verify-bar > svg {
  width: 18px;
  height: 18px;
  flex: none;
  stroke-width: 1.6;
  color: var(--warn);
}

.verify-bar > div {
  flex: 1;
  min-width: 240px;
}

.verify-bar strong {
  color: var(--ink);
  font-weight: 600;
}

.verify-bar form {
  margin-left: auto;
}

/* Précision sous un état vide : le quoi faire, après le pourquoi. */
.empty-hint {
  font-size: 13px !important;
  color: var(--faint) !important;
  margin-top: calc(-1 * var(--s3)) !important;
}
