/* Polices hebergees sur le domaine, plus chez Google : aucune adresse IP de
   visiteur ne part vers un tiers (point RGPD), la CSP n'a plus a autoriser
   fonts.googleapis.com, et l'app garde sa typographie hors ligne.
   Archivo et Familjen Grotesk sont sous licence SIL Open Font License 1.1.
   Sous-ensembles latin et latin-ext : tout le francais, accents compris. */

@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url(polices/archivo-normal-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url(polices/archivo-normal-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Familjen Grotesk';
  font-style: italic;
  font-weight: 400 700;
  font-display: swap;
  src: url(polices/familjengrotesk-italic-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Familjen Grotesk';
  font-style: italic;
  font-weight: 400 700;
  font-display: swap;
  src: url(polices/familjengrotesk-italic-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Familjen Grotesk';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url(polices/familjengrotesk-normal-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Familjen Grotesk';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url(polices/familjengrotesk-normal-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* Sortie bateau — Dinard, Côte d'Émeraude.
   Direction "Signal" : la réponse d'abord, en aplat plein écran. Vert on sort,
   marine on reste. Tout le reste vit dans un tiroir sombre qui remonte du bas. */

:root {
  /* autorise les transitions vers auto : sans ca, un repli s'ouvre en sautant */
  interpolate-size: allow-keywords;

  --bleu: 232;
  --vert: 168;

  --nuit:        oklch(0.148 0.030 var(--bleu));
  --nuit-creux:  oklch(0.212 0.038 var(--bleu));
  --nuit-relief: oklch(0.99 0.010 var(--bleu) / 0.06);
  --clair:       oklch(0.962 0.012 var(--bleu));
  --clair-doux:  oklch(0.835 0.024 var(--bleu));
  --clair-tenu:  oklch(0.690 0.026 var(--bleu));
  --filet:       oklch(0.95 0.014 var(--bleu) / 0.16);
  --filet-fin:   oklch(0.95 0.014 var(--bleu) / 0.09);

  --oui:         oklch(0.735 0.155 var(--vert));
  --vague:       oklch(0.615 0.120 var(--vert));
  /* Echelle du heros. On reste sur l'emeraude tant que la sortie est agreable,
     puis on bascule vers l'ambre quand elle devient penible. Le marine est
     reserve aux jours ou l'on ne sort pas : lui seul veut dire non. */
  --n-ideal:     oklch(0.760 0.165 var(--vert));
  --n-bon:       oklch(0.715 0.130 var(--vert));
  --n-moyen:     oklch(0.700 0.085 155);
  --n-mediocre:  oklch(0.755 0.105 78);
  --n-penible:   oklch(0.740 0.140 52);
  --n-inconnu:   oklch(0.660 0.030 var(--bleu));
  --oui-encre:   oklch(0.205 0.052 200);
  --oui-vif:     oklch(0.825 0.150 var(--vert));
  --non:         oklch(0.255 0.050 var(--bleu));

  --alerte:      oklch(0.745 0.145 38);
  --alerte-fond: oklch(0.745 0.145 38 / 0.13);

  --sp-2: 0.25rem; --sp-4: 0.5rem;  --sp-6: 0.75rem; --sp-8: 1rem;
  --sp-12: 1.5rem; --sp-16: 2rem;   --sp-24: 3rem;   --sp-32: 4rem;

  --titre: "Archivo", "Helvetica Neue", Arial, sans-serif;
  --sans: "Familjen Grotesk", "Helvetica Neue", Arial, sans-serif;
  --rayon: 20px;
  --sortie: cubic-bezier(0.16, 1, 0.3, 1);   /* décélération franche */
  --doux: cubic-bezier(0.25, 1, 0.5, 1);     /* plus feutré, pour les états */
}

* { box-sizing: border-box; }

html { background: var(--nuit); }

body {
  margin: 0;
  background: var(--nuit);
  color: var(--clair);
  font-family: var(--sans);
  font-size: 1.0625rem;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* L'app prenait 30 rem au maximum, centrees : sur une tablette ou un ordinateur,
   l'aplat de couleur s'arretait a 480 px et le heros devenait une carte flottant
   sur du sombre, alors que le principe "Signal" est la reponse en pleine page.
   Desormais les bandes vont d'un bord a l'autre et c'est le contenu qui reste
   dans une colonne lisible, centree par le padding lateral. */
:root { --colonne: 30rem; }
@media (min-width: 48rem) { :root { --colonne: 34rem; } }

.hero, .tiroir, .accueil {
  padding-inline: max(var(--sp-16), calc((100% - var(--colonne)) / 2));
}

/* ------------------------------------------------------------------ mouvement */

@keyframes surgit { from { opacity: 0; transform: translateY(28px); } }
@keyframes rideau { from { clip-path: inset(0 0 100% 0); transform: translateY(16px); } }
@keyframes glisse { from { opacity: 0; transform: translateX(24px); } }
@keyframes monte  { from { opacity: 0; transform: translateY(40px); } }
@keyframes respire { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: 0.4; transform: scale(0.78); } }

.surgit { animation: surgit 0.8s var(--sortie) both; }
.glisse { animation: glisse 0.85s var(--sortie) both; }

/* ---------------------------------------------------------------------- héros */

.hero {
  position: relative;
  overflow: hidden;
  min-height: 42svh;
  padding-block: max(var(--sp-24), env(safe-area-inset-top)) var(--sp-32);
  display: flex;
  flex-direction: column;
  background: var(--oui);
  color: var(--oui-encre);
  transition: background 0.6s var(--sortie), color 0.6s var(--sortie);
}
.hero[data-niveau="ideal"]    { background: var(--n-ideal); }
.hero[data-niveau="bon"]      { background: var(--n-bon); }
.hero[data-niveau="moyen"]    { background: var(--n-moyen); }
.hero[data-niveau="mediocre"] { background: var(--n-mediocre); }
.hero[data-niveau="penible"]  { background: var(--n-penible); }
.hero[data-niveau="inconnu"]  { background: var(--n-inconnu); color: var(--clair); }
.hero.non { background: var(--non); color: var(--clair); }
/* Le refus ne crie pas : le mot passe en retrait, la raison garde la pleine force. */
.hero.non .hero-mot { color: var(--clair-doux); opacity: 0.72; }
.hero.non .hero-mot-detail { margin-top: var(--sp-16); opacity: 1; max-width: 26ch; }
.hero.attente { background: var(--nuit-creux); color: var(--clair-tenu); min-height: 100svh; }

/* Une houle très lente au pied de l'aplat : le tiroir a l'air de flotter dessus.
   currentColor, donc elle suit le vert comme le marine sans code en double. */
.houle {
  position: absolute;
  left: -12%;
  bottom: 0;
  width: 124%;
  height: 78px;
  color: inherit;
  opacity: 0.1;
  pointer-events: none;
  animation: deriver 15s ease-in-out infinite alternate;
}
.houle + .houle {
  bottom: 6px;
  opacity: 0.07;
  animation-duration: 23s;
  animation-direction: alternate-reverse;
}
@keyframes deriver { to { transform: translateX(-58px); } }

/* Plus de ressort dans le heros. Il poussait le bloc en bas, ce qui creusait un
   trou variable au milieu ; le passer en haut ne faisait que deplacer le trou.
   Le contenu part donc du haut et le heros se dimensionne dessus, avec un simple
   plancher pour que l'aplat garde de la presence les jours a texte court. */
.hero-tete {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--sp-8);
  margin-bottom: var(--sp-12);
}

.place {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-4);
  min-height: 44px;
  padding: 0 var(--sp-6) 0 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  font-size: 0.6875rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  cursor: pointer;
  opacity: 0.75;
}
.place:hover { opacity: 1; }
.place:focus-visible { outline: 2px solid currentColor; outline-offset: 4px; border-radius: 6px; }
.place svg { flex: 0 0 auto; }

.direct {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-4);
  font-size: 0.6875rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  opacity: 0.72;
}
.direct i {
  width: 7px; height: 7px; border-radius: 50%;
  background: currentColor;
  animation: respire 4.5s ease-in-out infinite;
}

.hero-jour {
  margin: 0 0 var(--sp-8);
  font-size: 0.6875rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  opacity: 0.7;
}

.hero-mot {
  margin: 0;
  font-family: var(--titre);
  font-weight: 800;
  /* Ce n'est plus un mot d'ordre en capitales mais une phrase de verdict :
     elle passe a la ligne, et l'interligne laisse la place aux accents. */
  font-size: clamp(2.25rem, 12vw, 4rem);
  line-height: 0.98;
  letter-spacing: -0.035em;
  text-wrap: balance;
  max-width: 11ch;
  animation: rideau 1.05s var(--sortie) both;
}

.hero-heures {
  margin: var(--sp-16) 0 0;
  font-family: var(--titre);
  font-weight: 600;
  font-size: clamp(1.5rem, 7vw, 1.875rem);
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  animation: surgit 0.8s var(--sortie) 0.24s both;
}
.hero-suite {
  margin: var(--sp-2) 0 0;
  font-size: 0.9375rem;
  opacity: 0.72;
  font-variant-numeric: tabular-nums;
  animation: surgit 0.8s var(--sortie) 0.3s both;
}
.hero-mot-detail {
  margin: var(--sp-8) 0 0;
  font-size: 1.0625rem;
  line-height: 1.45;
  max-width: 24ch;
  opacity: 0.78;
  animation: surgit 0.8s var(--sortie) 0.34s both;
}

/* --------------------------------------------------------------------- tiroir */

.tiroir {
  position: relative;
  margin-top: -28px;
  border-radius: 30px 30px 0 0;
  background: var(--nuit);
  padding-block: var(--sp-24) calc(var(--sp-24) + env(safe-area-inset-bottom));
  display: flex;
  flex-direction: column;
  gap: 0;
  animation: monte 0.9s var(--sortie) 0.12s both;
}

/* Une rubrique : le titre porte la structure, le filet court jusqu'au bord.
   Plus d'aplats, plus de bandes — c'est la typographie qui segmente. */
.titret {
  display: flex;
  align-items: center;
  gap: var(--sp-6);
  margin: 0 0 var(--sp-12);
  font-family: var(--titre);
  font-size: 1.3125rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  text-transform: none;
  color: var(--clair);
}
.titret::after {
  content: "";
  flex: 1 1 auto;
  height: 1px;
  background: var(--filet);
}

/* Une section = un libellé, un filet au-dessus, de l'air autour. C'est ce
   découpage qui rend le tiroir lisible, pas des cartes empilées. */
.section { display: block; }
.section + .section,
.section + .replier,
.replier + .section { margin-top: var(--sp-32); }

/* Deux zones sortent du flux et prennent toute la largeur : la marée, qui est
   une image, et la semaine, qui est une barre de navigation. */
.graphe,
.semaine-bande { margin: var(--sp-32) 0 0; }
.graphe + .section,
.semaine-bande + .section,
.graphe + .replier,
.semaine-bande + .replier { margin-top: var(--sp-32); }

/* mesures */

.mesures { display: flex; gap: var(--sp-24); margin: 0; }
.mesures dd { color: var(--clair); }
.mesures div { display: grid; gap: 2px; }
.mesures dt {
  font-size: 0.625rem; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--clair-tenu);
}
.mesures dd {
  margin: 0;
  font-family: var(--titre);
  font-weight: 700;
  font-size: 1.375rem;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.mesures .val { font-weight: inherit; }
.mesures dd small { font-family: var(--sans); font-weight: 400; font-size: 0.6875rem; color: var(--clair-tenu); }

/* alertes */

.securite { margin: 0; padding: 0; list-style: none; display: grid; gap: var(--sp-4); }
.securite li {
  padding: var(--sp-6) var(--sp-8);
  border-radius: 14px;
  background: var(--alerte-fond);
  font-size: 0.875rem;
  line-height: 1.4;
  color: var(--clair-doux);
}
.securite li.moyenne { background: var(--nuit-relief); }
.securite b { color: var(--alerte); font-weight: 600; }
.securite li.moyenne b { color: var(--clair); }

/* où aller */

.dest { margin: 0; padding: 0; list-style: none; }
.dest li {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: baseline;
  gap: 0 var(--sp-6);
  min-height: 44px;
  padding: var(--sp-6) 0;
  border-bottom: 1px solid var(--filet-fin);
  opacity: 0;
  transform: translateX(22px);
  transition: opacity 0.6s var(--sortie), transform 0.6s var(--sortie);
}
/* .vu est posée par l'observateur de défilement : les lignes arrivent quand on
   descend dessus, pas au rendu alors qu'elles sont hors écran.

   Transition et non @keyframes : l'état final est le style déclaré ici, donc une
   animation qui ne démarre pas laisse quand même la ligne lisible. Avec un
   fill: both, elle serait restée bloquée sur son état de départ, invisible. */
.dest li.vu { opacity: 1; transform: none; }
.dest .nom { font-family: var(--titre); font-weight: 600; font-size: 1.0625rem; line-height: 1.25; }
.dest .quand {
  font-size: 0.8125rem; color: var(--oui-vif);
  font-variant-numeric: tabular-nums; text-align: right; white-space: nowrap;
}
.dest .dist { grid-column: 1 / -1; font-size: 0.75rem; color: var(--clair-tenu); }
.dest li { cursor: pointer; }
.dest li:focus-visible { outline: 2px solid var(--oui-vif); outline-offset: 4px; border-radius: 8px; }
.dest .mot {
  grid-column: 1 / -1;
  margin: var(--sp-6) 0 var(--sp-2);
  font-size: 0.875rem;
  line-height: 1.5;
  color: var(--clair-doux);
  max-width: 44ch;
}
.dest li[aria-expanded="false"] .nom::after {
  content: "";
  display: inline-block;
  width: 0.4em; height: 0.4em;
  margin-left: 0.5em;
  border-right: 1.5px solid var(--clair-tenu);
  border-bottom: 1.5px solid var(--clair-tenu);
  transform: translateY(-0.15em) rotate(45deg);
}

.perimee {
  margin: 0 0 var(--sp-24);
  padding: var(--sp-6) var(--sp-8);
  border-radius: 12px;
  background: var(--nuit-creux);
  font-size: 0.875rem;
  color: var(--clair-doux);
}

.plus {
  margin-top: var(--sp-8);
  min-height: 44px;
  padding: var(--sp-4) 0;
  border: 0; background: none;
  color: var(--oui-vif);
  font: inherit; font-size: 0.875rem;
  cursor: pointer;
  text-decoration: underline; text-underline-offset: 4px;
}
.plus:focus-visible { outline: 2px solid var(--oui-vif); outline-offset: 3px; }

/* engagement */

.note-cle {
  margin: 0;
  padding: var(--sp-8) var(--sp-12);
  border-radius: var(--rayon);
  background: var(--nuit-relief);
  font-size: 0.9375rem;
  color: var(--clair-doux);
}
.note-cle b { color: var(--clair); font-variant-numeric: tabular-nums; }

/* semaine */

.semaine {
  display: flex;
  justify-content: space-between;
  gap: var(--sp-2);
  margin: 0 calc(-1 * var(--sp-4));
}
.semaine-bande { padding: 0; }
.pastille[aria-selected="true"] {
  background: var(--nuit-creux);
  color: var(--clair);
  box-shadow: inset 0 0 0 1px var(--filet);
}
.pastille {
  flex: 1 1 0;
  display: grid;
  gap: var(--sp-6);
  justify-items: center;
  align-content: center;
  min-height: 60px;
  padding: var(--sp-4) 0;
  border: 0; border-radius: 14px;
  background: none;
  color: var(--clair-tenu);
  font: inherit;
  cursor: pointer;
  transition: background 0.25s var(--sortie), color 0.25s var(--sortie);
}
.pastille:hover { background: var(--nuit-relief); }
.pastille:focus-visible { outline: 2px solid var(--oui-vif); outline-offset: 2px; }
.pastille span { font-size: 0.75rem; }
.pastille i {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--filet);
  transition: background 0.25s var(--sortie), transform 0.25s var(--sortie);
}
.pastille.ouvert i { background: var(--oui-vif); }
.pastille[aria-selected="true"] { background: var(--nuit-creux); color: var(--clair); }
.pastille[aria-selected="true"] i { transform: scale(1.5); }

/* le détail */

.replier { margin: 0; }
.replier > summary {
  list-style: none;
  min-height: 44px;
  display: flex;
  align-items: center;
  cursor: pointer;
  font-size: 0.875rem;
  color: var(--clair-tenu);
}
.replier > summary::-webkit-details-marker { display: none; }
.replier > summary::after { content: " ▾"; margin-left: 0.35em; font-size: 0.8em; }
.replier[open] > summary::after { content: " ▴"; }
.replier > summary:focus-visible { outline: 2px solid var(--oui-vif); outline-offset: 3px; border-radius: 6px; }
.replier-corps { padding-top: var(--sp-8); animation: surgit 0.5s var(--sortie) both; }

.precisions { margin-top: var(--sp-12); }
.bornes { margin: 0 0 var(--sp-4); font-size: 1rem; color: var(--clair-doux); }
.bornes:last-child { margin-bottom: 0; }
.bornes b { color: var(--clair); font-weight: 600; font-variant-numeric: tabular-nums; }
.recousu { margin: var(--sp-8) 0 0; font-size: 0.8125rem; color: var(--clair-tenu); font-style: italic; }

/* La marée est une section à part entière, pas une vignette : elle a son titre,
   sa respiration, et un tracé assez grand pour se lire d'un coup d'œil. */
.graphe { padding: 0; }
.graphe figcaption { margin: 0 0 var(--sp-12); }
.graphe-svg { margin: 0; }
.graphe-svg text { font-family: var(--sans); }
.graphe-svg svg { display: block; width: 100%; height: auto; }
.graphe-mot {
  margin: var(--sp-12) 0 0;
  font-size: 0.9375rem;
  line-height: 1.5;
  color: var(--clair-doux);
  max-width: 40ch;
}

/* sorties suivantes */

.titret.second { margin-top: var(--sp-16); }
.sortie-suivante {
  margin: var(--sp-6) 0 0;
  font-family: var(--titre);
  font-weight: 600;
  font-size: 1.25rem;
  font-variant-numeric: tabular-nums;
  color: var(--oui-vif);
}
.sortie-suivante small {
  display: block;
  font-family: var(--sans); font-weight: 400; font-size: 0.9375rem;
  color: var(--clair-doux);
  margin-top: var(--sp-2);
}

/* réglages */

.reglages {
  display: grid;
  gap: var(--sp-12);
  padding: var(--sp-12);
  border-radius: var(--rayon);
  background: var(--nuit-creux);
  animation: surgit 0.5s var(--sortie) both;
}
.champ { display: grid; gap: var(--sp-2); margin: 0; }
.champ label {
  font-size: 0.625rem; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--clair-tenu);
}
.champ input {
  font: inherit;
  min-height: 48px;
  padding: var(--sp-6) var(--sp-8);
  border: 1px solid var(--filet);
  border-radius: 12px;
  background: var(--nuit);
  color: var(--clair);
}
.champ input:focus-visible { outline: 2px solid var(--oui-vif); outline-offset: 1px; }
.champ.erreur input { border-color: var(--alerte); }
.champ small { font-size: 0.75rem; color: var(--clair-tenu); }
.reglages-note { margin: 0; font-size: 0.8125rem; color: var(--clair-tenu); }
.reglages-note b { color: var(--clair-doux); font-variant-numeric: tabular-nums; }

