/* components.css – Buttons, Badges, Cards, Tabs (CLAUDE.md Abschnitt 5).
   Touch-Targets: interaktive Elemente min. 44×44 px, Bottom-Bar min. 48×48 px. */

/* ---- Buttons ---------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-width: 44px;
  min-height: 44px;
  padding: 10px 18px;
  border-radius: var(--radius-md);
  background: var(--bg-secondary);
  border: 1px solid var(--border-medium);
  font-weight: 500;
  transition: background 0.15s, border-color 0.15s;
}

.btn:hover { border-color: var(--color-primary); }
.btn:active { background: var(--border-light); }

/* Empfohlener nächster Schritt (Studentmodus-Führung): sanftes Pulsieren
   in der Akzentfarbe, damit Einsteiger den Ablauf finden. */
.btn.suggested:not(:disabled) {
  border-color: var(--color-accent);
  color: var(--color-accent);
  animation: suggestPulse 1.6s ease-in-out infinite;
}

@keyframes suggestPulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(255,122,26,0.0); }
  50%      { box-shadow: 0 0 0 4px rgba(255,122,26,0.25); }
}

@media (prefers-reduced-motion: reduce) {
  .btn.suggested:not(:disabled) { animation: none; box-shadow: 0 0 0 3px rgba(255,122,26,0.3); }
}

.btn-primary {
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: #0f1115;
}

.btn-primary:hover { filter: brightness(1.1); }

.btn-icon {
  min-width: 44px;
  min-height: 44px;
  padding: 0;
  border-radius: var(--radius-md);
  font-size: var(--text-lg);
}

/* Schmaler NUR in der Breite – die 44 px Höhe aus Abschnitt 5 bleiben, sonst
   wird das Antippen unzuverlässig. Für Knöpfe in der engen Statuszeile. */
.btn-slim {
  padding: 6px 10px;
  font-size: var(--text-sm);
}

/* Projekt-/Export-Knöpfe in der Statuszeile: Symbol + Text. Auf schmalen
   Bildschirmen fällt der Text weg – drei volle Beschriftungen sprengten die
   bewusst einzeilige Statuszeile (layout.css). Der title bleibt als Hinweis. */
.status-bar .btn-slim {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
}
.status-bar .btn-slim svg { flex: 0 0 auto; }
@media (max-width: 760px) {
  .status-bar .btn-slim .btn-text { display: none; }
}

/* Fußzeile der Startseite: Handreichungs-Knopf, darunter das Impressum
   (Nutzerwunsch: untereinander – der Knopf ist Einstieg, das Impressum
   Pflichtangabe). */
.startseiten-links {
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-items: center;
}

/* Link in Knopf-Optik: .btn ist für <button> gebaut – beim <a> müssen
   Unterstreichung weg und die Zeilenbox stimmen. */
.handreichung-knopf {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
  color: var(--text-primary);
}

/* Impressum-Link: dezent, aber klar als Link erkennbar (Pflichtangabe darf
   nicht versteckt wirken). */
.impressum-link {
  color: var(--text-secondary);
  font-size: var(--text-sm);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.impressum-link:hover { color: var(--text-primary); }

/* Versionszeile in den Einstellungen: klein und unaufdringlich – sie ist
   Nachschlagewert, kein Bedienelement. */
.version-zeile {
  margin: 4px 0 0;
  font-size: var(--text-xs);
  text-align: right;
}

/* Dieselbe Angabe auf der Startseite: mittig unter den Fußzeilen-Links und
   bewusst zurückhaltend – sie ist Nachschlage-Information (Fehlermeldung,
   Update-Kontrolle), nicht Teil der Moduswahl. Leer bleibt sie beim ersten
   Besuch; dann darf sie auch keinen Platz beanspruchen (:empty). */
.startseiten-version {
  margin-top: 14px;
  text-align: center;
  color: var(--text-secondary);
  letter-spacing: 0.02em;
}

.startseiten-version:empty { display: none; }

/* ---- Tutorial-Sprechblase (tutorial.js) ------------------------------------
   EINE Blase wandert von Schritt zu Schritt; position: fixed, weil die
   Zielkoordinaten aus getBoundingClientRect stammen (Viewport-Raum). */
.tutorial-blase {
  position: fixed;
  z-index: 1000;
  max-width: min(320px, calc(100vw - 16px));
  background: var(--bg-secondary);
  border: 1px solid var(--color-accent);
  border-radius: var(--radius-md);
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.55);
  padding: 12px 14px;
  /* Zeiger-DURCHLÄSSIG: Liegt die Blase über dem Video (kleine Bildschirme),
     darf sie die Zieh-Geste (Rahmen um das Objekt!) nicht wegfangen –
     bedienbar bleiben nur ihre Knöpfe. */
  pointer-events: none;
}
.tutorial-blase button { pointer-events: auto; }
.tutorial-blase .tutorial-text {
  margin: 0 18px 0 0;
  font-size: var(--text-sm);
  line-height: 1.45;
  color: var(--text-primary);
}
.tutorial-blase .tutorial-knoepfe {
  margin-top: 10px;
  display: flex;
  justify-content: flex-end;
  gap: 8px;
}

/* Zurück (v90) links, Weiter rechts – die gewohnte Leserichtung. */
.tutorial-blase .tutorial-zurueck { margin-right: auto; }
.tutorial-blase .tutorial-zu {
  position: absolute;
  top: 2px;
  right: 4px;
  background: none;
  border: none;
  color: var(--text-secondary);
  font-size: var(--text-lg);
  line-height: 1;
  padding: 6px;
  cursor: pointer;
}
/* Pfeil zum Ziel: Blase unter dem Ziel → Pfeil oben (und umgekehrt) */
.tutorial-blase::after {
  content: "";
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  border: 7px solid transparent;
}
.tutorial-blase.zeigt-oben::after {
  bottom: 100%;
  border-bottom-color: var(--color-accent);
}
.tutorial-blase.zeigt-unten::after {
  top: 100%;
  border-top-color: var(--color-accent);
}

/* Hervorgehobenes Ziel-Element */
.tutorial-ziel {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
  animation: tutorial-puls 1.6s ease-in-out infinite;
}
@keyframes tutorial-puls {
  0%, 100% { outline-color: var(--color-accent); }
  50%      { outline-color: rgba(255, 122, 26, 0.35); }
}

.bottom-bar .btn-icon {
  min-width: 48px;
  min-height: 48px;
}

