:root {
  --bg: #f4f6f4;
  --surface: #ffffff;
  --surface-2: #eef1ee;
  --border: #dde1dc;
  --ink: #101a16;
  --muted: #56655d;
  --accent: #0a6555;
  --accent-ink: #ffffff;
  --accent-soft: #dff0eb;
  --warn-bg: #fff4e5;
  --warn-ink: #7a4200;
  --warn-border: #f0c68a;
  /* Le rouge ne sert qu'au bandeau, et seulement quand ce qui est affiche peut
     etre faux: le garder rare est ce qui le rend lisible. */
  --alert-bg: #fdecec;
  --alert-ink: #8a1c1c;
  --alert-border: #eeb1b1;
  --radius: 14px;
  --radius-sm: 10px;
  --shadow: 0 1px 2px rgb(16 26 22 / 0.06), 0 6px 20px rgb(16 26 22 / 0.05);
  --tap: 44px;
  /* Fond clair impose: le theme sombre du systeme ne doit pas repeindre la page. */
  color-scheme: light;
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  padding: 0 1rem calc(3rem + env(safe-area-inset-bottom));
  background: var(--bg);
  color: var(--ink);
  font: 16px/1.55 system-ui, -apple-system, "Segoe UI", sans-serif;
  -webkit-text-size-adjust: 100%;
}

main { max-width: 44rem; margin: 0 auto; }

a { color: var(--accent); }

button { font: inherit; cursor: pointer; }

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

.icon { width: 1em; height: 1em; flex: none; }
.icon.flip { transform: scaleX(-1); }

/* ---------- en-tete ---------- */

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 1.1rem 0 0.9rem;
}

.brand {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0;
  font-size: 1.05rem;
  font-weight: 640;
  letter-spacing: -0.01em;
}

.brand .mark { width: 1.6rem; height: 1.6rem; color: var(--accent); }
.brand span { color: var(--accent); }

/* Le bandeau de fraicheur, sous la barre et sur toute sa largeur.

   Il etait une pastille dans l'en-tete, ou il s'allongeait avec la date du
   releve jusqu'a ne plus laisser de place au choix de langue. Ce n'est pas un
   ornement d'en-tete: c'est l'aveu du site sur l'age de ce qu'il montre, et il
   se lit mieux sur une ligne a lui. */
.freshness {
  display: flex;
  align-items: center;
    gap: 0.4rem;
  margin: 0 0 0.9rem;
  padding: 0.5rem 0.8rem;
  border-radius: var(--radius-sm);
  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--muted);
  font-size: 0.78rem;
}

.freshness::before {
  content: "";
  width: 0.5rem;
  height: 0.5rem;
  flex: none;
  border-radius: 50%;
  background: var(--accent);
}

/* Orange: quelque chose manque a l'appel - une source repliee sur le build
   precedent, une fin de saison qui approche - sans rendre faux ce qui est
   affiche. */
.freshness.warn {
  background: var(--warn-bg);
  border-color: var(--warn-border);
  color: var(--warn-ink);
}

/* Rouge: ce qui est affiche peut etre faux - releve de plus de deux jours, ou
   programme aerien passe. La seule couleur qui demande d'arreter et de
   verifier ailleurs. */
.freshness.alerte {
  background: var(--alert-bg);
  border-color: var(--alert-border);
  color: var(--alert-ink);
  font-weight: 560;
}

.freshness.warn::before,
.freshness.alerte::before { background: currentColor; }

/* Le choix de langue, tout a droite: une liste deroulante.

   Fermee, elle ne montre que deux lettres et un chevron - 38 px mesures, contre
   74 px pour trois entrees en ligne. C'est ce qui lui permet de tenir dans une
   barre qui portait deja la marque et la pastille de fraicheur, laquelle
   s'allonge avec la date du releve.

   Aucun rembourrage vertical sur le bloc, et l'interligne fixe a 1: la hauteur
   de la barre reste celle de la marque, le plus haut de ses enfants. Le
   rembourrage qui fait la cible tactile vit sur le resume, annule par une marge
   negative en face: trente pixels a toucher, zero ajoute a la barre. */
.topbar .langues {
  position: relative;
  margin-left: auto;
  flex: none;
  font-size: 0.75rem;
  font-weight: 640;
  line-height: 1;
  letter-spacing: 0.06em;
}

.topbar .langues summary {
  display: flex;
  align-items: center;
  gap: 0.15rem;
  padding: 0.55rem 0.15rem;
  margin: -0.55rem 0;
  color: var(--muted);
  cursor: pointer;
  list-style: none;
}

/* Le triangle natif de Safari en plus du chevron ferait deux fleches. */
.topbar .langues summary::-webkit-details-marker { display: none; }
.topbar .langues summary:hover { color: var(--ink); }
.topbar .langues summary .icon { width: 0.85rem; height: 0.85rem; }
.topbar .langues[open] summary .icon { transform: rotate(180deg); }

/* Le panneau flotte au-dessus de la page: l'ouvrir ne pousse rien, donc ni la
   barre ni ce qui la suit ne bouge. Cale a droite, il ne sort pas de l'ecran. */
.topbar .langues ul {
  position: absolute;
  z-index: 20;
  top: calc(100% + 0.5rem);
  right: 0;
  min-width: 8.5rem;
  margin: 0;
  padding: 0.25rem;
  list-style: none;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow);
  font-size: 0.85rem;
  font-weight: 500;
  letter-spacing: 0;
}

.topbar .langues a {
  display: block;
  padding: 0.5rem 0.6rem;
  border-radius: 0.5rem;
  color: var(--ink);
  text-decoration: none;
  white-space: nowrap;
}

.topbar .langues a:hover { background: var(--accent-soft); }
.topbar .langues [aria-current] { color: var(--accent); }

/* ---------- recherche ---------- */

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

.search { padding: 0.85rem; }

/* La barre de trajet: l'etat de la recherche, et le seul geste pour en changer. */
.tripbar {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.3rem;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 999px;
}

.stop {
  display: flex;
  align-items: center;
  flex: 1 1 0;
  min-width: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 999px;
}

.stop:focus-within { border-color: var(--accent); }