/* pied */

.pied {
  margin-top: var(--sp-24);
  border-top: 1px solid var(--filet-fin);
  padding-top: var(--sp-12);
  font-size: 0.75rem;
  line-height: 1.6;
  color: var(--clair-tenu);
}
.pied p { margin: 0 0 var(--sp-4); }
.avertissement { max-width: 46ch; }

/* L'entrée complète ne se joue qu'au premier chargement. Rejouer la révélation à
   chaque changement de jour donnerait une app lente à manipuler : au deuxième rendu,
   la transition de vue fait seule le raccord, et tout le reste est déjà en place. */

/* Les recommandations sont déjà sous les yeux quand on change de jour : elles ne
   doivent pas repartir de la droite. */
.rapide .dest li { opacity: 1; transform: none; transition: none; }

/* Le tracé de marée ne se redessine pas non plus : deux secondes de mise en scène
   par-dessus le fondu de la transition, c'est ce qui rendait le passage confus. */
.rapide .graphe-svg .trace { stroke-dashoffset: 0; }
.rapide .graphe-svg .trace,
.rapide .graphe-svg .aire,
.rapide .graphe-svg .seuil,
.rapide .graphe-svg .repere,
.rapide .graphe-svg .axe,
.rapide .graphe-svg .plage,
.rapide .graphe-svg .barre,
.rapide .graphe-svg .creux,
.rapide .graphe-svg .borne,
.rapide .graphe-svg .legende { animation: none; }
.rapide .graphe-svg .maintenant { animation: battre 4.5s ease-in-out infinite; }