/* ---- Badges ----------------------------------------------------------- */

.badge {
  display: inline-flex;
  align-items: center;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: var(--text-xs);
  font-weight: 500;
  border: 1px solid var(--border-medium);
  color: var(--text-secondary);
  white-space: nowrap;
}

.badge-mode {
  color: var(--color-accent);
  border-color: var(--color-accent);
}

/* ---- Cards (Modus-Auswahl) -------------------------------------------- */

.card {
  background: var(--bg-secondary);
  border: 1px solid var(--border-light);
  border-radius: var(--radius-lg);
  padding: 20px;
  text-align: left;
}

.mode-card {
  flex: 1 1 260px;
  max-width: 340px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  cursor: pointer;
  transition: border-color 0.15s, transform 0.15s;
}

.mode-card:hover {
  border-color: var(--color-primary);
  transform: translateY(-2px);
}

.mode-card h2 { color: var(--color-primary); }
.mode-card.mode-card-science h2 { color: var(--color-quaternary); }
.mode-card p { color: var(--text-secondary); font-size: var(--text-sm); flex: 1; }

/* ---- Tabs (Diagramm-Auswahl) ------------------------------------------ */

.tab {
  min-width: 44px;
  min-height: 44px;
  padding: 8px 14px;
  border-radius: var(--radius-sm);
  color: var(--text-secondary);
  font-weight: 500;
  border: 1px solid transparent;
}

.tab:hover { color: var(--text-primary); }

.tab.active {
  color: var(--text-primary);
  background: var(--bg-primary);
  border-color: var(--border-medium);
}

/* Linien-Toggle rechts in der Action-Bar */
.chart-lines-toggle {
  margin-left: auto;
  font-size: var(--text-sm);
}

.chart-lines-toggle.active {
  color: var(--color-primary);
  border-color: var(--color-primary);
}

/* Select im Button-Stil: <select> erbt die color der .btn NICHT
   (kein <button>), darum explizit setzen – sonst schwarzer Text
   auf dunklem Grund (unsichtbar im Dark Mode). */
.select-btn {
  color: var(--text-primary);
  -webkit-appearance: none;
  appearance: none;
  padding-right: 26px;
  /* Chevron als Hintergrundgrafik (kein externer Asset) */
  background-image:
    linear-gradient(45deg, transparent 50%, var(--text-secondary) 50%),
    linear-gradient(135deg, var(--text-secondary) 50%, transparent 50%);
  background-position:
    calc(100% - 14px) center,
    calc(100% - 9px) center;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}

.select-btn option {
  color: var(--text-primary);
  background: var(--bg-secondary);
}

/* Klickbare Größen-Auswahl direkt an den Diagrammachsen */
.axis-select {
  position: absolute;
  z-index: 5;
  font: inherit;
  /* Kompakt (Nutzerentscheidung): Die Auswahl liegt ÜBER dem Diagramm und
     verdeckte mit 44 px Höhe und voller Schrift zu viel davon. Mit den
     kurzen Formelzeichen-Texten reicht eine schlanke Kapsel; die native
     Auswahlliste des Browsers bleibt ohnehin fingerfreundlich. */
  font-size: var(--text-sm);
  color: var(--text-primary);
  background: var(--bg-secondary);
  border: 1px solid var(--border-medium);
  border-radius: var(--radius-md);
  padding: 6px 10px;
  min-height: 36px;
  max-width: 200px;
  cursor: pointer;
}

.axis-select:hover {
  color: var(--text-primary);
  border-color: var(--color-primary);
}

/* Große Schirme (PC/Beamer, gleiche Schwelle wie die geteilte Ansicht):
   Die kompakte Handy-Kapsel ging im Gesamtbild unter (Nutzerbefund) –
   hier volle Schrift und mehr Polster. Die Breitenanpassung in main.js
   misst mit der echten Schrift und wächst automatisch mit. */
@media (min-width: 900px) and (min-height: 480px) {
  .axis-select {
    /* Zweiter Anlauf (Nutzerbefund nach v48: "noch immer sehr klein"):
       Zielumgebung ist der Beamer im Klassenzimmer – 16 px gingen aus
       drei Metern weiter unter. Jetzt spürbar größer; die Kapseln liegen
       am PC über einem großen Diagramm, da darf die Höhe das sein. */
    font-size: var(--text-lg);
    font-weight: 500;
    padding: 12px 16px;
    min-height: 48px;
    max-width: 320px;
  }
}

/* Fit-Ziel-Auswahl im Reglerfeld (nur bei mehreren Objekten sichtbar) */
.fit-objekt-wahl {
  display: block;
  margin-bottom: 8px;
  max-width: 100%;
}

#axis-y-select {
  left: 10px;
  top: 12px;              /* oben an der y-Achse */
}

#axis-x-select {
  right: 10px;
  bottom: 12px;           /* rechts an der x-Achse */
}

/* Tab-Farbmarkierung nach Diagramm-Farbzuweisung */
.tab.active[data-chart="s"]      { border-bottom: 2px solid var(--color-primary); }
.tab.active[data-chart="v"]      { border-bottom: 2px solid var(--color-secondary); }
.tab.active[data-chart="a"]      { border-bottom: 2px solid var(--color-tertiary); }
.tab.active[data-chart="p"]      { border-bottom: 2px solid var(--color-quaternary); }
.tab.active[data-chart="energy"] { border-bottom: 2px solid var(--text-primary); }

/* ---- Sprachumschalter -------------------------------------------------- */

.lang-switch,
.format-switch {
  display: inline-flex;
  border: 1px solid var(--border-medium);
  border-radius: var(--radius-md);
  overflow: hidden;
}

.lang-switch button,
.format-switch button {
  min-width: 44px;
  min-height: 44px;
  padding: 8px 14px;
  color: var(--text-secondary);
  font-weight: 500;
}

.lang-switch button.active,
.format-switch button.active {
  background: var(--color-primary);
  color: #0f1115;
}

/* ---- Scrubber (Frame-Navigation) --------------------------------------- */

input[type="range"].scrubber {
  -webkit-appearance: none;
  appearance: none;
  cursor: pointer;
}

/* Bahn und Griff bewusst kräftig: Auf der vollen Leistenbreite bildet ein
   4,2-s-Video mit 252 Bildern rund 1,5 px je Bild ab – der Griff muss dick
   genug sein, um ihn mit dem Daumen sicher zu fassen. */