.stop input {
  flex: 1 1 auto;
  width: 100%;
  min-width: 0;
  min-height: 2.4rem;
  padding: 0.4rem 0.1rem 0.4rem 0.85rem;
  font: inherit;
  font-weight: 620;
  color: var(--ink);
  background: none;
  border: 0;
  border-radius: 999px;
  text-overflow: ellipsis;
}

.stop input:focus { outline: none; }
.stop input::placeholder { font-weight: 500; color: var(--muted); }

.clear {
  width: 1.8rem;
  height: 1.8rem;
  flex: none;
  display: grid;
  place-items: center;
  margin-right: 0.25rem;
  color: var(--muted);
  background: none;
  border: 0;
  border-radius: 999px;
  cursor: pointer;
}

.clear:hover { color: var(--ink); background: var(--surface-2); }
.clear .icon { width: 0.85rem; height: 0.85rem; }

.tb-go {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  flex: none;
  min-height: 2.4rem;
  padding-inline: 0.9rem;
  font: inherit;
  font-weight: 620;
  color: var(--accent-ink);
  background: var(--accent);
  border: 0;
  border-radius: 999px;
  cursor: pointer;
}

.tb-go .icon { width: 1.05rem; height: 1.05rem; }

/* Sous 30rem, "Rechercher" ecrase les deux pastilles: il ne reste que la
   loupe, qui dit la meme chose dans le quart de la place. */
@media (max-width: 30rem) {
  .tb-go span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  .tb-go { padding-inline: 0.7rem; }
  .stop input { padding-left: 0.6rem; }
}

/* La liste s'ouvre sous la barre, par-dessus le reste de la carte. */
.suggest {
  position: absolute;
  z-index: 5;
  top: calc(100% + 0.35rem);
  left: 0;
  right: 0;
  max-height: 50dvh;
  overflow-y: auto;
  list-style: none;
  margin: 0;
  padding: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

.suggest[hidden] { display: none; }

.suggest button {
  display: block;
  width: 100%;
  min-height: var(--tap);
  padding: 0.6rem 0.85rem;
  font: inherit;
  text-align: left;
  color: var(--ink);
  background: none;
  border: 0;
  cursor: pointer;
}

.suggest li + li button { border-top: 1px solid var(--border); }
.suggest button:hover { background: var(--accent-soft); }
.suggest .none { padding: 0.9rem 0.85rem; color: var(--muted); }


#swap {
  flex: none;
  width: 2rem;
  height: 2rem;
  display: grid;
  place-items: center;
  color: var(--muted);
  background: none;
  border: 0;
  border-radius: 50%;
  cursor: pointer;
  transition: transform 200ms ease-out, background 160ms ease-out;
}

#swap .icon { width: 1.05rem; height: 1.05rem; }
#swap:hover { color: var(--accent); background: var(--surface); }
#swap.turn { transform: rotate(180deg); }

/* ---------- bandeau de dates ---------- */

.days {
  display: flex;
  gap: 0.4rem;
  margin: 0.6rem -1rem 0;
  padding: 0.15rem 1rem 0.35rem;
  overflow-x: auto;
  scrollbar-width: none;
  scroll-snap-type: x mandatory;
  /* Sans cela, se caler sur une case fait passer le retrait de la bande sous
     le bord gauche, et la premiere case colle a l'ecran. */
  scroll-padding-inline: 1rem;
}

.days::-webkit-scrollbar { display: none; }

.day {
  flex: 1 0 4.1rem;
  scroll-snap-align: start;
  min-height: 62px;
  padding: 0.4rem 0.2rem 0.35rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.1rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--muted);
  transition: background 160ms ease-out, border-color 160ms ease-out;
}

.day .dow { font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.05em; }
.day .num { font-size: 1.15rem; font-weight: 640; color: var(--ink); font-variant-numeric: tabular-nums; }

.day .load {
  display: flex;
  gap: 2px;
  height: 6px;
  align-items: center;
}

.day .load i {
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--accent);
  opacity: 0.85;
}

.day .load i.faint { background: var(--muted); opacity: 0.45; }
.day.none { opacity: 0.5; }
.day.none .num { color: var(--muted); }

/* Trois degres, et non deux: pleine pour ce qu'on demande, chiffre seul terni
   quand la liaison circule sans le filtre, case entiere ternie quand personne
   ne part. Ternir toute la case ici la confondrait avec un jour mort, alors
   qu'il suffit de decocher pour y trouver un bateau. */
.day.hors-filtre .num { color: var(--muted); }

/* Inconnu n'est pas mort: le jour garde son encre, seule sa pastille se creuse. */
.day .load i.hollow { background: none; box-shadow: inset 0 0 0 1px var(--muted); opacity: 0.6; }

.day[aria-pressed="true"] {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent);
}

.day[aria-pressed="true"] .num { color: var(--accent); }
.day[aria-pressed="true"] .load i { background: var(--accent); }

.day.pick { position: relative; flex-basis: auto; padding-inline: 0.7rem; justify-content: center; gap: 0.3rem; cursor: pointer; }
.day.pick .icon { width: 1.15rem; height: 1.15rem; }
.day.pick .num { font-size: 0.8rem; font-weight: 560; color: inherit; }


.day.back { flex-basis: auto; padding-inline: 0.7rem; justify-content: center; gap: 0.3rem; }
.day.back .icon { width: 1.15rem; height: 1.15rem; }
.day.back .num { font-size: 0.8rem; font-weight: 560; color: inherit; }

/* Cinq jours pleins dans la largeur de la carte, plutot qu'une sixieme case
   coupee par le bord de l'ecran: c'est cette moitie de case qui donnait a la
   bande l'air de deborder de la page. Le reste de la semaine defile. */
@media (max-width: 40rem) {
  .day { flex: 0 0 calc((100% - 1.6rem) / 5); }
  .day.pick,
  .day.back { flex-basis: auto; }
}

/* ---------- calendrier ---------- */

/* Dans le flux, pas en surimpression: il pousse la page vers le bas au lieu
   de sortir de l'ecran, ce que faisait le selecteur natif du navigateur. */
.calendar { padding: 0.6rem 0.7rem 0.8rem; }