/* Le héros est déjà pris en charge par la transition de vue : lui laisser en plus
   ses animations d'entrée revenait à jouer deux fois le même mouvement, l'un sur
   l'instantané, l'autre sur l'élément réel une fois la transition finie. */
.rapide .hero-mot,
.rapide .hero-heures,
.rapide .hero-suite,
.rapide .hero-mot-detail,
.rapide .tiroir { animation: none; }

.rapide .replier-corps,
.rapide .reglages {
  animation-duration: 0.28s;
  animation-delay: 0s;
}

@media (min-width: 40rem) {
  .hero { min-height: 56svh; }
}

/* ------------------------------------------------- changement de jour

   Le geste le plus repete de l'app. L'API View Transitions fait le raccord :
   l'aplat fond d'une couleur a l'autre pendant que le mot d'etat bascule
   verticalement, comme un compteur mecanique. Les navigateurs qui ne
   l'implementent pas retombent sur un rendu direct, sans rien casser. */

.hero { view-transition-name: aplat; }
.hero-mot { view-transition-name: mot; }
.hero-heures { view-transition-name: heures; }
.hero-jour { view-transition-name: jour; }

::view-transition-group(root) { animation-duration: 0.34s; }

/* Le fond de la pastille selectionnee est un seul objet nomme : le navigateur
   le fait glisser d'un jour a l'autre au lieu de le teleporter. */