input[type="range"].scrubber::-webkit-slider-runnable-track {
  height: 8px;
  border-radius: 4px;
  background: var(--border-medium);
}

input[type="range"].scrubber::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 26px;
  height: 26px;
  margin-top: -9px;
  border-radius: 50%;
  background: var(--color-accent);
  border: 3px solid #fff;
}

input[type="range"].scrubber::-moz-range-track {
  height: 8px;
  border-radius: 4px;
  background: var(--border-medium);
}

input[type="range"].scrubber::-moz-range-thumb {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--color-accent);
  border: 3px solid #fff;
}

input[type="range"].scrubber:disabled { opacity: 0.4; cursor: default; }

button:disabled { opacity: 0.4; cursor: default; }

/* ---- Clip-Range (Videoausschnitt eingrenzen, S3) ------------------------ */

.clip-range {
  position: relative;
  height: 24px;
  margin: 0 13px;          /* ungefähr auf die Scrubber-Track-Enden ausrichten */
}

.clip-range::before {      /* Grundlinie über die volle Videolänge */
  content: "";
  position: absolute;
  top: 50%;
  left: 0;
  right: 0;
  height: 5px;
  margin-top: -2.5px;
  border-radius: 3px;
  background: var(--border-light);
}

.clip-selection {          /* gewählter Ausschnitt */
  position: absolute;
  top: 50%;
  height: 5px;
  margin-top: -2.5px;
  border-radius: 3px;
  background: var(--color-primary);
}

.clip-handle {
  position: absolute;
  top: 50%;
  width: 20px;
  height: 20px;
  transform: translate(-50%, -50%);
  border-radius: 5px;
  background: var(--color-primary);
  border: 2px solid #fff;
  cursor: ew-resize;
  touch-action: none;
}

.clip-handle::after {      /* unsichtbar vergrößertes Touch-Target (44px) */
  content: "";
  position: absolute;
  inset: -15px;
}

/* ---- Tracking-Fortschritt (Pflicht laut Abschnitt 8) --------------------- */

.track-progress {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 6px;
  background: rgba(0, 0, 0, 0.5);
}

.track-progress-fill {
  height: 100%;
  width: 0;
  background: var(--color-accent);
  transition: width 0.1s linear;
}

/* ---- Toast (Hinweise/Warnungen) ----------------------------------------- */

.toast {
  position: fixed;
  left: 50%;
  bottom: 84px;
  transform: translateX(-50%);
  max-width: min(90vw, 480px);
  padding: 12px 18px;
  background: var(--bg-secondary);
  border: 1px solid var(--border-medium);
  border-left: 3px solid var(--color-accent);
  border-radius: var(--radius-md);
  font-size: var(--text-sm);
  z-index: 100;
}

/* ---- Einstellungs-Dialog ----------------------------------------------- */

dialog {
  margin: auto;
  background: var(--bg-secondary);
  color: var(--text-primary);
  border: 1px solid var(--border-medium);
  border-radius: var(--radius-lg);
  padding: 24px;
  min-width: 280px;
  max-width: 90vw;
}

dialog::backdrop {
  background: rgba(0, 0, 0, 0.6);
}

/* AUCH die Textfelder, nicht nur Zahlenfelder: Ungestaltete Inputs fallen auf
   die Browservorgabe von rund 11 px zurück, und iOS ZOOMT DIE GANZE SEITE
   HINEIN, sobald ein Eingabefeld mit Schrift unter 16 px den Fokus erhält.
   showModal() fokussiert das erste Bedienelement des Dialogs von selbst –
   das Öffnen des PC-Dialogs zoomte damit ungefragt ins Bild. font:inherit
   ergibt 16 px (--text-base), das unterbindet den Auto-Zoom. */
dialog input[type="number"],
dialog input[type="text"],
dialog select {
  font: inherit;
  color: var(--text-primary);
  background: var(--bg-primary);
  border: 1px solid var(--border-medium);
  border-radius: var(--radius-sm);
  padding: 8px 10px;
  min-height: 44px;
}

dialog input[type="number"] { width: 100px; }

.calib-input {
  display: inline-flex;
  gap: 8px;
  align-items: center;
}

/* Umschalt-Buttons (z.B. Achsenkreuz ein/aus) */
.btn.active {
  border-color: var(--color-primary);
  color: var(--color-primary);
}

.settings-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 12px 0;
  border-bottom: 1px solid var(--border-light);
}

.settings-row:last-of-type { border-bottom: none; }

/* Zeile mit Umbruch: Auf dem Handy passt "Darstellung (Beamer)" plus drei
   Prozentknöpfe nicht nebeneinander – die 150 % standen halb außerhalb des
   Dialogs. Mit Umbruch rutscht der Schalter auf eine eigene Zeile und behält
   seine 44-px-Tippflächen; am PC bleibt alles nebeneinander. */
.settings-row-block { flex-wrap: wrap; }
.settings-row-block .format-switch { margin-left: auto; }

.settings-hinweis {
  flex-basis: 100%;
  margin: 6px 0 0;
  color: var(--text-secondary);
  font-size: var(--text-xs);
  line-height: 1.4;
}

/* Aufklapp-Bereich "Erweiterte Einstellungen" (Nutzerrückmeldung: der Dialog
   war zu lang). Natives <details>: Auf/Zu, Tastatur (Enter/Leertaste) und
   Vorlesen bringt der Browser mit, wir liefern nur die Optik – kein
   JavaScript und kein neuer Farbwert, alles aus base.css. */
.settings-erweitert {
  border-bottom: 1px solid var(--border-light);
}

.settings-erweitert > summary {
  display: flex;
  align-items: center;
  gap: 10px;
  /* Tippfläche mindestens 44 px (CLAUDE.md Abschnitt 5). box-sizing ist
     border-box, die Polsterung zählt also mit: 12 + 12 px plus die Zeile der
     16-px-Schrift. Nachgemessen im Dialog auf 390 px: 301 px breit und
     47,2 px (zu) bzw. 48,2 px (auf) hoch – der Unterschied kommt vom
     Dreieck unten, das eine Spur höher baut als das seitliche. */
  min-height: 44px;
  padding: 12px 0;
  cursor: pointer;
  user-select: none;
  color: var(--text-primary);
  /* Eigenes Dreieck statt des Browser-Markers: Chrome, Firefox und Safari
     zeichnen ihn verschieden groß, und bei display:flex verschwindet er
     teilweise ganz. So sieht der Pfeil überall gleich aus. */
  list-style: none;
}

