/* pythonlearn — Styles. Dunkles Theme, Lernseite nach Prototyp-Vorlage (Variante B). */

:root {
  --bg:          #0f172a;
  --surface:     #1e293b;
  --surface-2:   #243043;
  --surface-3:   #2c3a50;
  --border:      #334155;
  --border-soft: #283449;
  --text:        #e2e8f0;
  --text-muted:  #94a3b8;
  --text-dim:    #64748b;
  --accent:      #4ade80;
  --error-bg:    rgba(239, 68, 68, 0.1);
  --error-bd:    rgba(239, 68, 68, 0.3);
  --error-fg:    #f87171;

  /* Semantische Rollen (abgenommene UI-Vorlage). */
  --success:    var(--accent);     /* Grün:  erledigt, Primäraktion, Erfolg */
  --info:       #89b4fa;           /* Blau:  Modus-Pille, aktive Auswahl, Sensoren */
  --warning:    #facc15;           /* Amber: Tipps, Punkte, Aufmerksamkeit */
  --danger:     var(--error-fg);   /* Rot:   Stopp, Käfer, Fehler */
  --tertiary:   var(--text-muted); /* Grau:  gesperrt, Labels, Sekundär-Info */

  --success-bg: rgba(74, 222, 128, 0.12);
  /* ---- Bereichsfarben --------------------------------------------------
     Vier Abteilungen, die Schüler arbeiten meist nur einzelne davon durch.
     Die Farbe sagt, wo man ist, und traegt spaeter auch Punkte und Balken.

     Bewusst weg von Gruen, Rot und Gelb: die gehoeren den Signalen (richtig,
     falsch, Tipp) und duerfen nicht mit einer Ortsangabe konkurrieren.
     Muster aus sqllearn, dort seit dem 31.08. im Einsatz. */
  --bereich-signal:     #4f8ef7;          /* Grundwert: Joule */
  --bereich-signal-rgb: 79, 142, 247;

  --info-bg:    rgba(137, 180, 250, 0.14);
  --warning-bg: rgba(250, 204, 21, 0.12);
  --danger-bg:  var(--error-bg);

  /* Layout-Maße: durchgehender Header plus drei Spalten (Variante B, Bühne breit). */
  --header-h:   52px;
  --taskbar-h:  40px;
  --sidebar-w:  220px;
  /* Randwerte der beiden Kopfleisten. Beide ziehen daraus, damit die linke
     Kante von Marke, Navigationszone und Seitenleiste zusammenfaellt — sonst
     muesste jede Breakpoint-Stufe einzeln nachgerechnet werden. */
  --leiste-pad: 14px;
  --leiste-gap: 14px;
  --stage-w:    clamp(360px, 32vw, 560px);
  --rad-s:      6px;
  --rad-m:      8px;
  --rad-l:      12px;

  --speed:      280ms;

  --font: "Hanken Grotesk", ui-sans-serif, system-ui, -apple-system, sans-serif;
  --mono: "JetBrains Mono", ui-monospace, monospace;
}

* { box-sizing: border-box; }

/* Operatoren wie getippt: JetBrains Mono verschmilzt ==, !=, >= und <=
   per Ligatur zu Einzelzeichen. Im Lernkontext ist das Gift — die SUS
   muessen sehen, aus WELCHEN Tasten ein Operator besteht (Steves Befund
   2026-08-08 in der if-Theorie). Deshalb sind Ligaturen ueberall aus,
   wo Code dargestellt wird; der Editor ist zur Sicherheit dabei. */
code, pre, kbd,
.q-code, .q-block, .quiz-code,
.console-b, .cm-editor {
  font-variant-ligatures: none;
  font-feature-settings: "liga" 0, "calt" 0;
}

body {
  font-family: var(--font);
  background: var(--bg);
  color: var(--text);
  margin: 0;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--accent); }

/* ---- Auth-Seiten (Login / Registrierung) ---- */
.auth-wrap {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
}
.auth-box {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 2.5rem 2rem;
  width: 100%;
  max-width: 380px;
}
.auth-logo {
  font-size: 1.6rem;
  font-weight: 600;
  text-align: center;
  margin-bottom: 1.8rem;
}
.auth-logo span { color: var(--accent); }
.auth-field { margin-bottom: 1rem; }
.auth-field label {
  display: block;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--text-muted);
  margin-bottom: 0.4rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.auth-field input {
  width: 100%;
  padding: 0.65rem 0.9rem;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text);
  font-size: 0.95rem;
}
.auth-field input:focus { outline: none; border-color: var(--accent); }
.auth-hint { font-size: 0.75rem; color: var(--text-muted); margin-top: 0.3rem; }
.auth-hinweis { font-size: 0.85rem; color: var(--text-muted); line-height: 1.5; margin: 0 0 1rem; }
.auth-error {
  background: var(--error-bg);
  border: 1px solid var(--error-bd);
  color: var(--error-fg);
  border-radius: 6px;
  padding: 0.6rem 0.9rem;
  font-size: 0.88rem;
  margin-bottom: 1rem;
}
.auth-btn {
  width: 100%;
  padding: 0.7rem;
  background: var(--accent);
  color: #06281a;
  border: none;
  border-radius: 6px;
  font-size: 0.95rem;
  font-weight: 600;
  cursor: pointer;
  margin-top: 0.5rem;
}
.auth-btn:hover { opacity: 0.9; }
.auth-link { text-align: center; margin-top: 1.2rem; font-size: 0.85rem; color: var(--text-muted); }
.auth-link a { text-decoration: none; }
.auth-link a:hover { text-decoration: underline; }

/* ===========================================================================
   Lernseite — Header · Aufgabenzeile · Body [Sidebar | Editor | Bühne]
   =========================================================================== */
.shell { display: flex; flex-direction: column; height: 100vh; overflow: hidden; }
button { font-family: inherit; color: inherit; cursor: pointer; }
.spring { flex: 1 1 auto; }

/* ---- Header ---- */
.topbar {
  height: var(--header-h); flex: 0 0 auto;
  display: flex; align-items: center; gap: var(--leiste-gap); padding: 0 var(--leiste-pad);
  background: var(--surface); border-bottom: 1px solid var(--border);
}
/* ── Durchgangs-Signal ───────────────────────────────────────────────────
   Regel seit 2026-09-05 (Steve): Der Bereich faerbt die Dinge, der Durchgang
   faerbt die Kopfzeile. Ab Durchgang 2 nimmt jede Kopfzeile der Plattform
   denselben orangen Ton an, oben abgeschlossen durch einen Streifen. Orange
   ist die einzige in beiden Plattformen freie Farbe; Durchgang 3 nutzt
   dieselbe Flaeche in dunklerem Ton statt in mehr Hoehe.
   Der Streifen liegt fest ueber dem Inhalt und kostet keine Hoehe. */