.cal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin-bottom: 0.5rem;
}

.cal-head strong { font-size: 0.95rem; text-transform: capitalize; }

.cal-nav {
  width: var(--tap);
  height: 2.2rem;
  display: grid;
  place-items: center;
  color: var(--accent);
  background: none;
  border: 0;
  border-radius: 999px;
  cursor: pointer;
}

.cal-nav:hover { background: var(--accent-soft); }
.cal-nav .icon { width: 1.1rem; height: 1.1rem; }

.cal-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 0.15rem;
}

.cal-dow {
  padding-bottom: 0.25rem;
  font-size: 0.68rem;
  text-align: center;
  color: var(--muted);
}

.cal-day {
  aspect-ratio: 1;
  min-height: 2.1rem;
  display: grid;
  place-items: center;
  font: inherit;
  font-size: 0.9rem;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  background: none;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  cursor: pointer;
}

.cal-day:hover { background: var(--surface-2); }
.cal-day.none { color: var(--muted); opacity: 0.45; }
.cal-day.today { font-weight: 700; color: var(--accent); }

/* Le point sous le chiffre: plein s'il y a des departs, creux si on ne sait pas
   encore, absent si la liaison ne circule pas ce jour-la. Pose en absolu pour
   que le chiffre reste au centre de sa case, quel que soit son etat. */
.cal-day { position: relative; }

.cal-day .pip {
  position: absolute;
  bottom: 0.22rem;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  height: 4px;
}

.cal-day .pip i,
.cal-legende i {
  width: 4px;
  height: 4px;
  border-radius: 999px;
  background: var(--accent);
}

.cal-day .pip i.faint,
.cal-legende i.faint { background: var(--muted); opacity: 0.45; }

.cal-day .pip i.hollow,
.cal-legende i.hollow { background: none; box-shadow: inset 0 0 0 1px var(--muted); opacity: 0.6; }

/* Trois points et un chiffre terni ne se devinent pas: la legende les nomme
   une fois, sous la grille. Elle se demontre elle-meme - l'entree "pas de
   service" porte le terne des cases qu'elle decrit. */
.cal-legende {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 0.9rem;
  margin: 0.7rem 0 0;
  padding: 0.6rem 0 0;
  list-style: none;
  border-top: 1px solid var(--border);
  font-size: 0.68rem;
  color: var(--muted);
}

.cal-legende li {
  display: flex;
  align-items: center;
  gap: 0.3rem;
}

.cal-legende li.none { opacity: 0.45; }

/* Le meme terne que les cases decrites: le chiffre grisonne, le point reste. */
.cal-day.hors-filtre { color: var(--muted); }
.cal-legende li.hors-filtre { color: var(--muted); }

/* Le mois s'affiche avant ses horaires: la pulsation dit que ca continue. */
#calendar[aria-busy='true'] .cal-day { animation: pouls 1.1s ease-in-out infinite; }

@keyframes pouls {
  50% { opacity: 0.4; }
}

.cal-day[aria-pressed='true'] {
  color: var(--accent);
  background: var(--accent-soft);
  border-color: var(--accent);
}

/* ---------- filtres de mode ---------- */

.modes {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin: 0.6rem 0 0;
  padding: 0;
  border: 0;
}