.settings-erweitert > summary::-webkit-details-marker { display: none; }

.settings-erweitert > summary::before {
  content: "▸";
  width: 1em;
  text-align: center;
  color: var(--text-secondary);
}

.settings-erweitert[open] > summary::before { content: "▾"; }

/* Aufgeklappt trennt eine Linie die Überschrift von den Zeilen darunter –
   sonst klebte die erste Einstellung an der Beschriftung. */
.settings-erweitert[open] > summary {
  border-bottom: 1px solid var(--border-light);
}

/* Tastaturfokus sichtbar machen wie bei den Knöpfen. */
.settings-erweitert > summary:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

/* Zahlenzeilen der Wiedergabe-Messung. Feste Zeichenbreite und feste
   Ziffernbreite, weil die Karte abfotografiert und danach abgetippt oder
   verglichen wird – da darf keine Ziffer wandern.
   UMBRUCH STATT SCHIEBEN: Die Karte war am Handy rechts abgeschnitten. Zum
   Nachrechnen auf einem 390-px-Schirm: Der Dialog ist max-width 90vw = 351 px,
   davon gehen 2 × 24 px Polsterung und 2 × 1 px Rahmen ab – 301 px bleiben für
   den Text (im Browser nachgemessen: clientWidth 301). Die längsten Zeilen
   haben über 70 Zeichen; bei 13 px Nichtproportionalschrift (auf dem Handy
   ≈ 0,6 em, also 7,8 px je Zeichen) sind das rund 560 px – gut 260 px standen
   außerhalb. Das vorherige overflow-x half nicht: Auf dem Foto und beim ersten
   Blick fehlten genau die hinteren Zahlen ("präsentiert", "dekodiert").
   Jetzt bricht die Zeile um; es passen rund 38 Zeichen je Zeile (die erste
   Zeile ist um den hängenden Einzug breiter).
   Zahlen bleiben trotzdem heil: Wert und Einheit hält main.js mit geschützten
   Leerzeichen zusammen. Längstes unzerbrechliches Stück ist "{p} präsentiert ·"
   – bei fünfstelliger Bildzahl 19 Zeichen ≈ 150 px, passt also auch dann noch
   in eine Zeile. break-word ist nur der Notnagel für einen ungewöhnlich langen
   Dateityp ("video/mp4; codecs=avc1.640028").
   Gegengemessen bei 390 px und bei 360 px, DE und EN, auch im
   Präsentationsmodus 150 %: scrollWidth = clientWidth in allen sechs Zeilen,
   nichts steht mehr außerhalb.
   Der hängende Einzug zeigt, dass eine Folgezeile eine Fortsetzung ist. */
.mess-zeile {
  margin: 8px 0 0;
  font-family: ui-monospace, 'SFMono-Regular', Menlo, Consolas, monospace;
  font-size: var(--text-sm);
  font-variant-numeric: tabular-nums;
  line-height: 1.5;
  overflow-wrap: break-word;
  padding-left: 1.6em;
  text-indent: -1.6em;
}

/* Vektor-Dialog (S16): Farbpunkt = Pfeilfarbe im Video, damit die Zuordnung
   ohne Nachdenken klappt (Abschnitt 5) */
.vec-row label {
  display: flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
}

.vec-dot {
  width: 14px;
  height: 3px;
  border-radius: 2px;
  flex: 0 0 auto;
}

.vec-dot[data-vec="s"] { background: var(--color-primary); }
.vec-dot[data-vec="v"] { background: var(--color-secondary); }
.vec-dot[data-vec="a"] { background: var(--color-tertiary); }
.vec-dot[data-vec="p"] { background: var(--color-quaternary); }
.vec-dot[data-vec="f"] { background: #E85D75; }   /* Kraft F = m·a */

/* Regler im Vektor-Dialog: eigene Bahn, eigener Griff.
   Vorher stand hier nur accent-color. Das färbt den GEFÜLLTEN Teil der Bahn,
   den Rest überlässt es dem Browser – und dessen Grau auf dem sehr dunklen
   Dialoggrund war praktisch unsichtbar, der Griff an den Endanschlägen erst
   recht (Nutzerbefund). Aufbau wie beim Scrubber, nur kleiner: helle Bahn,
   Griff in Akzentfarbe mit weißem Rand, der ihn auf jedem Untergrund trägt. */
.vec-scale {
  flex: 0 0 110px;
  -webkit-appearance: none;
  appearance: none;
  background: transparent;
  cursor: pointer;
}

.vec-scale::-webkit-slider-runnable-track {
  height: 6px;
  border-radius: 3px;
  background: var(--border-medium);
}

.vec-scale::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 20px;
  height: 20px;
  margin-top: -7px;
  border-radius: 50%;
  background: var(--color-accent);
  border: 2px solid #fff;
}

.vec-scale::-moz-range-track {
  height: 6px;
  border-radius: 3px;
  background: var(--border-medium);
}

.vec-scale::-moz-range-thumb {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--color-accent);
  border: 2px solid #fff;
}

.vec-scale:disabled { opacity: 0.4; cursor: default; }

.vec-row input[type="checkbox"]:disabled + .vec-dot { opacity: 0.35; }

/* Koordinaten-Anzeige im Diagramm: OBEN rechts (Nutzerentscheidung – unten
   verdeckte sie die Kurve), Werte UNTEREINANDER: erst die x-, dann die
   y-Größe. Bei mehreren Objekten je Objekt ein Block in Kurvenfarbe. */
.coord-readout {
  position: absolute;
  right: 10px;
  top: 12px;
  z-index: 5;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 6px 10px;
  background: var(--bg-secondary);
  border: 1px solid var(--border-medium);
  border-radius: var(--radius-md);
  font-size: var(--text-sm);
  font-variant-numeric: tabular-nums;   /* Zahlen springen beim Abspielen nicht */
  pointer-events: none;                 /* darf Diagramm-Gesten nicht abfangen */
  white-space: nowrap;
  text-align: right;
}

.coord-readout .coord-gruppenstart { margin-top: 6px; }

.coord-readout-frame {
  color: var(--text-secondary);
  font-size: var(--text-xs);
}

/* Ergebnis der Flächenberechnung (S18): UNTEN rechts, über der x-Achsen-
   Auswahl – hat mit der Koordinaten-Anzeige die Plätze getauscht. */
