/* ══════════════════════════════════════════════════
   Simulation pédagogique — Physique-Chimie Lycée
   Auteur  : Mathieu Berdous
   Licence : CC BY-NC 4.0 — https://creativecommons.org/licenses/by-nc/4.0/
══════════════════════════════════════════════════ */

/* ══════════════════════════════════════════════════
   style.css — Simulation propagation onde sonore
══════════════════════════════════════════════════ */

/* ── Reset & base ────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0,0,0,0);
  white-space: nowrap;
  border: 0;
}

body {
  font-family: 'Segoe UI', Arial, sans-serif;
  background: #e8e4de;
  color: #2c3e50;
  /* dvh : suit la hauteur réellement visible (barres dynamiques du navigateur) ;
     vh reste le repli pour les navigateurs sans support dvh. */
  height: 100vh;
  max-height: 100vh;
  height: 100dvh;
  max-height: 100dvh;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

/* ── Grille principale ───────────────────────────── */
main {
  flex: 1;
  display: grid;
  grid-template-columns: 1fr clamp(200px, 22vw, 300px);
  min-height: 0;
  max-height: 100%;
  overflow: hidden;
}

/* ══════════════════════════════════════════════════
   COLONNE GAUCHE
══════════════════════════════════════════════════ */

#left-col {
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
}

/* ── Zone animation ─────────────────────────────────────────────────
   Grid 2 colonnes × 2 lignes :
     col 1 = largeur de la box source (fixe)
     col 2 = 1fr (canvas tube)
     row 1 = auto → zone boutons balises, à la hauteur des boutons
     row 2 = 1fr  → box source + canvas
   Garantit que les boutons balises sont toujours DANS la row 1,
   le canvas toujours dans la row 2 : aucune superposition possible.
   La row 1 était à `minmax(min-content, 10%)` : une piste minmax prend son
   maximum dès que la place existe, donc 10 % de la hauteur — soit ~60 px
   réservés à des boutons qui en font 34 sur une grande zone d'animation.
   `auto` donne exactement leur hauteur, le reste revient au canvas ; la
   séparation des deux zones est assurée par la grille, pas par ce 10 %.
──────────────────────────────────────────────────────────────────── */
#anim-area {
  /* Échelle de la colonne source, pilotée par tube.js (_applySourceScale).
     1 = tailles d'origine ; en dessous, la box source et le chronomètre
     rapetissent continûment, largeur de colonne comprise. */
  --src-s: 1;
  flex: 3;
  display: grid;
  grid-template-columns: calc(clamp(132px, 15vw, 212px) * var(--src-s)) 1fr;
  grid-template-rows: auto minmax(0, 1fr);
  min-height: 0;
  overflow: hidden;
  background: #fdf8f0;
  border-right: 1px solid #c8c0b4;
}

/* ── Colonne source retirée ──────────────────────────────────────────
   En dessous de SRC_S_MIN (cf. tube.js), la colonne ne serait plus ni lisible
   ni cliquable : plutôt que de la laisser rapetisser jusqu'à l'inutile, on la
   retire — et la colonne de grille avec elle, si bien que le canvas occupe
   toute la largeur. C'est le comportement voulu d'une zone d'animation réduite
   à une bande : une corde pleine largeur, et les contrôles retrouvés dès qu'on
   redonne de la hauteur à la zone.
   Déclaré AVANT .vagues-layout, qui redéfinit la grille pour son propre compte
   et doit garder la priorité à spécificité égale. ─────────────────────────── */
#anim-area.src-hidden {
  grid-template-columns: 0 1fr;
}
#anim-area.src-hidden #source-col {
  display: none;
}

/* Cellule vide ligne 1 / col 1 (au-dessus de la source) */
#anim-source-spacer {
  grid-column: 1;
  grid-row: 1;
}

/* ── Chronomètre — box propre, au-dessus de la source ─────────────────
   Une box par onglet, même gabarit pour toutes (cf. index.html) : le style
   passe donc par des CLASSES, les ids ne servant plus qu'à désigner la box
   d'un onglet et ses champs pour le module générique de ui.js.
   Habillage métal gris/noir repris du pot vibrant / de la membrane dessinés
   sur le canvas (mêmes gris bleutés #8a9aaa → #4a5a6a, contour #3a4a58).
   Afficheur clair (valeur + unité) sur la première ligne, commandes sur la
   seconde : marche/zéro à gauche, bascule d'unité s/T à droite. */
