/* Graphe de vérification.
   Palette catégorielle validée pour les deux modes (voir docs/adr/0006).
   Les couleurs sont posées en CSS et non en JavaScript : le mode sombre bascule
   sans rien recalculer, et une série garde sa teinte quand on en masque d'autres. */

.viz {
  --viz-surface: #ffffff;
  --viz-ink: #0b0b0b;
  --viz-ink-2: #52514e;
  --viz-muted: #898781;
  --viz-grille: #e1e0d9;
  --viz-axe: #c3c2b7;

  --serie-1: #2a78d6;
  --serie-2: #eb6834;
  --serie-3: #1baf7a;
  --serie-4: #eda100;
  --serie-5: #e87ba4;
  --serie-6: #008300;

  position: relative;
  margin-top: 1rem;
}

@media (prefers-color-scheme: dark) {
  :root:where(:not([data-theme="light"])) .viz {
    --viz-surface: #14161a;
    --viz-ink: #ffffff;
    --viz-ink-2: #c3c2b7;
    --viz-muted: #898781;
    --viz-grille: #2c2c2a;
    --viz-axe: #383835;

    --serie-1: #3987e5;
    --serie-2: #d95926;
    --serie-3: #199e70;
    --serie-4: #c98500;
    --serie-5: #d55181;
    --serie-6: #008300;
  }
}
:root[data-theme="dark"] .viz {
  --viz-surface: #14161a;
  --viz-ink: #ffffff;
  --viz-ink-2: #c3c2b7;
  --viz-muted: #898781;
  --viz-grille: #2c2c2a;
  --viz-axe: #383835;

  --serie-1: #3987e5;
  --serie-2: #d95926;
  --serie-3: #199e70;
  --serie-4: #c98500;
  --serie-5: #d55181;
  --serie-6: #008300;
}

/* Barre de commandes : une seule rangée, au-dessus du graphe. */
.viz-commandes {
  display: flex; flex-wrap: wrap; gap: .5rem; align-items: center;
  margin-bottom: .75rem;
}
.viz-commandes .groupe { display: flex; gap: .25rem; }
.viz-commandes button {
  font: inherit; font-size: .82rem; padding: .3rem .65rem; cursor: pointer;
  border: 1px solid var(--viz-axe); background: transparent; color: var(--viz-ink-2);
  border-radius: 8px;
}
.viz-commandes button[aria-pressed="true"] {
  border-color: var(--accent); color: var(--accent); font-weight: 600;
}
.viz-commandes .indice { font-size: .8rem; color: var(--viz-muted); margin-left: auto;
                         min-width: 0; }
@media (max-width: 560px) {
  .viz-commandes .indice { margin-left: 0; flex-basis: 100%; }
}

.viz-cadre { position: relative; touch-action: pan-y; }
.viz svg { width: 100%; height: auto; display: block; cursor: crosshair; }

.viz-grille-ligne { stroke: var(--viz-grille); stroke-width: 1; }
.viz-axe-ligne { stroke: var(--viz-axe); stroke-width: 1; }
.viz-graduation { fill: var(--viz-muted); font-size: 11px; font-variant-numeric: tabular-nums; }
.viz-graduation.y { text-anchor: end; }
.viz-graduation.x { text-anchor: middle; }