.area-readout {
  position: absolute;
  right: 10px;
  bottom: 68px;            /* über #axis-x-select */
  z-index: 5;
  display: flex;
  flex-direction: column;
  gap: 3px;
  max-width: 46%;
  padding: 8px 12px;
  background: var(--bg-secondary);
  border: 1px solid var(--border-medium);
  border-radius: var(--radius-md);
  font-size: var(--text-sm);
  font-variant-numeric: tabular-nums;
  pointer-events: none;
}

.area-readout-main { color: var(--text-primary); }
.area-readout-hint { color: var(--text-secondary); font-size: var(--text-xs); }

/* Fit-Parameter (S19), unten links im Diagramm. Farbe = Farbe der Modellkurve,
   damit die Zuordnung ohne Legende klappt. */
.fit-readout {
  position: absolute;
  left: 10px;
  bottom: 12px;
  z-index: 5;
  display: flex;
  flex-direction: column;
  gap: 2px;
  max-width: 48%;
  padding: 8px 12px;
  background: var(--bg-secondary);
  border: 1px solid #FFD60A;
  border-radius: var(--radius-md);
  font-size: var(--text-sm);
  font-variant-numeric: tabular-nums;
  pointer-events: none;
}

/* Große Schirme (PC/Beamer, gleiche Schwelle wie die Achsen-Kapseln): Die
   Info-Fenster im Diagramm – Flächenergebnis, Koordinaten, Fit-Parameter –
   gingen mit 13/11 px aus drei Metern unter (Nutzerbefund). Der Messwert
   der Fläche ist die Schlagzeile und wird am deutlichsten angehoben. */
@media (min-width: 900px) and (min-height: 480px) {
  .area-readout {
    font-size: var(--text-base);
    padding: 12px 16px;
    gap: 4px;
  }

  .area-readout-main {
    font-size: var(--text-lg);
    font-weight: 500;
  }

  .area-readout-hint { font-size: var(--text-sm); }

  .coord-readout {
    font-size: var(--text-base);
    padding: 10px 14px;
    gap: 3px;
  }

  .coord-readout-frame { font-size: var(--text-sm); }

  .fit-readout {
    font-size: var(--text-base);
    padding: 12px 16px;
    gap: 3px;
  }
}

.fit-formula { color: #FFD60A; }
.fit-params  { color: var(--text-primary); }
.fit-quality { color: var(--text-secondary); font-size: var(--text-xs); }

/* PC-Kopplung (S20) */
.pclink-server {
  flex: 1 1 auto;
  min-width: 0;
  font: inherit;
  font-size: var(--text-sm);
  color: var(--text-primary);
  background: var(--bg-primary);
  border: 1px solid var(--border-medium);
  border-radius: var(--radius-sm);
  padding: 8px 10px;
}

/* Sitzungscode: gross und mit Zeichenabstand, damit er vom Bildschirm
   abgelesen und fehlerfrei abgetippt werden kann. */
.pclink-code {
  margin: 10px 0;
  padding: 10px 14px;
  text-align: center;
  font-size: var(--text-xl);
  letter-spacing: 0.18em;
  color: var(--color-accent);
  background: var(--bg-primary);
  border: 1px solid var(--color-accent);
  border-radius: var(--radius-md);
}

.pclink-status {
  margin: 8px 0 0;
  min-height: 1.4em;
  font-size: var(--text-sm);
}

/* ---- Gruppen-Überschriften in Klappmenüs (Layout-Aufräumung S23) ----------
   Das Auswertungsmenü trägt inzwischen 10 Einträge – zwei beschriftete
   Gruppen gliedern es, ohne ein viertes Menü aufzumachen. Reine Anzeige:
   kleiner, grau, nicht anklickbar; die 44-px-Regel gilt für Bedienflächen. */
.menu-panel > .menu-gruppe {
  min-height: 0;
  padding: 6px 10px 0;
  font-size: var(--text-xs);
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.07em;
  user-select: none;
}

.menu-panel > .menu-gruppe:not(:first-child) {
  margin-top: 4px;
  border-top: 1px solid var(--border-light);
  padding-top: 8px;
}

/* ---- Messwerttabelle (S23, zwei Ansichten seit S31) ------------------------
   Die Tabelle ist ein GESCHWISTER des Diagrammfelds (nicht mehr darin), damit
   sie wahlweise dessen Platz einnehmen oder daneben stehen kann. Sie scrollt
   in beide Richtungen; Kopfzeile und t-Spalte bleiben stehen, damit man beim
   seitlichen Scrollen weiß, wo man ist. */
.tabelle-wrap {
  flex: 1;
  min-height: 0;
  overflow: auto;
  background: var(--bg-panel);
  overscroll-behavior: contain;
}

/* "Tabelle + Video": Die Tabelle tritt an die Stelle des Diagramms – am PC
   steht das Video links daneben, am Handy oben darüber. Das leere Diagrammfeld
   muss weichen, sonst behielte es seinen Flex-Anteil. */
#app-shell.tabelle-video .chart-area { display: none; }

/* "Tabelle + Diagramm": Wie im Fit-Modus weicht das Video – Diagramm und
   Tabelle teilen sich die volle Fläche. Am Handy übereinander (Diagramm oben,
   Tabelle unten), am PC nebeneinander (siehe Medienregel weiter unten). */
#app-shell.tabelle-diagramm .video-area,
#app-shell.tabelle-diagramm .pane-splitter {
  display: none !important;   /* übersteuert auch die Splitter-Medienregel */
}

#app-shell.tabelle-diagramm .tabelle-wrap {
  /* Voreinstellung 45 %; der Schieber überschreibt sie über --tabelle-anteil */
  flex: 0 0 var(--tabelle-anteil, 45%);
  border-top: 1px solid var(--border-medium);
}

/* ---- Schieber zwischen Diagramm und Tabelle (S31) --------------------------
   Nur sichtbar, wenn beide zugleich zu sehen sind. Am Handy waagerecht
   (verteilt Höhe), am PC senkrecht (verteilt Breite) – die Ausrichtung
   ergibt sich aus der Flex-Richtung der Spalte. */
.tabelle-splitter { display: none; }

#app-shell.tabelle-diagramm .tabelle-splitter {
  display: block;
  flex: 0 0 12px;
  position: relative;
  cursor: row-resize;
  background: var(--bg-secondary);
  touch-action: none;          /* sonst scrollt die Geste die Seite */
}