.modes legend { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
.modes input { position: absolute; opacity: 0; pointer-events: none; }

.modes label {
  /* Les pastilles se partagent la ligne au lieu de se serrer a gauche: une
     rangee de filtres qui s'arrete au tiers de la carte laisse croire qu'il
     manque quelque chose a sa droite. */
  flex: 1;
  min-height: 36px;
  padding: 0.35rem 0.85rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.35rem;
  font-size: 0.85rem;
  color: var(--muted);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 999px;
  cursor: pointer;
  transition: background 160ms ease-out, color 160ms ease-out;
}

.modes input:checked + label {
  color: var(--accent);
  background: var(--accent-soft);
  border-color: var(--accent);
}

.modes input:focus-visible + label { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Grisee, pas retiree: le ferry fait bien la liaison, la compagnie aussi, c'est
   ce jour-la qu'ils ne partent pas. Une liste qui change de contenu a chaque
   date ne se relit plus. */
.modes label.vide,
.filtre-compagnies label.vide { opacity: 0.45; }

/* Le filtre par compagnies: une liste deroulante, batie sur le meme `<details>`
   que le choix de langue de la barre.

   La rangee de pastilles qui la precedait faisait defiler les compagnies hors
   de l'ecran. Le resume dit ce qui est retenu sans qu'on ait a l'ouvrir. */
.filtre-compagnies {
  position: relative;
  margin-top: 0.4rem;
  /* Sur sa propre ligne, elle la prend entiere: c'est un filtre de meme rang
     que les modes, et sa largeur ne doit pas dependre du nom de la compagnie
     retenue, qui la faisait grandir et retrecir a chaque choix. */
  width: 100%;
}

.filtre-compagnies summary {
  min-height: 36px;
  padding: 0.35rem 0.7rem 0.35rem 0.85rem;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.35rem;
  font-size: 0.85rem;
  color: var(--muted);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 999px;
  cursor: pointer;
  list-style: none;
}

.filtre-compagnies summary::-webkit-details-marker { display: none; }
.filtre-compagnies summary .icon { width: 0.9rem; height: 0.9rem; }
.filtre-compagnies[open] summary .icon { transform: rotate(180deg); }

/* Une pastille qui filtre se voit comme celles des modes, juste au-dessus. */
.filtre-compagnies:has(input:checked) summary {
  color: var(--accent);
  background: var(--accent-soft);
  border-color: var(--accent);
}

/* Le panneau flotte: l'ouvrir ne pousse ni la carte ni les resultats. Il defile
   des que les compagnies sont plus nombreuses que la hauteur d'un telephone. */
.filtre-compagnies ul {
  position: absolute;
  z-index: 15;
  top: calc(100% + 0.4rem);
  /* Aussi large que le bouton qui l'ouvre: un panneau plus etroit que son
     resume donne deux bords a gauche et un vide a droite, et les noms longs
     s'y coupaient alors que la place existait juste a cote. */
  left: 0;
  right: 0;
  max-height: 15rem;
  overflow-y: auto;
  margin: 0;
  padding: 0.25rem;
  list-style: none;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow);
}

.filtre-compagnies li { margin: 0; }

.filtre-compagnies label {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  min-height: var(--tap);
  padding: 0.35rem 0.5rem;
  border-radius: 0.5rem;
  font-size: 0.85rem;
  color: var(--ink);
  cursor: pointer;
}

.filtre-compagnies label:hover { background: var(--surface-2); }
.filtre-compagnies input { accent-color: var(--accent); width: 1rem; height: 1rem; flex: none; }

/* Le geste inverse des cases, donc pas une case: un bouton, eteint tant qu'il
   n'y a rien a effacer. */
.filtre-compagnies .tout {
  width: 100%;
  min-height: 2.2rem;
  padding: 0.35rem 0.5rem;
  font-size: 0.8rem;
  text-align: left;
  color: var(--accent);
  background: none;
  border: 0;
  border-radius: 0.5rem;
}

.filtre-compagnies .tout:hover:not(:disabled) { background: var(--accent-soft); }
.filtre-compagnies .tout:disabled { color: var(--muted); opacity: 0.6; cursor: default; }

.mono {
  display: grid;
  place-items: center;
  width: 1.35rem;
  height: 1.35rem;
  flex: none;
  border-radius: 50%;
  background: var(--surface-2);
  color: var(--ink);
  font-size: 0.62rem;
  font-weight: 700;
  font-style: normal;
  letter-spacing: 0.02em;
}

.modes input:checked + label .mono { background: var(--surface); color: var(--accent); }

/* Les logos n'ont ni le meme cadrage ni le meme format: le fond blanc et le
   contain leur donnent la meme pastille sans les deformer. */
img.mono { background: #fff; object-fit: contain; padding: 2px; }

/* ---------- reponse ---------- */

.answer {
  margin-top: 0.9rem;
  padding: 1.1rem 1.1rem 1rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

.answer .kicker {
  margin: 0;
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--muted);
}

.answer .headline {
  display: flex;
  /* Centre sur l'heure: alignee sur la ligne de base, la pastille pendait sous
     un chiffre de 3.4rem, tres loin de son milieu. */
  align-items: center;
  flex-wrap: wrap;
  gap: 0.3rem 0.7rem;
  margin: 0.35rem 0 0;
}

.answer .big {
  font-size: clamp(2.4rem, 11vw, 3.4rem);
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.035em;
  font-variant-numeric: tabular-nums;
}

.answer .countdown {
  padding: 0.25rem 0.65rem;
  border-radius: 999px;
  background: var(--accent);
  color: var(--accent-ink);
  font-size: 0.85rem;
  font-weight: 600;
}

/* La carte du prochain depart reprend le chemin de la liste: depart en tete,
   arrivee au pied, reliees par le trait. Deux heures empilees ne disaient pas
   laquelle menait a l'autre. */
.answer .detail.trip-line {
  display: block;
}

/* Le chemin se lit de gauche a droite, comme la traversee: depart, trait,
   arrivee. Le reste du depart tient dessous, sur toute la largeur. */
.answer .trip-line .when {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 0.6rem;
}

/* La duree se pose au milieu du trait, sur ce qu'elle mesure: le fond de la
   carte la detoure, le trait passe de part et d'autre. */
.answer .trip-line .leg {
  position: relative;
  flex: 1;
  display: flex;
  align-items: center;
}

.answer .trip-line .leg .tag {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  background: var(--surface);
}

.answer .trip-line .rail {
  flex: 1;
  flex-direction: row;
  padding: 0;
}

.answer .trip-line .rail span {
  width: auto;
  height: 2px;
  min-height: 0;
  min-width: 12px;
}

/* `.when .dep` de la liste, declare plus bas, ecrasait la taille du gros
   chiffre a poids egal: la carte du jour le reprend explicitement. */
.answer .trip-line .dep {
  color: var(--ink);
  font-size: clamp(2.4rem, 11vw, 3.4rem);
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.035em;
}

.answer .trip-line .arr { font-size: 1.1rem; color: var(--muted); font-variant-numeric: tabular-nums; }

/* Sous le trait, les faits se rangent en lignes pleines plutot qu'en colonne
   etroite: compagnie et trajet cote a cote tant que la largeur le permet, les
   pastilles a la suite. Empile, le bloc laissait la moitie droite en blanc. */
.answer .trip-line .detail-body {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35rem 0.7rem;
  margin-top: 0.5rem;
}

.answer .trip-line .trip-sub { margin: 0; }
/* La marge haute des pastilles, faite pour la liste ou elles sont seules sur
   leur ligne, les posait deux pixels plus bas que le nom et le trajet. */
.answer .trip-line .tags { flex-wrap: wrap; margin: 0; }

.answer .detail {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin: 0.6rem 0 0;
  color: var(--muted);
  font-size: 0.9rem;
}

/* Sur un ecran large les faits tiennent sur une ligne; au telephone ils
   s'empilent, un par ligne, plutot que de se replier n'importe ou. */
.answer .detail-body {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.25rem 0.5rem;
  min-width: 0;
}

.answer .detail strong { color: var(--ink); font-weight: 600; }

/* Le logo tient a son nom: en colonne, sur telephone, il partirait sinon sur
   une ligne a lui, loin de la compagnie qu'il designe. */
.answer .detail-company { display: inline-flex; align-items: center; gap: 0.35rem; }
.answer .detail .icon { color: var(--accent); width: 1.05rem; height: 1.05rem; }

.answer .then {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  margin: 0.85rem 0 0;
  padding: 0.7rem 0 0;
  border-top: 1px solid var(--border);
  font-size: 0.85rem;
  color: var(--muted);
  align-items: center;
}

.answer .then b {
  color: var(--ink);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.answer.empty-state .big { font-size: 1.15rem; font-weight: 620; line-height: 1.4; letter-spacing: 0; }

/* Un jour vide sous filtre offre deux sorties - aller a la date suivante, ou
   lever le filtre - la ou il n'y en avait qu'une. Sur un telephone etroit
   elles s'empilent, plutot que de se comprimer l'une contre l'autre. */
.answer.empty-state .detail { flex-wrap: wrap; }


.jump {
  margin-top: 0.7rem;
  min-height: 40px;
  padding: 0.45rem 0.9rem;
  display: inline-flex;
  align-items: center;
  /* Le libelle est seul dans la pastille depuis que la flechette est partie:
     sans cela il tiendrait la gauche des que la pastille est etiree. */
  justify-content: center;
  gap: 0.4rem;
  color: var(--accent-ink);
  background: var(--accent);
  border: 0;
  border-radius: 999px;
  font-size: 0.88rem;
  font-weight: 560;
}

.book {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  font-size: 0.82rem;
  font-weight: 560;
}

/* Le menu de billets ouvre une modale, comme "Tarifs" juste a cote: deux
   boutons voisins qui ouvrent la meme sorte de contenu doivent l'ouvrir de la
   meme facon. */
.book-open {
  margin-top: 0.35rem;
  vertical-align: middle;
  background: none;
  border: 0;
  padding: 0;
  color: inherit;
  cursor: pointer;
  font: inherit;
  font-size: 0.82rem;
  font-weight: 560;
}

.book-list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 0.5rem;
}
.book-list a { font-size: 0.9rem; font-weight: 500; }
.fares-modal .fine { margin: 0.7rem 0 0; font-size: 0.75rem; color: var(--muted); }

/* ---------- annonce de la regie ---------- */

/* Une carte de la liste comme les autres, mais qu'on ne confond pas avec un depart:
   l'etiquette « Sponsorise » ouvre le texte, et l'image garde sa place reservee
   (16:9) pour que la liste ne saute pas quand elle arrive. */
.trip.pub, .card.pub { display: block; position: relative; padding: 0.6rem 0.85rem; }
.card.pub { margin-top: 1rem; }
.pub[hidden] { display: none; }

.pub-lien {
  display: grid;
  grid-template-columns: minmax(7rem, 11rem) 1fr;
  gap: 0.8rem;
  align-items: center;
  color: inherit;
  text-decoration: none;
}

.pub-lien img,
.pub-lien video {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  border-radius: calc(var(--radius) / 2);
  background: var(--accent-soft);
}

.pub-texte { min-width: 0; }
.pub-etiquette { display: block; font-size: 0.75rem; color: var(--muted); }
.pub-lien strong { display: block; color: var(--accent); }
.pub-lien:hover strong, .pub-lien:focus-visible strong { text-decoration: underline; }

/* Le pixel doit rester dans la mise en page: un element cache n'est jamais charge en lazy. */
.pub-pixel { position: absolute; bottom: 0; right: 0; opacity: 0; pointer-events: none; }

@media (max-width: 30rem) {
  .pub-lien { grid-template-columns: 1fr; }
}

/* Bandeau (6:1) sous la barre et colonnes (1:2) de chaque cote: l'image seule,
   l'etiquette posee dans un coin. Rien n'est reserve tant que l'annonce n'est pas la. */
.pub-haut-de-page, .pub-cote-gauche, .pub-cote-droit { position: relative; }
.pub-haut-de-page { margin-bottom: 1rem; }
.pub-visuel { display: block; position: relative; }
.pub-visuel img,
.pub-visuel video {
  display: block;
  width: 100%;
  aspect-ratio: 6 / 1;
  object-fit: cover;
  border-radius: var(--radius-sm);
  background: var(--accent-soft);
}
.pub-visuel .pub-etiquette {
  position: absolute;
  top: 0.4rem;
  left: 0.4rem;
  padding: 0 0.4rem;
  border-radius: 4px;
  background: rgb(255 255 255 / 0.85);
  color: var(--muted);
  font-size: 0.7rem;
}

/* Les colonnes de 300 px, fixes a l'ecran, de toute la hauteur sous la barre: voir COTES_MEDIA
   dans pages.js. Le contenu se resserre pour leur laisser la marge (--contenu: 704 px a 1400 px),
   a 24 px de chacune. Dedans, l'annonce entiere (contain) sur un fond flou de la meme image. */
.pub-cote-gauche, .pub-cote-droit { display: none; }
@media (min-width: 1400px) and (min-height: 720px) {
  :root { --contenu: min(44rem, calc(100vw - 696px)); }
  main, .promo { max-width: var(--contenu); }
  .pub-cote-gauche, .pub-cote-droit { display: block; position: fixed; top: 4.5rem; bottom: 16px; width: 300px; z-index: 10; }
  .pub-cote-gauche { right: calc(50% + var(--contenu) / 2 + 24px); }
  .pub-cote-droit { left: calc(50% + var(--contenu) / 2 + 24px); }
  .pub-cote-gauche .pub-visuel, .pub-cote-droit .pub-visuel { height: 100%; overflow: hidden; border-radius: var(--radius-sm); background: var(--accent-soft); }
  .pub-cote-gauche .pub-visuel :is(img, video),
  .pub-cote-droit .pub-visuel :is(img, video) { position: relative; width: 100%; height: 100%; aspect-ratio: auto; object-fit: contain; border-radius: 0; background: none; }
  .pub-cote-gauche .pub-visuel .pub-fond, .pub-cote-droit .pub-visuel .pub-fond { position: absolute; inset: 0; object-fit: cover; filter: blur(24px) saturate(1.2); transform: scale(1.15); opacity: 0.9; }
}

/* ---------- encart maison ---------- */

/* Flottant, et refermable. Il suit le bas de l'ecran plutot que le fil de la
   page, sans figer quoi que ce soit autour: le site reste un document qui
   defile d'un bloc. Le retrait bas du body lui reserve sa hauteur, pour que la
   fin de page se lise au-dessus plutot que dessous. */
.promo {
  position: fixed;
  inset: auto 1rem calc(0.7rem + env(safe-area-inset-bottom));
  z-index: 20;
  max-width: 44rem;
  margin-inline: auto;
}

.promo[hidden] { display: none; }

body:has(.promo:not([hidden])) {
  padding-bottom: calc(8.5rem + env(safe-area-inset-bottom));
}

/* Deux voisins, une seule place: ils se relaient. Les deux vues occupent la meme case de
   la grille, donc l'encart a la hauteur de la plus haute et ne saute pas d'une a l'autre.

   Le passage est un fondu, jamais un defilement continu: une animation qui ne s'arrete
   jamais est une gene, et app.js l'interrompt au survol, au focus, et tout a fait quand le
   systeme demande moins de mouvement. */
.promo-piste {
  display: grid;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow);
}

.promo-vue {
  grid-area: 1 / 1;
  display: flex;
  align-items: center;
  gap: 0.7rem;
  min-width: 0;
  padding: 0.7rem 0.85rem;
  color: inherit;
  text-decoration: none;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.5s ease-out, visibility 0.5s;
}

.promo-vue[data-vue='active'] { opacity: 1; visibility: visible; }

/* Les pastilles: le seul moyen de rattraper la vue qu'on vient de voir passer. Le point
   fait 6 px, la cible 22 - le rembourrage porte la difference. */
.promo-points {
  position: absolute;
  left: 50%;
  bottom: -0.35rem;
  transform: translateX(-50%);
  display: flex;
}

.promo-points button {
  width: 22px;
  height: 22px;
  padding: 0;
  display: grid;
  place-items: center;
  border: 0;
  background: none;
  cursor: pointer;
}

.promo-points button::before {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--border);
  box-shadow: 0 0 0 2px var(--bg);
  transition: background 160ms ease-out;
}