::view-transition-group(jour-actif) { animation-duration: 0.42s; animation-timing-function: var(--sortie); }
::view-transition-old(jour-actif),
::view-transition-new(jour-actif) { animation-duration: 0.2s; }

::view-transition-old(mot) { animation: mot-part 0.24s var(--doux) both; }
::view-transition-new(mot) { animation: mot-vient 0.42s var(--sortie) both; }
@keyframes mot-part  { to { opacity: 0; transform: translateY(-26px); } }
@keyframes mot-vient { from { opacity: 0; transform: translateY(30px); } }

::view-transition-old(heures),
::view-transition-old(jour) { animation: bref-part 0.2s var(--doux) both; }
::view-transition-new(heures),
::view-transition-new(jour) { animation: bref-vient 0.36s var(--sortie) 0.06s both; }
@keyframes bref-part  { to { opacity: 0; transform: translateY(-12px); } }
@keyframes bref-vient { from { opacity: 0; transform: translateY(14px); } }

/* --------------------------------------------------- tracé de la marée

   La courbe se dessine dans l'ordre du temps, de 0 h a 24 h : on voit la
   journee se derouler. Les reperes, la plage de sortie et la barre
   d'embarquement suivent, pour que l'oeil lise dans le bon ordre. */

.graphe-svg .trace {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  animation: tracer 1s var(--doux) 0.28s both;
}
@keyframes tracer { to { stroke-dashoffset: 0; } }