/* Griffmarke in der Mitte, damit der Balken als Bedienelement erkennbar ist */
#app-shell.tabelle-diagramm .tabelle-splitter::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 46px;
  height: 3px;
  transform: translate(-50%, -50%);
  border-radius: 2px;
  background: var(--border-medium);
}

#app-shell.tabelle-diagramm .tabelle-splitter:active::before {
  background: var(--color-primary);
}

/* Unsichtbar vergrößerte Trefffläche für den Finger */
#app-shell.tabelle-diagramm .tabelle-splitter::after {
  content: "";
  position: absolute;
  inset: -8px 0;
}

.tabelle-wrap table {
  border-collapse: collapse;
  font-size: var(--text-sm);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.tabelle-wrap th,
.tabelle-wrap td {
  padding: 6px 10px;
  text-align: right;
  border-bottom: 1px solid var(--border-light);
}

.tabelle-wrap thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--bg-secondary);
  color: var(--text-primary);
  font-weight: 500;
  border-bottom: 1px solid var(--border-medium);
}

.tabelle-einheit {
  display: block;
  font-size: var(--text-xs);
  color: var(--text-secondary);
  font-weight: 400;
}

/* Erste Spalte (t) angefroren – beim seitlichen Scrollen bleibt die Zeit da */
.tabelle-wrap th:first-child,
.tabelle-wrap td:first-child {
  position: sticky;
  left: 0;
  background: var(--bg-panel);
  z-index: 1;
}

.tabelle-wrap thead th:first-child {
  z-index: 3;
  background: var(--bg-secondary);
}

/* Zeile des aktuellen Bildes: Cursorfarbe wie der Laufpunkt im Diagramm */
.tabelle-wrap tr.aktuell td {
  color: #FF3B30;
  font-weight: 500;
}

.tabelle-wrap tr.aktuell td:first-child {
  box-shadow: inset 3px 0 0 #FF3B30;
}

/* Tippen springt zum Bild – die ganze Zeile ist Trefffläche */
.tabelle-wrap tbody tr { cursor: pointer; }
.tabelle-wrap tbody tr:hover td { background: var(--bg-secondary); }

/* ---- Spalte verdecken (S31) ------------------------------------------------
   Klick auf den Spaltenkopf verbirgt die WERTE dieser Größe – gedacht zum
   Selbst-Ausrechnen: verdecken, rechnen lassen, wieder aufdecken. Der Kopf
   bleibt stehen (er ist der Weg zurück) und wird durchgestrichen.
   Die Spalte schrumpft dabei auf die Breite ihres Formelzeichens zusammen,
   damit die hinteren Spalten nachrücken – genau dafür blendet man ja aus
   (Nutzerbefund: eine breite Leerspalte verdeckte weiterhin den Rest).
   Die Werte werden nur unsichtbar gemacht, nicht gelöscht. */
.tabelle-wrap thead th { cursor: pointer; }

.tabelle-wrap th.spalte-aus {
  /* Kein opacity: Der Kopf steht sticky über den Zeilen und müsste sonst
     durchscheinen. Stattdessen Farbe dämpfen und durchstreichen. */
  color: var(--text-secondary);
  text-decoration: line-through;
}

.tabelle-wrap th.spalte-aus .tabelle-einheit { opacity: 0.6; }

/* Die drei Selektoren decken auch die Cursor-Zeile (rot) und den Hover ab –
   sonst blitzte der verdeckte Wert dort wieder auf. */
.tabelle-wrap td.spalte-aus,
.tabelle-wrap tr.aktuell td.spalte-aus,
.tabelle-wrap tbody tr:hover td.spalte-aus {
  /* font-size: 0 statt color: transparent – so beansprucht der Wert AUCH
     KEINE BREITE mehr und die Spalte fällt auf das Maß ihres Kopfes
     zusammen. Der Text bleibt im Dokument (Wiedereinblenden ohne Neuaufbau). */
  font-size: 0;
  user-select: none;
  /* Feine Schraffur: zeigt, dass hier bewusst etwas verborgen ist – eine
     einfach leere Spalte sähe nach fehlenden Daten aus. */
  background-image: repeating-linear-gradient(
    -45deg,
    rgba(255, 255, 255, 0.05) 0 3px,
    transparent 3px 7px);
}

/* Minimales Polster für die zusammengeschobene Spalte; im Kopf entfallen
   Einheit und Sperrschrift, damit wirklich nur noch das Formelzeichen die
   Breite bestimmt (Nutzervorgabe: „Referenzbreite ist die Breite des
   Größenzeichens"). Am Handy zählt jeder Bildpunkt doppelt. */
.tabelle-wrap th.spalte-aus,
.tabelle-wrap td.spalte-aus {
  padding-left: 2px;
  padding-right: 2px;
  /* width: 1px heißt im Auto-Layout „so schmal wie der Inhalt erlaubt" –
     die Spalte fällt damit auf Zeichenbreite + Polster zusammen (gemessen
     375 px breit: 14,6 px → 10,6 px). max-width ist die Notbremse, falls
     das Layout doch Restbreite verteilen will; 3,5 Zeichen fassen auch
     Formelzeichen mit Index (vₓ, Eₘ), es wird nichts abgeschnitten. */
  width: 1px;
  max-width: 3.5ch;
  min-width: 0;
  overflow: hidden;
}

.tabelle-wrap th.spalte-aus {
  letter-spacing: 0;
  /* Der Durchstrich darf die Zelle nicht verbreitern */
  text-decoration-thickness: 1px;
}

.tabelle-wrap th.spalte-aus .tabelle-einheit { display: none; }

.tabelle-hinweis {
  display: block;
  padding: 24px 16px;
  color: var(--text-secondary);
}

/* ---- Fit von Hand (S23) ----------------------------------------------------
   Schieberegler-Feld UNTER dem Diagramm (nimmt Höhe im Fluss, statt die
   Kurve zu überdecken). Einklappbar auf eine schmale Kopfzeile. */
.fit-panel {
  flex: 0 0 auto;
  background: var(--bg-secondary);
  border-top: 1px solid #FFD60A;
  padding: 0 10px 6px;
  max-height: 45%;
  overflow-y: auto;
}

/* Kopfzeile trägt ALLES Einzeilige: Klappknopf, kompakten Auto-Fit und R² –
   eine eigene Aktionszeile kostete auf dem Handy ~60 px Diagrammhöhe. */
.fit-panel-kopf {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  min-height: 40px;
}