.promo-points button[aria-selected='true']::before { background: var(--accent); }

/* Le nom du site n'est la que pour la synthese vocale: une pastille nue ne dit pas ce
   qu'elle choisit. */
.promo-nom {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.promo-mark { width: 2.1rem; height: 2.1rem; flex: none; border-radius: 8px; }

.promo-text { display: flex; flex-direction: column; gap: 0.05rem; min-width: 0; }

.promo-kicker {
  font-size: 0.62rem;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--muted);
}

.promo-text strong { font-size: 0.95rem; font-weight: 640; }

.promo-sub {
  font-size: 0.8rem;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
}

.promo-vue > .icon { margin-left: auto; flex: none; color: var(--accent); }

.promo-close {
  position: absolute;
  top: -0.6rem;
  right: -0.4rem;
  display: inline-flex;
  padding: 0.3rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  color: var(--muted);
  box-shadow: var(--shadow);
}

.promo-close .icon { width: 0.9rem; height: 0.9rem; }

/* ---------- listes ---------- */

h2 {
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--muted);
  margin: 1.8rem 0 0.6rem;
}

.section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}


.section-head h2 { margin: 1.8rem 0 0.6rem; flex: none; }

ol { list-style: none; margin: 0; padding: 0; }

li.trip {
  display: grid;
  /* Colonne des heures a largeur fixe: en `auto`, elle suivait le nom du quai,
     et le chemin comme la compagnie sautaient d'une carte a l'autre. */
  grid-template-columns: 6rem 0.7rem 1fr;
  gap: 0 0.7rem;
  padding: 0.85rem 1rem;
  border-bottom: 1px solid var(--border);
}