.chrono-box {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 100%;
  margin-bottom: 8px;   /* marge entre le chrono et la box source */
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding: clamp(5px, 0.6vw, 8px);
  background: linear-gradient(#8a9aaa 0%, #6a7a8a 45%, #4a5a6a 100%);
  border: 1px solid #3a4a58;
  border-radius: 8px;
  box-shadow: 0 2px 6px rgba(0,0,0,0.22),
              inset 0 1px 0 rgba(200,220,230,0.35);
}

/* Afficheur : nombre en gros (lisible au vidéoprojecteur) + unité.
   Légèrement creusé dans le boîtier (ombre interne). */
.chrono-display {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 4px;
  padding: 2px 5px;
  background: #eef2f4;
  border: 1px solid #2e3c48;
  border-radius: 4px;
  box-shadow: inset 0 1px 3px rgba(20,30,40,0.35);
}
.chrono-value {
  font-variant-numeric: tabular-nums;
  font-size: clamp(21px, 2.6vw, 36px);
  font-weight: 700;
  line-height: 1.1;
  color: #16222c;
  white-space: nowrap;
}
.chrono-unit-lbl {
  font-size: clamp(16px, 2vw, 27px);
  font-weight: 600;
  color: #55636e;
}

/* Ligne de commandes : marche/zéro puis « Lier » à gauche, bascule d'unité
   à droite. Tout tient sur UNE ligne quelle que soit la largeur de colonne :
   les commandes rétrécissent (clamp) au lieu de passer à la ligne. */
.chrono-ctrl {
  display: flex;
  align-items: center;
  gap: clamp(2px, 0.3vw, 4px);
}

/* Case « Lier » : déclenchement du chrono à l'activation de la source */
.chrono-link {
  display: flex;
  align-items: center;
  gap: 3px;
  font-size: clamp(9px, 1.05vw, 14px);
  font-weight: 600;
  color: #eaf1f5;
  white-space: nowrap;
  cursor: pointer;
  user-select: none;
}
.chrono-link input {
  flex: 0 0 auto;
  width: clamp(10px, 1.1vw, 13px);
  height: clamp(10px, 1.1vw, 13px);
  margin: 0;
  accent-color: #3a6ea5;
  cursor: pointer;
}

/* Bascule s / T : deux demi-boutons accolés, calés à droite */
.chrono-units {
  display: flex;
  flex: 0 0 auto;
  margin-left: auto;
  border: 1px solid #2e3c48;
  border-radius: 5px;
  overflow: hidden;
}

/* Flex + line-height 1 : le glyphe est centré par la boîte, pas par les
   métriques de la police (les chasses de « s », « T », « ▶ » et « ⟲ »
   diffèrent trop pour se fier au centrage de texte par défaut).
   min-width identique pour que les deux moitiés de la bascule soient
   de même largeur quelle que soit la lettre. */
.chrono-unit {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: clamp(15px, 1.9vw, 28px);
  height: clamp(15px, 1.9vw, 22px);   /* + les 2 bordures du conteneur = hauteur des boutons */
  padding: 0;
  font-size: clamp(9px, 1.05vw, 14px);
  font-family: inherit;
  font-weight: 700;
  line-height: 1;
  color: #e6eef2;
  background: rgba(20,30,40,0.28);
  border: none;
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}
.chrono-unit + .chrono-unit { border-left: 1px solid #2e3c48; }
.chrono-unit:hover:not(:disabled):not(.active) { background: rgba(20,30,40,0.45); }
/* Unité sélectionnée : pastille claire, comme une touche allumée */
.chrono-unit.active {
  background: #eef2f4;
  color: #22303c;
}
.chrono-unit:disabled { opacity: 0.35; cursor: default; }

/* Marche/arrêt et remise à zéro : deux boutons-icônes en métal clair */
.chrono-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: clamp(19px, 2.3vw, 30px);
  height: clamp(17px, 2.1vw, 24px);
  padding: 0;
  font-size: clamp(10px, 1.15vw, 14px);
  font-family: inherit;
  line-height: 1;
  color: #1e2a34;
  background: linear-gradient(#c0d0da, #9aabb8);
  border: 1px solid #2e3c48;
  border-radius: 5px;
  cursor: pointer;
  transition: filter 0.15s, transform 0.1s;
}
.chrono-btn:hover { filter: brightness(1.08); }
.chrono-btn:active { transform: scale(0.92); }
.chrono-btn.running {
  background: linear-gradient(#f0c88a, #e0a44e);
  border-color: #8a5518;
  color: #4a2c08;
}

/* Icône marche/arrêt : SVG plutôt que les glyphes ▶/⏸, dont le rendu par
   la police emoji décale visiblement le symbole dans le bouton. */
.chrono-ico {
  display: block;
  width: clamp(9px, 1.15vw, 13px);
  height: clamp(9px, 1.15vw, 13px);
  fill: currentColor;
}

/* Boutons balises : ligne 1 / col 2 — alignés en bas à droite */
#tube-top-btns {
  grid-column: 2;
  grid-row: 1;
  display: flex;
  flex-direction: row;
  justify-content: flex-end;
  align-items: flex-end;
  gap: 5px;
  padding: 4px 6px 4px;
}

/* Colonne chronomètre + source : ligne 2 / col 1.
   Seule la box source occupe le flux, de sorte qu'elle reste centrée
   verticalement exactement comme avant l'ajout du chronomètre ; celui-ci
   est posé juste au-dessus, en absolu. */
#source-col {
  grid-column: 1;
  grid-row: 2;
  align-self: center;
  position: relative;
  min-width: 0;
  /* Largeur de mise en page FIXE, indépendante de --src-s : c'est elle qui
     rend la hauteur naturelle de la colonne invariante (cf. le commentaire de
     l'échelle plus bas). La largeur d'origine de la colonne de grille, moins
     les deux marges. */
  width: calc(clamp(132px, 15vw, 212px) - 12px);
  margin: 0 calc(6px * var(--src-s));
  /* Origine à gauche : la box réduite occupe alors exactement la colonne de
     grille, elle-même multipliée par le facteur — et reste centrée
     verticalement, l'origine étant à mi-hauteur.
     Le débordement en hauteur qui subsiste côté MISE EN PAGE (la hauteur de
     layout, elle, ne diminue pas) n'est jamais rogné : ce qui est peint est
     plus petit, et centré. */
  transform: scale(var(--src-s));
  transform-origin: left center;
}

/* Box source */
#source-box {
  display: flex;
  flex-direction: column;
  gap: 7px;
  padding: clamp(7px, 0.8vw, 12px) clamp(7px, 0.8vw, 11px);
  background: #e8e4de;
  border: 1px solid #c8c0b4;
  border-radius: 8px;
  box-shadow: 0 2px 6px rgba(0,0,0,0.07);
}