/* Der Klappknopf sieht aus wie ein KNOPF (Nutzerbefund: als bloße gelbe
   Zeile wurde er nicht als klickbar erkannt) – Rahmen und Fläche wie die
   übrigen Knöpfe, in der Modellfarbe. Auf- wie eingeklappt derselbe Knopf. */
.fit-panel-klapp {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  min-height: 38px;
  padding: 5px 12px;
  background: var(--bg-primary);
  border: 1px solid #FFD60A;
  border-radius: var(--radius-sm);
  color: #FFD60A;
  font-size: var(--text-sm);
  text-align: left;
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.fit-panel-klapp:hover {
  background: var(--bg-secondary);
}

/* Formelkasten-Umschalter neben der Klappleiste: blendet Gleichung + R²
   im Diagramm aus, wenn sie auf dem Handy zu viel Kurve verdecken. */
.fit-formel-knopf {
  flex: 0 0 auto;
  min-height: 38px;
  padding: 5px 12px;
  font-size: var(--text-sm);
}

.fit-formel-knopf.active {
  border-color: #FFD60A;
  color: #FFD60A;
}

/* Knopfzeile unter den Reglern: Auto-Fit und "Zurück zum Video" teilen
   sich die Breite – dort ist Platz, und beide sind so gut zu treffen. */
.fit-panel-aktionen {
  display: flex;
  gap: 10px;
  padding-top: 10px;
}

.fit-panel-aktionen .btn {
  flex: 1 1 0;
  min-width: 0;
}

.fit-panel-kopf .fit-panel-r2 {
  margin-left: auto;
  color: var(--text-secondary);
  font-size: var(--text-sm);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}


.fit-zeile {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 34px;
}

.fit-zeile label {
  flex: 0 0 24px;
  color: var(--text-primary);
  font-size: var(--text-sm);
}

.fit-zeile input[type="range"] {
  flex: 1;
  min-width: 0;
  min-height: 34px;             /* schmaler als 44: Regler sind breit genug */
  accent-color: #FFD60A;
}

.fit-zeile .fit-wert {
  flex: 0 0 76px;
  text-align: right;
  font-size: var(--text-sm);
  font-variant-numeric: tabular-nums;
  color: var(--text-primary);
}


/* ---- Stroboskopbild (S23) -------------------------------------------------- */
.strobo-preview {
  display: block;
  width: 100%;
  max-height: 40vh;
  object-fit: contain;
  margin: 10px 0;
  background: var(--bg-dark);
  border: 1px solid var(--border-medium);
  border-radius: var(--radius-sm);
}

.strobo-punkte-label {
  display: flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
}

/* ---- Ziehen & Ablegen (S25) ------------------------------------------------
   Vollflächige Markierung, solange eine Datei über dem Fenster schwebt.
   pointer-events:none, damit sie die Drag-Ereignisse nicht selbst abfängt. */
.drop-overlay {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(15, 17, 21, 0.82);
  pointer-events: none;
}

.drop-overlay span {
  padding: 18px 30px;
  font-size: var(--text-lg);
  color: var(--text-primary);
  background: var(--bg-secondary);
  border: 2px dashed var(--color-accent);
  border-radius: var(--radius-lg);
}

/* ---- Analyse-Sperre (v89) ----------------------------------------------------
   Solange die Analyse läuft: abdunkelnde Fläche über ALLEM, mittig das Feld
   "Analyse läuft. 37 % fertig." Die Fläche fängt jede Berührung ab (KEIN
   pointer-events:none – anders als die Ablage-Markierung); #app-shell ist
   währenddessen zusätzlich inert (main.js). Ebene 90: über Menüs (60/70),
   aber UNTER dem Toast (100) – Hinweise des Laufs ("Farbverfolgung übernimmt",
   KI-Korrekturen) müssen lesbar bleiben. touch-action:none, damit am Handy
   keine Wisch-/Zoomgeste durchrutscht. */
.analyse-sperre {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  background: rgba(10, 10, 10, 0.62);
  touch-action: none;
}

.analyse-sperre-karte {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  width: min(92vw, 380px);
  padding: 22px 24px 18px;
  background: var(--bg-secondary);
  border: 1px solid var(--border-medium);
  border-left: 4px solid var(--color-accent);
  border-radius: var(--radius-lg);
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.6);
  text-align: center;
}

.analyse-sperre-text {
  font-size: var(--text-xl);
  font-weight: 500;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;   /* Prozent zählt hoch, ohne zu zappeln */
}

/* Dünner Balken als zweiter Kanal neben der Zahl – derselbe Fortschritt */
.analyse-sperre-balken {
  width: 100%;
  height: 6px;
  border-radius: 3px;
  background: rgba(255, 255, 255, 0.1);
  overflow: hidden;
}

.analyse-sperre-fill {
  height: 100%;
  width: 0;
  background: var(--color-accent);
  transition: width 0.15s linear;
}

.analyse-sperre-hinweis {
  font-size: var(--text-sm);
}

#btn-analyse-abbrechen {
  margin-top: 4px;
  min-width: 180px;
}

/* ---- Fit-Modus (S24): Video weicht, solange die Regler ausgeklappt sind ----
   Beim Modellanpassen wird das Video nicht gebraucht (Nutzerentscheidung):
   Das Diagramm rückt an die Stelle des Videos, die Regler an die
   ursprüngliche Stelle des Diagramms – der Bildschirm gehört ganz dem Fit.
   Einklappen der Kopfzeile stellt das normale Layout wieder her. */
#app-shell.fit-modus .video-area,
#app-shell.fit-modus .pane-splitter {
  display: none !important;   /* übersteuert auch die Splitter-Medienregel */
}

#app-shell.fit-modus .fit-panel {
  max-height: 55%;            /* Handy: untere Hälfte für die Regler */
}

/* Untere Leiste im Fit-Modus auf die reine Zeitleiste reduzieren:
   Ausschnittsgriffe und die Knopfzeile ("Video laden", Einzelbild) gehören
   zum Video, das gerade gar nicht zu sehen ist. Die Zeitleiste bleibt –
   sie bewegt den Laufpunkt auf der Kurve. Spart ~100 px fürs Diagramm. */
#app-shell.fit-modus .bottom-bar .transport,
#app-shell.fit-modus .clip-range {
  display: none;
}

