/* =========================================================================
   UST — LES SCHÉMAS, dessins construits sur la donnée.
   Ils sont écrits par inc/schemas.php à partir des JSON de inc/donnees.

   Aucune valeur littérale de couleur, de durée ni de graisse : tout descend
   de tokens.css. Aucun survol non gardé.

   POURQUOI UN FICHIER À PART. Les schémas sont une famille de composants
   entière, avec sa palette, ses ancrages et ses requêtes de conteneur. Servie
   dans composants.css, elle en doublait la taille et noyait la graduation,
   qui est l'élément signature. Elle a son fichier, comme pages.css a le sien.

   PALETTE, ET POURQUOI C'EST CELLE DE LA GRADUATION.
   Un schéma n'est pas un ornement : c'est le geste de la graduation à deux
   dimensions. Il en reprend donc la palette jeton pour jeton — --filet-haut
   pour le cadre et la piste, --texte pour la donnée tracée, --gradue pour les
   repères — et il en reprend la discipline d'accent : --lampe ne paraît qu'au
   titre d'INDEX, sur le seul point que le dessin est fait pour lire (loi
   d'accent n° 2). Un schéma, un index, jamais deux.

   LE TEXTE N'EST JAMAIS DANS LE SVG. Il se mettrait à l'échelle avec le
   dessin, et serait lu 7 px à 390 ou 29 px à 1440. Les étiquettes sont du
   HTML ancré par --x et --y au-dessus du dessin, exactement comme
   .grad__seuils ancre les seuils de la graduation : elles gardent Martian
   Mono, l'échelle --d-mono et leur contraste à toutes les largeurs.
   ========================================================================= */
.sch {
  margin: 0;
  display: flex; flex-direction: column; gap: var(--e-5);
  /* Un schéma est son propre contexte de requête : ses seuils de mise en page
     suivent SA largeur, pas celle de la fenêtre. */
  container-type: inline-size;
  /* Un tracé de 1 240 px de large n'est pas plus lisible, il est plus long à
     parcourir des yeux. La mesure d'un schéma est celle d'une prose longue. */
  max-width: var(--etroit);
}
.sch__legende { display: flex; flex-direction: column; gap: var(--e-3); }
.sch__legende p { color: var(--champ); font-size: var(--d-petit); max-width: 62ch; }
.sch__sources { color: var(--gradue); }
.sch__sources .lien { font-size: inherit; }

/* --- La boîte de tracé, commune aux schémas à axes ----------------------- */
.sch__boite { display: flex; flex-direction: column; gap: var(--e-2); }
.sch__axe-x,
.sch__axe-y { color: var(--label); max-width: none; }
.sch__cadre {
  position: relative;
  aspect-ratio: 16 / 9;
  border-left: 1px solid var(--filet-haut);
  border-bottom: 1px solid var(--filet-haut);
}
@container (max-width: 26rem) { .sch__cadre { aspect-ratio: 4 / 3; } }
.sch__dessin { position: absolute; inset: 0; display: block; width: 100%; height: 100%; }

/* Les étiquettes ancrées. Même mécanique que .grad__seuils : l'ancrage glisse
   de gauche à droite avec la position, si bien qu'aucune ne déborde du puits. */
.sch__etiquettes { position: relative; display: block; width: 100%; max-width: none; color: var(--gradue); }
.sch__etiquettes span { position: absolute; white-space: nowrap; }
.sch__etiquettes--x,
.sch__etiquettes--haut { min-height: var(--grad-ligne); }
.sch__etiquettes--x span,
.sch__etiquettes--haut span,
.sch__etiquettes--bas span {
  top: 0; left: calc(var(--x) * 100%);
  transform: translateX(calc(var(--x) * -100%));
}
/* Les longueurs d'onde de l'éclairage public se resserrent entre 546 et
   589 nm : leurs étiquettes se lisent sur deux lignes, chacune sous son
   trait. Aucune n'est retirée. */
.sch__etiquettes--bas { min-height: calc(2 * var(--grad-ligne)); }
.sch__etiquettes--bas span:nth-child(2n) { top: var(--grad-ligne); }
/* Sous 26 rem, les quatre poses de la série se toucheraient : même remède. */
@container (max-width: 26rem) {
  .sch__etiquettes--x { min-height: calc(2 * var(--grad-ligne)); }
  .sch__etiquettes--x span:nth-child(2n) { top: var(--grad-ligne); }
}
/* Les paliers du rapport, posés à l'intérieur du cadre contre son bord
   gauche : ils n'y coûtent aucune gouttière et ne croisent jamais la courbe,
   qui passe sous eux. */
.sch__etiquettes--y { position: absolute; inset: 0; }
.sch__etiquettes--y span {
  left: var(--e-1); bottom: calc(var(--y) * 100%);
  transform: translateY(-2px);
}

/* --- 1. L'échelle d'empilement ------------------------------------------ */
.sch__grille { stroke: var(--filet);      stroke-width: 1; }
.sch__tige   { stroke: var(--filet-haut); stroke-width: 1; stroke-dasharray: 2 4; }
.sch__courbe { stroke: var(--texte);      stroke-width: 2; }
.sch__index  { stroke: var(--lampe);      stroke-width: var(--grad-index); }