.graphe-svg .aire { animation: paraitre 0.7s var(--sortie) 0.9s both; }
.graphe-svg .seuil { animation: paraitre 0.5s var(--sortie) 1.05s both; }
.graphe-svg .repere { animation: paraitre 0.45s var(--sortie) both; }
.graphe-svg .axe { animation: paraitre 0.5s var(--sortie) 0.15s both; }
@keyframes paraitre { from { opacity: 0; } }

.graphe-svg .plage,
.graphe-svg .barre,
.graphe-svg .creux {
  transform-box: fill-box;
  transform-origin: left center;
  animation: ouvrir 0.6s var(--sortie) both;
}
@keyframes ouvrir { from { transform: scaleX(0); opacity: 0.4; } }

.graphe-svg .borne {
  transform-box: fill-box;
  transform-origin: bottom center;
  animation: dresser 0.45s var(--sortie) both;
}
@keyframes dresser { from { transform: scaleY(0); } }

.graphe-svg .legende { animation: paraitre 0.5s var(--sortie) both; }

.graphe-svg .maintenant {
  transform-box: fill-box;
  transform-origin: top center;
  animation: dresser 0.5s var(--sortie) 1.15s both, battre 4.5s ease-in-out 1.7s infinite;
}
@keyframes battre { 0%, 100% { opacity: 0.5; } 50% { opacity: 0.16; } }

/* ------------------------------------------------------ retour au toucher */

.pastille, .plus, .place, .replier > summary {
  transition: transform 0.14s var(--doux), background 0.25s var(--sortie),
              color 0.25s var(--sortie), opacity 0.2s var(--doux);
}
.pastille:active { transform: scale(0.93); }
.plus:active, .place:active { transform: scale(0.97); }
.replier > summary:active { transform: scale(0.985); }
.pastille:active i { transform: scale(1.7); }

/* le repli s'ouvre en hauteur au lieu de sauter */
.replier::details-content {
  block-size: 0;
  overflow: hidden;
  transition: block-size 0.34s var(--sortie), content-visibility 0.34s allow-discrete;
}
.replier[open]::details-content { block-size: auto; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
  .graphe-svg .maintenant { animation: none !important; opacity: 0.5; }
  .houle { animation: none !important; }
  .dest li { opacity: 1; transform: none; }
  ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) {
    animation: none !important;
  }
}

/* urgences : pied de page, deux boutons et la position */

.urgences { margin-top: var(--sp-24); }
.appels { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-4); }
.appel {
  display: grid;
  gap: 2px;
  padding: var(--sp-6);
  border-radius: 16px;
  border: 1px solid var(--filet);
  background: oklch(0.95 0.014 var(--bleu) / 0.05);
  text-decoration: none;
  transition: transform 0.18s var(--doux), background 0.18s var(--doux);
}
.appel:active { transform: scale(0.96); }
.appel-quoi {
  font-size: 0.6875rem; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--clair-tenu);
}
.appel-num {
  font-family: var(--titre); font-weight: 700; font-size: 1rem;
  font-variant-numeric: tabular-nums; color: var(--clair);
}
.appel-vhf {
  font-family: var(--titre); font-weight: 600; font-size: 0.75rem;
  letter-spacing: 0.04em; color: var(--clair-tenu);
}
.appel.rouge { border-color: oklch(0.745 0.145 38 / 0.4); background: var(--alerte-fond); }
.appel.rouge .appel-num, .appel.rouge .appel-vhf { color: var(--alerte); }

.position {
  width: 100%;
  margin-top: var(--sp-4);
  padding: var(--sp-6);
  border-radius: 16px;
  border: 1px dashed var(--filet);
  background: none;
  font-family: var(--sans);
  font-size: 0.9375rem;
  color: var(--clair-doux);
  cursor: pointer;
  transition: transform 0.18s var(--doux), color 0.18s var(--doux);
}
.position:active { transform: scale(0.97); }
.position[disabled] { opacity: 0.5; cursor: default; }
.position-coord {
  display: flex; flex-wrap: wrap; gap: var(--sp-4);
  margin: var(--sp-6) 0 0;
}
.position-coord b {
  font-family: var(--titre); font-weight: 700; font-size: 1.0625rem;
  font-variant-numeric: tabular-nums; color: var(--clair);
}
.position-mot {
  margin: var(--sp-4) 0 0;
  font-size: 0.875rem; color: var(--clair-tenu);
}