/* Sur telephone, 6rem d'heures + marges laissaient ~200px a la compagnie:
   la colonne tient encore "08h00" et "Aéroport de" sur une ligne. */
@media (max-width: 30rem) {
  li.trip { grid-template-columns: 4.75rem 0.7rem 1fr; gap: 0 0.5rem; padding-inline: 0.75rem; }
}

li.trip:last-child { border-bottom: 0; }

.when {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  /* L'arrivee descend au pied du chemin, en face de sa pastille: lue collee
     sous le depart, elle passait pour une seconde heure de depart. */
  justify-content: space-between;
  font-variant-numeric: tabular-nums;
}

.when .dep { font-size: 1.2rem; font-weight: 650; letter-spacing: -0.01em; }
.when .arr { font-size: 0.85rem; color: var(--muted); }

/* Chaque lieu sous son heure. La colonne reste etroite: un "Aéroport de
   Nukutavake" se replie plutot que de pousser la compagnie hors de la carte. */
.when .point { display: flex; flex-direction: column; align-items: flex-end; }
.when .lieu {
  max-width: 100%;
  overflow-wrap: anywhere;
  font-size: 0.75rem;
  line-height: 1.2;
  color: var(--muted);
  text-align: right;
}

.rail {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 0.4rem 0 0.3rem;
}

.rail i {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  border: 2px solid var(--accent);
  flex: none;
}

.rail i:last-child { background: var(--accent); }
.rail span { flex: 1; width: 2px; background: var(--border); min-height: 12px; }

.trip-body { display: block; min-width: 0; }

.trip-title {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin: 0;
  font-size: 0.95rem;
  font-weight: 600;
}

.trip-title .icon { color: var(--accent); width: 1rem; height: 1rem; }

.trip-sub { display: block; margin: 0.15rem 0 0; font-size: 0.84rem; color: var(--muted); }
.trip-sub em { font-style: normal; color: var(--accent); }
/* Retard ou annulation: le rouge du bandeau, pour la meme raison - l'horaire
   affiche au-dessus ne sera pas tenu. */
.trip-sub em.retard { color: var(--alert-ink); font-weight: 560; }

.tags { display: flex; flex-wrap: wrap; gap: 0.3rem; margin-top: 0.35rem; }

/* Reserver est l'action de la carte: pastille pleine. Tarifs la seconde:
   meme pastille, contour seul, pour qu'un seul bouton attire l'oeil. */
.trip .book,
.answer .book {
  padding: 0.4rem 0.85rem;
  border-radius: 999px;
  text-decoration: none;
}
.trip .book:not(.fares-open),
.answer .book:not(.fares-open) {
  background: var(--accent);
  color: var(--accent-ink);
}
.trip .fares-open,
.answer .fares-open {
  border: 1px solid var(--border);
  background: none;
  color: var(--ink);
}

/* Les deux boutons se partagent la largeur: cote a cote et serres a gauche,
   ils laissaient une bande vide au bord droit de la carte. */
/* Deux moities egales tant que chacune tient un bouton chiffre; en dessous, les
   deux actions s'empilent plutot que de deborder de la carte. */