/* ── Échelle de la colonne source ────────────────────────────────────
   Un seul `transform: scale()`, piloté par tube.js (_applySourceScale), plutôt
   qu'un facteur multipliant une à une les tailles de police, marges et
   hauteurs de ces deux boîtes.

   La différence n'est pas cosmétique. Avec `width` FIXE ci-dessus, la mise en
   page interne de la colonne ne dépend plus du facteur : sa hauteur naturelle
   est donc invariante, et l'échelle qui la fait tenir dans la place
   disponible se calcule exactement, en une division. Mettre les tailles à
   l'échelle une par une, au contraire, resserre la colonne — les textes
   finissent par passer à la ligne et la boîte GRANDIT quand on cherche à la
   réduire ; il fallait alors une recherche par essais mesurés pour compenser,
   et le moindre `font-size` oublié (celui de `.param-value`, par exemple)
   ressortait comme un élément qui refuse de rapetisser.

   Le facteur vaut 1 dès que tout tient : l'aspect grand écran est alors celui
   d'origine au pixel près.

   Le titre « Source » est le seul écart à l'homothétie : purement décoratif,
   on récupère sa hauteur plutôt que de rapetisser davantage ce qui doit
   rester lisible et cliquable (seuil : SRC_S_NOTITLE dans tube.js). ────── */
#anim-area.src-tiny #source-box .section-title {
  display: none;
}


/* Canvas tube : ligne 2 / col 2 */
#tube-canvas-wrap {
  grid-column: 2;
  grid-row: 2;
  min-height: 0;   /* le splitter JS impose la borne basse via minAnim */
  min-width: 0;
  overflow: hidden;
  position: relative;
}

/* ── Mode vagues : canvas plein espace, boutons en overlay ─────────── */
#anim-area.vagues-layout {
  grid-template-columns: 1fr;
  grid-template-rows: 1fr;
  position: relative;
}
#anim-area.vagues-layout #anim-source-spacer { display: none; }