/* accueil : premier lancement, tant qu'on ne sait rien de l'usager.

   Depouille, comme le reste de l'app. Une premiere version avait une lueur en
   fond, des etapes numerotees, un mot colore dans le titre, une ombre portee et
   une fleche sur le bouton : de l'ornement plaque sur une app qui tient justement
   par son absence d'ornement. Tout est parti. Il reste le logo, une question, une
   phrase, deux cartes, un champ, une reponse. */

.accueil {
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  padding-block: max(var(--sp-16), env(safe-area-inset-top)) var(--sp-24);
  background: var(--non);
  overflow: hidden;
}
.accueil-tete { position: relative; margin-bottom: var(--sp-32); }
.accueil-corps, .accueil-ok { position: relative; }

/* les houles de fond : trois couches, trois vitesses, trois amplitudes */
.houles {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: min(46svh, 380px);
  color: var(--oui);
  overflow: hidden;          /* les couches font 128 % de large : on les coupe ici */
  pointer-events: none;
  mask-image: linear-gradient(to bottom, transparent, #000 42%);
}
.houle-fond {
  position: absolute;
  left: -32%;
  width: 164%;
  height: 100%;
  will-change: transform;
}
/* Une derive seule ne se voit pas : 58 px en 19 s sur une forme a 5 % d'opacite,
   l'oeil ne l'attrape pas. On y ajoute une respiration verticale, qui fait bouger
   la ligne de crete elle-meme, la ou le glissement horizontal ne changeait que
   des courbes toutes pareilles. */
@keyframes houler {
  from { transform: translate3d(0, 10px, 0) scaleY(0.94); }
  to   { transform: translate3d(-90px, -14px, 0) scaleY(1.08); }
}
.houle-fond { transform-origin: bottom center; }
.houle-fond.h1 { opacity: 0.16; animation: houler 9s ease-in-out infinite alternate; }
.houle-fond.h2 { opacity: 0.11; bottom: -22px; animation: houler 13s ease-in-out 0.6s infinite alternate-reverse; }
.houle-fond.h3 { opacity: 0.08; bottom: -46px; animation: houler 17s ease-in-out 1.2s infinite alternate; }

/* l'entree se fait en cascade : le titre, la phrase, les cartes, puis le reste */
.accueil-corps > *, .accueil-ok { animation: surgit 0.7s var(--sortie) both; }
.accueil-corps > *:nth-child(1) { animation-delay: 0.05s; }
.accueil-corps > *:nth-child(2) { animation-delay: 0.12s; }
.accueil-corps > *:nth-child(3) { animation-delay: 0.19s; }
.accueil-corps > *:nth-child(4) { animation-delay: 0.26s; }
.accueil-corps > *:nth-child(5) { animation-delay: 0.33s; }
.accueil-ok { animation-delay: 0.4s; }
.accueil-corps { flex: 1; display: grid; align-content: center; gap: var(--sp-12); }

.accueil-titre {
  margin: 0;
  font-family: var(--titre);
  font-weight: 800;
  font-size: clamp(2.25rem, 10vw, 3.25rem);
  line-height: 1;
  letter-spacing: -0.03em;
  text-wrap: balance;
  color: var(--clair);
}
.accueil-mot {
  margin: calc(var(--sp-8) * -1) 0 0;
  max-width: 38ch;
  font-size: 1.0625rem;
  line-height: 1.5;
  color: var(--clair-doux);
}
.accueil-calc {
  margin: 0;
  max-width: 40ch;
  font-size: 0.9375rem;
  line-height: 1.5;
  color: var(--clair-doux);
}
.accueil-calc b { color: var(--oui-vif); font-weight: 600; font-variant-numeric: tabular-nums; }

.accueil-ok {
  min-height: 56px;
  margin-top: var(--sp-12);
  border: 0;
  border-radius: 16px;
  background: var(--oui);
  font-family: var(--titre);
  font-weight: 700;
  font-size: 1.0625rem;
  color: var(--nuit);
  cursor: pointer;
  transition: transform 0.16s var(--doux), opacity 0.2s var(--doux);
}
.accueil-ok:active { transform: scale(0.98); }
.accueil-ok[disabled] { opacity: 0.25; cursor: default; }

/* respirations entre les blocs d'une meme section */

/* l'encadre d'engagement suit l'explication du graphe, il ne s'y colle pas */
.graphe .note-cle { margin-top: var(--sp-12); }

/* les horaires conseilles ne touchent pas la premiere destination */
.precisions + .dest,
.precisions + .bornes { margin-top: var(--sp-12); }

/* le panneau de reglages est un bloc a part : il ne colle pas au titre suivant */
.reglages + * { margin-top: var(--sp-32); }

/* la semaine porte les memes nuances que le heros : un jour penible et un jour
   ideal ne peuvent pas se ressembler dans la bande des sept jours */
.pastille[data-niveau="ideal"] i    { background: var(--n-ideal); }
.pastille[data-niveau="bon"] i      { background: var(--n-bon); }
.pastille[data-niveau="moyen"] i    { background: var(--n-moyen); }
.pastille[data-niveau="mediocre"] i { background: var(--n-mediocre); }
.pastille[data-niveau="penible"] i  { background: var(--n-penible); }
.pastille[data-niveau="inconnu"] i  { background: var(--n-inconnu); }

/* le banc de sable ferme la section "Pour sortir", apres les destinations */
.dest + .banc, .plus + .banc, .bornes + .banc { margin-top: var(--sp-12); }

/* fenetre courte : pas d'aplat sombre, un contour dans l'encre du heros.
   Visible sur n'importe quelle couleur, sans casser la teinte du jour. */
.hero-court {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-4);
  align-self: flex-start;
  margin: var(--sp-6) 0 0;
  padding: var(--sp-4) var(--sp-6);
  border: 2px solid currentColor;
  border-radius: 999px;
  font-family: var(--titre);
  font-weight: 800;
  font-size: 0.8125rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  animation: surgit 0.8s var(--sortie) 0.28s both;
}
.hero-court b {
  letter-spacing: 0.02em;
  font-variant-numeric: tabular-nums;
  opacity: 0.72;
}
.rapide .hero-court { animation: none; }