/* ---- Stapelansicht am HANDY (v88): Video weicht, der Stapel bekommt die
   ganze Fläche. Nutzerbefund: In der gestapelten Handy-Ansicht (Video oben,
   darunter drei Felder für x, vₓ, aₓ) war jedes Feld nur wenige Zentimeter
   hoch – die Zusammenhänge zwischen den Ableitungen kaum zu erkennen. Beim
   Vergleich der Ableitungen wird das Video nicht gebraucht (Nutzerentscheidung:
   auf den Videoausschnitt wird an dieser Stelle verzichtet).
   NUR in der Handy-Ansicht: Die Medienregel ist die Verneinung der PC-Schwelle
   aus layout.css (geteilte Ansicht) – dort steht der Stapel neben dem Video
   und hat Höhe genug; ein quer gehaltenes Handy bleibt "Handy" (zu wenig Höhe
   für zwei Spalten, siehe layout.css). Die Klasse setzt refreshChartView, und
   zwar nur, wenn der Stapel wirklich Kurven zeigt – ohne Daten bliebe sonst
   ein leerer Schirm ohne Video (z.B. Stapel eingeschaltet, dann Video laden
   und Objekt markieren – dafür muss das Bild da sein).
   Die untere Leiste bleibt VOLLSTÄNDIG (anders als im Fit-Modus): Zeitleiste
   und Bildschritte bewegen den Laufpunkt durch alle drei Felder – genau das
   macht den Ableitungszusammenhang sichtbar. Kein !important nötig: In der
   Handy-Ansicht greift keine Splitter-/Spalten-Medienregel auf .video-area. */
@media not all and (min-width: 900px) and (min-height: 480px) {
  #app-shell.stapel-vollbild .video-area {
    display: none;
  }
}

.fit-panel-formel {
  color: #FFD60A;
  font-size: var(--text-sm);
  padding: 0 0 6px;
}

/* Breite Schirme (PC/Tablet, gleiche Schwelle wie die geteilte Ansicht):
   Diagramm links (wo das Video war), Regler als rechte Spalte (wo das
   Diagramm war). */
@media (min-width: 900px) and (min-height: 480px) {
  #app-shell.fit-modus .chart-column {
    flex-direction: row;
  }

  #app-shell.fit-modus .chart-area {
    flex: 1 1 auto;
    min-width: 0;
  }

  #app-shell.fit-modus .fit-panel {
    flex: 0 0 340px;
    max-height: none;
    overflow-y: auto;
    border-top: none;
    border-left: 1px solid #FFD60A;
    padding: 0 14px 10px;
  }

  /* "Tabelle + Diagramm" am PC/Beamer: Diagramm links (wo das Video war),
     Tabelle als rechte Spalte. Die Breite ist gedeckelt – die Tabelle hat
     viele Spalten und würde dem Diagramm sonst zu viel Fläche nehmen. */
  #app-shell.tabelle-diagramm .chart-column {
    flex-direction: row;
  }

  #app-shell.tabelle-diagramm .chart-area {
    flex: 1 1 auto;
    min-width: 0;
  }

  #app-shell.tabelle-diagramm .tabelle-wrap {
    /* Voreinstellung 42 %; der Schieber überschreibt sie. Die Deckelung
       entfällt, sobald von Hand gezogen wurde – bei 19 Spalten will man
       die Tabelle bewusst breit ziehen können. */
    flex: 0 1 var(--tabelle-anteil, 42%);
    max-width: var(--tabelle-anteil, 660px);
    border-top: none;
    border-left: 1px solid var(--border-medium);
  }

  /* Am PC steht der Schieber senkrecht zwischen Diagramm und Tabelle */
  #app-shell.tabelle-diagramm .tabelle-splitter {
    flex: 0 0 10px;
    cursor: col-resize;
  }

  #app-shell.tabelle-diagramm .tabelle-splitter::before {
    width: 3px;
    height: 46px;
  }

  #app-shell.tabelle-diagramm .tabelle-splitter::after {
    inset: 0 -8px;
  }

  /* Messwerttabelle am PC/Beamer (Nutzerwunsch): Der Kopf trägt die
     Formelzeichen und muss aus drei Metern lesbar sein. Die Zahlen wachsen
     moderat mit – ein großer Kopf über 13-px-Werten wäre am Beamer nutzlos.
     Am Handy bleibt die kompakte Fassung unverändert. */
  /* Schrift und Polster kommen aus messtabelle.js: Dort wird gerechnet, wie
     groß beides sein darf, damit rund 12 Datenzeilen gleichzeitig sichtbar
     bleiben (Nutzervorgabe – vorher waren es ~32 winzige). Die Werte hier
     sind nur der Rückfall, falls die Messung nicht greift. */
  .tabelle-wrap table { font-size: var(--tab-schrift, var(--text-base)); }

  .tabelle-wrap thead th {
    font-size: calc(var(--tab-schrift, 16px) * 1.1);
    font-weight: 500;
    padding: calc(var(--tab-polster, 7px) * 1.1) 14px;
  }

  .tabelle-wrap .tabelle-einheit {
    font-size: calc(var(--tab-schrift, 16px) * 0.72);
    margin-top: 1px;
  }

  .tabelle-wrap tbody td { padding: var(--tab-polster, 7px) 14px; }

  /* ---- Restliche Anzeigen am PC/Beamer (Inventur S31) ---------------------
     Am 1280-px-Schirm gemessen: Diese Texte standen noch auf 11–13 px und
     waren aus Klassenzimmer-Entfernung nicht mehr zu lesen. Die
     Bedienknöpfe (16 px) und die Kapseln/Readouts (18 px) waren bereits
     angepasst. */
  .status-bar #status-text {
    font-size: var(--text-base);   /* t, Bildnummer, fps, Maßstab */
  }

  #mode-badge {
    font-size: var(--text-sm);     /* Modus-Plakette, war 11 px */
  }

  /* Beschriftungen der Kopfzeilen-Knöpfe (Projekt öffnen/speichern, Export,
     PC koppeln) und der Menü-Knöpfe mit eigenem Textspan */
  .status-bar .btn-text,
  #btn-pclink {
    font-size: calc(15px * var(--ui-skala));   /* folgt dem Präsentationsmodus */
  }

  .menu-panel > .menu-gruppe {
    font-size: var(--text-sm);     /* Gruppenüberschriften, waren 11 px */
  }

  /* Natives Auswahlfeld ohne eigene Größe – erbte die Browser-Vorgabe */
  #fit-select,
  #stack-count-select {
    font-size: var(--text-base);
  }
}