/* Colonne source en OVERLAY, et non en colonne de grille.
   La grille n'a ici qu'une seule cellule : y empiler la colonne source et le
   canvas suffit à poser la première PAR-DESSUS le second, sans position
   absolue. Elle garde donc sa place à l'écran des deux autres onglets — bord
   gauche, centrée verticalement (`align-self: center` et la largeur fixe de
   #source-col s'appliquent telles quelles) — pendant que le canvas occupe
   toute la largeur.

   Ce qui disparaît en Vagues, c'est la négociation de LARGEUR : la colonne ne
   prend plus de place au canvas. La contrainte de HAUTEUR reste entière —
   `.src-hidden #source-col { display: none }` continue de s'appliquer, et
   _applySourceScale rapetissse puis escamote la colonne comme ailleurs.

   En vue de coupe, c'est le CONTENU du canvas qui s'écarte : vagues.js
   élargit COUPE_LEFT_MARGIN d'après la largeur peinte de cette colonne, si
   bien que l'onde commence à sa droite. Rien à animer pendant la transition,
   la colonne ne bougeant pas d'une vue à l'autre. */
#anim-area.vagues-layout #source-col {
  grid-column: 1;
  grid-row: 1;
  justify-self: start;
  z-index: 12;   /* au-dessus du canvas, et de #tube-top-btns (z-index: 10) */
}
#anim-area.vagues-layout #tube-canvas-wrap {
  grid-column: 1;
  grid-row: 1;
}
#anim-area.vagues-layout #tube-top-btns {
  position: absolute;
  top: 6px;
  right: 8px;
  grid-column: unset;
  grid-row: unset;
  padding: 3px 4px;
  background: rgba(0,0,0,0.18);
  border-radius: 7px;
  z-index: 10;
}
#anim-area.vagues-layout #tube-top-btns .btn-tube-top {
  background: rgba(255,255,255,0.18);
  color: #fff;
  border-color: rgba(255,255,255,0.35);
}
/* Bande « Trajectoire des molécules d'eau » : overlay posé sous
   #tube-top-btns, affiché seulement en vue coupe (cf. syncBtnOrbitesVagues,
   qui pose aussi le `top` exact d'après la hauteur mesurée de la bande du
   dessus — celle-ci suit les clamp() de .btn-tube-top). */
#orbites-btns {
  position: absolute;
  top: 38px;
  right: 8px;
  display: none;
  padding: 3px 4px;
  background: rgba(0,0,0,0.18);
  border-radius: 7px;
  z-index: 10;
}
#orbites-btns.visible { display: flex; }
#orbites-btns .btn-tube-top {
  background: rgba(255,255,255,0.18);
  color: #fff;
  border-color: rgba(255,255,255,0.35);
}
#orbites-btns .btn-tube-top.active {
  background: rgba(255, 210, 74, 0.90);
  color: #2a2418;
  border-color: #ffd24a;
}

#anim-area.vagues-layout #tube-top-btns #btn-beacon1.active {
  background: rgba(224, 112, 32, 0.90);
  color: #fff;
  border-color: #e07020;
}
#anim-area.vagues-layout #tube-top-btns #btn-beacon2.active {
  background: rgba(42, 138, 80, 0.90);
  color: #fff;
  border-color: #2a8a50;
}

#tube-canvas {
  display: block;
  width: 100%;
  height: 100%;
}

.source-btns {
  display: flex;
  flex-direction: column;
  gap: 5px;
}

#freq-row {
  margin-bottom: 0;
}
#freq-row label {
  font-size: clamp(11px, 1.1vw, 13px);
}
#freq-row.disabled label {
  opacity: 0.5;
}

/* Bouton de la zone tube */
.btn-tube-top {
  width: auto;
  font-size: clamp(12px, 1.2vw, 15px);
  padding: 5px 10px;
  border-radius: 5px;
  cursor: pointer;
  font-weight: 600;
  font-family: inherit;
  transition: transform 0.1s, background 0.15s;
  background: #ece8e0;
  color: #5a6a78;
  border: 1.5px solid #c8c0b4;
  white-space: nowrap;
}
.btn-tube-top:hover { background: #dedad2; }
.btn-tube-top:active { transform: scale(0.96); }
.btn-tube-top.active {
  background: #fde8c8;
  color: #7a3a10;
  border-color: #d0a060;
}
.btn-tube-top:disabled {
  background: #d4d0c8;
  color: #a0b0bc;
  border-color: #c8c0b4;
  cursor: not-allowed;
  opacity: 0.6;
}
.btn-tube-top:disabled:hover {
  background: #d4d0c8;
}
.btn-tube-top:disabled:active {
  transform: none;
}

/* Balise 1 active */
#btn-beacon1.active {
  background: rgba(224, 112, 32, 0.18);
  color: #b05010;
  border-color: #e07020;
}
/* Balise 2 active */
#btn-beacon2.active {
  background: rgba(42, 138, 80, 0.18);
  color: #1a6030;
  border-color: #2a8a50;
}