.sch__points { position: absolute; inset: 0; list-style: none; margin: 0; padding: 0; }
.sch__point {
  position: absolute; width: 9px; height: 9px; border-radius: var(--r-pill);
  left: calc(var(--x) * 100%); bottom: calc(var(--y) * 100%);
  transform: translate(-50%, 50%);
  background: var(--texte);
}
/* La pose faite à un autre filtre est creuse : elle est sur la courbe du
   temps, elle n'est pas comparable en image. Le dessin l'avoue, la note sous
   le schéma le dit en toutes lettres. */
.sch__point--autre { background: var(--nuit); box-shadow: inset 0 0 0 2px var(--texte); }
.sch__point--index { background: var(--lampe); box-shadow: var(--ombre-index); }
.sch__etoile { color: var(--lampe); font-weight: var(--g-mono-fort); }

.sch__bulle {
  position: absolute; white-space: nowrap; color: var(--texte);
  font-weight: var(--g-mono-fort); max-width: none;
  left: calc(var(--x) * 100%); bottom: calc(var(--y) * 100% + var(--e-2));
  /* À cheval sur l'index, l'étiquette croisait la courbe : mesuré à 1440, la
     courbe passait derrière ses trois derniers caractères. Elle est posée à
     gauche de l'index, dans le quadrant que la courbe a déjà quitté. */
  transform: translateX(calc(-100% - var(--e-1)));
}

/* --- 2. Les champs de vision --------------------------------------------
   Une vignette par appareil, toutes au même cadre et à la même échelle :
   c'est ce partage qui les rend comparables. Celles dont le constructeur ne
   publie pas de champ en largeur et hauteur restent en place, vides. */
.sch__vignettes {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: var(--e-4);
  grid-template-columns: repeat(auto-fit, minmax(min(9rem, 100%), 1fr));
}
.sch__vignette { display: flex; flex-direction: column; gap: var(--e-1); min-width: 0; }
.sch__vue {
  display: block; width: 100%; height: auto;
  background: var(--ciel); border: 1px solid var(--filet); border-radius: var(--r-s);
}
.sch__champ { fill: none; stroke: var(--texte); stroke-width: 1.5; }
.sch__champ--absent { stroke: var(--filet-haut); stroke-dasharray: 5 5; }
/* L'ÉTALON, et l'unique index de ce schéma : le disque de la pleine Lune. */
.sch__lune { fill: var(--lampe-nuit); stroke: var(--lampe); stroke-width: 1.5; }
.sch__nom { font-size: var(--d-h4); line-height: var(--i-titre); max-width: none; }
.sch__valeur { color: var(--texte); font-weight: var(--g-mono-fort); max-width: none; }
.sch__muet { color: var(--label); max-width: none; }
.sch__vignette--muette .sch__valeur { color: var(--label); font-weight: var(--g-mono); }

/* --- 3. Le duo-bande ----------------------------------------------------
   Deux rangées sur le même axe de longueurs d'onde. Ce qui passe est en
   --texte, ce qui est coupé retombe au filet, et les deux fenêtres du filtre
   sont l'index : seul emploi de --lampe ici. */
.sch--duo .sch__boite { gap: var(--e-1); }
.sch__rangee-nom { color: var(--label); max-width: none; margin-top: var(--e-2); }
/* La rangée est une BARRE, pas une surface : à 36 px de haut, la rangée
   « sans filtre » devenait un aplat clair de la largeur de la colonne, ce que
   la loi n° 3 de la palette interdit (aucune surface claire, nulle part). À
   20 px elle a la densité d'une piste de graduation, et les raies de
   l'éclairage public s'y lisent comme des traits, pas comme des césures. */
.sch__rangee { position: relative; height: 1.25rem; }
.sch__spectre { display: block; width: 100%; height: 100%; }
.sch__passe { fill: var(--texte); }
.sch__coupe { fill: var(--filet); }
.sch__fenetre { fill: var(--lampe); }
.sch__tick { stroke: var(--gradue); stroke-width: 1; }
.sch__etiquettes--haut { color: var(--texte); }

/* --- 4. Le parc de l'auteur ---------------------------------------------
   Un carré, un objet du catalogue ; une trame identique sur toutes les
   lignes, si bien que leurs longueurs se comparent. Le zéro garde sa ligne
   et sa trame (G5) : une ligne vide est un appareil non testé, pas un
   mauvais appareil. */
.sch__parc { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--e-4); }
.sch__rang { display: flex; flex-direction: column; gap: var(--e-1); }
.sch__trame { display: block; width: 100%; height: auto; }
.sch__case { fill: none; stroke: var(--filet-haut); stroke-width: 1; }
.sch__case--pleine { fill: var(--texte); stroke: none; }
.sch__rang.est-vide .sch__case { stroke: var(--filet); }
.sch__rang.est-vide .sch__nom { color: var(--label); }
.sch__compte {
  display: flex; flex-wrap: wrap; gap: var(--e-1) var(--e-3);
  color: var(--label); max-width: none;
}
.sch__objets { color: var(--texte); font-weight: var(--g-mono-fort); }