.actions {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 10rem), 1fr));
  align-items: center;
  gap: 0.5rem;
  margin-top: 0.55rem;
}

.actions > * {
  margin: 0;
  width: 100%;
  /* Meme hauteur pour les deux, cible tactile comprise. */
  min-height: 40px;
  align-items: center;
  justify-content: center;
}

/* Seule (compagnie sans grille tarifaire), l'action prend la ligne entiere:
   coincee dans une demi-largeur, sa phrase s'enroulait en pave rond. */
.actions > :only-child { grid-column: 1 / -1; }

.tag {
  font-size: 0.7rem;
  letter-spacing: 0.03em;
  padding: 0.12rem 0.45rem;
  border-radius: 999px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  color: var(--muted);
  white-space: nowrap;
}

.tag.direct { background: var(--accent-soft); border-color: transparent; color: var(--accent); }

/* Pont vehicule plein: le rouge de la page, et le trait qui dit que la place
   n'est plus a prendre. Le renvoi au guichet garde le tag ordinaire - la
   compagnie vend encore, elle deplace le guichet. */
.tag.vehicule-complet { color: var(--alert-ink); text-decoration: line-through; }

#past { margin-top: 0.7rem; }

#past summary {
  min-height: 40px;
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.5rem 0.85rem;
  font-size: 0.82rem;
  color: var(--muted);
  border: 1px dashed var(--border);
  border-radius: var(--radius-sm);
  list-style: none;
  cursor: pointer;
}

#past summary::-webkit-details-marker { display: none; }
#past ol { margin-top: 0.5rem; opacity: 0.55; }

/* ---------- tarifs ---------- */

table { width: 100%; min-width: 26rem; border-collapse: collapse; font-size: 0.9rem; }

caption {
  text-align: left;
  padding: 0.9rem 1rem 0.4rem;
  font-weight: 600;
  font-size: 0.9rem;
}

th, td { padding: 0.5rem 1rem; text-align: right; }
th:first-child, td:first-child { text-align: left; }

thead th {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
  font-weight: 500;
  border-bottom: 1px solid var(--border);
}

tbody td {
  font-variant-numeric: tabular-nums;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}

tbody td:first-child { white-space: normal; }
tbody tr:last-child td { border-bottom: 0; }

.fares-scroll { overflow-x: auto; }

/* Grille tarifaire en modale, ouverte depuis le depart. <dialog> apporte le
   fond, la pile de focus et la touche Echap sans une ligne de script. */
.fares-modal {
  width: min(46rem, calc(100vw - 1.5rem));
  max-height: min(80vh, 46rem);
  padding: 1rem 1.1rem 1.2rem;
  border: 0;
  border-radius: var(--radius);
  background: var(--surface);
  color: inherit;
  overflow: auto;
}
.fares-modal::backdrop { background: rgb(16 26 22 / 0.45); }
.fares-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 0.6rem;
}
.fares-head h2 { margin: 0; }
.fares-close {
  display: inline-flex;
  padding: 0.35rem;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
}
/* Le bouton des tarifs vit desormais dans la ligne d'actions, qui lui donne sa
   taille et sa place. Ce qui restait ici de son ancienne vie de lien souligne
   - une marge haute et un alignement de texte - le posait trois pixels plus
   bas que "Reserver", juste a cote. */
.fares-open { cursor: pointer; font: inherit; font-size: 0.82rem; font-weight: 560; }

/* Sous 40rem, aucune grille a trois ou quatre formules ne tient dans la
   largeur: elle imposait un defilement horizontal a toute la page. Chaque
   ligne devient donc une carte, categorie en titre et un montant par formule,
   et le tableau reste un tableau pour qui le lit sans mise en forme. */
@media (max-width: 40rem) {
  .promo-sub {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
  }

  .answer .detail { align-items: flex-start; }

  .answer .detail-body {
    flex-direction: column;
    align-items: flex-start;
    gap: 0.2rem;
  }

  /* Feuille du bas: la grille arrive du bord de l'ecran, sur toute la largeur,
     la ou une boite centree laissait des marges perdues et un tableau etroit. */
  .fares-modal {
    width: 100%;
    max-width: none;
    max-height: 85vh;
    margin: auto 0 0;
    padding: 0.9rem 0.9rem 1.4rem;
    border-radius: var(--radius) var(--radius) 0 0;
  }

  .fares-scroll table { min-width: 0; }

  .fares-scroll table,
  .fares-scroll tbody,
  .fares-scroll tr,
  .fares-scroll td {
    display: block;
  }

  .fares-scroll thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
  }

  .fares-scroll tbody tr {
    padding: 0.75rem 1rem;
    border-bottom: 1px solid var(--border);
  }

  .fares-scroll tbody tr:last-child { border-bottom: 0; }

  .fares-scroll tbody td {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.15rem 0;
    white-space: normal;
    border-bottom: 0;
  }

  .fares-scroll tbody td::before {
    content: attr(data-label);
    color: var(--muted);
    font-size: 0.82rem;
  }

  .fares-scroll tbody td.cat {
    display: block;
    margin-bottom: 0.3rem;
    font-weight: 640;
    color: var(--ink);
  }
}

footer {
  margin-top: 2.5rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--border);
  font-size: 0.82rem;
  color: var(--muted);
}

@media (min-width: 40rem) {
  .answer { padding: 1.3rem 1.4rem; }
}

/* ---------- squelettes de chargement ---------- */

/*
 * Le gabarit sert une page nue: les horaires arrivent par le reseau, et la
 * reponse, la bande de jours et la liste restent vides le temps du voyage. Des
 * cadres a la taille de ce qui vient valent mieux qu'un blanc - la page ne
 * saute pas quand le contenu se pose - a condition de ne rien affirmer: ils
 * n'ont pas de texte, et la pulsation les distingue d'un contenu gris.
 *
 * Pose apres `.day`, a specificite egale: une case de jour en squelette prend
 * ce fond-ci et garde sa taille.
 */
.skel {
  background: var(--border);
  border-radius: var(--radius-sm);
  animation: skel-pulse 1.5s ease-in-out infinite;
}

@keyframes skel-pulse {
  50% { opacity: 0.45; }
}

.skel-answer {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.55rem;
}