/* ── Splitter draggable ───────────────────────────── */
#left-splitter {
  flex: 0 0 6px;
  background: #c8c0b4;
  cursor: row-resize;
  position: relative;
  z-index: 20;
  transition: background 0.15s;
  border-right: 1px solid #c8c0b4;
}
#left-splitter:hover,
#left-splitter.dragging {
  background: #2a6aaa;
}

/* Zone d'animation escamotée (cf. tube.js, _setAnimCollapsed) : le splitter
   se retrouve au ras du bord supérieur de #left-col, sans rien au-dessus pour
   le distinguer — un clic qui viserait précisément ses 6 px de haut serait
   pénible à réussir. `::after`, en position absolue, élargit sa zone
   cliquable vers le bas SANS agrandir sa boîte visuelle (donc sans repousser
   #graph-area) : le survol/clic reste possible sur une bande plus généreuse,
   qui empiète légèrement sur le haut du graphe plutôt que sur une zone
   d'animation qui, ici, n'existe plus. */
#left-col.anim-collapsed #left-splitter::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 16px;
}

/* ── Graphe masqué (bouton "Afficher graphe", onglets Son + Corde) ───
   La zone d'animation récupère alors tout l'espace disponible. ────── */
#left-col.graph-hidden #graph-area,
#left-col.graph-hidden #left-splitter,
/* Pré-masquage avant l'exécution de ui.js (cf. script inline dans <head>),
   pour l'onglet Corde ou Son chargé au premier paint (URL #corde, #son, ou
   sans hash — Son étant l'onglet par défaut) : évite le flash "graphe
   visible puis masqué" au refresh. */
html.init-graph-hidden #graph-area,
html.init-graph-hidden #left-splitter {
  display: none;
}

/* ── Zone graphes ─────────────────────────────────── */
#graph-area {
  flex: 2;
  display: flex;
  flex-direction: column;
  min-height: 60px;
  background: #faf9f6;
  border-top: 1px solid #c8c0b4;
  border-right: 1px solid #c8c0b4;
  overflow: hidden;
  position: relative;
}

/* Barre de contrôle graphes */
#graph-ctrl {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: clamp(4px, 0.5vw, 6px);
  padding: clamp(3px, 0.4vh, 5px) clamp(6px, 0.8vw, 10px) clamp(3px, 0.4vh, 4px);
  flex-wrap: wrap;
}

#graph-btns-left {
  display: flex;
  gap: 5px;
  align-items: center;
  flex-wrap: wrap;
}

#graph-btns-right {
  display: flex;
  gap: 5px;
  align-items: center;
}

/* Boutons gauche graphe */
.graph-mode-btn {
  height: clamp(24px, 2.8vh, 30px);
  padding: 0 clamp(6px, 0.8vw, 10px);
  font-weight: 700;
  font-size: clamp(11px, 1.1vw, 13px);
  background: #e8e4de;
  color: #5a6a78;
  border: 1px solid #b0a898;
  border-radius: 5px;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.12s, color 0.12s;
}
.graph-mode-btn:hover { background: #d0ccc4; color: #2c3e50; }
.graph-mode-btn.active {
  background: #d0dce8;
  border-color: #5a80a8;
  color: #1a3a5a;
}

/* Boutons droite graphe */
#graph-btns-right button {
  height: clamp(24px, 2.8vh, 30px);
  padding: 0 clamp(6px, 0.8vw, 10px);
  font-weight: 700;
  font-size: clamp(11px, 1.1vw, 13px);
  background: #e8e4de;
  color: #5a6a78;
  border: 1px solid #b0a898;
  border-radius: 5px;
  cursor: pointer;
  white-space: nowrap;
}
#btn-graph-cursor { font-size: clamp(14px, 1.6vw, 18px); padding: 0 clamp(5px, 0.7vw, 8px) !important; }

#btn-graph-cursor.active {
  background: #2a6aaa; color: #fff; border-color: #1a5a9a;
}
#graph-btns-right button:hover { background: #d0ccc4; color: #2c3e50; }
#btn-graph-cursor.active:hover { background: #1a5a9a; color: #fff; }

/* Tooltip hover graphe */
#graph-hover-tooltip {
  display: none;
  position: fixed;
  z-index: 9999;
  background: #2c3e50;
  color: #fff;
  font-size: 12px;
  font-family: monospace;
  padding: 4px 10px;
  border-radius: 5px;
  pointer-events: none;
  white-space: nowrap;
  top: 0; left: 0;
}