/* choix du type de mouillage, a l'accueil */
.genre { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-4); }
.genre-choix {
  display: grid; gap: 2px; justify-items: start;
  padding: var(--sp-6);
  border: 1px solid var(--filet);
  border-radius: 16px;
  background: none;
  color: var(--clair-doux);
  text-align: left;
  cursor: pointer;
  transition: transform 0.16s var(--doux), border-color 0.2s var(--doux),
              background 0.2s var(--doux);
}
.genre-choix b { font-family: var(--titre); font-weight: 700; font-size: 0.9375rem; color: var(--clair); }
.genre-choix small { font-size: 0.75rem; line-height: 1.3; color: var(--clair-tenu); }
.genre-choix:active { transform: scale(0.97); }
.genre-choix.actif {
  border-color: var(--oui);
  background: oklch(0.735 0.155 var(--vert) / 0.12);
}
.genre-choix.actif b { color: var(--oui-vif); }
/* `display: grid` sur .accueil-champs battait l'attribut hidden */
[hidden] { display: none !important; }

/* retour a l'ecran de depart, depuis le tiroir de reglages */
.reprendre {
  justify-self: start;
  padding: var(--sp-4) 0;
  border: 0;
  background: none;
  font: inherit;
  font-size: 0.9375rem;
  color: var(--oui-vif);
  text-decoration: underline;
  text-underline-offset: 4px;
  cursor: pointer;
}
.reprendre:active { opacity: 0.6; }

/* le logo : marque + nom, cliquable dans le heros pour revenir au depart */

.logo {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-4);
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  text-align: left;
  cursor: pointer;
  transition: transform 0.16s var(--doux), opacity 0.2s var(--doux);
}
span.logo { cursor: default; }
.logo:active { transform: scale(0.96); }
.logo-marque { display: block; flex: none; border-radius: 9px; }
.logo-mot {
  display: grid;
  font-family: var(--titre);
  font-weight: 700;
  font-size: 0.9375rem;
  line-height: 1.05;
  letter-spacing: -0.01em;
}
.logo-mot small {
  font-weight: 600;
  font-size: 0.625rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  opacity: 0.62;
}
/* la place rejoint la ligne de date */
.hero-jour {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  flex-wrap: wrap;
}
.hero-jour .place {
  min-height: 0;
  gap: 3px;
  padding: 3px var(--sp-4) 3px 6px;
  border: 1px solid currentColor;
  border-radius: 999px;
  font-size: 0.625rem;
  letter-spacing: 0.14em;
  opacity: 0.8;
}
.hero-jour .place:active { transform: scale(0.95); }

/* Sur l'aplat, la marque perd son carre emeraude (invisible sur du vert) et ne
   garde que la houle, dans l'encre du jour. */
.hero .logo-marque rect { fill: currentColor; opacity: 0.14; }
.hero .logo-marque path:first-of-type { fill: currentColor; opacity: 0.34; }
.hero .logo-marque path:last-of-type { fill: currentColor; opacity: 0.9; }


/* ------------------------------------------------- l'ambiance du jour

   Le heros prend l'humeur de la meteo : une couche sous le texte, choisie par
   `data-ciel`. Un seul motif a la fois, jamais deux superposes. Tout en
   `transform` et `opacity`, donc rien qui fasse recalculer la page. */

.ciel {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  /* `color: inherit` et pas `--oui-encre` : l'encre sombre se posait aussi sur
     l'aplat marine des jours fermes, sombre sur sombre, donc invisible. En
     heritant, la couche prend l'encre du jour, foncee sur l'emeraude et claire
     sur le marine. */
  color: inherit;
}

/* soleil : un halo qui respire, haut a droite, comme une lumiere rasante.
   Un disque plein et des rayons tournants ont ete essayes puis retires : sur un
   aplat de couleur pleine page, un soleil dessine fait vignette meteo la ou le
   heros doit rester un signal. */
.ciel.soleil i {
  position: absolute;
  top: -30%; right: -20%;
  width: 82%; aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle, currentColor 0%, transparent 68%);
  opacity: 0.22;
  animation: respirer-halo 6s ease-in-out infinite alternate;
}
@keyframes respirer-halo {
  from { transform: scale(0.78) translate(4%, 4%); opacity: 0.13; }
  to   { transform: scale(1.14) translate(-3%, -3%); opacity: 0.30; }
}

/* vent : des filets horizontaux qui traversent, decales dans le temps */
.ciel.vent i {
  position: absolute;
  left: -40%;
  top: calc(10% + var(--r) * 17%);
  width: 60%;
  height: 5px;
  border-radius: 5px;
  background: linear-gradient(90deg, transparent, currentColor 45%, transparent);
  animation: filer 3.4s linear infinite;
  animation-delay: calc(var(--r) * -0.68s);
}
@keyframes filer {
  from { transform: translateX(0) scaleX(0.6); opacity: 0; }
  20%  { opacity: 0.34; }
  80%  { opacity: 0.34; }
  to   { transform: translateX(230%) scaleX(1.25); opacity: 0; }
}