.viz-serie { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.viz-serie.observe { stroke: var(--viz-ink); stroke-width: 2.6; }
.viz-serie.s1 { stroke: var(--serie-1); }
.viz-serie.s2 { stroke: var(--serie-2); }
.viz-serie.s3 { stroke: var(--serie-3); }
.viz-serie.s4 { stroke: var(--serie-4); }
.viz-serie.s5 { stroke: var(--serie-5); }
.viz-serie.s6 { stroke: var(--serie-6); }

/* Mode bandes : une rangée par série, colorée aux heures de pluie annoncée. */
.viz-bande-fond { fill: var(--viz-grille); opacity: .45; }
.viz-bande-nom { fill: var(--viz-ink-2); font-size: 12px; text-anchor: end; }
.viz-bande.observe { fill: var(--viz-ink); }
.viz-bande.s1 { fill: var(--serie-1); }
.viz-bande.s2 { fill: var(--serie-2); }
.viz-bande.s3 { fill: var(--serie-3); }
.viz-bande.s4 { fill: var(--serie-4); }
.viz-bande.s5 { fill: var(--serie-5); }
.viz-bande.s6 { fill: var(--serie-6); }

.viz-tableau td.pluvieux { font-weight: 650; color: var(--viz-ink); }

.viz-curseur { stroke: var(--viz-axe); stroke-width: 1; pointer-events: none; }
.viz-point { stroke: var(--viz-surface); stroke-width: 2; pointer-events: none; }
.viz-selection { fill: var(--accent); opacity: .14; pointer-events: none; }

/* Infobulle : la valeur domine, le nom de la série suit. */
.viz-bulle {
  position: absolute; pointer-events: none; z-index: 5;
  background: var(--viz-surface); color: var(--viz-ink);
  border: 1px solid var(--viz-axe); border-radius: 8px;
  padding: .5rem .65rem; font-size: .82rem; min-width: 9.5rem;
  box-shadow: 0 4px 14px rgba(0,0,0,.12);
  opacity: 0; transition: opacity .12s;
}
.viz-bulle[data-visible="true"] { opacity: 1; }
.viz-bulle .quand { color: var(--viz-muted); font-size: .76rem; margin-bottom: .35rem; }
.viz-bulle table { width: 100%; border-collapse: collapse; }
.viz-bulle td { padding: .1rem 0; border: 0; }
.viz-bulle .valeur {
  text-align: right; font-weight: 650; font-variant-numeric: tabular-nums;
  color: var(--viz-ink); padding-left: .6rem;
}
.viz-bulle .nom { color: var(--viz-ink-2); }
.viz-bulle .cle { display: inline-block; width: 12px; height: 2px; margin-right: .4rem;
                  vertical-align: middle; border-radius: 1px; }

/* Légende : bascule l'affichage d'une série. */
.viz-legende { list-style: none; display: flex; flex-wrap: wrap; gap: .4rem;
               padding: 0; margin: .75rem 0 0; }
.viz-legende button {
  display: flex; align-items: center; gap: .4rem; cursor: pointer;
  font: inherit; font-size: .82rem; color: var(--viz-ink-2);
  background: transparent; border: 1px solid transparent; border-radius: 6px;
  padding: .2rem .5rem;
}
.viz-legende button:hover { border-color: var(--viz-axe); }
.viz-legende button[aria-pressed="false"] { opacity: .45; text-decoration: line-through; }
.viz-legende .cle { width: 14px; height: 3px; border-radius: 2px; }
.viz-legende .cle.observe { background: var(--viz-ink); height: 4px; }
.viz-legende .cle.s1 { background: var(--serie-1); }
.viz-legende .cle.s2 { background: var(--serie-2); }
.viz-legende .cle.s3 { background: var(--serie-3); }
.viz-legende .cle.s4 { background: var(--serie-4); }
.viz-legende .cle.s5 { background: var(--serie-5); }
.viz-legende .cle.s6 { background: var(--serie-6); }

/* Vue tableau : rend chaque valeur atteignable sans survol, et lève
   l'avertissement de contraste des teintes claires. */
.viz-tableau { margin-top: 1rem; font-size: .82rem; }
.viz-tableau summary { cursor: pointer; color: var(--viz-ink-2); }
.viz-tableau .defilable { max-height: 22rem; overflow: auto; margin-top: .6rem; }
.viz-tableau table { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; }
.viz-tableau th, .viz-tableau td {
  padding: .3rem .5rem; text-align: right; border-bottom: 1px solid var(--viz-grille);
  white-space: nowrap;
}
.viz-tableau th:first-child, .viz-tableau td:first-child { text-align: left; }
.viz-tableau thead th { position: sticky; top: 0; background: var(--viz-surface);
                        color: var(--viz-muted); font-weight: 600; }

.viz-vide { color: var(--viz-muted); font-size: .9rem; }

@media (forced-colors: active) {
  .viz-serie { stroke: CanvasText; }
  .viz-legende button[aria-pressed="false"] { opacity: 1; }
}

/* ---------------------------------------------------------------------------
   Graphe climat : le nuage des années, la droite ajustée, son incertitude.

   Deux séries seulement, et ce ne sont pas deux identités interchangeables mais
   deux grandeurs physiques : le maximum du jour et le minimum de la nuit. On
   reprend donc la paire chaud/froid des cartes de conditions (ADR 0007) plutôt
   que la palette catégorielle des modèles, qui ferait lire « série 1, série 2 »
   là où il faut lire « le jour, la nuit ».

   Paire vérifiée pour le daltonisme : ΔE protanope 19,3 en clair, 20,4 en sombre,
   très au-dessus du plancher de 8. Le mode sombre a ses propres valeurs, plus
   sombres et non plus claires : c'est la bande de luminosité utilisable sur fond
   noir qui l'impose. */
.viz.climat {
  --maxi: #bd512c;
  --mini: #2f6cad;
}

@media (prefers-color-scheme: dark) {
  :root:where(:not([data-theme="light"])) .viz.climat {
    --maxi: #d97648;
    --mini: #5695d8;
  }
}
:root[data-theme="dark"] .viz.climat {
  --maxi: #d97648;
  --mini: #5695d8;
}

.climat-point { fill: var(--teinte); opacity: .5; }
.climat-point.maxi { --teinte: var(--maxi); }
.climat-point.mini { --teinte: var(--mini); }

.climat-droite {
  fill: none;
  stroke: var(--teinte);
  stroke-width: 2.5;
  stroke-linecap: round;
}
.climat-droite.maxi { --teinte: var(--maxi); }
.climat-droite.mini { --teinte: var(--mini); }

/* Le prolongement se distingue par la forme et non par la couleur seule : un
   lecteur qui ne perçoit pas la teinte doit voir qu'on a quitté le mesuré. */
.climat-droite.prolongee { stroke-dasharray: 7 5; opacity: .85; }

.climat-bande { fill: var(--teinte); opacity: .13; stroke: none; }
.climat-bande.maxi { --teinte: var(--maxi); }
.climat-bande.mini { --teinte: var(--mini); }

.climat-frontiere { stroke: var(--viz-axe); stroke-width: 1; stroke-dasharray: 3 3; }
.climat-frontiere-texte { fill: var(--viz-muted); font-size: 11px; }

.climat-curseur { stroke: var(--viz-axe); stroke-width: 1; }
.climat-halo { fill: none; stroke: var(--viz-surface); stroke-width: 2.5; }

.viz-legende .cle.maxi { background: var(--maxi); }
.viz-legende .cle.mini { background: var(--mini); }

.viz .mention { font-size: .82rem; color: var(--viz-muted); }

/* ---------------------------------------------------------------------------
   Cycle annuel : une courbe par année, du 1er janvier au 31 décembre.

   Ici la couleur encode le *temps*, une grandeur ordonnée — donc une rampe
   séquentielle d'une seule teinte, et non la palette catégorielle. La teinte
   est celle de l'accent de l'interface, délibérément non thermique : reprendre
   le chaud du graphe précédent ferait croire que la couleur dit la température,
   alors que c'est la hauteur de la courbe qui la dit.

   Rampes vérifiées en mode ordinal : luminosité monotone, écarts de paliers
   visibles, extrémité pâle à 2,87:1 sur fond clair et 2,90:1 sur fond sombre.

   Les paliers intermédiaires ne sont pas énumérés : color-mix interpole entre
   les deux bornes selon --age, que le script pose sur chaque courbe. Les
   couleurs restent ainsi en CSS, seule la position vient de la donnée. */
.viz.cycle {
  --cycle-ancien: #a08ccc;
  --cycle-recent: #412876;
}

@media (prefers-color-scheme: dark) {
  :root:where(:not([data-theme="light"])) .viz.cycle {
    --cycle-ancien: #6b57a0;
    --cycle-recent: #cdc6f8;
  }
}
:root[data-theme="dark"] .viz.cycle {
  --cycle-ancien: #6b57a0;
  --cycle-recent: #cdc6f8;
}

/* Le fond du graphe : toutes les années, presque effacées. Elles ne sont pas
   décoratives — c'est leur épaisseur collective qui montre l'étendue de ce
   qu'une année peut faire, et sans elles les décennies sembleraient régulières. */
.cycle-annee {
  fill: none;
  stroke: var(--viz-ink);
  stroke-width: 1;
  opacity: .07;
}

/* Sur fond sombre le nuage est clair, donc plus lumineux que le bas de la rampe :
   sans cette atténuation, les décennies anciennes passeraient derrière le bruit
   qu'elles sont censées surplomber. */
@media (prefers-color-scheme: dark) {
  :root:where(:not([data-theme="light"])) .cycle-annee { opacity: .045; }
}
:root[data-theme="dark"] .cycle-annee { opacity: .045; }

.cycle-repere {
  fill: none;
  stroke: color-mix(in oklab, var(--cycle-recent) calc(var(--age) * 100%), var(--cycle-ancien));
  stroke-width: 2;
  stroke-linejoin: round;
  stroke-linecap: round;
}

/* L'année en cours se distingue par l'épaisseur autant que par la teinte : elle
   reste repérable pour qui ne perçoit pas la nuance du haut de la rampe. */
.cycle-repere.courante { stroke-width: 3.4; }

.cycle-etiquette {
  fill: var(--viz-ink);
  font-size: 12px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.cycle-jour-choisi { stroke: var(--viz-axe); stroke-width: 1; stroke-dasharray: 3 3; }
.cycle-jour-texte { fill: var(--viz-muted); font-size: 11px; }

/* Vaut pour la légende comme pour la bulle de survol : les deux vivent sous
   .viz.cycle et doivent porter la même teinte que la courbe qu'elles désignent. */
.viz.cycle .cle.decennie {
  background: color-mix(in oklab, var(--cycle-recent) calc(var(--age) * 100%), var(--cycle-ancien));
}

/* ---------------------------------------------------------------------------
   Franchissements de seuils : trois comptages sur un axe commun.

   Un seul axe parce qu'une seule unité — des jours par an. Jamais deux échelles
   sur un même graphe : c'est la façon la plus sûre de faire dire n'importe quoi
   à deux courbes.

   Trois teintes ordonnées du froid au très chaud, vérifiées toutes paires
   confondues : ΔE deutéranope 11,8 en clair, 11,6 en sombre, très au-dessus du
   plancher de 8. Le magenta pour la forte chaleur plutôt qu'un second orange :
   deux teintes chaudes ne tiennent pas à distance suffisante dans la bande de
   luminosité utilisable sur fond noir. */
.viz.seuils {
  --gel: #2f6cad;
  --ete: #c9761c;
  --chaleur: #a8296b;
}

@media (prefers-color-scheme: dark) {
  :root:where(:not([data-theme="light"])) .viz.seuils {
    --gel: #5695d8;
    --ete: #b87b2a;
    --chaleur: #c9497f;
  }
}
:root[data-theme="dark"] .viz.seuils {
  --gel: #5695d8;
  --ete: #b87b2a;
  --chaleur: #c9497f;
}

.seuil-serie { fill: none; stroke: var(--teinte); stroke-width: 1.4; opacity: .5; }
.seuil-droite { fill: none; stroke: var(--teinte); stroke-width: 2.6; stroke-linecap: round; }
.seuil-point { fill: var(--teinte); }
.seuil-serie.gel, .seuil-droite.gel, .seuil-point.gel { --teinte: var(--gel); }
.seuil-serie.ete, .seuil-droite.ete, .seuil-point.ete { --teinte: var(--ete); }
.seuil-serie.chaleur, .seuil-droite.chaleur, .seuil-point.chaleur { --teinte: var(--chaleur); }

.viz.seuils .cle.gel { background: var(--gel); }
.viz.seuils .cle.ete { background: var(--ete); }
.viz.seuils .cle.chaleur { background: var(--chaleur); }

/* ---------------------------------------------------------------------------
   Saison sans gel : une ligne par année, les périodes de gel possible aux deux
   bouts. C'est le chenal libre au milieu qui porte le message, donc c'est le
   gel qu'on peint — le vide se lit tout seul. */
.viz.gel { --gelee: #2f6cad; }

@media (prefers-color-scheme: dark) {
  :root:where(:not([data-theme="light"])) .viz.gel { --gelee: #5695d8; }
}
:root[data-theme="dark"] .viz.gel { --gelee: #5695d8; }

.gel-segment { fill: var(--gelee); opacity: .55; }
.gel-decennie { stroke: var(--viz-grille); stroke-width: 1; }
.gel-annee-texte { fill: var(--viz-muted); font-size: 10px; }

/* ---------------------------------------------------------------------------
   Records : deux séries appariées par décennie, rapportées à 1,00.

   La paire chaud/froid est celle du premier graphe — même sens, même teintes,
   pour qu'un lecteur qui a parcouru la page n'ait pas à réapprendre. */
.viz.records { --chaud: #bd512c; --froid: #2f6cad; }

@media (prefers-color-scheme: dark) {
  :root:where(:not([data-theme="light"])) .viz.records {
    --chaud: #d97648;
    --froid: #5695d8;
  }
}
:root[data-theme="dark"] .viz.records { --chaud: #d97648; --froid: #5695d8; }

.record-barre.chaleur { fill: var(--chaud); }
.record-barre.froid { fill: var(--froid); }
.records-bruit { fill: var(--viz-ink); opacity: .06; }
.records-reference { stroke: var(--viz-axe); stroke-width: 1.4; }
.records-reference-texte { fill: var(--viz-muted); font-size: 11px; }

.viz.records .cle.chaleur { background: var(--chaud); }
.viz.records .cle.froid { background: var(--froid); }