/* Wrapper canvas graphe */
#graph-canvas-wrap {
  flex: 1;
  min-height: 0;
  min-width: 0;
  overflow: hidden;
  position: relative;
}

/* Prolongement du séparateur vertical dans #graph-ctrl en mode both */
#graph-area {
  --both-sep-x: 50%;
  --both-sep-w: 3px;
}
#graph-area.mode-both #graph-ctrl {
  position: relative;
}
#graph-area.mode-both #graph-ctrl::after {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  left: var(--both-sep-x);
  width: var(--both-sep-w);
  background: #c8c0b4;
  pointer-events: none;
}

#graph-canvas {
  display: block;
  width: 100%;
  height: 100%;
  cursor: default;
}

/* ══════════════════════════════════════════════════
   PANNEAU DE CONTRÔLE DROIT
══════════════════════════════════════════════════ */

#panel {
  background: #e8e4de;
  border-left: 1.5px solid #c8c0b4;
  display: flex;
  flex-direction: column;
  height: 100%;
  font-size: clamp(11px, 1.1vw, 14px);
  overflow: hidden;
}

/* ── Onglets principaux ───────────────────────────── */
.panel-main-tabs {
  display: flex;
  flex-shrink: 0;
  border-bottom: 1.5px solid #b0a898;
}

.panel-main-tab {
  flex: 1;
  padding: 9px 4px;
  font-size: clamp(12px, 1.2vw, 15px);
  font-weight: 700;
  font-family: inherit;
  cursor: pointer;
  border: none;
  background: #d4d0c8;
  color: #8a9aaa;
  border-right: 1px solid #b0a898;
  transition: background 0.12s, color 0.12s;
}
.panel-main-tab:last-child { border-right: none; }
.panel-main-tab:hover { background: #ccc8c0; color: #2c3e50; }
.panel-main-tab.active {
  background: #e8e4de;
  color: #2a6aaa;
  border-bottom: 1.5px solid #e8e4de;
  margin-bottom: -1.5px;
}

/* ── Corps scrollable du panneau ─────────────────── */
#panel-body {
  flex: 1;
  overflow-y: auto;
  padding: clamp(8px, 1vw, 14px) clamp(8px, 1vw, 12px);
  display: flex;
  flex-direction: column;
  gap: 0;
}

/* ── Section panneau ─────────────────────────────── */
.panel-section {
  margin-bottom: 8px;
}

/* ── Titres de section ───────────────────────────── */
.section-title {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 1px;
  color: #7a8a96;
  margin-bottom: 7px;
}

/* ── Séparateur ──────────────────────────────────── */
.sep {
  border: none;
  border-top: 1px solid #c8c0b4;
  margin: 8px 0;
}

/* ── Boutons ─────────────────────────────────────── */
.btn {
  width: 100%;
  border: none;
  border-radius: 6px;
  font-weight: 700;
  font-family: inherit;
  cursor: pointer;
  transition: transform 0.1s, background 0.15s;
}
.btn:active { transform: scale(0.97); }