/* pluie : trois nappes de traits obliques, a trois vitesses */
.ciel.pluie i {
  position: absolute;
  inset: -20% -10%;
  background-image: repeating-linear-gradient(74deg,
    currentColor 0 1.5px, transparent 1.5px 20px);
  opacity: 0.13;
  animation: tomber 1.5s linear infinite;
}
.ciel.pluie i:nth-child(2) { opacity: 0.08; animation-duration: 2.2s; background-size: 130% 130%; }
.ciel.pluie i:nth-child(3) { opacity: 0.05; animation-duration: 3s;   background-size: 165% 165%; }
@keyframes tomber { to { transform: translate3d(-19px, 66px, 0); } }

/* voile : deux nappes tres larges qui glissent lentement, un ciel couvert */
.ciel.voile i {
  position: absolute;
  left: -30%; right: -30%;
  top: -10%; height: 60%;
  border-radius: 50%;
  background: radial-gradient(ellipse at 50% 50%, currentColor 0%, transparent 62%);
  opacity: 0.14;
  animation: glisser-voile 12s ease-in-out infinite alternate;
}
.ciel.voile i:nth-child(2) {
  top: 12%; height: 48%;
  opacity: 0.10;
  animation-duration: 17s;
  animation-direction: alternate-reverse;
}
@keyframes glisser-voile {
  from { transform: translateX(-22%) scale(0.92); }
  to   { transform: translateX(22%) scale(1.16); }
}

/* Houle : pas une couche de plus, c'est celle du pied qui grossit.

   Premiere version : plus opaque et plus RAPIDE. Contresens. Rapide et petit,
   c'est du clapot de vent ; la houle est lente et ample, longue periode. Les
   vagues grandissent donc au lieu d'accelerer, tout le plan d'eau se souleve sur
   9 secondes, et un roulis de moins d'un degre, decale, evite le simple
   mouvement vertical. */
.hero[data-ciel="houle"] .houle {
  height: 150px;
  opacity: 0.2;
  transform-origin: bottom center;
  animation: lever 4.4s ease-in-out infinite alternate;
}
.hero[data-ciel="houle"] .houle + .houle {
  height: 128px;
  bottom: 0;
  opacity: 0.14;
  animation: lever 6.2s ease-in-out -2.1s infinite alternate-reverse;
}
/* Une version "cassante" a ete essayee puis retiree : cycle asymetrique, crete
   penchee au `skewX`, effondrement rapide. Le mouvement du deferlement etait la,
   mais il agitait le fond d'un ecran qu'on lit, et le heros doit rester calme.
   On garde la respiration ample et symetrique, simplement plus rapide. */
@keyframes lever {
  from { transform: translate3d(-16px, 18px, 0) scaleY(0.68) rotate(-0.6deg); }
  to   { transform: translate3d(16px, -24px, 0) scaleY(1.34) rotate(0.7deg); }
}

@media (prefers-reduced-motion: reduce) {
  .ciel { display: none; }
}

/* avis : le jour affiche en clair, les jours suivants dans un bandeau d'une ligne */
.avis-jour { display: grid; gap: var(--sp-4); }
.avis-plus { margin: 0; }
.avis-plus > summary {
  display: flex; align-items: center; gap: var(--sp-4);
  padding: var(--sp-4) 0;
  list-style: none;
  font-size: 0.875rem;
  color: var(--clair-tenu);
  cursor: pointer;
}
.avis-plus > summary::-webkit-details-marker { display: none; }
.avis-plus > summary::before {
  content: "";
  width: 6px; height: 6px; flex: none;
  border-radius: 50%;
  background: var(--alerte);
  opacity: 0.8;
}
.avis-plus > summary::after {
  content: "▾";
  font-size: 0.6875rem;
  transition: transform 0.2s var(--doux);
}
.avis-plus[open] > summary::after { transform: rotate(180deg); }
.avis-plus .securite { margin-top: var(--sp-4); }
.avis-jour + *, .avis-plus + * { margin-top: var(--sp-24); }

/* sans JavaScript : un texte lisible plutot qu'un ecran vide (et du contenu pour
   les robots qui n'executent pas le script) */
.sans-js {
  padding: var(--sp-24) var(--sp-16);
  max-width: var(--colonne);
  margin: 0 auto;
  color: var(--clair-doux);
  line-height: 1.5;
}
.sans-js h1 { font-family: var(--titre); font-size: 2rem; color: var(--clair); margin: 0 0 var(--sp-8); }

/* page des mentions legales */
.legal {
  max-width: 40rem;
  margin: 0 auto;
  padding: max(var(--sp-16), env(safe-area-inset-top)) var(--sp-16) var(--sp-32);
  color: var(--clair-doux);
  font-size: 1rem;
  line-height: 1.6;
}
.legal h1 { font-family: var(--titre); font-weight: 800; font-size: clamp(2rem, 8vw, 2.75rem);
  line-height: 1; letter-spacing: -0.03em; color: var(--clair); margin: var(--sp-16) 0 var(--sp-4); }
.legal h2 { font-family: var(--titre); font-weight: 700; font-size: 1.125rem; color: var(--clair);
  margin: var(--sp-24) 0 var(--sp-4); }
.legal p, .legal ul { margin: 0 0 var(--sp-6); }
.legal ul { padding-left: 1.2em; }
.legal li { margin-bottom: var(--sp-4); }
.legal b { color: var(--clair); font-weight: 600; }
.legal a { color: var(--oui-vif); text-underline-offset: 3px; }
.legal-maj { font-size: 0.875rem; color: var(--clair-tenu); }
.legal-retour { font-size: 0.9375rem; text-decoration: none; }
.pied-legal { margin-top: var(--sp-6); font-size: 0.8125rem; }
.pied-legal a { color: var(--clair-tenu); text-underline-offset: 3px; }