.dg-streifen { position: fixed; top: 0; left: 0; right: 0; height: 3px; z-index: 1000; pointer-events: none; background: transparent; }
body.dg-2 { --dg-signal: #f97316; --dg-signal-soft: rgba(249, 115, 22, .18); }
body.dg-3 { --dg-signal: #c2410c; --dg-signal-soft: rgba(194, 65, 12, .28); }
body.theme-light.dg-2 { --dg-signal: #c2410c; --dg-signal-soft: rgba(194, 65, 12, .18); }
body.theme-light.dg-3 { --dg-signal: #9a3412; --dg-signal-soft: rgba(154, 52, 18, .26); }
body.dg-2 .dg-streifen, body.dg-3 .dg-streifen { background: var(--dg-signal); }
body.dg-2 .topbar, body.dg-3 .topbar {
  /* Fester Wert zuerst: color-mix kennen aeltere Schul-Tablets nicht. */
  background: rgba(249, 115, 22, .09);
  border-bottom-color: rgba(249, 115, 22, .38);
  background: color-mix(in srgb, var(--dg-signal) 9%, var(--surface));
  border-bottom-color: color-mix(in srgb, var(--dg-signal) 38%, var(--border));
}
body.dg-3 .topbar {
  background: rgba(194, 65, 12, .14);
  border-bottom-color: rgba(194, 65, 12, .45);
  background: color-mix(in srgb, var(--dg-signal) 14%, var(--surface));
  border-bottom-color: color-mix(in srgb, var(--dg-signal) 45%, var(--border));
}
/* Die aktive Durchgangs-Pille traegt ab Durchgang 2 dieselbe Farbe wie die
   Flaeche — in Durchgang 1 bleibt sie in der Bereichsfarbe. */
body.dg-2 .dg-btn.active, body.dg-3 .dg-btn.active {
  background: var(--dg-signal-soft); color: var(--dg-signal);
}

.brand {
  display: flex; align-items: center; gap: 8px;
  /* Feste Breite OHNE Schrumpfen: die Marke bildet die linke Flucht zur
     Seitenleiste. Ohne flex-shrink: 0 gab sie nach, sobald die Reiter Platz
     brauchten (gemessen von 206 auf 140px bei 1160), und dehnte sich wieder
     aus, sobald diese bei 1150 ihre Namen verloren — die Bereiche wanderten
     dabei erst nach links und mit einem Satz zurueck (Befund Steve
     2026-09-05). Konstant bis zu ihrem Verschwinden bei 800px. */
  width: calc(var(--sidebar-w) - var(--leiste-pad));
  flex: 0 0 calc(var(--sidebar-w) - var(--leiste-pad));
  font-size: 15px; font-weight: 600; letter-spacing: -0.01em; white-space: nowrap;
}
/* Logo, Reiter, Punktestand und Balken tragen die Bereichsfarbe. Der frueher
   feste gruene Verlauf sagte in allen vier Abteilungen dasselbe. */
.brand .logo {
  width: 26px; height: 26px; border-radius: 8px; display: grid; place-items: center;
  background: rgba(var(--bereich-signal-rgb), .16); color: var(--bereich-signal);
  font-size: 16px;
}
.brand { color: var(--bereich-signal); }
.brand b { font-weight: 700; }
.brand .dot { color: var(--accent); }

/* Alle Gruppen der Kopfleiste tragen dieselbe Hoehe — vorher standen 34, 33
   und 39 nebeneinander und sprangen gegeneinander (Befund Steve 2026-09-05). */
.modes, .dg, .status, .uicon { height: 34px; box-sizing: border-box; }
.modes {
  display: flex; align-items: center; gap: 2px;
  background: var(--bg); border: 1px solid var(--border); border-radius: var(--rad-m); padding: 3px;
}
.mode {
  display: flex; align-items: center; gap: 5px; border: none; background: transparent; color: var(--text-muted);
  padding: 5px 11px; border-radius: 7px; font-size: 13px; font-weight: 500;
  transition: background .15s, color .15s;
}
.mode i { font-size: 16px; }
.mode.active { background: rgba(var(--bereich-signal-rgb), .14); color: var(--bereich-signal); }
.mode.locked { color: var(--text-dim); cursor: not-allowed; }
.mode.locked .ti-lock { font-size: 13px; }
.mode:not(.active):not(.locked):hover { background: var(--surface-2); color: var(--text); }

.status {
  display: flex; flex-direction: column; justify-content: center; gap: 3px;
  background: var(--bg); border: 1px solid var(--border); border-radius: var(--rad-m);
  padding: 0 12px; min-width: 120px;
}
.status .row { display: flex; align-items: center; justify-content: space-between; gap: 14px; }
.status .metric { display: flex; align-items: center; gap: 5px; font-weight: 600; font-size: 13px; }
/* Der Stern traegt die Bereichsfarbe, der Blitz bleibt gelb: Punkte gehoeren
   zur Abteilung, die Joker sind eine eigene Waehrung. */
.status .metric i { font-size: 15px; color: var(--warning); }
.status .metric:first-child i { color: var(--bereich-signal); }
.bar { height: 4px; border-radius: 3px; background: var(--border); overflow: hidden; }
.bar > span { display: block; height: 100%; width: 0%; background: var(--bereich-signal); border-radius: 3px; transition: width .4s, background .2s; }

.uicon {
  width: 34px; border-radius: 9px; display: grid; place-items: center;
  background: transparent; border: 1px solid transparent; color: var(--text-muted); font-size: 19px;
  transition: background .15s, color .15s, border-color .15s;
}
.uicon:hover { background: var(--surface-2); color: var(--text); border-color: var(--border); }

/* Die Marke weicht als Ganzes, Schriftzug und Logo zusammen. Ihr Icon allein
   waere doppelt gemoppelt: direkt daneben steht der Bereichsreiter mit
   demselben Bild, und es braechte nichts, weil ihre Breite an die
   Seitenleiste gekoppelt ist: Nur den Schriftzug auszublenden spart gemessen
   null Pixel (2026-09-10).
   Die Schwelle lag zuerst bei 800px, dann bei 950 und 975. Seit 2026-09-10
   steht sie hier bei 1180px und damit VOR den Bereichsnamen: Die Marke ist
   mit 220px der groesste einsparbare Posten der Zeile, und ihr Platz ist
   genau das, was die Bereichsnamen 220px laenger stehen laesst (Entscheid
   Steve 2026-09-10, Vorgabe „Namen so lange wie moeglich"). */
@media (max-width: 1180px) {
  .topbar .brand { display: none; }
  /* Ohne Marke gibt es keine Flucht mehr zu halten: die Navigation nimmt nur
     noch, was sie braucht. */
  .taskbar > .nav { width: auto; margin-right: 0; }
}

/* Bereichsnamen als letzte Stufe der Kopfzeile. Vor ihnen weichen der
   Durchgang (1500), der Punktestand samt Abstaenden (1290) und die Marke
   (1180) — erst wenn alles davon weg ist, bleiben hier die blossen Icons,
   der Name steht weiter im title- und aria-label-Attribut.
   960px ist gemessen: Ohne Marke braucht die Zeile mit ausgeschriebenen Namen
   943px, das laesst 17px Luft. Vorher lag die Stufe bei 1180px. */
@media (max-width: 960px) {
  .mode-txt { display: none; }
  .mode { padding: 5px 9px; }
}

/* ---- Werkstatt (Personalisierung, Drawer-Inhalt) ---- */
.ws-cat { margin-bottom: 15px; }
.ws-cat .ws-label { font-size: 12px; font-weight: 600; color: var(--text-muted); margin-bottom: 7px; display: flex; align-items: center; gap: 8px; }
.ws-lock { font-size: 11px; font-weight: 500; color: var(--text-dim); display: inline-flex; align-items: center; gap: 3px; }
.ws-swatches { display: flex; gap: 8px; flex-wrap: wrap; }
.ws-swatch { width: 30px; height: 30px; border-radius: 50%; border: 2px solid transparent; padding: 0; }
.ws-swatch.active { border-color: var(--text); box-shadow: 0 0 0 2px var(--bg); }
.ws-cat.locked .ws-swatch { opacity: .35; cursor: not-allowed; filter: grayscale(0.4); }
.ws-swatch.ws-form { background: var(--surface-2); border-color: var(--border); color: var(--text-muted); display: grid; place-items: center; }
.ws-swatch.ws-form svg { width: 22px; height: 22px; }
.ws-swatch.ws-form.active { border-color: var(--text); color: var(--text); box-shadow: none; }
#btn-werkstatt, #btn-nachrichten, #btn-results { position: relative; }
#btn-nachrichten.has-new::after,
#btn-results.has-new::after,
#btn-werkstatt.has-new::after {
  content: ""; position: absolute; top: 5px; right: 5px;
  width: 8px; height: 8px; border-radius: 50%; background: var(--warning);
}

/* Theme-Umschalter: farbiges Kärtchen — amber Sonne im Dark, blauer Mond im Light. */
#btn-theme { background: var(--surface-2); border-color: var(--border); color: #f5a623; }
#btn-theme:hover { color: #ffbe45; border-color: var(--border); background: var(--surface-3); }
body.theme-light #btn-theme {
  background: #ffffff; border-color: var(--border); color: #2c6bd0;
  box-shadow: 0 2px 7px rgba(30,40,60,0.14);
}
body.theme-light #btn-theme:hover { color: #1d55b0; background: #ffffff; }

.account { position: relative; }
.avatar {
  width: 34px; height: 34px; border-radius: 50%; display: grid; place-items: center;
  background: var(--info-bg); color: var(--info); border: 1px solid #2c4060;
  font-size: 12px; font-weight: 600; letter-spacing: .02em;
}
.account-menu {
  position: absolute; top: 42px; right: 0; min-width: 170px; z-index: 30;
  background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--rad-m);
  box-shadow: 0 12px 30px rgba(0,0,0,.4); padding: 6px; display: flex; flex-direction: column; gap: 2px;
}
.account-menu[hidden] { display: none; }
.account-menu .account-name {
  display: flex; flex-direction: column; padding: 6px 8px 8px; border-bottom: 1px solid var(--border-soft);
  font-size: 13px; font-weight: 600; margin-bottom: 4px;
}
.account-menu .account-name span { font-size: 11px; font-weight: 400; color: var(--text-dim); text-transform: capitalize; }
.account-menu a {
  display: flex; align-items: center; gap: 8px; padding: 7px 8px; border-radius: 6px;
  color: var(--text); text-decoration: none; font-size: 13px;
}
.account-menu a i { font-size: 16px; color: var(--text-muted); }
.account-menu a:hover { background: var(--surface-3); }

/* ---- Aufgabenzeile ---- */
.taskbar {
  height: var(--taskbar-h); flex: 0 0 auto;
  display: flex; align-items: center; gap: 7px; padding: 0 var(--leiste-pad);
  background: var(--bg); border-bottom: 1px solid var(--border); font-size: 13px;
}
.nav { display: flex; align-items: center; gap: 6px; color: var(--text-muted); }
/* Die Navigation bekommt eine eigene Zone, so breit wie die Marke in der Zeile
   darueber. Dadurch beginnt alles Folgende auf derselben Kante wie die
   Bereichsreiter, statt irgendwo an der Seitenleiste zu haengen (Wunsch Steve
   2026-09-05). Der zusaetzliche Rand gleicht aus, dass die zweite Zeile mit
   7px Abstand arbeitet und die erste mit 14px. */
.taskbar > .nav {
  width: calc(var(--sidebar-w) - var(--leiste-pad));
  flex: 0 0 auto;
  /* Die zweite Zeile arbeitet mit 7px Abstand, die erste mit --leiste-gap.
     Der Rand gleicht die Differenz aus, damit beide Kanten zusammenfallen. */
  margin-right: calc(var(--leiste-gap) - 7px);
}
/* Drei gleich breite Plaetze. Feste Breite statt Inhaltsbreite, weil hier
   Beschriftungen sehr verschiedener Laenge stehen — „1.1" neben „5 Quiz", in
   der Sammelansicht „Quiz 12". Ohne sie verschob sich bei jedem Schritt die
   ganze Zeile und mit ihr die Knoepfe dahinter (Befund Steve 2026-09-05).
   Die Zone misst 210px: drei Plaetze zu 66px und zwei Luecken zu 6px gehen
   genau auf. */
.nav .pos, .nav .nav-schritt {
  display: inline-flex; align-items: center; justify-content: center;
  gap: 1px; width: 66px; padding: 2px 4px; border-radius: 6px;
  border: none; background: transparent;
  color: var(--text-dim); font: inherit; font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
/* Pfeil und Nachbarname sind ein Knopf: die ganze Flaeche fuehrt zum Ziel. */
.nav .nav-schritt { cursor: pointer; }
.nav .nav-schritt i { font-size: 16px; }
.nav .nav-schritt:hover:not(:disabled) { background: var(--surface-2); color: var(--text); }
.nav .nav-schritt:disabled { cursor: default; }
/* Am Anfang und Ende der Liste haelt der Knopf den Platz und zeigt nichts. */
.nav .nav-leer { visibility: hidden; }
.nav .pos.now { background: var(--info-bg); color: var(--info); font-weight: 600; }

.tchip {
  display: inline-flex; align-items: center; gap: 6px;
  background: transparent; border: 1px solid var(--border); color: var(--text-muted);
  padding: 4px 10px; border-radius: 8px; font-size: 12.5px; font-weight: 500; white-space: nowrap;
  transition: background .15s, color .15s, border-color .15s;
}
.tchip i { font-size: 15px; }
.tchip:hover { color: var(--text); border-color: var(--surface-3); background: var(--surface-2); }
.divider { width: 1px; height: 18px; background: var(--border); margin: 0 2px; }

.hint {
  display: inline-flex; align-items: center; gap: 5px; padding: 4px 10px; border-radius: 8px;
  background: transparent; border: 1px solid var(--border); color: var(--text-muted);
  font-size: 12.5px; font-weight: 600; white-space: nowrap;
  transition: background .15s, color .15s, border-color .15s;
}
.hint i { font-size: 15px; }

/* Zweite Leiste auf schmalen Geraeten. Gemessen bleiben bei 768px noch 57px
   Reserve; in Bereichen mit breiterer Lernpfad-Navigation ist die schneller
   aufgebraucht. Ab 820px verlieren deshalb Quiz und Loesung ihren Text und
   behalten nur das Icon — Einfuehrung, Theorie und Glossar behalten ihren
   Namen, weil ihre Icons allein nicht verstaendlich sind (Entscheid Steve
   2026-09-05). Darunter ruecken zusaetzlich die Abstaende zusammen. */
.chip-txt { display: inline; }

/* Punktestand ab 1290px nur als Icon. Die Kachel schrumpft dort zwar mit, ihr
   Inhalt aber nicht: die beiden Zahlen brauchen 69px in einer 63px breiten
   Zeile und schoben sich uebereinander (Befund Steve 2026-09-05). Der Knopf
   bleibt als Einstieg ins Fortschrittsfenster erhalten.
   Der Wert lag zuerst bei 920, dann bei 1030. Beide waren zu spaet: Gemessen
   braucht die volle Kopfzeile im schlimmsten Fall (Schueler in Joule, drei
   Durchgaenge, Schloss-Icons an den gesperrten Bereichen) 1269px, und unter
   1200px kommen 36px fuer die Touch-Groesse der Icon-Knoepfe dazu. Zwischen
   1269 und 1181 lief die Zeile deshalb ueber den Rand, am schlimmsten bei
   1181px um 124px: Theme-Knopf und Avatar waren abgeschnitten, und das traf
   mit 1194px genau ein iPad-Querformat (Befund 2026-09-08).
   Die Kachel gibt 80px frei, die engeren Abstaende 70px. Zusammen reicht das,
   und es ist bewusst dieser Posten: Die Bereichsnamen haben Vorrang
   (Entscheid Steve 2026-09-08), und die Zahlen der Kachel stehen ohnehin auch
   im Fortschrittsfenster. */
.status-icon { display: none; font-size: 19px; color: var(--text-muted); }
/* Seit 2026-09-11 (Befund Steve, iPad quer): die Kachel klappt nicht mehr nach
   fester Fensterbreite zusammen, sondern nur, wenn die Kopfzeile tatsaechlich
   ueberlaeuft. Das misst pruefeStatusKachel() in app.js und setzt dann
   body.status-kompakt; unter 1290px wird gemessen, darueber nie geklappt. Mit
   einem Durchgang-Knopf bleibt die Kachel auf dem iPad damit offen, mit dreien
   weicht sie wie bisher. */
body.status-messung .topbar > * { flex-shrink: 0 !important; }
body.status-schmal .status { min-width: 0; padding: 0 8px; }
body.status-schmal .status .bar { display: none; }
body.status-schmal .status .row { gap: 8px; }
body.status-kompakt .status { min-width: 0; width: 40px; padding: 0; align-items: center; justify-content: center; flex: 0 0 auto; }
body.status-kompakt .status .row, body.status-kompakt .status .bar { display: none; }
body.status-kompakt .status-icon { display: block; }
body.status-kompakt .status:hover .status-icon { color: var(--text); }
@media (max-width: 1290px) {
  /* Elf Elemente mit je 14px Luecke sind allein 140px. Auf schmalen Geraeten
     (iPad hochkant liegt bei 810px) zaehlt jeder Pixel mehr als die Luft.
     Beide Leisten ziehen aus denselben Variablen, die Flucht bleibt.
     Stand bis 2026-09-08 im 1180er-Block; hochgezogen, damit die
     Bereichsnamen dort nicht als Naechstes weichen muessen. */
  :root { --leiste-pad: 10px; --leiste-gap: 8px; }
}

/* Hier stand bis 2026-09-10 die Marken-Stufe (zuletzt 975px). Sie ist nach
   oben auf 1180px gewandert und steht jetzt beim Block der Bereichsnamen. */

@media (max-width: 765px) {
  #nav-pos { display: none; }
}

/* Dritte und letzte Stufe der Durchgangsleiste: unter 740px bleibt die blosse
   Zahl. Drei Knoepfe mit „DG" messen 160px, ohne 100px — das war der letzte
   grosse Posten, der die Kopfzeile unter 730px sprengte (gemessen
   2026-09-05). Der aktive Knopf traegt weiter seine Farbe, und die Gruppe
   steht direkt neben den Bereichsreitern; die Zahl bleibt damit eindeutig.
   Seit 2026-09-08 bei 760px: Bei 740 griff die Stufe zu spaet, von 749 bis
   741 ragte die Zeile um einen Pixel ueber den Rand. */
@media (max-width: 760px) {
  .dg-praefix { display: none; }
  .dg-btn { padding: 5px 8px; }
}

@media (max-width: 880px) {
  .chip-txt { display: none; }
  .taskbar { gap: 5px; padding: 0 10px; }
  /* Zusammen mit dem Text ruecken auch die Knoepfe enger: mit Text allein
     blieben bei 768px nur vier Pixel Reserve. */
  .tchip, .hint { padding-left: 8px; padding-right: 8px; }
}
.hint.t.ready { background: var(--warning-bg); color: var(--warning); border-color: #4a3c17; }
.hint.t.ready:hover { filter: brightness(1.12); }
.hint.kit:hover { color: var(--text); border-color: var(--surface-3); }
.hint.kit.ready, .hint.sol.ready { background: var(--warning-bg); color: var(--warning); border-color: #4a3c17; }
.hint.kit.ready:hover, .hint.sol.ready:hover { filter: brightness(1.12); }
.tcard pre { margin: 6px 0 0; padding: 8px 10px; background: var(--surface-2); border-radius: 6px; overflow: auto; }
.tcard pre code { font-family: 'JetBrains Mono', monospace; font-size: 12px; white-space: pre; }
/* Strukto: die Musterlösung ist eine Text-Form mit langen Operator-Zeilen —
   in der schmalen Tipp-Spalte umbrechen statt horizontal scrollen. */
body.mode-strukto .tcard pre code { white-space: pre-wrap; }
.hint.locked { color: var(--text-dim); border-color: var(--border-soft); cursor: not-allowed; }
/* KI-Kontingent: Rest am KIT-Knopf; „leer" = aufgebraucht (kein Abzug, Lösung bleibt erreichbar). */
.kit-rest { font-size: 10.5px; font-weight: 600; padding: 0 5px; border-radius: 999px; background: var(--surface-3); color: var(--text-muted); line-height: 16px; }
.hint.kit.ready .kit-rest { background: rgba(0,0,0,.18); color: inherit; }
.hint.kit.leer, .hint.kit.leer:hover { background: transparent; color: var(--text-dim); border-color: var(--border-soft); filter: none; }
.hint.kit.leer .kit-rest { background: var(--danger-bg); color: var(--danger); }
/* Stufen-Pille in Freigaben (J1 blau, J2 amber) und Sortier-Chips */
.adm-pill.stufe { font-weight: 700; margin-right: 6px; padding: 0 7px; }
.adm-pill.stufe.s1 { color: var(--info); border-color: var(--info); background: var(--info-bg); }
.adm-pill.stufe.s2 { color: var(--warning); border-color: var(--warning); background: var(--warning-bg); }
/* Freigaben-Tabelle: Modus-Auswahl farbig (zu grau, kette blau, frei grün, erledigt amber), Block daneben, DG rechts. */
.frg-form { display: inline-flex; align-items: center; gap: 4px; }
.frg-modus { font: inherit; font-size: 12px; font-weight: 600; padding: 6px 5px; min-height: 34px; border-radius: 6px; border: 1px solid var(--border); background: transparent; color: var(--text-muted); }
.frg-m-zu .frg-modus { color: var(--text-dim); border-style: dashed; }
.frg-m-kette .frg-modus { color: var(--info); border-color: var(--info); background: var(--info-bg); }
.frg-m-frei .frg-modus { color: var(--success); border-color: var(--success); background: var(--success-bg); }
.frg-m-erledigt .frg-modus { color: var(--warning); border-color: var(--warning); background: var(--warning-bg); }
.frg-block { font: inherit; font-size: 12px; padding: 6px 5px; min-height: 34px; border-radius: 6px; border: 1px solid var(--border); background: transparent; color: var(--text); max-width: 100%; }
.frg-dgz { text-align: center; }
.frg-dgz .frg-dg { width: auto; min-width: 3.5ch; text-align: center; }
th.frg-dgk { font-size: 10px; white-space: nowrap; width: 1%; }
/* Lernpfad: gesperrter Block in der Kette */
.blk-h.locked { color: var(--text-dim); cursor: not-allowed; }
.blk-h.locked .blk-lock { margin-left: auto; font-size: 13px; }
.hint.locked .ti-lock { font-size: 12px; }
/* Gesperrter Tipp-Button (auch im Quiz-Modus): disabled schlägt jede .ready-Färbung. */
.hint:disabled { background: transparent; color: var(--text-dim); border-color: var(--border-soft); cursor: not-allowed; opacity: .55; filter: none; }
.hint:disabled:hover { background: transparent; color: var(--text-dim); border-color: var(--border-soft); filter: none; }

/* ---- Body ---- */
.body { flex: 1 1 auto; display: flex; min-height: 0; position: relative; }

/* Sidebar / Lernpfad */
.rail {
  width: var(--sidebar-w); flex: 0 0 auto; background: var(--surface);
  border-right: 1px solid var(--border); padding: 14px 12px; overflow-y: auto;
}
.rail h2 { margin: 2px 4px 10px; font-size: 10.5px; font-weight: 600; letter-spacing: .13em; color: var(--text-dim); text-transform: uppercase; }
.lernpfad { display: flex; flex-direction: column; gap: 6px; }
.blk { display: flex; flex-direction: column; }
.blk-h { display: flex; align-items: center; gap: 8px; padding: 7px 8px; border-radius: 8px; font-size: 12.5px; color: var(--text-muted); font-weight: 500; text-transform: uppercase; letter-spacing: .03em; }
.blk-h i { font-size: 16px; }
/* Der Abschluss steht rechts, dort wo bei den Aufgaben die Punkte stehen.
   Links bleibt der Pfeil: er sagt auf- oder zugeklappt, nicht fertig. */
.blk-fertig { margin-left: auto; display: inline-flex; align-items: center; color: var(--accent); }
.blk-fertig i { font-size: 15px; }
.blk-h.done i { color: var(--accent); }
.blk-h.open { color: var(--text); font-weight: 600; }
.blk-h.open > .ti-chevron-down { color: var(--info); }
.blk-h.lock { color: var(--text-dim); }
.items { margin: 2px 0 6px; display: flex; flex-direction: column; gap: 2px; }
.item {
  display: flex; align-items: center; gap: 8px; width: 100%; text-align: left;
  padding: 6px 8px 6px 14px; border-radius: 7px; font-size: 12.5px; color: var(--text-muted);
  background: transparent; border: 1px solid transparent;
}
.item i { font-size: 15px; color: var(--text-dim); }
.item:hover { background: var(--surface-2); color: var(--text); }
.item.done i { color: var(--accent); }
.item.active { background: var(--info-bg); color: var(--info); font-weight: 600; border-color: #26405f; }
.item.active i { color: var(--info); }
.item .pts { margin-left: auto; font-family: var(--mono); font-size: 11px; font-weight: 600; color: var(--accent); display: flex; align-items: center; gap: 3px; }
.item .pts i { font-size: 13px; color: var(--accent); }
.item .pts.full, .item .pts.full i { color: var(--accent); }
.item .pts.mid,  .item .pts.mid i  { color: var(--warning); }
.item .pts.low,  .item .pts.low i  { color: #d98a2b; }
.item .pts.zero, .item .pts.zero i { color: var(--text-dim); }
.item .num { font-family: var(--mono); font-size: 12px; letter-spacing: .02em; }

/* Quiz im Lernpfad (Entscheid Steve 2026-09-05): Es steht als letztes Ziel
   unter den Aufgaben seines Blocks, weil es ein Arbeitsauftrag ist und kein
   Nachschlagewerk. Ein feiner Abstand nach oben setzt es von den Aufgaben ab,
   ohne eine Trennlinie zu ziehen — es gehoert zum Block, ist aber anderer Art. */
.item.quiz-item { margin-top: 4px; }
.item.quiz-item .num { font-family: inherit; letter-spacing: 0; }
.item.quiz-item i { color: var(--warning); }
.item.quiz-item.done i { color: var(--accent); }
/* Gesperrt: sichtbar, aber erkennbar nicht anklickbar. Der Grund steht im
   title-Attribut, damit die Zeile keine zweite Textzeile braucht. */
.item.quiz-item.locked { opacity: .45; cursor: not-allowed; }
.item.quiz-item.locked:hover { background: transparent; color: var(--text-muted); }
.item.quiz-item.locked i { color: var(--text-dim); }
/* Sammelansicht ohne Quiz: eine Zeile Erklaerung statt einer leeren Leiste. */
.lp-leer { margin: 8px 4px; font-size: 12.5px; line-height: 1.5; color: var(--text-dim); }

/* Umschalter „Alle Quiz" im Quiz-Kopf. Gedrueckter Zustand wie bei den
   Bereichsreitern oben: leichte Farbfuellung statt wechselnder Beschriftung. */
#btn-quiz-alle.active {
  background: rgba(var(--bereich-signal-rgb), .14);
  color: var(--bereich-signal);
  border-color: rgba(var(--bereich-signal-rgb), .35);
}

/* Hauptbereich */
/* overflow-y: auto statt hidden — bei kleiner Viewport-Höhe (iPad) wurde die
   Konsole sonst unsichtbar abgeschnitten, ohne dass man hinscrollen konnte. */
.work { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 11px; padding: 16px 18px; overflow-y: auto; overflow-x: hidden; }
.task-title { display: flex; align-items: center; gap: 9px; font-size: 18px; font-weight: 700; letter-spacing: -0.015em; color: var(--text); }
.task-title .taskico { width: 23px; height: 23px; border-radius: 7px; display: grid; place-items: center; background: var(--success-bg); color: var(--accent); font-size: 15px; }
/* pre-line: Zeilenumbrüche aus dem Content bleiben erhalten (Python-Aufgaben
   zeigen z.B. den geforderten Soll-Output mehrzeilig in der Beschreibung). */
/* Keine Breitenbegrenzung: Der Aufgabentext läuft so breit wie der Editor
   darunter, sonst brechen kurze Aufträge unnötig früh um. */
.task-desc { color: var(--text); font-size: 15px; line-height: 1.6; white-space: pre-line; }
.task-desc code { font-family: var(--mono); font-size: 13.5px; color: var(--accent); background: var(--success-bg); padding: 1px 5px; border-radius: 5px; }
/* Aufgabentext-Auszeichnung: Objektfarben, Richtungswörter, Code-Chips in Editor-Farben. */
.task-desc .desc-code {
  font-family: var(--mono); font-size: 12.5px; color: var(--text);
  background: var(--surface-2); border: 1px solid var(--border-soft);
  padding: 1px 5px; border-radius: 5px;
}
.task-desc .desc-code.chip-cmd    { color: #a6e3a1; }
.task-desc .desc-code.chip-sensor { color: #7dd3fc; }
.task-desc .desc-code.chip-userfn { color: #7dd3fc; }
.task-desc .desc-code.chip-kw     { color: #e2a2ff; }
/* Arbeitsauftrag in der Beschreibung: Balken + Akzentfarbe (Muster sqllearn),
   damit der eigentliche Auftrag beim Überfliegen nicht untergeht. */
.task-desc .desc-auftrag { border-left: 3px solid var(--info); border-radius: 0; padding: 0 0 0 12px; margin: 0; color: var(--text); font-weight: 500; line-height: 1.6; }
.task-desc .kw-joule { color: #5f8de8; font-weight: 600; }
.task-desc .kw-box   { color: #93a0b2; font-weight: 600; }
.task-desc .kw-wall  { color: #c96b4d; font-weight: 600; }
.task-desc .kw-cell  { color: #f9d54a; font-weight: 600; }
.task-desc .kw-mark  { color: #f9d54a; font-weight: 600; }
.task-desc .dir-word { font-weight: 600; text-decoration: underline dotted; text-underline-offset: 3px; }
body.theme-light .task-desc .desc-code.chip-cmd    { color: #1f8f54; }
body.theme-light .task-desc .desc-code.chip-sensor { color: #2c6bd0; }
body.theme-light .task-desc .desc-code.chip-userfn { color: #2c6bd0; }
body.theme-light .task-desc .desc-code.chip-kw     { color: #8839ef; }
body.theme-light .task-desc .kw-joule { color: #3c66c4; }
body.theme-light .task-desc .kw-box   { color: #5d6879; }
body.theme-light .task-desc .kw-wall  { color: #a44a2f; }
/* Gelb lässt sich auf hellem Grund nicht abdunkeln, ohne braun zu wirken —
   im Light laufen Energiezelle/Zielfeld deshalb als Textmarker: heller
   Gelb-Hintergrund, Schrift im Goldton des Zellen-Blitzes. */
body.theme-light .task-desc .kw-cell,
body.theme-light .task-desc .kw-mark {
  color: #7a5800; background: #fdeeb0; padding: 0 4px; border-radius: 4px;
}

.editor { background: var(--surface); border: 1px solid var(--border); border-radius: var(--rad-l); overflow: hidden; flex: 0 0 auto; }
.editor-top { display: flex; align-items: center; gap: 8px; padding: 8px 13px; border-bottom: 1px solid var(--border-soft); font-size: 11px; letter-spacing: .1em; text-transform: uppercase; color: var(--text-dim); font-weight: 600; }
.editor-top i { font-size: 14px; }
.editor-top .lang { margin-left: auto; text-transform: none; letter-spacing: 0; font-family: var(--mono); font-size: 11px; }
.editor-resize {
  height: 16px; cursor: ns-resize; touch-action: none; user-select: none;
  display: grid; place-items: center; border-top: 1px solid var(--border-soft);
}
.editor-resize::before { content: ""; width: 46px; height: 4px; border-radius: 2px; background: var(--border); }
.editor-resize:hover::before, .editor-resize:active::before { background: var(--text-dim); }

.runbar { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; flex-wrap: wrap; }
.btn {
  display: inline-flex; align-items: center; gap: 7px; padding: 7px 14px; border-radius: 9px;
  font-size: 13px; font-weight: 600; border: 1px solid var(--border); background: var(--surface-2); color: var(--text);
  transition: transform .08s, background .15s, border-color .15s, opacity .15s;
}
.btn i { font-size: 16px; }
.btn:active { transform: translateY(1px); }
.btn.primary { background: linear-gradient(150deg, var(--accent), #34ac68); color: #08220f; border-color: transparent; }
.btn.primary:hover { filter: brightness(1.06); }
.btn.ghost { padding: 7px 9px; background: transparent; color: var(--text-muted); }
.btn.ghost:hover { background: var(--surface-2); color: var(--text); }
.btn.danger { color: var(--danger); }
.btn:disabled { opacity: .4; pointer-events: none; }
.tempo { display: flex; align-items: center; gap: 8px; color: var(--text-muted); padding-left: 4px; }
.tempo i { font-size: 16px; color: var(--text-dim); }
.tries { display: flex; align-items: center; gap: 5px; font-size: 11.5px; color: var(--text-muted); white-space: nowrap; padding-left: 2px; }
.tries i { font-size: 14px; }
.tries.warn { color: var(--warning); font-weight: 500; }
.tempo input[type=range] { width: 96px; accent-color: var(--accent); }
.tempo .ms { font-family: var(--mono); font-size: 11.5px; color: var(--text-dim); min-width: 50px; }

.console { background: var(--surface); border: 1px solid var(--border); border-radius: var(--rad-l); flex: 1 1 auto; min-height: 140px; display: flex; flex-direction: column; overflow: hidden; }
.console-h { padding: 8px 13px; border-bottom: 1px solid var(--border-soft); font-size: 11px; letter-spacing: .1em; text-transform: uppercase; color: var(--text-dim); font-weight: 600; }
.console-b { flex: 1; padding: 11px 14px; font-family: var(--mono); font-size: 12.5px; line-height: 1.55; color: var(--text-muted); overflow-y: auto; white-space: pre-wrap; }
.console-b:empty::before { content: "Ausgaben und Rückmeldungen erscheinen hier."; color: var(--text-dim); }

/* ----- Theorie-Bereich (ersetzt Editor + Bühne, wenn geöffnet) ----- */
/* ---- Theorie als Overlay über der Arbeitsfläche (Muster aus sqllearn) ----
   Die Theorie ist ein Blatt zum Lesen, kein Streifen neben dem Editor.
   Sie legt sich über .body: beim Lesen der ganze Platz, danach ist sie weg.
   Die Fläche nutzt den Platz (bis 96ch), der Fließtext bleibt auf
   Lesebreite (72ch). Geschlossen wird über das X, Esc oder einen Klick
   neben das Blatt (app.js). */
.theory {
  display: none; position: absolute; inset: 0; z-index: 40;
  background: color-mix(in srgb, var(--bg) 94%, transparent);
  backdrop-filter: blur(3px);
  overflow-y: auto; overscroll-behavior: contain;
  justify-content: center; padding: 22px 24px 40px;
}
body.theory-open .theory { display: flex; }
.theory-blatt { width: 100%; max-width: min(96ch, 100%); }
.theory-h { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; border-bottom: 1px solid var(--border); padding-bottom: 10px; margin-bottom: 18px; }
.theory-kopf-txt { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.theory-marke { font-family: var(--mono); font-size: 11px; font-weight: 600; letter-spacing: .12em; text-transform: uppercase; color: var(--text-dim); }
.theory-title { margin: 0; font-size: 19px; font-weight: 600; color: var(--text); }
.theory-title code { font-family: var(--mono); font-size: 0.85em; background: var(--surface-2); padding: 2px 7px; border-radius: 6px; }
.theory-zu { display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px; flex-shrink: 0; margin-left: auto; background: none; border: none; border-radius: 8px; color: var(--text-muted); cursor: pointer; }
.theory-zu:hover { background: var(--surface-2); color: var(--text); }
.theory-zu:focus-visible { outline: 2px solid var(--info); outline-offset: 2px; }
.theory-zu i { font-size: 18px; }
.theory-b { color: var(--text-muted); line-height: 1.68; font-size: 14.5px; text-wrap: pretty; }
.theory-b > p, .theory-b > ul { max-width: 72ch; }
.theory-b h3 { font-size: 15px; font-weight: 600; color: var(--text); margin: 20px 0 8px; }
.theory-b h3:first-child { margin-top: 2px; }
.theory-b p { margin: 0 0 11px; }
.theory-b ul { margin: 0 0 11px; padding-left: 20px; }
.theory-b li { margin: 3px 0; }
.theory-b code { font-family: var(--mono); font-size: 12.5px; background: var(--surface-2); padding: 1px 5px; border-radius: 5px; color: var(--text); }
.theory-b pre { background: var(--surface); border: 1px solid var(--border); border-radius: var(--rad-l); padding: 11px 13px; overflow-x: auto; margin: 0 0 13px; }
.theory-b pre code { background: none; padding: 0; font-size: 12.5px; line-height: 1.5; color: var(--text); display: block; }

/* ---- Theorie-Bausteine: Merksatz, Lauf-Beispiel, Merk-Karten, Video, Knopf-Erklärung ---- */
.theory-b .th-merk { margin: 11px 0; padding: 10px 14px; background: var(--success-bg); border: 1px solid rgba(74, 222, 128, 0.35); border-radius: var(--rad-m); color: var(--text); font-size: 15px; font-weight: 600; line-height: 1.5; }
.theory-b .th-rot { color: var(--danger); font-weight: 600; }
.theory-b .th-lauf { display: flex; align-items: stretch; gap: 10px; margin: 0 0 11px; flex-wrap: wrap; }
.theory-b .th-lauf-box { flex: 1 1 180px; min-width: 0; }
.theory-b .th-lauf-box pre { margin: 0; padding: 8px 12px; }
.theory-b .th-lauf-label { display: block; font-size: 10.5px; font-weight: 600; letter-spacing: .1em; text-transform: uppercase; color: var(--text-dim); margin-bottom: 3px; }
.theory-b .th-lauf-pfeil { align-self: center; margin-top: 13px; font-size: 18px; color: var(--text-dim); }
.theory-b .th-karten { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 8px; margin: 0 0 11px; }
.theory-b .th-karte { display: flex; flex-direction: column; gap: 3px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--rad-m); padding: 9px 12px; }
.theory-b .th-karte-kopf { display: flex; align-items: center; gap: 7px; }
.theory-b .th-karte-kopf i { font-size: 16px; color: var(--info); flex: 0 0 auto; }
.theory-b .th-karte-t { color: var(--text); font-weight: 600; font-size: 13.5px; line-height: 1.35; }
.theory-b .th-karte-x { color: var(--text-muted); font-size: 13px; line-height: 1.5; }
.theory-b .th-video { display: flex; align-items: center; gap: 9px; margin: 0 0 11px; padding: 6px 12px; border: 1px dashed var(--border); border-radius: var(--rad-m); color: var(--text-dim); font-size: 13px; }
.theory-b .th-video i { font-size: 16px; }
/* Klickbarer Verweis auf die Einführung: gleiche Zeilenform wie der Video-
   Platzhalter, aber durchgezogen und anklickbar statt gestrichelt und grau. */
.theory-b .th-einf { width: 100%; border-style: solid; border-color: var(--info); background: none; color: var(--info); font: inherit; font-size: 13px; text-align: left; cursor: pointer; }
.theory-b .th-einf:hover { background: color-mix(in srgb, var(--info) 12%, transparent); }
/* Einführung je Aufgabe (Arrays-Block 2): Knopf mit Name, farbig abgesetzt,
   damit das Video zur Aufgabe nicht übersehen wird. */
#btn-einfuehrung.aufgabe { border-color: var(--info); color: var(--info); font-weight: 600; }
#btn-einfuehrung.aufgabe:hover { background: color-mix(in srgb, var(--info) 12%, transparent); }
.theory-b .th-knopf-zeile { display: flex; align-items: center; gap: 12px; margin: 0 0 8px; }
.theory-b .th-knopf { flex: 0 0 auto; pointer-events: none; }
.theory-b .th-knopf-x { color: var(--text-muted); font-size: 13.5px; line-height: 1.5; }
.out-info { color: var(--text-muted); }
.out-msg { color: var(--accent); }
.out-error { color: var(--danger); }
.out-success { color: var(--accent); font-weight: 700; }
.out-hint { color: var(--warning); }
.out-unlock { color: var(--warning); font-weight: 700; }

/* ----- Quiz-Modus (ersetzt Editor + Bühne, volle Breite, wenn geöffnet) ----- */
/* Quiz-Button in der Aufgabenzeile: aktiv markiert (Info-Blau) bzw. ausgegraut. */
.tchip.active { background: var(--info-bg); color: var(--info); border-color: #26405f; }
.tchip:disabled { color: var(--text-dim); border-color: var(--border-soft); cursor: not-allowed; opacity: .7; }
.tchip:disabled:hover { background: transparent; color: var(--text-dim); border-color: var(--border-soft); }

.quiz { display: none; flex: 1 1 auto; min-width: 0; flex-direction: column; gap: 13px; padding: 16px 18px; overflow: hidden; }
body.quiz-open .work, body.quiz-open .stage { display: none; }
body.quiz-open .quiz { display: flex; }
.quiz-h { display: flex; align-items: flex-end; gap: 12px; border-bottom: 1px solid var(--border-soft); padding-bottom: 11px; }
.quiz-eyebrow { display: block; font-size: 10.5px; font-weight: 600; letter-spacing: .13em; text-transform: uppercase; color: var(--text-dim); margin-bottom: 3px; }
.quiz-title { margin: 0; font-size: 19px; font-weight: 600; color: var(--text); }
.quiz-b { flex: 1 1 auto; overflow-y: auto; max-width: 760px; padding-right: 8px; }
.quiz-loading { color: var(--text-muted); font-size: 14px; }

.quiz-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--rad-l); padding: 18px 20px; }
.quiz-code { margin: 0 0 14px; padding: 12px 14px; background: var(--surface-2); border: 1px solid var(--border-soft); border-radius: var(--rad-m); overflow-x: auto; }
.quiz-code code { font-family: var(--mono); font-size: 13px; line-height: 1.6; color: var(--text); white-space: pre; }
.quiz-q { font-size: 15.5px; font-weight: 600; color: var(--text); line-height: 1.5; }
.quiz-multi-hint { display: flex; align-items: center; gap: 6px; margin-top: 6px; font-size: 12px; color: var(--info); }
.quiz-multi-hint i { font-size: 15px; }

/* Sprungleiste: Fragen direkt anwählen, Farbe zeigt richtig/falsch.
   padding 3px, damit der Fokus-Ring (box-shadow) nicht vom scrollenden
   Container abgeschnitten wird. */
.quiz-steps { display: flex; flex-wrap: wrap; gap: 7px; padding: 3px; margin-bottom: 12px; }
.quiz-step { min-width: 30px; height: 30px; padding: 0 8px; border-radius: var(--rad-m); border: 1px solid var(--border); background: var(--surface); color: var(--text-dim); font: 600 13px/1 inherit; cursor: pointer; display: inline-flex; align-items: center; justify-content: center; gap: 5px; }
.quiz-step:hover { border-color: var(--info); color: var(--text); }
.quiz-step.ok { border-color: var(--success); color: var(--success); }
.quiz-step.no { border-color: var(--danger); color: var(--danger); }
.quiz-step.now { box-shadow: 0 0 0 2px var(--info); color: var(--text); }
.quiz-step.res { font-size: 12px; }
.quiz-step.res i { font-size: 15px; }
.quiz-opts { display: flex; flex-direction: column; gap: 9px; margin-top: 15px; }
.quiz-opt {
  display: flex; align-items: center; gap: 11px; width: 100%; text-align: left;
  padding: 12px 14px; border-radius: var(--rad-m); font-size: 14px; color: var(--text);
  background: var(--surface-2); border: 1px solid var(--border);
  transition: background .12s, border-color .12s;
}
.quiz-opt:not(.locked):hover { border-color: var(--info); background: var(--surface-3); }
.quiz-opt.sel { border-color: var(--info); background: var(--info-bg); }
.quiz-mark { flex: 0 0 auto; width: 18px; height: 18px; border: 2px solid var(--text-dim); display: grid; place-items: center; }
.quiz-mark.radio { border-radius: 50%; }
.quiz-mark.box { border-radius: 5px; }
.quiz-opt.sel .quiz-mark { border-color: var(--info); }
.quiz-opt.sel .quiz-mark::after { content: ""; width: 8px; height: 8px; background: var(--info); border-radius: inherit; }
.quiz-opt-txt { flex: 1 1 auto; }
/* Code in Quiz-Texten: Monospace, damit " und ' klar unterscheidbar sind. */
.q-code { font-family: var(--mono); font-size: 13px; letter-spacing: .2px; background: var(--surface-2); border: 1px solid var(--border-soft); padding: 1px 6px; border-radius: 5px; color: var(--text); white-space: pre-wrap; }
/* Ganze Antwortoption als Ausgabeblock (Option beginnt mit ```): mehrzeilig
   in Monospace, so wie die Konsole es zeigt. So wird eine Ausgabe gezeigt
   statt in Prosa beschrieben. */
.q-block { display: block; font-family: var(--mono); font-size: 13px; line-height: 1.65; white-space: pre; color: var(--text); }
.quiz-opt.locked { cursor: default; }
.quiz-opt.correct { border-color: var(--success); background: var(--success-bg); }
.quiz-opt.correct .quiz-mark { border-color: var(--success); }
.quiz-opt.correct .quiz-mark::after { content: ""; width: 8px; height: 8px; background: var(--success); border-radius: inherit; }
.quiz-opt.wrong { border-color: var(--danger); background: var(--danger-bg); }
.quiz-opt.wrong .quiz-mark { border-color: var(--danger); }
.quiz-opt.wrong .quiz-mark::after { content: ""; width: 8px; height: 8px; background: var(--danger); border-radius: inherit; }

.quiz-answer { margin-top: 14px; }
.quiz-feedback { margin-top: 15px; padding: 13px 15px; border-radius: var(--rad-m); border: 1px solid var(--border); }
.quiz-feedback.ok { background: var(--success-bg); border-color: var(--success); }
.quiz-feedback.no { background: var(--danger-bg); border-color: var(--danger); }
.quiz-verdict { display: flex; align-items: center; gap: 7px; font-weight: 600; font-size: 14px; }
.quiz-feedback.ok .quiz-verdict { color: var(--success); }
.quiz-feedback.no .quiz-verdict { color: var(--danger); }
.quiz-verdict i { font-size: 18px; }
.quiz-feedback p { margin: 8px 0 0; font-size: 13.5px; line-height: 1.55; color: var(--text); }
.quiz-cardfoot { display: flex; justify-content: flex-end; margin-top: 16px; }

.quiz-result { background: var(--surface); border: 1px solid var(--border); border-radius: var(--rad-l); padding: 20px 22px; }
.quiz-score { display: flex; align-items: center; gap: 11px; font-size: 18px; color: var(--text); padding-bottom: 15px; border-bottom: 1px solid var(--border-soft); }
.quiz-score i { font-size: 26px; color: var(--info); }
.quiz-score b { color: var(--accent); }
.quiz-reslist { display: flex; flex-direction: column; gap: 4px; margin-top: 14px; }
.quiz-resrow { display: flex; align-items: center; gap: 10px; width: 100%; text-align: left; padding: 9px 11px; border-radius: var(--rad-m); background: transparent; border: 1px solid transparent; font-size: 13px; color: var(--text-muted); }
.quiz-resrow:hover { background: var(--surface-2); border-color: var(--border); }
.quiz-resrow i { font-size: 17px; flex: 0 0 auto; }
.quiz-resrow.ok i { color: var(--success); }
.quiz-resrow.no i { color: var(--danger); }
.quiz-resrow.skip i { color: var(--text-dim); }
.quiz-resnum { flex: 0 0 auto; font-weight: 600; color: var(--text); }
.quiz-restxt { flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---- Bühne ---- */
.stage {
  width: var(--stage-w); flex: 0 0 auto; position: relative; overflow: hidden;
  background: var(--bg); border-left: 1px solid var(--border);
  display: flex; flex-direction: column; gap: 10px; padding: 14px;
}
.stage-status { font-size: 11px; color: var(--warning); }
.cmd-ref { display: flex; flex-direction: column; gap: 8px; }
.cmd-group-label { font-size: 10.5px; font-weight: 600; letter-spacing: .13em; color: var(--text-dim); text-transform: uppercase; margin-bottom: 5px; }
.cmd-chips { display: flex; flex-wrap: wrap; gap: 5px; }
.cmd-chip {
  font-family: var(--mono); font-size: 11.5px; padding: 3px 8px; border-radius: 6px;
  background: var(--surface-2); border: 1px solid var(--border); color: var(--text-muted);
  transition: background .12s, border-color .12s, color .12s;
}
.cmd-chip.sensor { color: var(--info); background: var(--info-bg); border-color: #274062; }
/* Kontrollstrukturen in der Keyword-Farbe des Editors (for, while, if …) */
.cmd-chip.struktur { color: #e2a2ff; background: rgba(226, 162, 255, 0.10); border-color: #4b3a5c; white-space: nowrap; }
.cmd-chip.cmd-active { background: var(--accent); border-color: var(--accent); color: #08220f; font-weight: 700; }

.world-wrap { flex: 1 1 auto; display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: 0; }
.world-wrap h3 { width: 100%; margin: 0 0 7px; font-size: 10.5px; font-weight: 600; letter-spacing: .13em; color: var(--text-dim); text-transform: uppercase; }
.world {
  align-self: center;
  display: grid; gap: 3px; padding: 7px;
  background: radial-gradient(130% 130% at 30% 0%, #1b231d 0%, #161b18 65%, #141815 100%);
  border: 1px solid var(--border); border-radius: var(--rad-l);
}
.cell {
  width: var(--cell, 44px); height: var(--cell, 44px); border-radius: 5px;
  background: rgba(255,255,255,0.022); box-shadow: inset 0 0 0 1px rgba(255,255,255,0.03);
  display: flex; align-items: center; justify-content: center; position: relative; user-select: none;
  font-size: calc(var(--cell, 44px) * 0.6);
}
.cell.highlight { background: rgba(137,180,250,0.10); }
.cell.cell-error { box-shadow: inset 0 0 0 2px var(--danger) !important; background: rgba(243,139,168,0.30) !important; }
.joule-wrap { width: 88%; height: 88%; display: flex; align-items: center; justify-content: center; }
.joule-svg { width: 100%; height: 100%; transition: transform 0.12s linear; }
/* Fühler-Varianten (Werkstatt): nur die zu data-jant passende Gruppe rendern,
   Standard 'single'. Roboter-SVG enthält immer alle vier. */
.jant { display: none; }
:root[data-jant="single"] .jant-single,
:root[data-jant="double"] .jant-double,
:root[data-jant="bow"] .jant-bow,
:root[data-jant="bolt"] .jant-bolt,
:root:not([data-jant]) .jant-single { display: inline; }
.wall-block { width: 92%; height: 92%; display: flex; }
.wall-block svg { width: 100%; height: 100%; }
.box-crate { width: 92%; height: 92%; display: flex; }
.box-crate svg { width: 100%; height: 100%; }
.energy-cell { width: 60%; height: 60%; display: flex; }
.energy-cell svg { width: 100%; height: 100%; }
.energy-dot { position: absolute; bottom: 2px; left: 3px; width: 32%; height: 32%; }
.energy-dot svg { width: 100%; height: 100%; }
.goal-mark {
  position: absolute; inset: 8%; pointer-events: none;
  border: 2px dashed rgba(249,213,74,0.6); border-radius: 18%;
}
.goal-mark::after {
  content: ""; position: absolute; inset: 36%;
  border-radius: 50%; background: rgba(249,213,74,0.32);
}
body.theme-light .goal-mark { border-color: rgba(164,114,11,0.55); }
body.theme-light .goal-mark::after { background: rgba(164,114,11,0.28); }

/* ---- Tipp-Overlay ---- */
.scrim { position: absolute; inset: 0; background: rgba(8,10,13,0.45); opacity: 0; pointer-events: none; transition: opacity .25s; z-index: 5; }
.scrim.open { opacity: 1; pointer-events: auto; }
.tips {
  /* max-width, weil die Spalte absolut in .stage liegt und diese overflow:hidden
     traegt: im Strukto-Bereich ist die Buehne unter 1366px nur 300px breit, die
     Spalte wuerde dort sonst um 20px angeschnitten. */
  position: absolute; top: 0; right: 0; bottom: 0; width: 320px; max-width: 100%; z-index: 6;
  background: var(--surface); border-left: 2px solid var(--info);
  box-shadow: -16px 0 38px rgba(0,0,0,.34);
  display: flex; flex-direction: column;
  transform: translateX(108%); transition: transform .28s cubic-bezier(.3,.7,.3,1);
}
/* Auf heller Flaeche liest ein schwarzer Schatten als grauer Schleier statt
   als Tiefe. Blaugrau und deutlich schwaecher, Wert wie in sqllearn. */
body.theme-light .tips { box-shadow: -16px 0 38px rgba(15,23,42,.16); }
.tips.open { transform: translateX(0); }
.tips-h { display: flex; align-items: center; gap: 8px; padding: 13px 14px; border-bottom: 1px solid var(--border-soft); }
.tips-h .ti-bulb { color: var(--warning); font-size: 18px; }
.tips-h b { font-size: 14px; font-weight: 600; }
.tips-h .tag { font-size: 11px; color: var(--text-dim); }
.tips-h .x { margin-left: auto; width: 28px; height: 28px; border-radius: 7px; border: none; background: transparent; color: var(--text-muted); font-size: 18px; display: grid; place-items: center; }
.tips-h .x:hover { background: var(--surface-2); color: var(--text); }
.tips-b { padding: 13px 14px; display: flex; flex-direction: column; gap: 11px; overflow-y: auto; flex: 1; }
.tips-b:empty::before { content: "Tippe oben auf T1, um den ersten Hinweis zu öffnen."; color: var(--text-dim); font-size: 12.5px; }
.tcard { background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--rad-m); padding: 11px 13px; }
.tcard .lbl { font-family: var(--mono); font-size: 11px; color: var(--warning); margin-bottom: 5px; display: flex; align-items: center; gap: 6px; }
.tcard p { margin: 0; font-size: 13px; color: var(--text); line-height: 1.55; }
.tcard p code { font-family: var(--mono); font-size: 12px; color: var(--accent); }
.tcard .cost { margin-top: 7px; font-size: 11px; color: var(--text-dim); }
.tcard .cost.ok { color: var(--accent); display: flex; align-items: center; gap: 4px; }
.tcard .cost.ok i { font-size: 13px; }
.tcard.locked { opacity: .6; }
.tcard.locked .lbl { color: var(--text-dim); }
.tips-foot { margin-top: auto; padding: 11px 14px; border-top: 1px solid var(--border-soft); font-size: 11px; color: var(--text-dim); display: flex; align-items: center; gap: 6px; }

/* ---------------------------------------------------------------------------
   Bereichsfarben je Abteilung. Getragen werden sie nur von Logo, aktivem
   Reiter, Punktestand und Fortschrittsbalken — nicht von der Flaeche. Sonst
   besetzt die Ortsangabe Aufmerksamkeit, die den Signalfarben gehoert.

   Die vier Farben stehen einmal als Token. Zwei Verbraucher greifen darauf zu:
   body.bereich-* faerbt die Kopfleiste des Bereichs, in dem gerade gearbeitet
   wird; im Fortschritts-Overlay traegt jede Bereichs-Sektion ihre eigene Farbe
   (dort stehen alle vier gleichzeitig untereinander).
   --------------------------------------------------------------------------- */
:root {
  --f-joule:  #4f8ef7; --f-joule-rgb:  79, 142, 247;
  --f-python: #8b5cf6; --f-python-rgb: 139, 92, 246;
  --f-strukto:#14b8a6; --f-strukto-rgb:20, 184, 166;
  --f-arrays: #d946ef; --f-arrays-rgb: 217, 70, 239;
}
body.theme-light {
  --f-joule:  #2563eb; --f-joule-rgb:  37, 99, 235;
  --f-python: #7c3aed; --f-python-rgb: 124, 58, 237;
  --f-strukto:#0d9488; --f-strukto-rgb:13, 148, 136;
  --f-arrays: #c026d3; --f-arrays-rgb: 192, 38, 211;
}

body.bereich-joule        { --bereich-signal: var(--f-joule);   --bereich-signal-rgb: var(--f-joule-rgb); }
body.bereich-python       { --bereich-signal: var(--f-python);  --bereich-signal-rgb: var(--f-python-rgb); }
body.bereich-struktogramm { --bereich-signal: var(--f-strukto); --bereich-signal-rgb: var(--f-strukto-rgb); }
body.bereich-arrays       { --bereich-signal: var(--f-arrays);  --bereich-signal-rgb: var(--f-arrays-rgb); }

/* ---- CodeMirror (Python) ---- */
.CodeMirror {
  height: 250px; border: none;
  background: var(--surface-2); color: var(--text);
  font-family: var(--mono); font-size: 13px; line-height: 1.7;
}
.CodeMirror-gutters { background: var(--surface-2); border-right: 1px solid var(--border-soft); }
.CodeMirror-linenumber { color: var(--text-dim); }
.CodeMirror-cursor { border-left: 2px solid #f9e2af; }
.CodeMirror-selected { background: #33415560 !important; }
.CodeMirror-focused .CodeMirror-selected { background: #33415590 !important; }
/* .cm-s-default davor: gleiche Spezifität wie das CodeMirror-Default-Theme,
   gewinnt durch spätere Ladereihenfolge (sonst überstimmt das CDN-Theme uns). */
.cm-s-default .cm-comment  { color: #7e8aad; font-style: italic; }
.cm-s-default .cm-keyword  { color: #e2a2ff; font-weight: 600; }
.cm-s-default .cm-builtin  { color: #7dd3fc; }
.cm-s-default .cm-string   { color: var(--accent); }
.cm-s-default .cm-number   { color: #ffb86c; font-weight: 600; }
.cm-joule-obj    { color: #f9e2af !important; font-weight: 600; }
.cm-joule-cmd    { color: #a6e3a1 !important; font-weight: 600; }
.cm-joule-sensor { color: #7dd3fc !important; }
.cm-joule-userfn { color: #7dd3fc !important; }
.cm-joule-bad    { color: #ff5555 !important; font-weight: 700; text-decoration: underline wavy #ff5555; }
.CodeMirror .bad-indent-line, .CodeMirror .bad-indent-line span { color: #ff2d2d !important; font-weight: bold; }

/* ===========================================================================
   Light-Modus — aktiviert über body.theme-light (Theme-Button im Header).
   Die meisten Elemente folgen den Tokens und kippen automatisch; Welt und
   Editor-Syntax haben eigene Farben und bekommen hier explizite Light-Werte.
   =========================================================================== */
body.theme-light {
  --bg:          #f3f1ea;
  --surface:     #ffffff;
  --surface-2:   #f6f4ee;
  --surface-3:   #eceae1;
  --border:      #e2dfd4;
  --border-soft: #ebe8df;
  --text:        #21242a;
  --text-muted:  #565c67;
  --text-dim:    #8a8f9a;
  --accent:      #1f9d5e;
  --error-bg:    #fbe4dd;
  --error-bd:    rgba(219,79,49,0.3);
  --error-fg:    #db4f31;
  --info:        #2c6bd0;
  --warning:     #a4720b;
  --success-bg:  #e0f2e8;
  --info-bg:     #e6eefb;
  --warning-bg:  #faeed1;
  --danger-bg:   #fbe4dd;
}

/* Welt im Light hell, Roboter mit feinem Schatten zur Abhebung */
body.theme-light .world {
  background: radial-gradient(130% 130% at 30% 0%, #fbfdf8 0%, #f1f4ed 70%);
}
body.theme-light .cell {
  background: rgba(40,70,45,0.045);
  box-shadow: inset 0 0 0 1px rgba(40,60,45,0.06);
}
body.theme-light .cell.highlight { background: rgba(44,107,208,0.10); }
body.theme-light .joule-svg { filter: drop-shadow(0 2px 3px rgba(70,40,25,0.22)); }

/* Primär-Buttons und aktive Chips: weisser Text auf dem dunkleren Light-Grün */
body.theme-light .btn.primary,
body.theme-light .cmd-chip.cmd-active { color: #ffffff; }
body.theme-light .cmd-chip.struktur { color: #8839ef; background: #f1e8fd; border-color: #d9c2f7; }

/* Editor-Syntax für hellen Hintergrund */
body.theme-light .CodeMirror-cursor { border-left-color: #b58900; }
body.theme-light .CodeMirror-selected { background: #d8d6cc !important; }
body.theme-light .cm-comment     { color: #8a8f7a; }
body.theme-light .cm-keyword     { color: #8839ef; }
body.theme-light .cm-builtin     { color: #2c6bd0; }
body.theme-light .cm-number      { color: #c2630c; }
body.theme-light .cm-joule-obj    { color: #b58900 !important; }
body.theme-light .cm-joule-cmd    { color: #1f8f54 !important; }
body.theme-light .cm-joule-sensor { color: #2c6bd0 !important; }
body.theme-light .cm-joule-userfn { color: #2c6bd0 !important; }

/* ===========================================================================
   Globaler Drawer (Notizen, Hilfe, Glossar) — von rechts, über den ganzen Screen.
   =========================================================================== */
.drawer-scrim { position: fixed; inset: 0; background: rgba(8,10,13,0.45); opacity: 0; pointer-events: none; transition: opacity .25s; z-index: 40; }
.drawer-scrim.open { opacity: 1; pointer-events: auto; }
.drawer {
  position: fixed; top: 0; right: 0; bottom: 0; width: 340px; max-width: 92vw; z-index: 41;
  background: var(--surface); border-left: 1px solid var(--border);
  box-shadow: -22px 0 50px rgba(0,0,0,.4);
  display: flex; flex-direction: column;
  transform: translateX(106%); transition: transform .28s cubic-bezier(.3,.7,.3,1);
}
.drawer.open { transform: translateX(0); }
/* Angedockter Zustand (Operatorenliste, breite Schirme): Spalte in
   Bühnenbreite unterhalb der Kopfleisten, ohne Scrim — der Rest der
   Seite bleibt bedienbar. */
.drawer.dock {
  top: calc(var(--header-h) + var(--taskbar-h));
  width: calc(var(--stage-w) + 14px);
  box-shadow: -10px 0 30px rgba(0,0,0,.25);
}
.drawer-h { display: flex; align-items: center; gap: 9px; padding: 14px 15px; border-bottom: 1px solid var(--border-soft); }
.drawer-h > i { font-size: 18px; color: var(--info); }
.drawer-h b { font-size: 15px; font-weight: 600; flex: 1; }
.drawer-h .x { width: 30px; height: 30px; border-radius: 8px; border: none; background: transparent; color: var(--text-muted); font-size: 19px; display: grid; place-items: center; }
.drawer-h .x:hover { background: var(--surface-2); color: var(--text); }
.drawer-b { flex: 1; padding: 15px; overflow-y: auto; font-size: 13.5px; line-height: 1.6; color: var(--text); }
.drawer-b textarea { width: 100%; min-height: 200px; resize: vertical; background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--rad-m); color: var(--text); font-family: var(--font); font-size: 13.5px; padding: 10px 12px; }
.drawer-b textarea:focus { outline: none; border-color: var(--info); }
.drawer-actions { display: flex; gap: 8px; margin-top: 10px; }
.drawer-b .muted { color: var(--text-dim); font-size: 12px; margin-top: 10px; }
.help-list { display: flex; flex-direction: column; gap: 12px; }
.help-list .row { display: flex; gap: 9px; align-items: flex-start; }
.help-list .row i { color: var(--info); font-size: 17px; margin-top: 1px; flex: 0 0 auto; }
.help-list .row b { font-weight: 600; }

/* ===========================================================================
   Weiter/Zurück in der Werkzeugzeile: Sie bleiben so lange stehen, wie die
   Zeile sie einzeilig trägt, und weichen erst dann in die Pfeile des
   Navigators oben aus.

   Bis 2026-09-10 flogen sie überall pauschal ab 1350px. Nachgemessen bricht
   die Zeile aber je Bereich völlig verschieden um, weil sie unterschiedlich
   bestückt ist (mit Weiter/Zurück drin, Umbruch ab):
     Joule 1322 · Python und Arrays 1202 · Struktogramm gar nicht (bis 600
     geprüft, dort stehen nur Prüfen und Versuche).
   Zwei Kürzungen schieben das weiter nach unten: die Beschriftung von
   „Weiter" (Joule 1250, Python 1130) und der Tempo-Regler in Joule, der mit
   186px der dickste Posten der Zeile ist, dicker als „Ausführen" mit 113
   (Joule 1214). Beide zusammen: Joule 1140, Python 1130.
   Entscheid Steve 2026-09-10: beide Kürzungen, danach eine gemeinsame
   Ausblend-Schwelle bei 1160 mit rund 20px Luft — Struktogramm ausgenommen.
   =========================================================================== */
@media (max-width: 1350px) {
  /* Tempo-Regler kompakt: Die Millisekunden-Zahl steht ohnehin nur zur
     Kontrolle, die Schieberposition zeigt das Tempo selbst. Nur in Joule
     sichtbar, die anderen Bereiche blenden .tempo ganz aus. */
  .tempo .ms { display: none; }
  .tempo input[type="range"] { width: 80px; }
}

/* Beschriftung von „Weiter" weicht vor dem ganzen Knopf: Der Pfeil allein
   bleibt eindeutig, und der Knopf behält seine Fläche als Touch-Ziel.
   „Zurück" trägt ohnehin nur den Pfeil. */
@media (max-width: 1230px) {
  #btn-next .btn-txt { display: none; }
  #btn-next { padding-left: 11px; padding-right: 11px; }
}

@media (max-width: 1160px) {
  #btn-prev, #btn-next { display: none; }
  /* Struktogramm behält sie: Dort trägt die Zeile nur Prüfen und Versuche und
     bricht in keiner unterstützten Breite um. */
  body.mode-strukto #btn-prev, body.mode-strukto #btn-next { display: inline-flex; }
}

/* ===========================================================================
   Python-Modus (Bereich 2): rechte Spalte zeigt statt Joule-Welt die
   erwarteten Ergebnisse und optional einen "Neu in dieser Aufgabe"-Kasten.
   Umschaltung über body.mode-python (setzt python_mode.js beim Aktivieren);
   Joule-Markup bleibt im DOM und wird nur ausgeblendet.
   =========================================================================== */
.py-stage { display: none; flex-direction: column; gap: 14px; min-height: 0; overflow-y: auto; }
body.mode-python .py-stage { display: flex; }
body.mode-python .cmd-ref, body.mode-python .world-wrap { display: none; }
body.mode-python .tempo { display: none; }
/* Werkstatt personalisiert den Joule-Roboter — im Python-Bereich ohne Funktion. */
body.mode-python #btn-werkstatt { display: none; }
.py-stage [hidden] { display: none !important; }
.py-stage h3 { margin: 0 0 7px; font-size: 10.5px; font-weight: 600; letter-spacing: .13em; color: var(--text-dim); text-transform: uppercase; }
.py-faelle { display: flex; flex-direction: column; gap: 8px; }
.py-fall { background: var(--surface); border: 1px solid var(--border); border-radius: var(--rad-l); overflow: hidden; }
.py-fall-h { padding: 6px 11px; border-bottom: 1px solid var(--border-soft); font-size: 11px; color: var(--text-dim); font-weight: 600; }
.py-fall-b { margin: 0; padding: 9px 12px; font-family: var(--mono); font-size: 13px; line-height: 1.6; color: var(--text); white-space: pre-wrap; }
.py-versteckt { display: flex; align-items: center; gap: 6px; margin-top: 8px; font-size: 11.5px; color: var(--text-dim); line-height: 1.45; }
.py-versteckt i { font-size: 14px; flex: 0 0 auto; }
.py-neu { background: var(--surface); border: 1px solid var(--border); border-radius: var(--rad-l); padding: 11px 13px; flex: 0 0 auto; }
.py-neu-text { margin: 0 0 8px; font-size: 12.5px; color: var(--text-muted); line-height: 1.55; }
.py-neu-beispiel { margin: 0; padding: 8px 10px; background: var(--surface-2); border: 1px solid var(--border-soft); border-radius: var(--rad-m); font-family: var(--mono); font-size: 12px; line-height: 1.5; color: var(--text); white-space: pre-wrap; }

/* ===========================================================================
   Strukto-Bereich (Bereich 3): Mittelbereich zeigt statt Editor+Konsole die
   eingebettete Struktogramm-Werkbank (same-origin iframe, ?embed=1); die
   rechte Spalte zeigt Python-Programm und Beispiel-Lauf der Aufgabe.
   Umschaltung über body.mode-strukto (setzt struktogramm_mode.js).
   Ansicht nach Skizze A, siehe Vault: Entwurf Struktogramm-Bereich.
   =========================================================================== */
.wb { display: none; flex: 1 1 auto; min-height: 320px; flex-direction: column;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--rad-l); overflow: hidden; }
body.mode-strukto .wb { display: flex; }
.wb-top { display: flex; align-items: center; gap: 8px; padding: 8px 13px;
  border-bottom: 1px solid var(--border-soft); font-size: 11px;
  letter-spacing: .1em; text-transform: uppercase; color: var(--text-dim);
  font-weight: 600; }
.wb-top i { font-size: 14px; }
/* Unter 640px Einbettbreite entfällt die Kopfzeile (Schwellwert wie der
   Kompakt-Modus der Werkbank; Klasse setzt struktogramm_mode.js). */
.wb.schmal .wb-top { display: none; }
/* Unter 1366px Fensterbreite hat die Werkbank Vorrang vor der Bühne:
   rechte Spalte fest 300px statt clamp(360px, 32vw, 560px).
   (Unter 980px stapelt die Plattform ohnehin, siehe Tablet-Block unten.) */
@media (max-width: 1366px) {
  body.mode-strukto { --stage-w: 300px; }
}
/* Das iframe wird absolut in den Rahmen gelegt statt mit height:100% an ihm
   zu haengen. Firefox loest eine Prozenthoehe nur gegen einen Elternteil mit
   fester Hoehe auf; hier kommt die Hoehe aus dem Flex-Wachstum, also blieb das
   iframe auf der HTML-Vorgabe von 150px stehen und der Rest des Kastens war
   leer (Befund Steve 2026-09-05, Firefox). Chrome rechnete es durch, deshalb
   fiel es hier nie auf. Absolut positioniert loest die Hoehe in beiden
   Browsern gegen den Rahmen auf. */
.wb-frame { flex: 1 1 auto; min-height: 0; position: relative; }
.wb-frame iframe { display: block; position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
body.mode-strukto .editor, body.mode-strukto .console { display: none; }
body.mode-strukto #btn-run, body.mode-strukto #btn-stop,
body.mode-strukto #btn-reset { display: none; }
body.mode-strukto .tempo { display: none; }
body.mode-strukto .cmd-ref, body.mode-strukto .world-wrap { display: none; }
body.mode-strukto #btn-werkstatt { display: none; }
.sk-stage { display: none; flex-direction: column; gap: 14px; min-height: 0; overflow-y: auto; }
body.mode-strukto .sk-stage { display: flex; }
.sk-stage [hidden] { display: none !important; }
.sk-stage h3 { margin: 0 0 7px; font-size: 10.5px; font-weight: 600; letter-spacing: .13em; color: var(--text-dim); text-transform: uppercase; }
/* Selbstkontrolle-Aufklapper gibt es nur bei Aufgaben ohne Testfälle;
   bei prüfbaren Aufgaben laufen KIT und Lösung über die Tipp-Treppe
   (seit Etappe 3 auch im Strukto-Bereich). */
.sk-loesung { background: var(--surface); border: 1px solid var(--border); border-radius: var(--rad-l); padding: 11px 13px; flex: 0 0 auto; }
.sk-loesung summary { display: flex; align-items: center; gap: 7px; cursor: pointer; list-style: none; font-size: 12.5px; font-weight: 600; color: var(--warning); }
.sk-loesung summary::-webkit-details-marker { display: none; }
.sk-loesung summary i { font-size: 15px; }
.sk-loesung[open] summary { margin-bottom: 9px; }
/* Operatorenliste im Seitenpanel (Strukto-Bereich): schmal-taugliches,
   gestapeltes Layout; lange Operator-Muster brechen um statt zu scrollen. */
/* Suchfeld klebt beim Scrollen oben am Panel (über den Kategorie-Titeln). */
.op-suche-wrap { position: sticky; top: -15px; z-index: 3;
  margin: 6px -15px 0; padding: 10px 15px 9px; background: var(--surface); }
.op-suche { width: 100%; padding: 7px 11px;
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: var(--rad-m); color: var(--text); font-family: var(--font);
  font-size: 13px; }
.op-suche:focus { outline: none; border-color: var(--info); }
.op-quelle { margin-top: 14px; font-size: 11px; line-height: 1.5;
  text-wrap: balance; }
.op-cat { margin-top: 18px; }
.op-cat:first-of-type { margin-top: 12px; }
/* Kategorie-Titel als Block-Überschrift: Akzentfarbe, Trennlinie über die
   volle Panelbreite, und beim Scrollen oben klebend (Orientierung). */
.op-cat h4 { position: sticky; top: 38px; z-index: 2;
  margin: 0 -15px 9px; padding: 9px 15px 7px;
  background: var(--surface); border-bottom: 1px solid var(--border);
  font-size: 12.5px; font-weight: 700; letter-spacing: .12em;
  text-transform: uppercase; color: var(--info); }
.op-item { background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--rad-m); padding: 9px 11px; margin-bottom: 8px; }
.op-op { display: block; font-family: var(--mono); font-size: 12px;
  color: var(--accent); white-space: pre-wrap; overflow-wrap: break-word;
  margin-bottom: 5px; }
.op-desc { margin: 0 0 6px; font-size: 12.5px; color: var(--text);
  line-height: 1.5; text-wrap: pretty; }
/* Beispiele als gezeichnete Struktogramm-Kästchen (Optik des Original-PDF) */
.nsd-bsp { margin-bottom: 6px; font-family: var(--mono); font-size: 12px;
  color: var(--text); }
.op-item[data-ins] { cursor: pointer; }
.op-item[data-ins]:hover { border-color: var(--info); }
.nsd-box { border: 1.4px solid var(--text-muted); background: var(--surface-2);
  padding: 6px 9px; white-space: pre-wrap; overflow-wrap: break-word; }
.nsd-box + .nsd-box { border-top: 0; }
.nsd-call { padding-left: 14px; padding-right: 14px; position: relative; }
.nsd-call::before, .nsd-call::after { content: ''; position: absolute;
  top: 0; bottom: 0; width: 1.4px; background: var(--text-muted); }
.nsd-call::before { left: 5px; }
.nsd-call::after { right: 5px; }
.nsd-if { border: 1.4px solid var(--text-muted); }
.nsd-if-kopf { position: relative; background: var(--surface-2);
  padding: 6px 22px 22px; text-align: center; white-space: pre-wrap;
  overflow-wrap: break-word; }
.nsd-if-diag { position: absolute; left: 0; right: 0; bottom: 0;
  width: 100%; height: 18px; color: var(--text-muted); display: block; }
.nsd-if-kopf i { position: absolute; bottom: 2px; font-size: 10px;
  font-style: normal; color: var(--text-dim); }
.nsd-if-kopf .nsd-j { left: 6px; }
.nsd-if-kopf .nsd-n { right: 6px; }
.nsd-if-zweige { display: flex; border-top: 1.4px solid var(--text-muted); }
.nsd-if-zweige div { flex: 1; padding: 5px 9px; text-align: center;
  color: var(--text-dim); }
.nsd-if-zweige div + div { border-left: 1.4px solid var(--text-muted); }
.nsd-loop { border: 1.4px solid var(--text-muted); background: var(--surface-2); }
.nsd-loop-kopf { padding: 6px 9px; white-space: pre-wrap; overflow-wrap: break-word; }
.nsd-loop-body { padding: 0 0 6px 22px; }
.nsd-loop-body .nsd-box { border-right: 0; color: var(--text-dim); }

.op-bsp { display: flex; flex-direction: column; gap: 2px; padding: 6px 8px;
  background: var(--surface-2); border: 1px solid var(--border-soft);
  border-radius: var(--rad-s); margin-bottom: 5px; }
.op-bsp span { font-size: 10px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--text-dim); }
.op-bsp code { font-family: var(--mono); font-size: 12px; color: var(--text);
  white-space: pre-wrap; overflow-wrap: break-word; }
.op-bsp.op-py code { color: var(--info); }
.op-bsp.op-aus code { color: var(--text-muted); }
/* Bereichs-Glossar: Einleitungssatz einer Kategorie und gesperrte
   Kategorien (Block noch nicht offen), Muster SQL-Referenz. */
.op-intro { margin: 0 0 8px; font-size: 12.5px; color: var(--text-muted);
  line-height: 1.5; text-wrap: pretty; }
.op-cat.op-locked h4 { color: var(--text-dim); }
/* Beispiele des Bereichs-Glossars brechen nie mitten im Python-Ausdruck:
   Zeile bleibt ganz, längere Zeilen scrollen im Kasten. Der Drawer ist
   dafür etwas breiter als bei Notizen und Hilfe. */
.pl-gloss .op-bsp code { white-space: pre; overflow-x: auto; }
.drawer.gloss-breit { width: 400px; }
.op-lock-hinweis { margin: 0; font-size: 11.5px; color: var(--text-dim);
  font-style: italic; }
.op-hint { margin: 0; font-size: 11.5px; color: var(--text-muted);
  line-height: 1.5; text-wrap: pretty; }

/* Prüfungs-Ergebnis (Stufe 2): Zeilen + Soll/Ist-Blöcke */
#sk-ergebnis-body { display: flex; flex-direction: column; gap: 6px; }
.sk-erg { margin: 0; font-size: 12.5px; line-height: 1.5; color: var(--text);
  white-space: normal; overflow-wrap: break-word; text-wrap: pretty; }
.sk-erg.ok { color: var(--success); }
.sk-erg.err { color: var(--danger); }
.sk-erg.hint { color: var(--text-muted); }
/* Formulierungsfehler: rotes Kästchen-Label „K1:" und rot zitierte
   Fehl-Schreibweise (setzt struktogramm_mode.panelFehlerZeile).
   display: block schlägt die globale .hint-Pill (inline-flex), die
   die mehrteilige Meldungszeile sonst in Flex-Items zerlegte. */
.sk-erg.hint { display: block; }
.sk-erg .sk-knr { color: var(--danger); font-weight: 600; }
.sk-erg .sk-falsch { color: var(--danger); }

/* ----- Python-Modus: Ausprobieren/Prüfen + echtes input() + Soll/Ist-Diff ----- */
/* Elemente, die nur im Python-Modus existieren (z.B. der Prüfen-Knopf). */
.py-only { display: none; }
body.mode-python .py-only { display: flex; }
/* Prüfen ist im Strukto-Bereich sichtbar, aber bis Stufe 2 deaktiviert. */
body.mode-strukto .py-only { display: flex; }
/* Prüfen: blaue Variante neben dem grünen Ausprobieren. */
.btn.pruefen { background: var(--info-bg); color: var(--info); border-color: #2c4060; }
.btn.pruefen:hover:not(:disabled) { background: rgba(137, 180, 250, 0.24); }
.btn.pruefen:disabled { opacity: .55; cursor: not-allowed; }
/* Eingabezeile in der Konsole (wartendes input() beim Ausprobieren). */
.py-eingabezeile { display: flex; align-items: center; gap: 7px; margin: 3px 0; }
.py-eingabe-prompt { color: var(--accent); white-space: pre-wrap; }
.py-eingabe-feld {
  flex: 0 1 260px; background: var(--surface-2); border: 1px solid var(--info);
  border-radius: 6px; color: var(--text); font-family: var(--mono); font-size: 12.5px;
  padding: 3px 8px; outline: none;
}
.py-eingabe-feld:focus { box-shadow: 0 0 0 2px var(--info-bg); }
/* Soll/Ist-Gegenüberstellung: abweichende Zeile rot markiert, erwartete
   Ausgabe in Blau, eigene Ausgabe im neutralen Konsolen-Grau (out-info). */
.out-diff { background: var(--danger-bg); color: var(--danger); font-weight: 600; }
.out-expect { color: var(--info); }

/* ===========================================================================
   Admin-Bereich (admin.php): Sidebar-Layout (abgenommen 2026-07-26), Karten
   im Content. Bezugsgröße iPad Pro quer — Tabellen brechen um statt quetschen.
   =========================================================================== */
.adm-shell { display: flex; height: 100vh; overflow: hidden; }
.adm-side {
  width: 200px; flex: 0 0 auto; display: flex; flex-direction: column;
  background: var(--surface); border-right: 1px solid var(--border); padding: 12px 10px;
}
/* flex zuruecksetzen, nicht nur die Breite: In der Kopfleiste der Lernseite
   traegt .brand `flex: 0 0 206px` fuer die Flucht zur Seitenleiste. Die
   Admin-Sidebar stapelt aber senkrecht, dort wurde aus den 206px eine Hoehe.
   Das Logo stand deshalb tief in einem 206px hohen Kasten und schob die
   Navigation nach unten (Befund Steve 2026-09-10). */
.adm-side .brand { flex: 0 0 auto; width: auto; padding: 2px 6px 12px; font-size: 14px; }
.adm-nav { display: flex; flex-direction: column; gap: 2px; }
.adm-nav-label {
  font-size: 10px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--text-dim); padding: 12px 8px 4px;
}
.adm-nav-item {
  display: flex; align-items: center; gap: 8px; padding: 7px 9px;
  border-radius: 7px; font-size: 13px; font-weight: 500;
  color: var(--text-muted); text-decoration: none;
  transition: background .15s, color .15s;
}
.adm-nav-item i { font-size: 16px; }
.adm-nav-item:hover { background: var(--surface-2); color: var(--text); }
.adm-nav-item.active { background: var(--info-bg); color: var(--info); font-weight: 600; }
.adm-main { flex: 1 1 auto; }

/* Design, Rueckweg und Abmelden oben rechts in der Inhaltsspalte.
   `align-self: flex-end` haelt die Gruppe an der rechten Kante der Spalte und
   damit auf jeder Fensterbreite in Sichtweite des Inhalts; am Fensterrand
   geklebt driftete sie auf breiten Schirmen davon. `sticky` haelt sie beim
   Scrollen oben, der negative Rand gibt ihre Hoehe an den Inhalt zurueck:
   Eine echte Kopfzeile haette jeden Reiter rund 45px gekostet, und gerade die
   Tabellen leben davon. Optik wie die Kopfleiste der Lernplattform, nicht wie
   die eckigen Sidebar-Knoepfe von frueher. */
.adm-kopfaktionen {
  position: sticky; top: 0; z-index: 6;
  align-self: flex-end; margin-bottom: -42px;
  display: flex; gap: 4px; padding: 4px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--rad-m);
}
.adm-kopfaktionen .uicon { text-decoration: none; }

/* Die Spalte waechst jetzt mit dem Fenster, statt bei 1000px stehen zu
   bleiben: Admin-Arbeit passiert auch am grossen Bildschirm, und bei 1900px
   standen sonst 700px Leere rechts (Entscheid Steve 2026-09-10). Die
   Obergrenze bleibt, damit Tabellenzeilen auf sehr breiten Schirmen nicht
   auseinanderlaufen. */
.admin { flex: 1 1 auto; overflow-y: auto; padding: 18px; display: flex; flex-direction: column; gap: 16px; max-width: 1600px; }

/* Rechts Platz fuer die Aktionsgruppe, damit sie nichts ueberdeckt: Im
   Nachrichten-Reiter sitzt dort das Klassen-Auswahlfeld, im System-Reiter die
   Pille „nur Admin" (Vorgabe Steve: nichts verdecken).
   150px, weil die Gruppe je nach Fensterbreite unterschiedlich misst: Unter
   1200px wachsen die Icon-Knoepfe auf Touch-Groesse, damit wird sie von 120px
   auf 138px breit. Mit 132px ueberlappte das Klassen-Feld bei 1024px um sechs
   Pixel (gemessen 2026-09-10). */
.adm-kopf { padding-right: 150px; }
.admin-msg { padding: 9px 13px; border-radius: var(--rad-m); font-size: 13.5px; }
.admin-msg.ok { background: var(--success-bg); color: var(--success); border: 1px solid rgba(74, 222, 128, .3); }
.admin-msg.err { background: var(--danger-bg); color: var(--danger); border: 1px solid var(--error-bd); }
.admin-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--rad-l); padding: 15px 17px; }
.admin-card h2 { margin: 0 0 12px; font-size: 15px; font-weight: 600; display: flex; align-items: center; gap: 8px; }
.admin-card h2 i { color: var(--info); font-size: 18px; }
.admin-tbl { width: 100%; border-collapse: collapse; font-size: 13px; }
.admin-tbl th { text-align: left; padding: 6px 8px; color: var(--text-dim); font-size: 11px; text-transform: uppercase; letter-spacing: .08em; border-bottom: 1px solid var(--border); }
/* Sortierbare Spaltenköpfe (js/admin.js): Klick sortiert, Pfeil zeigt Richtung. */
.admin-tbl th.sortierbar { cursor: pointer; user-select: none; white-space: nowrap; }
.admin-tbl th.sortierbar:hover { color: var(--text-muted); }
.admin-tbl th.sortierbar::after { content: " ↕"; opacity: .45; }
.admin-tbl th.sortierbar.asc::after { content: " ↑"; opacity: 1; }
.admin-tbl th.sortierbar.desc::after { content: " ↓"; opacity: 1; }
.admin-tbl th.sortierbar.asc, .admin-tbl th.sortierbar.desc { color: var(--info); }
.admin-tbl td.mono, input.mono { font-family: var(--mono); font-size: 12px; }
.admin-aktionen select, .admin-tbl form.inline select {
  background: var(--bg); border: 1px solid var(--border); border-radius: var(--rad-s);
  color: var(--text); font-size: 12px; padding: 4px 6px; max-width: 240px;
}
.admin-aktionen select { max-width: 110px; }
.adm-klasse-name {
  width: 110px; background: var(--bg); border: 1px solid var(--border); border-radius: var(--rad-s);
  color: var(--text); font-size: 12.5px; padding: 4px 7px;
}
.adm-klasse-name:focus { outline: none; border-color: var(--info); }
button.adm-pill { cursor: pointer; }
button.adm-pill:hover { border-color: var(--danger); }

/* Bereichs-Kopf mit Unterreitern (Liste/Anlegen/Löschen) */
.adm-kopf { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.adm-titel { margin: 0; font-size: 17px; font-weight: 600; display: flex; align-items: center; gap: 8px; }
.adm-titel i { color: var(--info); font-size: 19px; }
.adm-sub { display: inline-flex; gap: 2px; background: var(--bg); border: 1px solid var(--border); border-radius: var(--rad-m); padding: 3px; }
.adm-sub-item { color: var(--text-muted); padding: 4px 13px; font-size: 12.5px; font-weight: 500; border-radius: 6px; text-decoration: none; }
.adm-sub-item:hover { color: var(--text); }
.adm-sub-item.active { background: var(--info-bg); color: var(--info); font-weight: 600; }
.adm-sub-item.rot { color: var(--danger); }
.adm-sub-item.rot.active { background: var(--danger-bg); color: var(--danger); }

/* Filterzeile: Suche + Chips (Rolle, Klassen-Mehrfachauswahl) */
.adm-filterzeile { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 10px; }
.adm-suche { display: flex; align-items: center; gap: 7px; background: var(--bg); border: 1px solid var(--border); border-radius: var(--rad-m); padding: 5px 10px; }
.adm-suche i { color: var(--text-dim); font-size: 15px; }
.adm-suche input { background: transparent; border: none; outline: none; color: var(--text); font-size: 13px; width: 210px; }
.adm-chips { display: flex; gap: 5px; flex-wrap: wrap; align-items: center; }
.adm-chip { border: 1px solid var(--border); color: var(--text-muted); border-radius: 999px; padding: 3px 12px; font-size: 12px; text-decoration: none; }
.adm-chip:hover { color: var(--text); border-color: var(--text-dim); }
.adm-chip.active { background: var(--info-bg); color: var(--info); border-color: transparent; font-weight: 600; }
.adm-chip.klasse.active { background: var(--success-bg); color: var(--success); }
.adm-chip.reset { border-style: dashed; display: inline-flex; align-items: center; gap: 4px; }

/* Rollen-/Klassen-Pillen in Tabellen */
.adm-pill { display: inline-flex; align-items: center; gap: 4px; flex: 0 0 auto; border: 1px solid var(--border); color: var(--text-muted); border-radius: 999px; padding: 1px 9px; font-size: 11px; white-space: nowrap; }
.adm-pill.klasse { border-color: #2c4060; color: var(--info); }
.adm-pill.lehrer, .adm-pill.warn { background: var(--warning-bg); color: var(--warning); border-color: #4a3c17; }
.adm-pill.admin { background: var(--danger-bg); color: var(--danger); border-color: var(--error-bd); }
.adm-pill.ok { background: var(--success-bg); color: var(--success); border-color: rgba(74,222,128,.3); }

/* Anlegen: zwei Karten nebeneinander (bricht auf iPad sauber um), Formulare */
.adm-spalten { display: grid; grid-template-columns: repeat(auto-fit, minmax(340px, 1fr)); gap: 16px; }
.adm-form { display: flex; flex-direction: column; gap: 8px; }
.adm-form input[type=text], .adm-form select, .adm-form textarea {
  background: var(--bg); border: 1px solid var(--border); border-radius: var(--rad-s);
  color: var(--text); font-size: 13px; padding: 7px 10px; font-family: var(--font);
}
.adm-form textarea { font-family: var(--mono); font-size: 12.5px; resize: vertical; }
.adm-form input[type=file] { color: var(--text-muted); font-size: 12px; max-width: 220px; }
.adm-form input[type=file]::file-selector-button {
  background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--rad-s);
  color: var(--text); font-size: 12px; padding: 5px 10px; margin-right: 8px; cursor: pointer; font-family: var(--font);
}
.adm-form input:focus, .adm-form select:focus, .adm-form textarea:focus { outline: none; border-color: var(--info); }
.adm-form .btn.primary { align-self: flex-start; }
.admin-hinweis a { color: var(--info); }

/* Löschen-Reiter: Gefahren-Optik */
.admin-card.gefahr { border-color: var(--error-bd); }
.adm-gefahr-kopf { display: flex; align-items: flex-start; gap: 8px; color: var(--danger); font-size: 13px; line-height: 1.5; margin-bottom: 12px; }
.adm-gefahr-kopf i { font-size: 17px; flex: 0 0 auto; margin-top: 1px; }
.adm-gefahr-fuss { border-top: 1px solid var(--border-soft); padding-top: 12px; }
.adm-gefahr-fuss input[name=bestaetigung] {
  width: 130px; background: var(--bg); border: 1px solid var(--error-bd); border-radius: var(--rad-s);
  color: var(--text); padding: 6px 9px;
}

/* Auswertung: Fortschritts-Matrix (Klasse × Blöcke). Schüler-Spalte bleibt
   beim Seitwärts-Scrollen stehen (sticky), Block-Spalten kompakt. */
.awf-wrap { overflow-x: auto; }
/* Admin-Tabellen, die schmaler als ihr Inhalt werden können (CSV-Vorschau
   auf dem iPad hoch): Scrollen bleibt in der Karte. */
.adm-tbl-scroll { overflow-x: auto; }
.awf-tab { white-space: nowrap; }
.awf-tab th:first-child, .awf-tab td:first-child {
  position: sticky; left: 0; background: var(--surface); z-index: 2;
}
.awf-tab .awf-b { text-align: center; padding: 6px 5px; }
.awf-tab td.awf-z { text-align: center; padding: 6px 5px; font-size: 15px; }
.awf-tab .awf-sum { text-align: right; }
.awf-strike { color: var(--warning); }
.awf-gut    { color: var(--accent); }
.awf-abg    { color: var(--info); }
.awf-pot    { color: #d98a2b; }
.awf-teil   { color: var(--text-muted); font-family: var(--mono); font-size: 11.5px; }
.awf-offen  { color: var(--text-dim); }
.awf-warn   { color: #d98a2b; font-weight: 600; }
.awf-name {
  background: none; border: none; padding: 0; font: inherit;
  color: var(--info); font-weight: 600; cursor: pointer;
}
.awf-name:hover { text-decoration: underline; }
.awf-schwach td { background: rgba(217, 138, 43, 0.07); }
.awf-schwach td:first-child { background: #2a2f3d; }
body.theme-light .awf-schwach td:first-child { background: #f5efe0; }

/* Nachrichten: Sidebar-Badge, Admin-Posteingang + Verlauf, Schüler-Drawer.
   Grundsatz: Verlauf bleibt immer vollständig stehen, nichts verschwindet. */
.adm-nav-badge {
  margin-left: auto; background: var(--warning); color: #241c02;
  border-radius: 999px; padding: 0 7px; font-size: 10.5px; font-weight: 700; line-height: 16px;
}
.nx-layout { display: grid; grid-template-columns: minmax(220px, 300px) minmax(0, 1fr); gap: 16px; align-items: start; }
@media (max-width: 900px) { .nx-layout { grid-template-columns: 1fr; } }
.nx-eingang { display: flex; flex-direction: column; gap: 2px; padding: 8px; }
.nx-thread { display: flex; flex-direction: column; gap: 2px; padding: 8px 10px; border-radius: 7px; text-decoration: none; }
.nx-thread:hover { background: var(--surface-2); }
.nx-thread.active { background: var(--info-bg); }
.nx-thread-name { color: var(--text); font-weight: 600; font-size: 13px; display: flex; align-items: center; gap: 7px; }
.nx-thread-meta { color: var(--text-dim); font-size: 11.5px; }
.nx-punkt {
  background: var(--warning); color: #241c02; border-radius: 999px;
  padding: 0 7px; font-size: 10.5px; font-weight: 700; line-height: 16px;
}
.nx-verlauf-kopf { display: flex; align-items: center; gap: 9px; border-bottom: 1px solid var(--border-soft); padding-bottom: 10px; margin-bottom: 12px; }
.nx-blasen { display: flex; flex-direction: column; gap: 9px; max-height: 55vh; overflow-y: auto; padding: 2px; }
.nx-blase {
  max-width: 78%; border-radius: 10px; padding: 8px 12px;
  background: var(--surface-2); border: 1px solid var(--border-soft); align-self: flex-start;
}
.nx-blase.lehrer, .nx-blase.eigene { align-self: flex-end; background: var(--info-bg); border-color: #2c4060; }
body.theme-light .nx-blase.lehrer, body.theme-light .nx-blase.eigene { border-color: #c9d8f0; }
.nx-blase.eigene { background: var(--success-bg); border-color: rgba(74, 222, 128, .25); }
.nx-bezug { display: inline-flex; align-items: center; gap: 4px; font-size: 11px; color: var(--info); margin-bottom: 4px; }
.nx-text { font-size: 13px; line-height: 1.5; overflow-wrap: anywhere; }
.nx-code { margin-top: 6px; }
.nx-code summary {
  display: inline-flex; align-items: center; gap: 5px; cursor: pointer;
  font-size: 11.5px; color: var(--info); list-style: none;
}
.nx-code summary::-webkit-details-marker { display: none; }
.nx-code pre {
  margin: 6px 0 0; padding: 8px 10px; background: var(--bg);
  border: 1px solid var(--border-soft); border-radius: var(--rad-s);
  font-family: var(--mono); font-size: 12px; line-height: 1.5;
  white-space: pre-wrap; overflow-wrap: anywhere; max-height: 260px; overflow-y: auto;
}
.nx-meta { display: block; margin-top: 4px; font-size: 10.5px; color: var(--text-dim); }
.nx-antwort { display: flex; gap: 8px; margin-top: 12px; align-items: flex-end; }
.nx-antwort textarea {
  flex: 1; background: var(--bg); border: 1px solid var(--border); border-radius: var(--rad-m);
  color: var(--text); font-family: var(--font); font-size: 13px; padding: 8px 10px; resize: vertical;
}
.nx-antwort textarea:focus { outline: none; border-color: var(--info); }

/* Schüler-Drawer */
.nx-s-verlauf { display: flex; flex-direction: column; gap: 9px; max-height: 46vh; overflow-y: auto; margin-bottom: 12px; }
.nx-s-verlauf .nx-blase.lehrer { align-self: flex-start; background: var(--surface-2); border-color: var(--border-soft); }
.nx-s-verlauf .nx-blase.eigene { align-self: flex-end; }
.nx-s-senden textarea {
  width: 100%; background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--rad-m);
  color: var(--text); font-family: var(--font); font-size: 13.5px; padding: 9px 11px; resize: vertical;
}
.nx-s-senden textarea:focus { outline: none; border-color: var(--info); }
.nx-bezug-chip {
  display: inline-flex; align-items: center; gap: 5px; margin-bottom: 7px;
  background: var(--info-bg); color: var(--info); border: none; border-radius: 999px;
  padding: 3px 11px; font-size: 11.5px; font-weight: 600;
}
.nx-bezug-chip.aus { background: transparent; border: 1px dashed var(--border); color: var(--text-dim); font-weight: 400; }
.nx-s-status { font-size: 12px; }
.nx-s-status.ok { color: var(--accent); }
.nx-s-status.err { color: var(--danger); }

/* System: Zustand-Kacheln, Radios (Berechtigungen) */
.sys-kacheln { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }
.sys-label { font-size: 10.5px; letter-spacing: .08em; text-transform: uppercase; color: var(--text-dim); }
.sys-wert { font-size: 19px; font-weight: 600; margin: 6px 0; }
.sys-wert small { font-size: 12px; color: var(--text-dim); font-weight: 400; }
.sys-wert.ok { color: var(--accent); font-size: 15px; }
.sys-wert.err { color: var(--danger); font-size: 15px; }
.sys-klein { font-size: 11px; color: var(--text-dim); font-weight: 400; }
.sys-radio { display: flex; align-items: center; gap: 7px; font-size: 13.5px; }
.sys-radio.aus { color: var(--text-dim); }
.sys-radio input { accent-color: var(--info); }

/* Einmal-Anzeige Startpasswörter (Overlay) */
.pwov-scrim { position: fixed; inset: 0; background: rgba(8,10,13,0.55); display: grid; place-items: center; z-index: 70; }
.pwov { width: min(430px, calc(100vw - 32px)); max-height: 84vh; overflow-y: auto; background: var(--surface); border: 1px solid var(--border); border-radius: var(--rad-l); padding: 16px 18px; }
.pwov-h { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
.pwov-h i { color: var(--warning); font-size: 18px; }
.pwov-h b { font-size: 14px; }
.pwov-b { margin-bottom: 12px; }
.pwov-zeile { display: flex; align-items: center; gap: 10px; padding: 4px 0; }
.pwov-name { font-family: var(--mono); font-size: 12.5px; color: var(--text-muted); flex: 1; }
.pwov-pw { font-family: var(--mono); font-size: 18px; color: var(--accent); background: var(--bg); border: 1px dashed var(--border); border-radius: 7px; padding: 6px 14px; letter-spacing: .04em; }
.pwov-liste .pwov-pw { font-size: 14px; padding: 3px 10px; }
.pwov-foot { display: flex; gap: 8px; align-items: center; }
.pwov-hinweis { margin: 10px 0 0; color: var(--text-dim); font-size: 11.5px; }
@media print {
  body:has(.pwov-scrim) .adm-shell { display: none !important; }
  .pwov-scrim { position: static; background: none; }
  .pwov { border: none; width: auto; max-height: none; }
  .pwov-foot, .pwov-hinweis { display: none; }
  .pwov-pw { color: #000; }
  .pwov-name { color: #333; }
}
.admin-tbl td { padding: 7px 8px; border-bottom: 1px solid var(--border-soft); color: var(--text-muted); }
.admin-tbl form.inline { display: inline-flex; align-items: center; gap: 5px; margin-right: 6px; }
.admin-aktionen { white-space: nowrap; }
.admin-row { display: flex; align-items: center; gap: 8px; margin-top: 12px; flex-wrap: wrap; }
.admin-row input[type=text], .admin-aktionen input[type=text], .admin-row select {
  background: var(--bg); border: 1px solid var(--border); border-radius: var(--rad-s);
  color: var(--text); font-size: 13px; padding: 6px 9px;
}
.admin-num { width: 64px; background: var(--bg); border: 1px solid var(--border); border-radius: var(--rad-s); color: var(--text); font-size: 13px; padding: 5px 7px; }
.admin-code { border: 1px solid var(--border); border-radius: 999px; padding: 3px 10px; font-family: var(--mono); font-size: 12px; background: var(--surface-2); }
.admin-code.an { color: var(--success); border-color: rgba(74, 222, 128, .4); }
.admin-code.aus { color: var(--text-dim); text-decoration: line-through; }
.admin-leer { color: var(--text-dim); font-size: 13px; margin: 8px 0 0; }
.admin-hinweis { display: flex; align-items: flex-start; gap: 7px; color: var(--text-dim); font-size: 12.5px; margin: 12px 0 0; line-height: 1.5; }
.admin-hinweis i { font-size: 15px; flex: 0 0 auto; margin-top: 1px; }
.topbar a.btn { text-decoration: none; display: inline-flex; align-items: center; gap: 6px; }

/* ===========================================================================
   Fortschritts-Overlay ("Mein Fortschritt", Klick auf die Status-Pille).
   Farben ausschliesslich über Variablen — der Light-Mode kommt automatisch mit.
   =========================================================================== */
.status:hover { border-color: var(--text-dim); }
.status:focus-visible { outline: 2px solid var(--info); outline-offset: 2px; }

.fs-scrim { position: fixed; inset: 0; background: rgba(8,10,13,0.45); opacity: 0; pointer-events: none; transition: opacity .25s; z-index: 60; }
.fs-scrim.open { opacity: 1; pointer-events: auto; }
.fs {
  position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%) scale(.97);
  width: min(620px, calc(100vw - 32px)); max-height: min(86vh, 780px);
  display: flex; flex-direction: column; overflow: hidden;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--rad-l);
  opacity: 0; pointer-events: none; transition: opacity .25s, transform .25s; z-index: 61;
}
.fs.open { opacity: 1; pointer-events: auto; transform: translate(-50%, -50%) scale(1); }
.fs-h { display: flex; align-items: center; gap: 9px; padding: 14px 16px; border-bottom: 1px solid var(--border-soft); }
.fs-h > i { font-size: 18px; color: var(--accent); }
.fs-h b { font-size: 15px; font-weight: 600; flex: 0 0 auto; }
/* Durchgangs-Pillen in der Kopfzeile: sie stehen neben dem Titel und sind in
   jeder Ansicht bedienbar (Entscheid Steve 2026-09-04). Der Slot nimmt den
   Rest der Zeile, damit das Schliessen-Kreuz rechts bleibt. */
.fs-dgs-slot { flex: 1; display: flex; align-items: center; gap: 4px; }
/* Die Pillen liegen eine Ebene tiefer im Slot — ohne eigenen Abstand hier
   kleben sie aneinander. */
.fs-dgs { display: inline-flex; align-items: center; gap: 4px; }
.fs-dg-pill {
  border: 1px solid var(--border); background: var(--bg); color: var(--text-muted);
  border-radius: var(--rad-m); padding: 3px 9px; font-size: 11.5px; font-weight: 600;
  font-family: inherit; display: inline-flex; align-items: center; gap: 4px;
  transition: background .15s, color .15s, border-color .15s;
}
.fs-dg-pill i { font-size: 12px; }
.fs-dg-pill:hover { color: var(--text); border-color: var(--text-dim); }
/* Die aktive Durchgangs-Pille traegt die Bereichsfarbe, wie der
   Durchgangs-Schalter in der Kopfleiste der Lernseite (.dg-btn.active). */
.fs-dg-pill.on {
  border-color: transparent;
  background: var(--dg-signal-soft, rgba(var(--sec-farbe-rgb, 79, 142, 247), .14));
  color: var(--dg-signal, var(--sec-farbe, var(--accent)));
}

/* Durchgangs-Signal: eigene Farbachse in Orange, gestaffelt in der Kraft
   (Entscheid Steve 2026-09-04, gleichlautend mit sqllearn). Orange ist die
   einzige in beiden Plattformen freie Farbe — Blau, Violett, Tuerkis und
   Magenta sind die vier Bereiche, Gruen heisst richtig, Rot falsch, Gelb Tipp.
   Die Staffelung traegt auch einen vierten Durchgang. Durchgang 1 bleibt
   ungetoent, damit nur der Wechsel auffaellt. */
.fs.dg-2, .fs.dg-3 { --dg-signal: #f97316; }
body.theme-light .fs.dg-2, body.theme-light .fs.dg-3 { --dg-signal: #c2410c; }
.fs.dg-2 { --dg-signal-soft: rgba(249, 115, 22, .18); }
.fs.dg-3 { --dg-signal-soft: rgba(249, 115, 22, .34); }
.fs.dg-2 .fs-h, .fs.dg-3 .fs-h {
  /* Fester Wert zuerst: color-mix kennen aeltere Schul-Tablets nicht. */
  background: rgba(249, 115, 22, .09);
  border-bottom-color: rgba(249, 115, 22, .38);
  background: color-mix(in srgb, var(--dg-signal) 9%, transparent);
  border-bottom-color: color-mix(in srgb, var(--dg-signal) 38%, var(--border-soft));
}
.fs.dg-3 .fs-h {
  background: rgba(249, 115, 22, .22);
  border-bottom: 2px solid rgba(249, 115, 22, .7);
  background: color-mix(in srgb, var(--dg-signal) 22%, transparent);
  border-bottom: 2px solid color-mix(in srgb, var(--dg-signal) 70%, transparent);
}
.fs.dg-2 .fs-h > i, .fs.dg-3 .fs-h > i { color: var(--dg-signal); }
.fs-dg-pill:focus-visible { outline: 2px solid var(--info); outline-offset: 1px; }
.fs-h .x { width: 30px; height: 30px; border-radius: 8px; border: none; background: transparent; color: var(--text-muted); font-size: 19px; display: grid; place-items: center; }
.fs-h .x:hover { background: var(--surface-2); color: var(--text); }
.fs-b { flex: 1; padding: 16px; overflow-y: auto; font-size: 13px; }
.fs-b .fs-lade { color: var(--text-dim); font-size: 12.5px; }
/* Bereichsfarbe fuer alles, was ausserhalb einer Bereichskarte steht
   (Offen-Symbol in der Legende, Ring im Kopf). */
.fs.joule        { --sec-farbe: var(--f-joule);   --sec-farbe-rgb: var(--f-joule-rgb); }
.fs.python       { --sec-farbe: var(--f-python);  --sec-farbe-rgb: var(--f-python-rgb); }
.fs.struktogramm { --sec-farbe: var(--f-strukto); --sec-farbe-rgb: var(--f-strukto-rgb); }
.fs.arrays       { --sec-farbe: var(--f-arrays);  --sec-farbe-rgb: var(--f-arrays-rgb); }
.fs-h > i { color: var(--sec-farbe, var(--accent)); }

/* Kopf des Overlays. --sec-farbe traegt die Bereichsfarbe an Ring und
   Umschalter weiter; ohne Bereich (Gesamtsicht) bleibt der Akzent stehen. */
.fs-hero-wrap { margin-bottom: 12px; }
.fs-hero-wrap.joule        { --sec-farbe: var(--f-joule);   --sec-farbe-rgb: var(--f-joule-rgb); }
.fs-hero-wrap.python       { --sec-farbe: var(--f-python);  --sec-farbe-rgb: var(--f-python-rgb); }
.fs-hero-wrap.struktogramm { --sec-farbe: var(--f-strukto); --sec-farbe-rgb: var(--f-strukto-rgb); }
.fs-hero-wrap.arrays       { --sec-farbe: var(--f-arrays);  --sec-farbe-rgb: var(--f-arrays-rgb); }

/* Eine Pille je Bereich, dahinter „Alle Bereiche". Sie sind der einzige
   Umschalter des Overlays: unten steht immer nur, was hier gewaehlt ist. */
.fs-pills { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 12px; }
.fs-pill {
  border: 1px solid var(--border); background: var(--bg); color: var(--text-muted);
  border-radius: var(--rad-m); padding: 4px 10px; font-size: 12px; font-weight: 600;
  font-family: inherit; display: inline-flex; align-items: center; gap: 4px;
  transition: background .15s, color .15s, border-color .15s;
}
.fs-pill i { font-size: 12px; }
.fs-pill:hover { color: var(--text); border-color: var(--text-dim); }
.fs-pill.on { border-color: transparent;
  background: rgba(var(--sec-farbe-rgb, 79, 142, 247), .14);
  color: var(--sec-farbe, var(--accent)); }
.fs-pill.on.gesamt { background: var(--surface-3); color: var(--text); }
.fs-pill.joule        { --sec-farbe: var(--f-joule);   --sec-farbe-rgb: var(--f-joule-rgb); }
.fs-pill.python       { --sec-farbe: var(--f-python);  --sec-farbe-rgb: var(--f-python-rgb); }
.fs-pill.struktogramm { --sec-farbe: var(--f-strukto); --sec-farbe-rgb: var(--f-strukto-rgb); }
.fs-pill.arrays       { --sec-farbe: var(--f-arrays);  --sec-farbe-rgb: var(--f-arrays-rgb); }
.fs-pill:focus-visible { outline: 2px solid var(--info); outline-offset: 1px; }
/* Zeilenlaenge im Lesetext begrenzen, statt sie der Panelbreite zu ueberlassen. */
.fs-hero-note { margin: 9px 0 0; max-width: 52ch; font-size: 11.5px; line-height: 1.5; color: var(--text-dim); text-wrap: pretty; }

.fs-hero { display: flex; gap: 16px; align-items: center; }
.fs-ring { position: relative; width: 92px; height: 92px; flex: 0 0 auto; }
.fs-ring svg { display: block; }
.fs-ring-txt { position: absolute; inset: 0; display: grid; place-items: center; text-align: center; }
.fs-ring-txt b { display: block; font-size: 19px; font-weight: 700; }
.fs-ring-txt span { font-size: 10.5px; color: var(--text-muted); }
.fs-mets { flex: 1; display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.fs-met { background: var(--bg); border: 1px solid var(--border); border-radius: var(--rad-m); padding: 8px 11px; display: flex; align-items: center; gap: 8px; }
.fs-met i { font-size: 16px; color: var(--warning); flex: 0 0 auto; }
.fs-met b { font-size: 15px; font-weight: 600; }
.fs-met span { color: var(--text-muted); font-size: 12px; }
.fs-met.dim i, .fs-met.dim b { color: var(--text-dim); }
/* Auf Schuelerbreite reicht der Platz nicht fuer Ring und Metrik-Kaesten
   nebeneinander: der Ring rueckt nach oben, die Kaesten bekommen die volle
   Breite. Ohne das laufen "Joker verfuegbar" und "Strikes" aus dem Panel. */
@media (max-width: 460px) {
  .fs-hero { flex-direction: column; align-items: center; gap: 12px; }
  .fs-mets { width: 100%; }
}
/* Noch schmaler bleibt fuer zwei Spalten kein Platz: "Joker verfuegbar" bricht
   sonst zwischen die beiden Woerter. Eine Spalte haelt die Begriffe zusammen. */
@media (max-width: 400px) {
  .fs-mets { grid-template-columns: 1fr; }
}


.fs-sec { background: var(--bg); border: 1px solid var(--border); border-radius: var(--rad-m); padding: 10px 12px; margin-bottom: 8px; }
.fs-sec-h { display: flex; align-items: center; gap: 9px; width: 100%; background: none; border: none; padding: 0; text-align: left; font-size: 13px; }
.fs-sec-h:disabled { cursor: default; }
/* Jede Sektion traegt die Farbe ihres Bereichs — hier stehen alle vier
   untereinander, deshalb faerbt nicht body.bereich-*, sondern die Sektion. */
.fs-sec.joule        { --sec-farbe: var(--f-joule);   --sec-farbe-rgb: var(--f-joule-rgb); }
.fs-sec.python       { --sec-farbe: var(--f-python);  --sec-farbe-rgb: var(--f-python-rgb); }
.fs-sec.struktogramm { --sec-farbe: var(--f-strukto); --sec-farbe-rgb: var(--f-strukto-rgb); }
.fs-sec.arrays       { --sec-farbe: var(--f-arrays);  --sec-farbe-rgb: var(--f-arrays-rgb); }
.fs-sec-h .ico {
  width: 26px; height: 26px; border-radius: 8px; display: grid; place-items: center;
  background: rgba(var(--sec-farbe-rgb, 79, 142, 247), .16);
  color: var(--sec-farbe, var(--accent)); font-size: 15px; flex: 0 0 auto;
}
.fs-sec.locked .ico { background: transparent; border: 1px solid var(--border); color: var(--text-dim); }
.fs-sec-h b { font-weight: 600; font-size: 13.5px; }
.fs-sec.locked .fs-sec-h b { color: var(--text-muted); }
.fs-sec-h .cnt { margin-left: auto; color: var(--text-muted); font-size: 12px; font-family: var(--mono); }
.fs-sec-h .chev { color: var(--text-dim); font-size: 15px; flex: 0 0 auto; transition: transform .2s; }
.fs-sec.open .fs-sec-h .chev { transform: rotate(90deg); }
.fs-sec .bar { margin: 9px 0 0; }
.fs-sec .bar > span { background: var(--sec-farbe, var(--accent)); }

/* Punkte- und Jokerstand des Bereichs, direkt unter dem Balken. */
.fs-sec-stand { display: flex; flex-wrap: wrap; gap: 4px 14px; margin-top: 7px; font-size: 11.5px; color: var(--text-muted); }
.fs-sec-stand span { display: inline-flex; align-items: center; gap: 4px; white-space: nowrap; }
.fs-sec-stand i { font-size: 13px; color: var(--sec-farbe, var(--accent)); }
.fs-sec-stand span:nth-child(2) i { color: var(--warning); }
.fs-blks { display: none; margin-top: 4px; }
.fs-blks .fs-blk:first-child { border-top: none; }
.fs-sec.open .fs-blks { display: block; }

.fs-blk { display: flex; align-items: center; gap: 8px; padding: 6px 2px 6px 4px; border-top: 1px solid var(--border-soft); font-size: 12.5px; }
.fs-blk .num { color: var(--text-dim); font-family: var(--mono); font-size: 11.5px; width: 16px; flex: 0 0 auto; }
.fs-blk .titel { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fs-fill { flex: 1 1 auto; min-width: 8px; }
/* Feste Spalte neben den Punkten, Inhalt linksbuendig: alle "Quiz" beginnen
   auf derselben Hoehe, lange Staende wachsen nach rechts (Wunsch Steve). */
.fs-quiz { display: flex; gap: 3px; align-items: center; justify-content: flex-start; flex: 0 0 auto; width: 108px; }
.fs-quiz .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--border); }
.fs-quiz .dot.on { background: var(--info); }
.fs-quiz .txt { font-size: 11px; color: var(--text-dim); font-family: var(--mono); }
.fs-blk .pts { font-family: var(--mono); font-size: 11.5px; font-weight: 600; width: 86px; text-align: right; flex: 0 0 auto; white-space: nowrap; }
.fs-blk .pts.full { color: var(--accent); }
.fs-blk .pts.mid  { color: var(--warning); }
.fs-blk .pts.low  { color: #d98a2b; }
.fs-blk .pts.zero { color: var(--text-dim); }
.fs-st { width: 22px; text-align: center; flex: 0 0 auto; font-size: 15px; }
.fs-st.strike i { color: var(--warning); }
.fs-st.gut i    { color: var(--accent); }
.fs-st.abg i    { color: var(--info); }
.fs-st.pot i    { color: #d98a2b; }
/* „Offen" ist ein gestrichelter Kreis in der Bereichsfarbe, kein Wort: der
   breite Schriftzug stoerte zwischen den schmalen Symbolen der anderen
   Zustaende (Entscheid Steve 2026-09-04). */
.fs-st.offen i { color: var(--sec-farbe, var(--accent)); }
.fs-st.lock i  { color: var(--text-dim); }
.fs-blk.lk, .fs-blk.lk .pts, .fs-blk.lk .titel { color: var(--text-dim); }
.fs-lock { color: var(--text-muted); font-size: 12px; }

.fs-legende { display: flex; gap: 12px; margin-top: 12px; color: var(--text-muted); font-size: 11.5px; align-items: center; white-space: nowrap; }
/* Auf voller Fensterbreite steht die Legende in einer Zeile (Vorgabe Steve).
   Sobald das Fenster schmaler wird als seine 620px, darf sie umbrechen —
   abgeschnittener Text waere schlechter als zwei Zeilen. */
@media (max-width: 680px) {
  .fs-legende { flex-wrap: wrap; white-space: normal; gap: 8px 12px; }
  /* Nummer und Titel oben, Quiz, Punkte und Symbol darunter eingerueckt:
     nebeneinander blieben fuer den Blocktitel nur rund 50px. */
  .fs-blk { flex-wrap: wrap; row-gap: 2px; }
  .fs-blk .titel { flex: 1 1 calc(100% - 25px); min-width: 0; }
  .fs-quiz { width: auto; margin-left: 25px; }
  .fs-fill { display: none; }
}
.fs-legende i { font-size: 14px; margin-right: 3px; vertical-align: -2px; }
.fs-legende .l-strike i { color: var(--warning); }
.fs-legende .l-gut i    { color: var(--accent); }
.fs-legende .l-abg i    { color: var(--info); }
.fs-legende .l-pot i    { color: #d98a2b; }
.fs-legende .l-offen i  { color: var(--sec-farbe, var(--accent)); }
.fs-legende .l-lock i   { color: var(--text-dim); }

/* Die Quiz-Punkte tragen dieselbe Farbstufe wie die Blockpunkte daneben,
   damit die Zeile auf einen Blick eine Farbe spricht. */
.fs-quiz.q-full .dot.on { background: var(--accent); }
.fs-quiz.q-mid  .dot.on { background: var(--warning); }
.fs-quiz.q-low  .dot.on { background: #d98a2b; }
.fs-quiz.q-full .txt { color: var(--accent); }
.fs-quiz.q-mid  .txt { color: var(--warning); }

/* ---- Eingangsabfrage „Dein Startpunkt" (startpunkt.php) ----
   Zentrierte Karte in Auth-Optik, aber breiter (Fragen + Optionen).
   Bewusst freundlich-ruhig: kein Timer, kein Score, kein Rot/Grün. */
.sp-wrap {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px 16px;
}
.sp-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--rad-l);
  padding: 2rem 2.2rem;
  width: 100%;
  max-width: 640px;
}
.sp-title { font-size: 1.5rem; margin: 0 0 1rem; }
.sp-text  { color: var(--text-muted); line-height: 1.55; margin: 0 0 0.9rem; }
.sp-text b { color: var(--text); }
.sp-progress {
  font-size: 0.8rem;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-bottom: 0.8rem;
}
.sp-frage { font-size: 1.1rem; line-height: 1.45; margin: 0 0 1rem; font-weight: 600; }
.sp-code {
  font-family: var(--mono);
  font-size: 0.95rem;
  background: var(--surface-2);
  border: 1px solid var(--border-soft);
  border-radius: var(--rad-m);
  padding: 0.8rem 1rem;
  margin: 0 0 1rem;
  white-space: pre;
  overflow-x: auto;
}
.sp-bild {
  display: block;
  width: 100%;
  max-width: 420px;
  margin: 0 auto 1rem;
}
/* hidden-Attribut muss auch gegen eigene display-Regeln gewinnen. */
.sp-card [hidden] { display: none !important; }

/* ---- Admin-Auswertung: Startpunkt-Matrix (Können × Zutrauen) ---- */
.aw-mx { width: 100%; border-collapse: separate; border-spacing: 5px; margin: 4px 0 6px; }
.aw-mx td.kopf {
  color: var(--text-dim); font-size: 11px; text-transform: uppercase;
  letter-spacing: .08em; padding: 4px 6px; vertical-align: middle;
}
.aw-mx td.kopf.zeile { width: 160px; text-transform: none; letter-spacing: 0; font-size: 12.5px; color: var(--text-muted); }
.aw-mx td.kopf.zeile small { color: var(--text-dim); }
.aw-mx td.zelle {
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: var(--rad-m); padding: 9px 11px; width: 40%; vertical-align: top;
}
.aw-mx td.zelle.hot { border-color: var(--warning); background: var(--warning-bg); }
.aw-mx td.zelle.hot i { color: var(--warning); font-size: 14px; margin-left: 4px; }
.aw-mx-zahl { font-size: 19px; font-weight: 700; }
.aw-mx-namen { font-size: 11.5px; color: var(--text-muted); margin-top: 2px; line-height: 1.45; }
.aw-stand { font-size: 12.5px; color: var(--text-muted); }
.aw-user { color: var(--text-dim); font-size: 11.5px; }
.aw-badge {
  display: inline-block; border: 1px solid var(--border); border-radius: 999px;
  padding: 0 8px; font-size: 11px; margin-left: 4px; color: var(--text-muted);
}
.aw-badge.gruen { border-color: var(--success); color: var(--success); background: var(--success-bg); }
.aw-badge.amber { border-color: var(--warning); color: var(--warning); background: var(--warning-bg); }
.aw-badge.grau  { color: var(--text-dim); }
.aw-hinweis { font-size: 11.5px; color: var(--text-dim); margin: 8px 0 0; }
.aw-hinweis i { color: var(--warning); vertical-align: -1px; }
.sp-hinweis { font-size: 0.8rem; color: var(--text-dim); margin-bottom: 0.6rem; }
.sp-optionen { display: flex; flex-direction: column; gap: 0.55rem; margin-bottom: 1.2rem; }
.sp-option {
  text-align: left;
  font: inherit;
  font-size: 0.95rem;
  color: var(--text);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--rad-m);
  padding: 0.7rem 0.9rem;
  cursor: pointer;
  transition: border-color var(--speed), background var(--speed);
}
.sp-option:hover { border-color: var(--text-dim); }
.sp-option.gewaehlt {
  border-color: var(--info);
  background: var(--info-bg);
}
.sp-done-icon { font-size: 2.4rem; color: var(--accent); margin-bottom: 0.4rem; }
.sp-error {
  margin-top: 0.9rem;
  background: var(--error-bg);
  border: 1px solid var(--error-bd);
  color: var(--error-fg);
  border-radius: var(--rad-m);
  padding: 0.6rem 0.8rem;
  font-size: 0.85rem;
}
#sp-weiter:disabled, #sp-weiter[disabled] { opacity: 0.45; cursor: default; }

/* ===== Einführungs-Modal (Theorie-Player im Iframe) =====================
   Rahmen und Schliessen-Knopf; das Aussehen im Inneren bringt der Player
   selbst mit (/einfuehrung/player.css). Die ID #video-modal-close ist Teil
   der Embed-Konvention: der Schluss-Screen des Players klickt sie an.
   Breite: bewusst 94vw, damit die Player-Bühne auf dem iPad hoch (768px)
   über der 700px-Schwelle bleibt und ihre 640px-Breite behält. */
#video-modal-overlay {
  display: none; position: fixed; inset: 0; z-index: 200;
  background: rgba(8, 10, 13, 0.62); backdrop-filter: blur(3px);
  justify-content: center; align-items: center;
}
#video-modal-overlay.open { display: flex; }
#video-modal {
  position: relative;
  width: min(94vw, 1180px); height: min(90vh, 940px);
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--rad-l); overflow: hidden;
}
#video-modal-iframe { display: block; width: 100%; height: 100%; border: none; background: transparent; }
#video-modal-close {
  position: absolute; top: 8px; right: 10px; z-index: 2;
  width: 32px; height: 32px; border: none; border-radius: 8px;
  background: transparent; color: var(--text-dim);
  font-size: 22px; line-height: 1; display: grid; place-items: center;
  cursor: pointer; transition: color var(--speed), background var(--speed);
}
#video-modal-close:hover { color: var(--text); background: var(--surface-3); }
body.theme-light #video-modal-overlay { background: rgba(15, 23, 42, 0.42); }
body.theme-light #video-modal { background: #ffffff; }
body.theme-light #video-modal-close:hover { background: rgba(0, 0, 0, 0.06); }

/* ===========================================================================
   Tablet hoch (iPad 768 und schmaler, Schwelle 980px): Die drei Spalten passen nicht mehr
   nebeneinander — bei 768px blieben dem Arbeitsbereich 152px, der
   Aufgabentext brach nach jedem zweiten Wort um und vom Editor war ein
   Drittel zu sehen. Deshalb wandert die Bühne unter den Arbeitsbereich:
   Sidebar bleibt links, rechts stehen Editor/Konsole oben und die Bühne
   (Joule-Welt bzw. Beispiel-Lauf) darunter. Umgesetzt als Grid, weil das
   Markup .rail/.work/.stage als Geschwister nebeneinanderliegen.
   =========================================================================== */
/* ===========================================================================
   Touch-Groessen (Tablet). Der Breakpoint ist bewusst 1200px: Das iPad quer
   misst 1180 bzw. 1194 und fiel durch alle vorhandenen Raster (1350, 1366,
   980) hindurch — ausgerechnet das Geraet, fuer das groessere Ziele gedacht
   sind, bekam sie nie. Vorlage ist der Block aus sqllearn, die Klassennamen
   hier sind andere.

   Steht bewusst VOR dem 980er-Block: der engere Breakpoint fuer schmale
   Schirme muss diese Werte gezielt ueberschreiben koennen.
   =========================================================================== */
@media (max-width: 1200px) {
  /* Die Aufgabenleiste hat eine feste Hoehe (40px). Ohne Anhebung passen die
     40px-Ziele nicht hinein und sprengen die Leiste. Angehoben wird die
     Variable, nicht .taskbar direkt: die angedockte Spalte rechnet mit ihr
     (.drawer.dock berechnet daraus ihren Abstand von oben). */
  :root { --taskbar-h: 52px; }

  /* flex-shrink ausschalten: In der vollen Kopfleiste drueckt der Flex-Umbruch
     die Icons sonst wieder auf 34px Breite zusammen, gemessen bei 900px. */
  .uicon { width: 40px; height: 40px; font-size: 20px; flex: 0 0 auto; }
  .status { min-height: 40px; }
  .btn { min-height: 40px; }
  .hint, .tchip { min-height: 40px; }
  /* Pfeil und Nachbarname sind ein Knopf und damit schon breit genug; hier
     waechst nur die Hoehe auf das Touch-Mass. Die Breite bleibt fest, sonst
     bricht die Flucht zur Seitenleiste. */
  .nav .nav-schritt, .nav .pos { min-height: 40px; }
  /* Touch-Mass ueber die Gruppe, nicht ueber den einzelnen Knopf: Eine
     Mindesthoehe am Bereichsknopf sprengte die 34px-Gruppe von oben, waehrend
     der Durchgangsknopf daneben auf 26px stehen blieb — zwei verschieden hohe
     Knoepfe in einer Reihe (Befund Steve 2026-09-05). Jetzt wachsen beide
     Gruppen auf das Mass der Icon-Knoepfe, und ihre Knoepfe fuellen sie aus. */
  .modes, .dg, .avatar { height: 40px; }
  .mode, .dg-btn { align-self: stretch; }

  /* Listeneintraege bleiben groesser als die 40px der Leisten: in der
     Seitenleiste stehen viele Zeilen dicht untereinander, ein Fehlgriff
     trifft die Nachbaraufgabe. */
  .item { min-height: 44px; }
  .blk-h { min-height: 44px; }
}

@media (max-width: 980px) {
  .body {
    display: grid;
    grid-template-columns: var(--sidebar-w) minmax(0, 1fr);
    grid-template-rows: auto auto;
    overflow-y: auto;
  }
  .rail  { grid-column: 1; grid-row: 1 / -1; }
  /* Beide Zeilen wachsen mit ihrem Inhalt, gescrollt wird gemeinsam in .body —
     sonst scrollt der Arbeitsbereich in sich und die Buehne bleibt unten
     ausserhalb des Bildes stehen. */
  /* Etwas engere Abstaende: Auf 1024px Hoehe entscheiden 20px darueber, ob
     die Buehne noch ins Bild passt. */
  .work  { grid-column: 2; grid-row: 1; overflow: visible; padding: 12px 14px; gap: 8px; }
  /* overflow bleibt hidden: Das Tipp-Overlay liegt absolut in .stage und
     wuerde die Breite sonst auf 871px aufblaehen (horizontaler Scrollbalken).
     Die Hoehe waechst trotzdem mit dem Inhalt. */
  .stage {
    grid-column: 2; grid-row: 2;
    width: auto;
    border-top: 1px solid var(--border);
  }
  /* Die Joule-Welt richtet ihre Zellgroesse nach dem verfuegbaren Platz.
     Ohne Mindesthoehe entsteht ein Teufelskreis: wenig Platz, kleine Welt,
     dadurch wieder wenig Inhaltshoehe — gemessen 173x93px. Im Python-Bereich
     traegt die Buehne nur den Beispiel-Lauf und darf mit dem Inhalt wachsen. */
  body:not(.mode-python) .stage { min-height: 34vh; }
  /* Die leere Konsole nimmt sonst den halben Schirm und schiebt die Buehne
     aus dem Bild. Im Joule-Bereich faellt sie knapper aus, weil dort die Welt
     darunter den Platz braucht; im Python-Bereich ist die Konsole selbst das
     Ergebnisfenster und darf groesser sein. */
  .console-b { max-height: 34vh; }
  body:not(.mode-python) .console-b { max-height: 16vh; }
  /* Das Quiz ersetzt beide Zeilen, nicht nur die obere. Die Theorie steht
     hier bewusst NICHT: Sie liegt absolut über .body, und eine Platzierung
     in Spalte 2 hätte sie neben die Seitenleiste gesetzt. Ohne Platzierung
     deckt sie den ganzen Rahmen, die Leiste bleibt wie am Desktop verdeckt
     (Entscheid Steve 2026-09-12). Solange sie offen ist, scrollt .body
     nicht unter ihr weg; app.js setzt den Scroll beim Öffnen auf 0. */
  .quiz { grid-column: 2; grid-row: 1 / -1; }
  body.theory-open .body { overflow: hidden; }

  /* Strukto: Die obere Rasterzeile waechst hier sonst nur mit ihrem Inhalt,
     und die Werkbank blieb auf ihrer Mindesthoehe stehen, waehrend darunter
     Platz bis zum Fensterrand frei lag (Befund Steve 2026-09-05). Sie nimmt
     deshalb den freien Platz, faellt aber nie unter 320px — dann scrollt der
     Arbeitsbereich, statt die Zeichenflaeche unbrauchbar zu machen.
     Gilt nur im Strukto-Bereich: in Joule und Python traegt die untere Zeile
     die Buehne und soll ihren Anteil behalten. */
  body.mode-strukto .body { grid-template-rows: minmax(320px, 1fr) auto; }
  body.mode-strukto .work { overflow: hidden auto; }

  /* Kopf- und Aufgabenzeile passen in einer Reihe nicht mehr in 768px.
     Der Schriftzug weicht auf das Logo zurueck, die Aufgabenzeile darf
     umbrechen — sonst schiebt sie die Tipp-Knoepfe aus dem Bild. */
  /* Die Marke bleibt hier noch vollstaendig; sie faellt erst bei 800px, siehe
     unten. Vorher verschwand nur ihr Text, waehrend ihre feste Breite von
     204px weiter belegt blieb. */
  .taskbar { height: auto; min-height: var(--taskbar-h); flex-wrap: wrap; row-gap: 6px; padding-top: 5px; padding-bottom: 5px; }
}

/* Klassengruppen (Welle 1, Auftrag 24): Jahrgangsfelder und Merkmale. */
.adm-jahrgang { white-space: nowrap; color: var(--text-muted); font-size: 12px; }
label.adm-jahrgang { display: inline-flex; align-items: center; gap: 4px; }
td.adm-jahrgang .adm-jahr { margin: 0 2px; }
.adm-jahr { width: 6ch; font: inherit; font-size: 12px; padding: 3px 4px; border: 1px solid var(--border); border-radius: 6px; background: transparent; color: var(--text); text-align: center; -moz-appearance: textfield; appearance: textfield; }
.adm-jahr:focus { outline: none; border-color: var(--info); }
.adm-jahr::-webkit-outer-spin-button, .adm-jahr::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.adm-pill.offen { border-style: dashed; color: var(--text-dim); }

/* Jahrgangsstufe (Klassen-Admin): J1 blau, J2 amber, damit die Stufe auf einen Blick unterscheidbar ist. */
.adm-stufe { font: inherit; font-size: 12px; font-weight: 600; padding: 3px 6px; border-radius: 999px; border: 1px solid var(--border); background: transparent; color: var(--text); }
.adm-stufe.s1 { color: var(--info); border-color: var(--info); background: var(--info-bg); }
.adm-stufe.s2 { color: var(--warning); border-color: var(--warning); background: var(--warning-bg); }
.admin-row select.adm-stufe { width: auto; }
button.adm-pill.abi { color: var(--text-dim); border-style: dashed; }
button.adm-pill.abi.an { background: var(--info-bg); color: var(--info); border-color: transparent; border-style: solid; font-weight: 600; }
button.adm-pill.abi:hover { border-color: var(--info); color: var(--info); }

/* Durchgang (Welle 2, Auftrag 24): Umschalter im Kopf, Marke im Overlay, Freigabe-Matrix. */
.dg { display: flex; align-items: center; gap: 2px; margin-left: 8px; background: var(--bg); border: 1px solid var(--border); border-radius: var(--rad-m); padding: 3px; }
.dg-btn { display: flex; align-items: center; gap: 5px; border: none; background: transparent; color: var(--text-muted); padding: 5px 11px; border-radius: 7px; font-size: 13px; font-weight: 500; cursor: pointer; transition: background .15s, color .15s; white-space: nowrap; }
.dg-btn i { font-size: 16px; }
.dg-btn.active { background: rgba(var(--bereich-signal-rgb), .14); color: var(--bereich-signal); cursor: default; }
.dg-btn:not(.active):hover { background: var(--surface-2); color: var(--text); }
/* Ab 1200px wird die Kopfleiste zu eng fuer „1. Durchgang" — dort steht nur
   noch „DG 1". Das Touch-Ziel bleibt gleich gross, nur der Text kuerzt sich
   (Befund Steve 2026-09-04; iPad quer liegt bei 1180px). */
.dg-kurz { display: none; }
@media (max-width: 1200px) {
  .dg-lang { display: none; }
  .dg-kurz { display: inline; }
  .dg-btn { padding: 5px 10px; }
  .dg-btn i { display: none; }
}
/* Bei drei und mehr Durchgaengen kommt die Enge frueher: die Gruppe misst
   ausgeschrieben 370px statt 249px, und seit der Results-Knopf in der Zeile
   steht, braucht die volle Fassung 1493px (nachgemessen 2026-09-08 am
   schlimmsten Fall: Schueler in Joule mit Schloss-Icons). Die Kurzform greift
   dort deshalb ab 1500px statt erst ab 1200 (gemessen 2026-09-05). Sie ist
   damit die erste Sparstufe der Zeile ueberhaupt und steht bewusst ueber
   allen anderen: so kuerzt erst der Durchgang, dann der Punktestand (1290)
   und erst zuletzt die Bereichsnamen (1180). Die Zahl der Knoepfe steht als
   Klasse am Body, siehe renderDurchgang in app.js. */
@media (max-width: 1500px) {
  body.dgn-3 .dg-lang, body.dgn-4 .dg-lang { display: none; }
  body.dgn-3 .dg-kurz, body.dgn-4 .dg-kurz { display: inline; }
  body.dgn-3 .dg-btn, body.dgn-4 .dg-btn { padding: 5px 10px; }
  body.dgn-3 .dg-btn i, body.dgn-4 .dg-btn i { display: none; }
}
.frg-wrap { overflow-x: visible; }
.frg-tbl { width: 100%; table-layout: auto; }
.frg-tbl th:first-child, .frg-tbl td:first-child { width: 1%; white-space: nowrap; }
.frg-tbl th.frg-b { white-space: nowrap; }
.frg-klasse { white-space: nowrap; }
.frg-klasse .adm-jahrgang { margin-left: 6px; }
/* Je Zelle: Block-Stufe in der ersten Zeile, Durchgang und Häkchen darunter.
   So passt die Matrix in jede Breite, ohne zu scrollen oder abzuschneiden. */
.frg-wrap { overflow-x: auto; }
.frg-zelle { white-space: nowrap; vertical-align: top; }
.frg-zelle .frg-form { display: grid; grid-template-columns: auto auto; gap: 7px 10px; align-items: center; justify-content: start; }
.frg-form select { font-size: 12px; }
.frg-zelle .frg-dgz { display: inline-flex; align-items: center; gap: 4px; font-size: 11px; color: var(--text-dim); }
.frg-zelle .frg-block { grid-column: 1 / -1; width: 100%; min-width: 0; }
.frg-klasse { white-space: nowrap; }
.frg-form select.frg-dg { font-size: 12px; padding: 6px 4px; min-height: 34px; border-radius: 6px; }
.frg-form select.frg-dg.an { color: var(--info); font-weight: 600; }
.frg-tbl td { padding: 10px 4px; }
.frg-tbl th { padding-left: 6px; padding-right: 6px; }
.frg-gruppen { margin-bottom: 8px; }
.frg-chip { cursor: pointer; display: inline-flex; align-items: center; gap: 5px; }
.frg-chip input { margin: 0; }
.frg-chip:has(input:checked) { background: var(--success-bg); color: var(--success); border-color: transparent; font-weight: 600; }
.frg-check { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; color: var(--text-muted); white-space: nowrap; }
.adm-chip-trenner { width: 1px; height: 18px; background: var(--border); margin: 0 4px; }
.adm-chip.dg.active { background: var(--warning-bg); color: var(--warning); }
@media (max-width: 1200px) {
  .dg-btn { padding: 5px 8px; font-size: 12px; }
}
@media (max-width: 900px) {
  .frg-wrap { overflow-x: auto; }
  .frg-tbl { table-layout: auto; }
}

/* Jahrgang (Welle 4, Auftrag 24): Kennzahlen und die drei Schritte. */
.abs-jahrgang h2 .adm-jahrgang { margin-left: 10px; font-weight: 400; }
.abs-kennzahlen td:not(:first-child) { font-variant-numeric: tabular-nums; }
.abs-kennzahlen tr.abs-fehlt td { color: var(--text-dim); }
.abs-kennzahlen tr.abs-ok td:last-child { color: var(--success); }
.abs-kennzahlen tr.abs-warn td { color: var(--warning); }
.abs-aktionen { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin-top: 12px; }
.abs-karte { border: 1px solid var(--border); border-radius: var(--rad-m); padding: 12px 14px; display: flex; flex-direction: column; gap: 8px; }
.abs-karte.gefahr { border-color: var(--error-bd); }
.abs-karte h3 { margin: 0; font-size: 14px; display: flex; align-items: center; gap: 8px; }
.abs-karte p { margin: 0; font-size: 12.5px; line-height: 1.5; color: var(--text-muted); max-width: 46ch; text-wrap: pretty; flex: 1; }
.abs-karte code { font-size: 11.5px; }
.abs-nr { display: inline-flex; width: 22px; height: 22px; border-radius: 50%; background: var(--info-bg); color: var(--info); align-items: center; justify-content: center; font-size: 12px; font-weight: 700; }
.abs-karte.gefahr .abs-nr { background: var(--danger-bg); color: var(--danger); }
.abs-liste { margin: 6px 0 0; padding-left: 20px; font-size: 12.5px; line-height: 1.6; color: var(--text-muted); max-width: 80ch; }
@media (max-width: 1200px) { .abs-aktionen { grid-template-columns: 1fr; } }

/* Abitur-Block (Welle 5): Marke im Lernpfad, im Overlay und in der Auswertung. */
.blk-abi, .fs-abi { display: inline-flex; align-items: center; margin-left: 6px; padding: 0 6px; border-radius: 999px; font-size: 10px; font-weight: 700; letter-spacing: .02em; background: var(--info-bg); color: var(--info); line-height: 16px; vertical-align: middle; }
th.awf-abi { color: var(--info); }
.adm-chip.abi { display: inline-flex; align-items: center; gap: 4px; }
.adm-chip.abi.active { background: var(--info-bg); color: var(--info); }

/* Admin zurücksetzen (Freigaben): eigenes Konto der Lehrkraft leeren. */
.frg-klein { font-size: 11px; color: var(--text-dim); white-space: nowrap; }

/* Klassen: Registrierungs-Codes bearbeitbar (Steve 2026-09-11) */
.adm-codes { white-space: nowrap; }
.adm-code-zeile { display: flex; align-items: center; gap: 4px; margin: 2px 0; }
.adm-code-edit { width: 18ch; font-size: 12px; padding: 3px 6px; border: 1px solid var(--border); border-radius: 6px; background: transparent; color: var(--success); font-weight: 600; letter-spacing: .02em; }
.adm-code-edit.aus { color: var(--text-dim); text-decoration: line-through; }
.adm-code-edit:focus { outline: none; border-color: var(--info); }

/* ---- Strike-Feier (js/feier.js) ----
   Ebene über der ganzen Seite mit eigener Bühne: Joule-Raster oder Editor-
   Karte, dazu Sternenregen auf einem Canvas. Farben laufen über die Tokens,
   damit Hell und Dunkel passen; der Schleier ist in beiden Themes dunkel. */
.feier { position: fixed; inset: 0; z-index: 9000; display: grid; place-items: center; cursor: pointer;
  background: rgba(8, 13, 28, 0); backdrop-filter: blur(0); -webkit-backdrop-filter: blur(0);
  transition: background .35s, backdrop-filter .35s, -webkit-backdrop-filter .35s; }
.feier.an  { background: rgba(8, 13, 28, .72); backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px); }
.feier.aus { background: rgba(8, 13, 28, 0); backdrop-filter: blur(0); -webkit-backdrop-filter: blur(0); }
.feier-regen { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.feier-buehne { position: relative; z-index: 2; transform: scale(.7); opacity: 0;
  transition: transform .45s cubic-bezier(.2,1.3,.4,1), opacity .3s; }
.feier.an  .feier-buehne { transform: scale(1); opacity: 1; }
.feier.aus .feier-buehne { transform: scale(.85); opacity: 0; }
.feier-abzeichen { position: absolute; left: 50%; bottom: -58px; transform: translateX(-50%) scale(.6); opacity: 0;
  background: #facc15; color: #3a2b00; font-weight: 700; font-size: 17px; padding: 10px 20px;
  border-radius: 999px; white-space: nowrap; box-shadow: 0 8px 28px rgba(0,0,0,.5); }
/* Festes Gelb statt --warning: im hellen Theme ist --warning dunkles Amber, das
   Abzeichen soll in beiden Themes dieselbe Feierfarbe tragen. */
.feier-abzeichen.an { animation: feier-abz .6s ease forwards; }
@keyframes feier-abz {
  0%   { opacity: 0; transform: translateX(-50%) scale(.6); }
  65%  { opacity: 1; transform: translateX(-50%) scale(1.08); }
  100% { opacity: 1; transform: translateX(-50%) scale(1); }
}
.feier-weiter { position: absolute; left: 50%; bottom: -96px; transform: translateX(-50%); color: #cbd5e1;
  font-size: 12.5px; white-space: nowrap; opacity: 0; transition: opacity .4s 1.2s; }
.feier.an .feier-weiter { opacity: 1; }

/* Joule-Bühne: 5x5 in groß, Zellen wie die echte Welt, nur ohne deren Skalierung */
.feier-welt { display: grid; gap: 3px; grid-template-columns: repeat(5, 72px); grid-template-rows: repeat(5, 72px);
  padding: 14px; background: var(--surface); border: 1px solid var(--border); border-radius: 14px;
  box-shadow: 0 30px 80px rgba(0,0,0,.6); }
.feier-zelle { position: relative; border-radius: 5px; background: var(--surface-2); border: 1px solid var(--border);
  transition: background .25s, box-shadow .25s, border-color .25s; }
.feier-zelle.glow { background: rgba(79,142,247,.35); border-color: #4f8ef7; box-shadow: 0 0 16px rgba(79,142,247,.7); }
.feier-zelle svg { position: absolute; inset: 10%; width: 80%; height: 80%; }
.feier-zelle .joule-svg { transition: none; transform-origin: 50% 50%; }
.feier-zelle .joule-svg.tanz { animation: feier-tanz 2.6s cubic-bezier(.3,.7,.3,1) both; }
@keyframes feier-tanz {
  0%   { transform: translateY(0) rotate(0deg) scale(1); filter: brightness(1); }
  14%  { transform: translateY(-22px) rotate(180deg) scale(1.18); filter: brightness(1.9) drop-shadow(0 0 10px #fff); }
  28%  { transform: translateY(0) rotate(360deg) scale(1); filter: brightness(1); }
  40%  { transform: translateY(-14px) rotate(540deg) scale(1.1); filter: brightness(1.9) drop-shadow(0 0 10px #fff); }
  52%  { transform: translateY(0) rotate(720deg) scale(1); filter: brightness(1); }
  62%  { transform: translateY(-8px) rotate(720deg) scale(1.06); filter: brightness(1.8) drop-shadow(0 0 8px #facc15); }
  70%  { transform: translateY(0) rotate(720deg) scale(1); filter: brightness(1); }
  78%  { transform: translateY(-8px) rotate(720deg) scale(1.06); filter: brightness(1.8) drop-shadow(0 0 8px #facc15); }
  86%  { transform: translateY(0) rotate(720deg) scale(1); filter: brightness(1); }
  93%  { filter: brightness(1.8) drop-shadow(0 0 8px #facc15); }
  100% { transform: translateY(0) rotate(720deg) scale(1); filter: brightness(1); }
}
.feier-funke { position: absolute; left: 50%; top: 50%; width: 9px; height: 9px; border-radius: 50%;
  pointer-events: none; animation: feier-funke 1s ease-out forwards; }
.feier-funke.stern { border-radius: 0; width: 13px; height: 13px;
  clip-path: polygon(50% 0, 62% 38%, 100% 50%, 62% 62%, 50% 100%, 38% 62%, 0 50%, 38% 38%); }
@keyframes feier-funke {
  0%   { transform: translate(-50%,-50%) translate(0,0) scale(.6); opacity: 1; }
  100% { transform: translate(-50%,-50%) translate(var(--dx), var(--dy)) scale(1.2); opacity: 0; }
}

/* Editor-Bühne: Karte, in die sich der Feier-Schnipsel tippt */
.feier-buehne.code { width: min(560px, 92vw); background: var(--surface); border: 1px solid var(--border);
  border-radius: 14px; box-shadow: 0 30px 80px rgba(0,0,0,.6); }
/* Kein overflow:hidden auf der Karte, sonst wird das Abzeichen darunter
   abgeschnitten; Kopf und Ausgabe tragen die Rundung selbst. */
.feier-kopf { display: flex; align-items: center; gap: 8px; padding: 10px 14px; border-bottom: 1px solid var(--border);
  font-size: 12.5px; color: var(--text-muted); border-radius: 13px 13px 0 0; }
.feier-kopf i { width: 10px; height: 10px; border-radius: 50%; display: inline-block; }
.feier-kopf i:nth-child(1) { background: var(--danger); } .feier-kopf i:nth-child(2) { background: var(--warning); }
.feier-kopf i:nth-child(3) { background: var(--accent); }
.feier-kopf span { margin-left: 6px; font-family: var(--mono); }
.feier-zeilen { padding: 16px 18px; font: 16px/1.7 var(--mono); white-space: pre; min-height: 96px; color: var(--text); }
.feier-zeilen .kw  { color: #f472b6; } .feier-zeilen .fn { color: var(--info); }
.feier-zeilen .str { color: var(--warning); } .feier-zeilen .num { color: var(--accent); }
body.theme-light .feier-zeilen .kw  { color: #be185d; } body.theme-light .feier-zeilen .fn { color: #1d4ed8; }
body.theme-light .feier-zeilen .str { color: #a16207; } body.theme-light .feier-zeilen .num { color: #15803d; }
.feier-cursor { display: inline-block; width: 9px; height: 1.1em; background: var(--text); vertical-align: -3px;
  animation: feier-blink .9s steps(1) infinite; }
@keyframes feier-blink { 50% { opacity: 0; } }
.feier-ausgabe { border-top: 1px solid var(--border); background: var(--bg); padding: 12px 18px;
  font: 15px/1.6 var(--mono); white-space: pre-wrap; min-height: 64px; border-radius: 0 0 13px 13px; }
.feier-ausgabe .z { display: block; opacity: 0; transform: translateX(-6px); transition: opacity .25s, transform .25s; }
.feier-ausgabe .z.an { opacity: 1; transform: none; }
.feier-ausgabe .z.strike { color: var(--warning); font-weight: 700; }
.feier-ausgabe .z.ok { color: var(--accent); font-weight: 700; }
body.theme-light .feier-ausgabe .z.strike { color: #a16207; }

@media (max-width: 480px) {
  .feier-welt { grid-template-columns: repeat(5, 54px); grid-template-rows: repeat(5, 54px); padding: 10px; }
  .feier-abzeichen { font-size: 14.5px; padding: 8px 14px; }
  .feier-zeilen { font-size: 14px; } .feier-ausgabe { font-size: 13.5px; }
}
@media (prefers-reduced-motion: reduce) {
  .feier, .feier-buehne { transition: none; }
  .feier-abzeichen.an { animation-duration: .01s; }
}

/* Struktogramm-Bühne: nsd-Klassen des Operatoren-Panels, hochskaliert.
   Nur Schleife und Anweisung, Kästen blenden nacheinander ein. */
.feier-nsd { padding: 16px 18px; min-height: 96px; }
.feier-nsd .nsd-bsp { font-size: 17px; margin: 0; }
.feier-nsd .nsd-loop-kopf, .feier-nsd .nsd-box { padding: 9px 13px; }
.feier-nsd .nsd-loop-body { padding: 0 0 9px 30px; }
.feier-nsd .nsd-loop-body .nsd-box { color: var(--text); }
.feier-nsd .nsd-loop, .feier-nsd .nsd-box { opacity: 0; transform: translateY(-6px); transition: opacity .3s, transform .3s; }
.feier-nsd .an { opacity: 1; transform: none; }
@media (max-width: 480px) { .feier-nsd .nsd-bsp { font-size: 15px; } }

/* Test-Knöpfe im Admin (System → Zustand) */
.feier-test { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