.btn-pause {
  background: #c08020;
  color: #fff;
  font-size: clamp(14px, 1.4vw, 18px);
  padding: 10px 6px;
}
.btn-pause:hover { background: #a06010; }

.btn-play {
  background: #2a8a50;
  color: #fff;
  font-size: clamp(14px, 1.4vw, 18px);
  padding: 10px 6px;
}
.btn-play:hover { background: #1a6a38; }

.btn-raz {
  background: #dedad2;
  color: #5a6a78;
  font-size: clamp(12px, 1.2vw, 15px);
  padding: 9px 6px;
  border: 1.5px solid #c8c0b4;
}
.btn-raz:hover { background: #ccc8c0; }

/* Ligne de boutons côte à côte (ex. Pause + RAZ) : chacun garde le style
   .btn habituel, seule la largeur devient partagée au lieu de 100%. RAZ
   reste étroit (texte court et fixe) pour laisser toute la place à
   Pause/Reprendre, dont le texte change et ne doit pas passer à la ligne. */
.btn-row {
  display: flex;
  gap: 6px;
}
.btn-row > .btn {
  width: auto;
  flex: 1 1 0;
  white-space: nowrap;
}
.btn-row > .btn-raz {
  flex: 0 0 auto;
}

/* Bouton bascule option */
.btn-toggle-one {
  width: 100%;
  background: #ece8e0;
  color: #5a6a78;
  font-size: clamp(12px, 1.2vw, 15px);
  padding: 8px 6px;
  border: 1.5px solid #c8c0b4;
  border-radius: 6px;
  font-family: inherit;
  font-weight: 700;
  cursor: pointer;
  text-align: center;
  transition: transform 0.1s, background 0.15s;
}
.btn-toggle-one:hover { background: #dedad2; }
.btn-toggle-one:active { transform: scale(0.97); }
.btn-toggle-one.active {
  background: #fde8c8;
  color: #7a3a10;
  border-color: #d0a060;
}
.btn-toggle-one:disabled {
  background: #d4d0c8;
  color: #a0b0bc;
  border-color: #c8c0b4;
  cursor: not-allowed;
  opacity: 0.6;
}
.btn-toggle-one:disabled:hover  { background: #d4d0c8; }
.btn-toggle-one:disabled:active { transform: none; }

/* ── Sélecteur segmenté (deux choix exclusifs, ex. aspect de la corde) ── */
.seg-toggle {
  display: flex;
  border: 1px solid #c8c0b4;
  border-radius: 6px;
  overflow: hidden;
}

.seg-btn {
  flex: 1;
  padding: 8px 4px;
  font-size: clamp(12px, 1.1vw, 14px);
  font-weight: 700;
  font-family: inherit;
  border: none;
  background: #ece8e0;
  color: #5a6a78;
  cursor: pointer;
  transition: background 0.12s, color 0.12s;
}
.seg-btn:not(:last-child) { border-right: 1px solid #c8c0b4; }
.seg-btn:hover  { background: #ddd8ce; }
.seg-btn.active { background: #2a6aaa; color: #fff; }

/* Curseur neutralisé (ex. f et A en mode Libre) */
.param-row.disabled label,
.param-row.disabled .input-hint { opacity: 0.45; }
.param-row.disabled input[type="range"] {
  opacity: 0.45;
  cursor: not-allowed;
}

/* Sélecteur de mode de la source (Impulsion / Sinusoïdale) */
.select-mode {
  width: 100%;
  background: #ece8e0;
  color: #5a6a78;
  font-size: clamp(12px, 1.2vw, 15px);
  padding: 8px 6px;
  border: 1.5px solid #c8c0b4;
  border-radius: 6px;
  font-family: inherit;
  font-weight: 700;
  cursor: pointer;
  text-align: center;
  text-align-last: center;
}
.select-mode:hover { background: #dedad2; }

/* Flash impulsion — conservé pour usage futur */

/* ── Paramètres ──────────────────────────────────── */
.param-row {
  display: flex;
  flex-direction: column;
  gap: 3px;
  margin-bottom: 10px;
}

.param-row label {
  font-size: clamp(12px, 1.15vw, 15px);
  color: #2c3e50;
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 6px;
}

.param-value {
  color: #2a5080;
  font-weight: 600;
  white-space: nowrap;
  font-size: clamp(12px, 1.15vw, 15px);
}

.param-row input[type="range"] {
  width: 100%;
  accent-color: #4a7aaa;
  cursor: pointer;
}

.input-hint {
  font-size: clamp(10px, 0.9vw, 13px);
  color: #7a8a96;
  line-height: 1.4;
}

/* Labels alignés sur les 4 crans d'un slider pas=1 (0-3) */
.speed-ticks {
  display: grid;
  grid-template-columns: repeat(3, 1fr) 0fr;
  font-size: clamp(9px, 0.85vw, 11px);
  color: #7a8a96;
  padding: 0 7px;   /* compense le padding interne du thumb sur les bords */
  line-height: 1;
  margin-top: 1px;
}
.speed-ticks span:not(:last-child) {
  text-align: left;
}
.speed-ticks span:last-child {
  text-align: right;
  white-space: nowrap;
}

/* ── Afficheurs valeur ───────────────────────────── */
.readout {
  background: #fff;
  border: 1px solid #c8c0b4;
  border-radius: 6px;
  padding: 7px 9px;
  margin-bottom: 8px;
}

.ro-label {
  font-size: clamp(11px, 1vw, 13px);
  color: #7a8a96;
  margin-bottom: 2px;
}

.ro-value {
  font-size: clamp(15px, 1.6vw, 20px);
  font-weight: 700;
  color: #2a5080;
  font-variant-numeric: tabular-nums;
}

.ro-unit {
  font-size: 1em;
  font-weight: 700;
  color: #2a5080;
}

/* Titre de section dans le readout étendu */
.ro-label-section {
  font-size: clamp(12px, 1.15vw, 15px);
  font-weight: 700;
  color: #2c3e50;
  margin-bottom: 4px;
}

/* Ligne nom = valeur dans le readout étendu */
.ro-props-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 6px;
}

.ro-props-name {
  font-weight: 400;
  color: #7a8a96;
  font-family: monospace;
  font-size: 0.85em;
  /* Une formule coupée en deux ne se lit plus : « c = √(K/ρ) » reste d'un
     seul tenant, quitte à ce que ce soit le membre de droite qui passe à la
     ligne. Le flex-shrink par défaut suffirait à la comprimer sinon. */
  white-space: nowrap;
  flex: 0 0 auto;
}

/* Membre de droite : c'est LUI qui se replie quand la place manque, et le
   pli se fait entre la valeur et son unité — jamais au milieu de l'écriture
   scientifique, d'où le nowrap sur les deux enfants. */
.ro-props-row > span:last-child {
  text-align: right;
}
.ro-props-row > span:last-child > span {
  white-space: nowrap;
}

/* Exposant de l'écriture scientifique (λ, c). line-height:0 empêche le <sup>
   d'agrandir la boîte de ligne et de décaler la ligne du readout. */
.ro-props-row sup,
.ro-value sup {
  font-size: 0.7em;
  line-height: 0;
  vertical-align: super;
}

/* ── Placeholder "À venir" ───────────────────────── */
.coming-soon {
  text-align: center;
  padding: clamp(20px, 3vh, 40px) 10px;
  color: #7a8a96;
}
.coming-soon-icon {
  font-size: clamp(24px, 3vw, 36px);
  margin-bottom: 8px;
}
.coming-soon-title {
  font-size: clamp(13px, 1.3vw, 16px);
  font-weight: 700;
  color: #5a6a78;
  margin-bottom: 6px;
}
.coming-soon-text {
  font-size: clamp(11px, 1vw, 13px);
  font-style: italic;
}

/* ══════════════════════════════════════════════════
   BANDEAU INSTRUCTIONS (collapsible)
   Même pattern que titrage/ et radioactivite/
══════════════════════════════════════════════════ */

.panel-hint {
  flex-shrink: 0;
  color: #5a6a78;
  line-height: 1.5;
  background: #fff;
  border: 1.5px solid #b0a898;
  /* Pas de bordure gauche propre : #panel a déjà la sienne (border-left,
     1.5px) sur ce bord. Avec la largeur de #panel en clamp() (donc
     fractionnaire en px), deux bordures superposées à cet endroit
     arrondissent chacune de leur côté et laissent un décalage d'~1px
     entre elles — en confiant ce bord à #panel seul, une seule bordure
     le trace, sans place pour ce décalage. */
  border-left: none;
  overflow: hidden;
  transition: padding 0.2s;
}

.panel-hint-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 6px 10px;
  cursor: default;
}

.panel-hint-title {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 1px;
  color: #7a8a96;
  margin-left: auto;
  margin-right: 6px;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.panel-hint-menu-btn {
  background: #f0f4f7;
  border: 1px solid #c8d4dc;
  border-radius: 6px;
  cursor: pointer;
  font-size: 11px;
  font-weight: 600;
  color: #4a5a68;
  padding: 4px 9px;
  line-height: 1.2;
  transition: background 0.15s, color 0.15s;
  white-space: nowrap;
}
.panel-hint-menu-btn:hover { background: #dde6ec; color: #2a6aaa; }

.panel-hint-toggle {
  background: none;
  border: none;
  cursor: pointer;
  font-size: 13px;
  color: #7a8a96;
  padding: 0 2px;
  line-height: 1;
  transition: transform 0.2s;
}
.panel-hint-toggle:hover { color: #2a6aaa; }

.panel-hint-body {
  font-size: clamp(12px, 1.15vw, 15px);
  padding: 0 10px 8px;
  overflow-x: hidden;
  overflow-y: hidden;
  transition: max-height 0.25s ease, padding 0.25s ease;
  max-height: 250px;
}

/* Texte plus long sur l'onglet Corde (source, atténuation, graphe, balises) :
   hauteur plafonnée et défilement interne plutôt que de pousser le panneau
   à grandir indéfiniment (ou de couper la fin du texte). */
.panel-hint:not(.collapsed) #panel-hint-corde-body {
  max-height: 220px;
  overflow-y: auto;
}

/* État replié */
.panel-hint.collapsed .panel-hint-body {
  max-height: 0;
  padding-top: 0;
  padding-bottom: 0;
}
.panel-hint.collapsed .panel-hint-header {
  padding-bottom: 6px;
}

/* Flèche ▲ : tourne à 180° quand déplié (→ ▼) */
.panel-hint:not(.collapsed) .panel-hint-toggle {
  transform: rotate(180deg);
}