.skel-answer .skel-kicker { width: 6.5rem; height: 0.7rem; }
/* La meme hauteur que l'heure qui viendra s'y mettre. */
.skel-answer .skel-big { width: 9rem; height: clamp(2.4rem, 11vw, 3.4rem); }
.skel-answer .skel-line { width: min(60%, 16rem); height: 0.9rem; }
/* Le bouton de reservation ferme la carte: sans sa hauteur ici, l'arrivee des
   horaires pousserait tout ce qui suit d'un cran. */
.skel-answer .skel-cta { align-self: stretch; height: 2.6rem; border-radius: 999px; }

.trip .skel-time { width: 3.2rem; height: 1.2rem; }
.trip .skel-line { align-self: center; height: 1rem; }

/*
 * Changer de trajet va chercher un fragment sur le reseau. Ce qui reste a
 * l'ecran est celui d'avant: on cesse de l'affirmer, sans le jeter - le cache
 * repond souvent sans reseau, et un squelette de vingt millisecondes clignote
 * sans rien apprendre.
 */
#answer[aria-busy="true"],
.card[aria-busy="true"] {
  opacity: 0.55;
  transition: opacity 160ms ease-out;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  * { transition-duration: 1ms !important; animation-duration: 1ms !important; }
  /* L'encart ne tourne plus tout seul - app.js le sait aussi, et cesse de compter. Il ne
     reste que les deux pastilles, et le passage est net plutot que fondu. */
  .promo-vue { transition: none; }
  /* La regle universelle eteint la pulsation; l'attente doit rester lisible
     autrement, d'ou l'attenuation. Un seul bloc: deux se sont croises en
     fusion, et le premier venu decidait pour tout le reste. */
  #calendar[aria-busy='true'] .cal-day { animation: none; opacity: 0.6; }
}

/* Les definitions d'icones ne doivent occuper aucune place dans le flux. */
.defs { position: absolute; }

/* ---------- pages de trajet ---------- */

/* Hors accueil, la marque n'est plus le titre de la page mais le retour vers elle. */
.brand a {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  color: inherit;
  text-decoration: none;
}

.route-head {
  padding: 0.2rem 0 0.9rem;
}

.route-head h1 {
  margin: 0;
  font-size: 1.5rem;
  line-height: 1.2;
  letter-spacing: -0.02em;
}

/* Les liaisons voisines, au bas d'une page de trajet. Elles ne paraissent
   jamais sur l'accueil: c'est la place qu'on a voulu rendre. */
.related ul {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.related a {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  min-height: 36px;
  padding: 0.35rem 0.8rem;
  font-size: 0.85rem;
  color: var(--muted);
  text-decoration: none;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 999px;
}

.related a:hover { color: var(--ink); background: var(--accent-soft); }

.route-head p {
  margin: 0.35rem 0 0;
  color: var(--muted);
  font-size: 0.9rem;
}


/*
 * Ce qu'on ne sait pas encore. Discret par construction: c'est une precision,
 * pas un avertissement, et le lecteur pressé doit pouvoir la sauter.
 */
.unpublished {
  margin: 0.6rem 0.2rem 0;
  font-size: 0.84rem;
  line-height: 1.45;
  color: var(--muted);
}

/* Le voyage pour lequel le prix sera demande. Replie, il tient sur une ligne
   et ne pousse rien; ouvert, ses champs se rangent en grille qui se replie
   d'elle-meme au telephone. */
.voyage {
  margin: 0.75rem 0 0;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  font-size: 0.9rem;
}

.voyage summary {
  padding: 0.6rem 0.85rem;
  cursor: pointer;
  color: var(--muted);
}

.voyage summary #voyage-resume {
  color: var(--ink);
  font-weight: 600;
}

.voyage-corps {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: 0.6rem 1rem;
  padding: 0 0.85rem 0.85rem;
}

.voyage-corps label {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
}

/* Un libelle cache l'est vraiment: `display: flex` bat sinon la regle
   `[hidden]` du navigateur, et le champ de retour restait la sur un aller
   simple. */
.voyage-corps [hidden] {
  display: none;
}

.voyage-corps .voyage-ar {
  justify-content: flex-start;
}

.voyage-corps input[type='number'] {
  width: 4.5rem;
}

.voyage-corps input {
  padding: 0.35rem 0.5rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg);
  color: var(--ink);
  font: inherit;
  /* La case cochee et le jour retenu du calendrier natif sortaient en bleu
     systeme au milieu d'un site vert: une ligne les repeint, la ou refaire
     ces commandes a la main couterait leur accessibilite. */
  accent-color: var(--accent);
}

/* Les listes du panneau prennent l'allure des champs voisins: laissees a leur
   apparence d'usine, elles sortaient plus hautes et plus grises au milieu de la
   grille. La fleche reste celle du navigateur, qui la dessine mieux. */
.voyage-corps select {
  padding: 0.35rem 0.5rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg);
  color: var(--ink);
  font: inherit;
}

/* La case garde sa forme native, pas sa taille: 13 px de haut n'est pas une
   cible tactile. */
.voyage-corps input[type='checkbox'] {
  width: 1.15rem;
  height: 1.15rem;
  padding: 0;
  border: 0;
}

/* La date de retour ouvre le calendrier du site, pas celui du navigateur:
   celui-la est du chrome, qu'aucune feuille de style n'atteint. Le bouton se
   donne donc l'allure des autres champs du panneau. */
#voyage-date {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  cursor: pointer;
  padding: 0.35rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg);
  color: var(--ink);
  font: inherit;
}

#voyage-date .icon {
  color: var(--muted);
}

/* Rentrer avant d'etre parti ne se clique pas, et doit se voir: le navigateur
   ne ternit que le texte, ce que la couleur propre des cases annule - un jour
   desservi restait noir et se lisait comme choisissable. */
.cal-day[disabled] {
  opacity: 0.35;
  cursor: not-allowed;
}

/* Dans la modale le calendrier occupe toute la boite: la carte et sa marge
   sont celles de la modale, pas les siennes. */
#cal-modal .calendar {
  margin: 0;
  padding: 0;
}

.voyage-corps .voyage-quand {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
}
