/* SketchLeague Social — die ganze Gestaltung der Oberflaeche.
 *
 * Fortsetzung von web/index.html des ShortMaker-Werkzeugs: dieselben
 * Farbnamen, dieselben Radien, derselbe Ton. Was das Werkzeug baut, sieht so
 * aus, und was den Betrieb steuert, sieht aus wie das Werkzeug.
 *
 * Paper 127: ein Operations-Dashboard, keine Marketingseite. Dichte Tabellen,
 * Monospace fuer IDs und Zahlen, wenige Klicks. Bewegung gibt es nur dort, wo
 * sie einen Zustand zeigt (laufende Arbeit) — sonst nirgends.
 *
 * Kein CDN, keine Schrift von aussen: die Oberflaeche muss ohne Internetzugang
 * vollstaendig funktionieren. Der Server, der sie ausliefert, hat im Ernstfall
 * gerade keinen.
 */

:root {
  /* Vier Ebenen statt drei: Grund, Karte, Feld in der Karte, und was darauf
     unter der Maus liegt. Mit dreien musste ein Knopf in einem Feld dieselbe
     Farbe tragen wie das Feld selbst und war nur am Rand zu erkennen.

     Der Grund ist nicht mehr neutralgrau, sondern einen Hauch blau — derselbe
     Nachtton wie der Hintergrund der Shorts (dart/short_theme.dart). Was das
     Panel baut und was es steuert, soll nach derselben Marke aussehen. */
  --bg: #0a0c11;
  --flaeche: #12151c;
  --flaeche2: #191d27;
  --flaeche3: #212633;
  --linie: #252a36;
  --linie-stark: #363d4d;
  --schrift: #eef1f6;
  --leise: #939bab;
  --blau: #2196F3;
  /* Blau als SCHRIFT auf dunklem Grund. Das Markenblau selbst ist dafuer zu
     dunkel (Kontrast 5,6 auf der Karte); als Flaeche bleibt es, wie es ist. */
  --blau-hell: #6cb8ff;
  --lila: #9C27B0;
  --cyan: #00BCD4;
  --gut: #4fd197;
  --warn: #f0b04a;
  --schlecht: #f0655c;
  --canvas: #F4F2EE;
  --r: 14px;
  --r-klein: 9px;

  /* Die Hintergruende der Statusfarben. Sie stehen hier und nicht in den
     Regeln, damit Pille, Zeile und Kachel garantiert denselben Ton treffen. */
  --gut-grund: #12281f;
  --warn-grund: #2c2413;
  --schlecht-grund: #2d1817;
  --blau-grund: #11253b;
  --aus-grund: #1e222b;

  /* Der Markenverlauf — Signet, Hauptknopf, laufende Balken. Er steht EINMAL
     hier; vorher war er an vier Stellen ausgeschrieben, an zweien ohne Lila. */
  --verlauf: linear-gradient(135deg, #2196F3 0%, #6a5cf0 55%, #9C27B0 100%);
  --verlauf-balken: linear-gradient(90deg, var(--blau), var(--cyan));

  --schatten: 0 1px 0 rgba(255, 255, 255, .035) inset, 0 12px 28px -18px rgba(0, 0, 0, .8);
  --schatten-hoch: 0 1px 0 rgba(255, 255, 255, .05) inset, 0 18px 40px -16px rgba(0, 0, 0, .85);

  --spalte-breite: 232px;
  --familie: ui-sans-serif, "Segoe UI Variable Text", "Segoe UI", system-ui, -apple-system, sans-serif;
  --familie-mono: ui-monospace, "Cascadia Code", Consolas, "DejaVu Sans Mono", monospace;
  --schrift-normal: 14px/1.5 var(--familie);
  --schrift-mono: 12.5px/1.5 var(--familie-mono);
}

* { box-sizing: border-box; }
html, body { height: 100%; }
html { color-scheme: dark; scrollbar-color: var(--linie-stark) transparent; }

body {
  margin: 0;
  /* Zwei weiche Lichter oben, fest am Fenster: Blau links, Lila rechts — die
     Ecken des Markenverlaufs. Sie rollen nicht mit, sonst waeren sie nach
     einer Bildschirmlaenge weg und die Seite darunter wieder flach. */
  background:
    radial-gradient(900px 520px at 12% -12%, rgba(33, 150, 243, .13), transparent 62%),
    radial-gradient(1000px 560px at 96% -16%, rgba(156, 39, 176, .12), transparent 60%),
    var(--bg);
  background-attachment: fixed;
  color: var(--schrift);
  font: var(--schrift-normal);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3 { margin: 0; font-weight: 650; letter-spacing: -.01em; }
a { color: var(--blau-hell); text-decoration: none; }
a:hover { text-decoration: underline; }
button, select, input, textarea { font: inherit; color: inherit; }
::selection { background: rgba(33, 150, 243, .4); }

.mono { font: var(--schrift-mono); font-variant-numeric: tabular-nums; }
.leise { color: var(--leise); }
.klein { font-size: 12px; }
.rechts { text-align: right; }
.warnton { color: var(--warn); }
.schlechtton { color: var(--schlecht); }
.gutton { color: var(--gut); }

/* ── Geruest ─────────────────────────────────────────────────────────────── */

/* EINE LEISTE, DREI ZIELE (partials/layout.ejs). Die Spalte mit sechs
   Bereichen und die Reiter darunter sind weg: sechzehn Orte hat niemand im
   Kopf behalten. Oben steht jetzt, wo man ist und wohin es sonst geht —
   Studio, Zahlen, Mehr — und darunter gehoert die ganze Breite der Arbeit. */
.leiste {
  display: flex;
  align-items: center;
  gap: 22px;
  padding: 10px 24px;
  border-bottom: 1px solid var(--linie);
  background: rgba(12, 14, 20, .86);
  -webkit-backdrop-filter: blur(14px) saturate(1.3);
  backdrop-filter: blur(14px) saturate(1.3);
  position: sticky;
  top: 0;
  z-index: 20;
}

.marke { display: flex; align-items: center; gap: 11px; color: var(--schrift); flex: none; }
.marke:hover { text-decoration: none; }
/* Das Signet: der Markenverlauf mit einem Stiftstrich darin. Der Strich ist
   ein eingebettetes SVG und keine Datei — die Oberflaeche laedt nichts von
   aussen, und fuer ein einziges Zeichen lohnt keine zweite Anfrage. */
.marke-zeichen {
  width: 32px; height: 32px; border-radius: 10px; flex: none;
  background:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32' fill='none' stroke='white' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 22c3-7 5 3 8-4s4-8 8-7'/%3E%3Ccircle cx='24' cy='11' r='1.4' fill='white' stroke='none'/%3E%3C/svg%3E") center / 100% no-repeat,
    var(--verlauf);
  box-shadow: 0 6px 18px -6px rgba(106, 92, 240, .7), 0 1px 0 rgba(255, 255, 255, .25) inset;
}
.marke-zeichen.gross { width: 52px; height: 52px; border-radius: 15px; }
.marke-text { font-size: 14.5px; font-weight: 650; letter-spacing: -.015em; line-height: 1.15; }
.marke-text b {
  display: block;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--cyan);
}

/* Die drei Ziele. Gross genug, dass man sie nicht suchen muss, und das
   gewaehlte traegt den Markenverlauf — es gibt nur eines, das so aussieht. */
.haupt-nav {
  display: flex;
  gap: 4px;
  padding: 4px;
  border-radius: 13px;
  background: var(--flaeche2);
  border: 1px solid var(--linie);
}
.haupt-nav a {
  padding: 7px 20px;
  border-radius: 9px;
  color: var(--leise);
  font-size: 14.5px;
  font-weight: 600;
  transition: color .12s ease, background .12s ease;
}
.haupt-nav a:hover { color: var(--schrift); background: rgba(255, 255, 255, .05); text-decoration: none; }
.haupt-nav a[aria-current="page"] {
  color: #fff;
  background: var(--verlauf);
  box-shadow: 0 8px 18px -10px rgba(106, 92, 240, .9), 0 1px 0 rgba(255, 255, 255, .2) inset;
}
.haupt-nav a:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }

.app { display: flex; flex-direction: column; min-height: 100vh; }
.haupt { min-width: 0; display: flex; flex-direction: column; flex: 1; }

.kopf-rechts { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-left: auto; }
.benutzer {
  display: flex; align-items: center; gap: 8px;
  margin-left: 4px; padding-left: 12px;
  border-left: 1px solid var(--linie);
}
.benutzer-name { font-size: 13px; font-weight: 600; }
.kopf-rechts > .info { margin-left: -3px; margin-right: 4px; }

/* Die Kopfzeile einer Seite unter "Mehr": der Rueckweg, der Name, ein Halbsatz.
   Sie ersetzt die Reiterleiste — eine Seite, die man ueber die Uebersicht
   gefunden hat, braucht keinen zweiten Wegweiser zu ihren Nachbarn. */
.seitenkopf-zeile {
  display: flex;
  align-items: baseline;
  gap: 14px;
  flex-wrap: wrap;
  padding: 22px 28px 0;
  max-width: 1480px;
  width: 100%;
}
.seitenkopf-zeile h1 { font-size: 24px; font-weight: 700; letter-spacing: -.02em; }
.seitenkopf-zeile .knopfreihe { margin-left: auto; }
.rueckweg {
  align-self: center;
  padding: 4px 11px;
  border-radius: 999px;
  border: 1px solid var(--linie-stark);
  background: var(--flaeche2);
  color: var(--leise);
  font-size: 12.5px;
  font-weight: 600;
}
.rueckweg:hover { color: var(--schrift); border-color: #4a5366; text-decoration: none; }

/* Der Umschalter zwischen "einfach" und "alles". Leise gestaltet: er ist ein
   Werkzeug fuer die Ansicht und nicht Teil der Arbeit. */
.modus-schalter {
  background: transparent;
  border: 1px solid var(--linie);
  border-radius: 999px;
  padding: 4px 12px;
  font-size: 12px;
  color: var(--leise);
  cursor: pointer;
  white-space: nowrap;
  transition: color .12s ease, border-color .12s ease;
}
.modus-schalter:hover { color: var(--schrift); border-color: var(--linie-stark); }
.modus-schalter:focus-visible { outline: 2px solid var(--blau); outline-offset: 2px; }
.modus-schalter[aria-pressed="true"] { color: var(--schrift); border-color: var(--blau); background: var(--blau-grund); }

/* ── Der einfache Modus ──────────────────────────────────────────────────────
   Was selten gebraucht wird, ist zu — nicht weg. Das Attribut setzt
   partials/layout.ejs im Kopf der Seite, noch bevor der Koerper steht; ohne
   JavaScript wird es nie gesetzt, und dann ist alles sichtbar. Verstecken darf
   nicht der Ausfallzustand sein. */
html[data-modus="einfach"] .nur-mehr { display: none !important; }

/* Die Breite ist begrenzt: auf einem breiten Schirm lief eine Tabelle mit
   vier Spalten sonst ueber 2000 px, und das Auge fand von der ersten zur
   letzten Spalte die Zeile nicht wieder. */
.inhalt { padding: 22px 28px 72px; display: flex; flex-direction: column; gap: 16px; max-width: 1480px; width: 100%; }

/* Ohne Anmeldung: nur der Inhalt, mittig. */
.allein { min-height: 100vh; display: grid; place-items: center; align-content: center; padding: 24px; }

/* ── Karten und Kacheln ─────────────────────────────────────────────────── */

.karte {
  background: var(--flaeche);
  border: 1px solid var(--linie);
  border-radius: var(--r);
  padding: 18px 20px;
  box-shadow: var(--schatten);
}
/* Die Kartenueberschrift war grau, klein und in Grossbuchstaben — und stand
   damit auf derselben Stufe wie ein Tabellenkopf. Jetzt ist sie das Lauteste
   in der Karte, wie es sich fuer eine Ueberschrift gehoert; die Grossbuchstaben
   bleiben den Spaltenkoepfen. */
.karte > h2,
.karte > .karte-kopf > h2 {
  font-size: 15px;
  font-weight: 650;
  color: var(--schrift);
  margin-bottom: 12px;
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
/* Ueberschrift mit einer Aktion daneben. Der Knopf rueckt nach rechts, die
   Zeile bleibt eine Zeile — die Ueberschrift traegt ihren Abstand dann nicht
   mehr selbst, sonst staende der Knopf zu hoch. */
.karte-kopf {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 12px;
}
.karte-kopf > h2 { margin-bottom: 0; }
.karte-kopf > form { margin-left: auto; }
.karte h3 {
  font-size: 11.5px;
  text-transform: uppercase;
  letter-spacing: .07em;
  color: var(--leise);
  margin: 16px 0 8px;
}
/* Steht ein h3 als ERSTES in der Karte, ist es ihre Ueberschrift und keine
   Zwischenzeile — so schreiben es die Seiten aus pages2.js (Sendezeiten,
   Rezepte, Stimmen). Es sieht dann aus wie das h2 der anderen Karten; sonst
   haette die halbe Oberflaeche laute und die andere halbe leise Titel. */
.karte > h3:first-child,
.karte > .karte-kopf:first-child > h3 {
  font-size: 15px;
  font-weight: 650;
  text-transform: none;
  letter-spacing: -.01em;
  color: var(--schrift);
  margin: 0 0 12px;
}
.zaehler {
  color: var(--schrift); font-weight: 600;
  background: var(--flaeche3); border-radius: 999px; padding: 0 8px;
}
.mehr { margin-left: auto; font-size: 12.5px; font-weight: 500; text-transform: none; letter-spacing: 0; }

/* Der Block, den static/app.js beim Filtern austauscht. Er ist eine eigene
   Spalte, damit der Abstand zwischen den Karten derselbe bleibt wie ohne ihn. */
.ergebnis { display: flex; flex-direction: column; gap: 16px; }

.spalten { display: grid; gap: 16px; }
.spalten.zwei { grid-template-columns: 1fr 1fr; }
.spalten.seite-links { grid-template-columns: minmax(280px, 460px) 1fr; align-items: start; }
.spalten.seite-links > div { display: flex; flex-direction: column; gap: 16px; }

.kacheln { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 14px; }
.kachel {
  position: relative;
  background: linear-gradient(180deg, var(--flaeche2), var(--flaeche));
  border: 1px solid var(--linie);
  border-radius: var(--r);
  padding: 16px 18px 15px;
  display: flex;
  flex-direction: column;
  gap: 5px;
  min-width: 0;
  overflow: hidden;
  box-shadow: var(--schatten);
}
/* Ein Lichtstreifen an der Oberkante. Er sagt nichts — er macht aus vier
   grauen Kaesten vier Anzeigen. */
.kachel::before {
  content: "";
  position: absolute;
  left: 0; right: 0; top: 0;
  height: 2px;
  background: var(--verlauf-balken);
  opacity: .55;
}
.kachel-titel {
  font-size: 12.5px; color: var(--leise); font-weight: 500;
  display: flex; align-items: center; gap: 6px;
}
/* Die grosse Zahl steht in der Textschrift, nicht in der Festbreitschrift:
   deren Ziffern sind fuer Tabellen gezeichnet und wirken in 30 px grob.
   Gleich breit bleiben sie trotzdem (tabular-nums). */
.kachel-wert {
  font-family: var(--familie);
  font-size: 32px; font-weight: 700; line-height: 1.1; letter-spacing: -.03em;
  font-variant-numeric: tabular-nums;
}
.kachel-unter { font-size: 12px; color: var(--leise); overflow-wrap: anywhere; }

.werte { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; }
.werte.eng { grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); margin-top: 10px; }
.wert {
  background: var(--flaeche2);
  border: 1px solid var(--linie);
  border-radius: 11px;
  padding: 10px 12px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.wert span { font-size: 12px; color: var(--leise); }
.wert b { font-family: var(--familie); font-size: 19px; font-weight: 650; letter-spacing: -.01em; font-variant-numeric: tabular-nums; }

.paare { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 4px 16px; }
.paare > div { display: flex; gap: 8px; align-items: baseline; padding: 4px 0; border-bottom: 1px solid rgba(37, 42, 54, .6); }
.paare > div > span { color: var(--leise); font-size: 12px; min-width: 108px; flex: none; }
.paare > div > b { font-weight: 600; overflow-wrap: anywhere; }

.brotkrumen { margin: 0; font-size: 13px; }
/* Der leere Zustand: ein Satz in einem gestrichelten Feld. Ohne das Feld
   stand der Satz allein in einer sonst leeren Karte und sah aus wie ein
   Ladefehler. */
.leer {
  color: var(--leise);
  padding: 22px 16px;
  text-align: center;
  margin: 0;
  border: 1px dashed var(--linie-stark);
  border-radius: 11px;
  background: rgba(255, 255, 255, .012);
}
.leer.gut { color: var(--gut); border-color: rgba(79, 209, 151, .3); }

/* ── Tabellen ───────────────────────────────────────────────────────────── */

.tabelle { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.tabelle th {
  text-align: left;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .07em;
  color: var(--leise);
  font-weight: 600;
  padding: 8px 10px;
  border-bottom: 1px solid var(--linie);
  white-space: nowrap;
}
.tabelle td {
  padding: 9px 10px;
  border-bottom: 1px solid rgba(37, 42, 54, .6);
  vertical-align: middle;
}
.tabelle tbody tr { transition: background .1s ease; }
.tabelle tbody tr:hover { background: rgba(255, 255, 255, .03); }
.tabelle tbody tr:last-child td { border-bottom: 0; }
.tabelle td.mono, .tabelle td .mono { font: var(--schrift-mono); font-variant-numeric: tabular-nums; }
.tabelle .aktionen { white-space: nowrap; text-align: right; }
.tabelle .aktionen form { display: inline-block; }
.tabelle-breit td { vertical-align: top; }

/* Ueberfaellig: die Zeile traegt den Ton, nicht nur die Pille — sonst muss man
   sie in einer langen Liste suchen. */
.zeile-warn td { background: rgba(240, 176, 74, .07); }
.zeile-warn td:first-child { box-shadow: inset 2px 0 0 var(--warn); }

.vorschau-zelle { width: 100px; }

/* Das Standbild in einer Liste. Hochkant wie der Short selbst, klein genug,
   dass zwanzig Zeilen auf den Schirm passen — erkennbar ist ein Video daran
   trotzdem schneller als an seiner Kennung. */
.vorschau {
  display: block;
  width: 54px;
  aspect-ratio: 9 / 16;
  object-fit: cover;
  border-radius: 8px;
  border: 1px solid var(--linie-stark);
  background: var(--flaeche2);
  box-shadow: 0 6px 14px -8px rgba(0, 0, 0, .9);
}
.leer-bild {
  display: grid;
  place-items: center;
  color: var(--leise);
  font-size: 12px;
}

.balken-zelle { width: 140px; }
.balken {
  display: block;
  height: 7px;
  border-radius: 999px;
  background: var(--flaeche3);
  overflow: hidden;
}
.balken-fuellung {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: var(--verlauf-balken);
}

/* ── Pillen (Paper 129) ─────────────────────────────────────────────────── */

/* Ein Punkt vor dem Wort. Die Farbe allein traegt den Zustand nicht fuer
   jeden — und in einer Tabelle mit zwanzig Pillen findet das Auge den einen
   roten Punkt schneller als das eine rote Wort. */
.pille {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font: 600 11.5px/1.6 var(--familie);
  letter-spacing: .01em;
  padding: 2px 9px 2px 8px;
  border-radius: 999px;
  border: 1px solid transparent;
  white-space: nowrap;
  vertical-align: middle;
}
.pille::before {
  content: "";
  width: 6px; height: 6px;
  border-radius: 50%;
  background: currentColor;
  flex: none;
}
.pille-gut { background: var(--gut-grund); color: var(--gut); border-color: rgba(79, 209, 151, .26); }
.pille-warn { background: var(--warn-grund); color: var(--warn); border-color: rgba(240, 176, 74, .3); }
.pille-schlecht { background: var(--schlecht-grund); color: var(--schlecht); border-color: rgba(240, 101, 92, .32); }
.pille-aus { background: var(--aus-grund); color: var(--leise); border-color: var(--linie); }
.pille-wartet { background: var(--flaeche2); color: #b3bccb; border-color: var(--linie-stark); }

/* Blau heisst laeuft — und nur das bewegt sich auf dieser Oberflaeche. Es
   pulst der Punkt, nicht die ganze Pille: ein Wort, das blasser wird, liest
   sich schlechter, ein Punkt, der Wellen schlaegt, sagt "arbeitet". */
.pille-laeuft {
  background: var(--blau-grund);
  color: var(--blau-hell);
  border-color: rgba(33, 150, 243, .38);
}
.pille-laeuft::before { animation: pulsen 1.6s ease-out infinite; }
@keyframes pulsen {
  0% { box-shadow: 0 0 0 0 rgba(108, 184, 255, .7); }
  100% { box-shadow: 0 0 0 7px rgba(108, 184, 255, 0); }
}
@media (prefers-reduced-motion: reduce) { .pille-laeuft::before { animation: none; } }

.marke-typ {
  font: 600 10.5px/1.6 var(--familie-mono);
  padding: 1px 7px;
  border-radius: 6px;
  background: var(--flaeche2);
  border: 1px solid var(--linie);
  color: var(--leise);
}

/* ── Hinweise ───────────────────────────────────────────────────────────── */

.hinweis {
  border-radius: 11px;
  padding: 11px 14px;
  font-size: 13.5px;
  border: 1px solid var(--linie);
  border-left: 3px solid var(--linie-stark);
  background: var(--flaeche2);
}
.hinweis-gut { background: var(--gut-grund); border-color: rgba(79, 209, 151, .22); border-left-color: var(--gut); color: #bdebd3; }
.hinweis-warn { background: var(--warn-grund); border-color: rgba(240, 176, 74, .22); border-left-color: var(--warn); color: #f3dcab; }
.hinweis-schlecht { background: var(--schlecht-grund); border-color: rgba(240, 101, 92, .25); border-left-color: var(--schlecht); color: #f6c2bd; }

/* ── Formulare ──────────────────────────────────────────────────────────── */

/* Die Eingabefelder werden ueber den ELEMENTNAMEN gestaltet und nicht ueber
   eine Klasse, die man an jedes einzelne schreiben muss.
   `select` war das schon immer; die elf Seiten mit eigenem Stilblock haben es
   fuer `input` jedes Mal selbst nachgeholt. Ein Feld, an dem die Klasse
   vergessen wurde, war dann ein weisser Kasten auf dunklem Grund — sichtbar
   kaputt, und der haeufigste Fehler beim Anlegen einer neuen Seite.

   `.eingabe` bleibt gueltig: es steht in den Seiten, die es schon benutzen,
   und trifft dieselbe Regel. */
.eingabe,
select,
textarea,
input[type="text"],
input[type="search"],
input[type="number"],
input[type="password"],
input[type="email"],
input[type="url"],
input[type="date"],
input[type="time"],
input[type="datetime-local"] {
  background: #0e1118;
  border: 1px solid var(--linie-stark);
  border-radius: var(--r-klein);
  padding: 7px 10px;
  min-width: 0;
  max-width: 100%;
  color: var(--schrift);
  transition: border-color .12s ease, box-shadow .12s ease;
}
.eingabe:hover, select:hover, textarea:hover, input:hover { border-color: #475063; }
::placeholder { color: #6b7383; opacity: 1; }
/* Der Fokus ist ein Ring im Feld und kein Umriss daneben: in einer Reihe
   enger Felder ueberdeckte der Umriss sonst den Nachbarn. */
.eingabe:focus-visible, select:focus-visible, textarea:focus-visible, input:focus-visible {
  outline: none;
  border-color: var(--blau);
  box-shadow: 0 0 0 3px rgba(33, 150, 243, .28);
}
/* Kaestchen und Schalter tragen ihre eigene Gestalt — die Regel oben wuerde
   sie zu leeren Rechtecken machen. */
input[type="checkbox"], input[type="radio"], input[type="range"] {
  accent-color: var(--blau);
  background: none;
  border: 0;
  padding: 0;
  box-shadow: none;
}
input[type="checkbox"]:focus-visible, input[type="radio"]:focus-visible, input[type="range"]:focus-visible {
  outline: 2px solid var(--blau);
  outline-offset: 2px;
  box-shadow: none;
}
.eingabe.schmal { width: 86px; }
textarea.eingabe { width: 100%; resize: vertical; font: var(--schrift-mono); }
select { cursor: pointer; }

.filter {
  display: flex;
  align-items: flex-end;
  gap: 12px;
  flex-wrap: wrap;
  background: var(--flaeche);
  border: 1px solid var(--linie);
  border-radius: var(--r);
  padding: 12px 16px;
  box-shadow: var(--schatten);
}
.feld { display: flex; flex-direction: column; gap: 4px; }
.feld > span { font-size: 12px; font-weight: 500; color: var(--leise); }
/* Dieselbe Form, ohne dass man ein <span> um die Beschriftung legen muss:
   `<label>Sprache <select>…</select></label>` reicht. Die elf Seiten mit
   eigenem Stilblock haben es alle so geschrieben — nur eben elfmal selbst
   gestaltet. Ausgenommen sind Kaestchen: die gehoeren neben ihre Beschriftung
   und nicht darueber. */
.filter > label:not(.haken) {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 12px;
  font-weight: 500;
  color: var(--leise);
}
.filter > label:not(.haken) > select,
.filter > label:not(.haken) > input {
  font-size: 13.5px;
  font-weight: 400;
  color: var(--schrift);
}

.feld-hoch { display: flex; flex-direction: column; gap: 6px; margin-bottom: 14px; }
.feld-hoch > span { font-size: 12.5px; font-weight: 500; color: var(--leise); }
.feld-hoch input { width: 100%; padding: 10px 12px; }

.feld-zeile { display: grid; grid-template-columns: 92px 1fr; gap: 8px; align-items: center; margin-bottom: 6px; }
.feld-zeile > span { font-size: 12px; color: var(--leise); }
.feld-zeile select, .feld-zeile input { width: 100%; }
.feld-hinweis { margin: -3px 0 8px 100px; }

.knopf {
  display: inline-block;
  background: var(--flaeche3);
  border: 1px solid var(--linie-stark);
  border-radius: var(--r-klein);
  padding: 7px 13px;
  cursor: pointer;
  white-space: nowrap;
  color: var(--schrift);
  font-size: 13.5px;
  font-weight: 550;
  line-height: 1.4;
  box-shadow: 0 1px 0 rgba(255, 255, 255, .05) inset;
  transition: background .12s ease, border-color .12s ease, filter .12s ease, transform .08s ease;
}
.knopf:hover { border-color: #4a5366; background: #2a3040; text-decoration: none; }
.knopf:active { transform: translateY(1px); }
.knopf:focus-visible { outline: 2px solid var(--blau-hell); outline-offset: 2px; }
/* Der Hauptknopf traegt Weiss auf dem Markenblau. Vorher stand dunkle Schrift
   auf hellem Blau — lesbar, aber er sah aus wie ein Verweis und nicht wie die
   eine Handlung, um die es auf der Seite geht. */
.knopf.haupt {
  background: linear-gradient(180deg, #3aa3f6, #1c85e0);
  border-color: #1c85e0;
  color: #fff;
  font-weight: 650;
  box-shadow: 0 1px 0 rgba(255, 255, 255, .25) inset, 0 8px 18px -10px rgba(33, 150, 243, .9);
}
.knopf.haupt:hover { background: linear-gradient(180deg, #55b2fa, #2a92ec); border-color: #2a92ec; }
.knopf.gefahr { background: var(--schlecht-grund); border-color: rgba(240, 101, 92, .5); color: #f8aea8; font-weight: 650; }
.knopf.gefahr:hover { background: #3d1f1d; border-color: var(--schlecht); }
.knopf.warn { background: var(--warn-grund); border-color: rgba(240, 176, 74, .45); color: #f3dcab; }
.knopf.warn:hover { background: #3a2f17; border-color: var(--warn); }
.knopf.klein { padding: 4px 10px; font-size: 12.5px; border-radius: 8px; }
.knopf.gross { padding: 10px 20px; font-size: 14.5px; border-radius: 11px; }
.knopf.breit { width: 100%; text-align: center; }
.knopf[disabled], .knopf.aus { opacity: .4; cursor: not-allowed; pointer-events: none; }

.inline { display: inline-block; }
.knopfreihe { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.aktionsleiste { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.aktionsleiste.hoch { align-items: flex-start; }
.aktionsleiste form { display: flex; gap: 6px; align-items: center; }

.haken { display: inline-flex; align-items: center; gap: 6px; font-size: 13.5px; cursor: pointer; }
.haken.klein { font-size: 12px; color: var(--leise); }
.haken input { accent-color: var(--blau); }
.haken-reihe { display: flex; gap: 12px; flex-wrap: wrap; margin-bottom: 8px; }

.block-form {
  background: var(--flaeche2);
  border: 1px solid var(--linie);
  border-radius: 11px;
  padding: 12px 14px;
}
.block-form h3 { margin-top: 0; }
.block-form .knopf { margin-top: 6px; }
.gefahr-form { border-color: rgba(240, 101, 92, .35); }
.unter-form { margin-top: 8px; display: flex; flex-direction: column; gap: 6px; }

/* ── Not-Aus (Paper 41, 128) ────────────────────────────────────────────── */

.notaus { border-width: 1px; }
.notaus-an { border-color: var(--linie); }
.notaus-aus { border-color: rgba(240, 101, 92, .5); background: linear-gradient(180deg, rgba(240, 101, 92, .09), transparent 60%), var(--flaeche); }
.notaus-lage { display: flex; gap: 16px; align-items: center; flex-wrap: wrap; justify-content: space-between; }
.notaus-lage h2 { font-size: 15px; font-weight: 650; }
.notaus-satz { margin: 4px 0 0; font-size: 14px; color: #c9cfda; }
.notaus-satz b { color: var(--schlecht); }
.notaus-formular { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.notaus .aktionsleiste { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--linie); }

/* ── Vorschau und Video ─────────────────────────────────────────────────── */

.zeichnung { display: block; border-radius: 8px; background: var(--canvas); }
.zeichnung-grund { fill: var(--canvas); }
.zeichnung-leer {
  display: grid;
  place-items: center;
  background: var(--flaeche2);
  border: 1px dashed var(--linie);
  color: var(--leise);
  font-size: 11px;
  border-radius: 8px;
}
.zeichnung.klein { border: 1px solid var(--linie); }
.vorschau-gross { display: grid; place-items: center; background: var(--canvas); border-radius: 10px; padding: 8px; }
.vorschau-gross .zeichnung { background: transparent; }


/* ── Content-Detail ──────────────────────────────────────────────────────────
   Der erste Block ist das Bedienpult einer Videoidee: oben, wer sie ist, und
   darunter je Sprachfassung eine Leiste mit Vorschau, Stand und den vier
   Knoepfen des Weges. Alles Weitere steht in Klappbloecken darunter — sichtbar
   ist, was zu TUN ist, nicht, was es alles gibt. */

.kopf-karte { display: flex; flex-direction: column; gap: 0; }
.kopf-oben { display: grid; grid-template-columns: auto 1fr auto; gap: 16px; align-items: start; }
.kopf-bild { display: flex; }
.kopf-mitte { min-width: 0; }
.kopf-mitte h2 {
  font-size: 15px; text-transform: none; letter-spacing: 0; color: var(--schrift);
  margin-bottom: 6px; display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
.kopf-fakten { display: flex; align-items: baseline; gap: 7px; flex-wrap: wrap; font-size: 13.5px; }
.kopf-rechts { display: flex; gap: 8px; align-items: flex-start; }

/* Eine Fassung, eine Zeile. */
.fassung-leiste {
  display: grid;
  grid-template-columns: 112px 1fr;
  gap: 14px;
  align-items: start;
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--linie);
}
.fl-vorschau { display: flex; }
.fl-video {
  width: 112px;
  aspect-ratio: 9 / 16;
  border-radius: 12px;
  background: #07080b;
  border: 1px solid var(--linie-stark);
  box-shadow: 0 14px 26px -16px rgba(0, 0, 0, .95);
  display: block;
  object-fit: contain;
}
.fl-leer { display: grid; place-items: center; }
.fl-mitte { min-width: 0; display: flex; flex-direction: column; gap: 8px; }
.fl-kopf { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }

/* Die Knopfreihe. `display: contents` an den Formularen: sonst waere jedes
   Formular ein eigener Kasten, und die Knoepfe stuenden in vier Gruppen statt
   in einer Reihe. */
.fl-knoepfe { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.fl-form { display: contents; }
.fl-knoepfe .trenner { width: 1px; align-self: stretch; min-height: 22px; background: var(--linie); }
/* Der gefaehrlichste Knopf steht ganz rechts und nicht neben den harmlosen. */
.fl-knoepfe .schub button { margin-left: 12px; }

.senden { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 10px; align-items: start; }

/* ── Fertig: eine Karte je Video ─────────────────────────────────────────────
   Dieselbe Fassungsleiste wie im Content-Detail, nur ohne den Rest der Seite:
   auf /fertig ist jede Videoidee eine eigene Karte, und Deutsch und Englisch
   liegen darin untereinander statt irgendwo in derselben langen Liste.

   Der Kopf traegt hier ein WORT und keine Rubrik ("Klavier", nicht "FERTIGE
   VIDEOS"), deshalb nimmt er die Grossbuchstaben der Kartenueberschrift wieder
   zurueck. */

.fertig-karte .karte-kopf { align-items: baseline; flex-wrap: wrap; }
.fertig-karte .karte-kopf > h2 {
  font-size: 14px;
  text-transform: none;
  letter-spacing: 0;
  color: var(--schrift);
  flex: 1 1 auto;
}
.fertig-karte .loesung { font-size: 15px; }
/* Die Knoepfe der Karte rutschen nach rechts — wie `.karte-kopf > form`, nur
   fuer die Huelle, die zwei davon nebeneinander haelt. */
.karte-aktionen { margin-left: auto; display: flex; gap: 8px; align-items: center; }
/* Die erste Fassungsleiste braucht ihren Trennstrich: im Content-Detail steht
   darueber der Kopfblock, hier die Kartenueberschrift. */
.fertig-karte .fassung-leiste:first-of-type { margin-top: 10px; }
.fertig-karte .fl-video { object-fit: cover; }

/* Der Blaetterer allein in seiner Karte — der Strich, der ihn sonst von der
   Liste darueber trennt, traenne hier nichts. */
.blaetter-karte .blaetterer { margin-top: 0; padding-top: 0; border-top: 0; }

/* ── Veroeffentlicht: ein Block je Videoidee ─────────────────────────────────
   Dieselbe Zusammenfassung wie auf /fertig, nur eine Stufe spaeter: alles, was
   von EINEM Video draussen ist, steht beieinander — vier Plattformen mal zwei
   Sprachen in einem Block statt acht Zeilen zwischen denen anderer Videos. */

.upload-gruppe {
  border: 1px solid var(--linie);
  border-radius: 9px;
  padding: 8px 10px 2px;
  margin-top: 10px;
  background: var(--flaeche2);
}
.ug-kopf { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin-bottom: 4px; }
/* Die Tabelle im Block traegt ihren eigenen Rahmen nicht noch einmal. */
.upload-gruppe .tabelle { background: transparent; }

/* ── Blaetterer ──────────────────────────────────────────────────────────── */

.blaetterer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--linie);
  color: var(--leise);
  font-size: 12.5px;
}
.blaetterer-stand { font-variant-numeric: tabular-nums; }
.blaetterer-knoepfe { display: flex; gap: 6px; }

/* ── Anmeldung und Fehlerseite ──────────────────────────────────────────── */

.anmeldung { width: min(400px, 92vw); display: flex; flex-direction: column; gap: 18px; }
.anmeldung-marke { display: flex; align-items: center; gap: 12px; }
.anmeldung-marke h1 { font-size: 22px; letter-spacing: -.02em; }
.anmeldung-marke h1 b { color: var(--cyan); }
.anmeldung-marke p { margin: 2px 0 0; font-size: 13px; }
.anmeldung-formular { padding: 24px 24px 22px; box-shadow: var(--schatten-hoch); background: linear-gradient(180deg, var(--flaeche2), var(--flaeche)); }
.anmeldung-formular .knopf.breit { padding: 10px 14px; font-size: 14.5px; margin-top: 4px; }
.anmeldung > p { text-align: center; margin: 0; }
.ohne-geruest .hinweis { width: min(380px, 92vw); margin: 0 auto 12px; }

.fehlerseite { text-align: center; padding: 40px 24px; }
.fehler-status { font-size: 52px; font-weight: 700; color: var(--leise); line-height: 1; }
.fehlerseite h2 { font-size: 18px; margin: 10px 0 6px; }
.fehler-text { color: var(--leise); margin: 0 0 16px; }
.fehlerseite .knopfreihe { justify-content: center; }

/* ── Enge Fenster ───────────────────────────────────────────────────────── */

@media (max-width: 1100px) {
  .spalten.zwei, .spalten.seite-links { grid-template-columns: 1fr; }
  .kopf-oben { grid-template-columns: 1fr; }
  /* Die Knopfreihe darf umbrechen, der gefaehrliche Knopf bleibt aber der
     letzte — auf einer zweiten Zeile stuende er sonst neben "Rendern". */
  .fl-knoepfe .schub button { margin-left: 0; }
}

@media (max-width: 620px) {
  .fassung-leiste { grid-template-columns: 1fr; }
  .fl-video { width: 96px; }
}

@media (max-width: 820px) {
  /* Im schmalen Fenster bricht die Leiste um: Marke und Zustand oben, die
     drei Ziele darunter ueber die ganze Breite — mit dem Daumen zu treffen. */
  .leiste { flex-wrap: wrap; gap: 10px; padding: 10px 14px; position: static; }
  .marke-text { display: none; }
  .haupt-nav { order: 3; width: 100%; }
  .haupt-nav a { flex: 1; text-align: center; padding: 9px 8px; }
  .benutzer-name { display: none; }
  .benutzer { margin-left: 0; padding-left: 0; border-left: 0; }
  .seitenkopf-zeile { padding: 16px 14px 0; }
  .inhalt { padding: 16px 14px 48px; }
  .karte { padding: 14px; }
  /* Eine dichte Tabelle bleibt dicht — sie rollt lieber seitwaerts, als dass
     sie sich in unlesbare Stapel aufloest. */
  .karte { overflow-x: auto; }
}

/* ── Das i im Kreis ────────────────────────────────────────────────────────
   Markup kommt aus helpers.info(). Ohne diese Regeln bleibt ein "i" mit
   title-Attribut stehen — lesbar, nur unauffaellig. Erst der Kreis macht
   sichtbar, DASS es hier etwas zu erklaeren gibt. */
.info {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 15px;
  height: 15px;
  margin-left: 5px;
  border-radius: 50%;
  border: 1px solid var(--linie);
  background: var(--flaeche2);
  color: var(--leise);
  font-size: 10px;
  font-weight: 700;
  font-style: normal;
  line-height: 1;
  cursor: help;
  user-select: none;
  vertical-align: middle;
  flex: none;
}
.info:hover, .info:focus-visible {
  border-color: var(--blau);
  background: var(--blau);
  color: #fff;
  outline: none;
}
/* Im Tabellenkopf sitzt das Zeichen zwischen Grossbuchstaben — dort waere die
   volle Groesse zu laut. */
th .info { width: 13px; height: 13px; font-size: 9px; margin-left: 4px; }

/* Die Sprechblase, die static/app.js an den Koerper haengt. Sie liegt bewusst
   NICHT im Element: eine Tabelle mit overflow-x wuerde sie an ihrer Kante
   abschneiden, und das ist genau die Stelle, an der die meisten stehen. */
.info-blase {
  position: fixed;
  z-index: 200;
  max-width: 320px;
  padding: 9px 11px;
  border-radius: 8px;
  border: 1px solid var(--linie);
  background: #1b202b;
  border-color: var(--linie-stark);
  color: var(--schrift);
  font-size: 12.5px;
  font-weight: 400;
  line-height: 1.45;
  box-shadow: 0 8px 24px rgba(0, 0, 0, .55);
  pointer-events: none;
}

/* ── Der Hilfemodus (static/app.js, Abschnitt 8) ─────────────────────────────
   Das eigene Fragezeichen am Mauszeiger, weil das des Systems auf Windows nur
   ein winziger Zusatz am Pfeil ist. `help` bleibt als Rueckfall. */
.hilfe-schalter {
  width: 26px;
  height: 26px;
  flex: none;
  border-radius: 50%;
  border: 1px solid var(--linie);
  background: transparent;
  color: var(--leise);
  font-size: 14px;
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
}
.hilfe-schalter:hover { color: var(--schrift); border-color: var(--linie-stark); }
.hilfe-schalter:focus-visible { outline: 2px solid var(--blau); outline-offset: 2px; }
.hilfe-schalter[aria-pressed="true"] { color: #fff; background: var(--blau); border-color: var(--blau); }
html.hilfe-an, html.hilfe-an * {
  cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32'%3E%3Ccircle cx='16' cy='16' r='14' fill='%232196F3' stroke='white' stroke-width='2'/%3E%3Ctext x='16' y='23' font-family='Arial' font-size='21' font-weight='700' text-anchor='middle' fill='white'%3E%3F%3C/text%3E%3C/svg%3E") 16 16, help !important;
}
.hilfe-markiert { outline: 2px solid var(--blau) !important; outline-offset: 2px; }
.hilfe-blase { max-width: 420px; font-size: 13.5px; }
.hilfe-blase[hidden] { display: none; }
.hilfe-blase b { display: block; margin-bottom: 4px; font-size: 14px; }
.hilfe-blase p { margin: 0; }
.hilfe-blase .hilfe-folge { margin-top: 7px; color: var(--warn); }
.hilfe-leiste {
  position: fixed;
  z-index: 199;
  left: 50%;
  bottom: 14px;
  transform: translateX(-50%);
  max-width: calc(100vw - 24px);
  padding: 6px 14px;
  border-radius: 999px;
  background: var(--blau);
  color: #fff;
  font-size: 12.5px;
  pointer-events: none;
}

/* Der ausgeschriebene Hinweis unter einer Seitenueberschrift. */
.seitenhinweis {
  margin: 0 0 4px;
  max-width: 84ch;
  color: var(--leise);
  font-size: 13.5px;
  line-height: 1.55;
}

/* ── Fortschritt eines Renderlaufs (helpers.fortschritt) ─────────────────────
   Balken, Zahl und Satz in einer Zelle. Der Balken erscheint NUR, wenn wirklich
   gemessen wurde — ohne Messung stuende dort eine Null, die niemand geprueft
   hat, und genau die las sich bisher als "es passiert nichts". */

.fortschritt-zelle { min-width: 190px; }
.fortschritt { display: flex; flex-direction: column; gap: 3px; }
.fortschritt-oben { display: flex; align-items: center; gap: 8px; }
.fortschritt-balken {
  flex: 1;
  min-width: 70px;
  height: 6px;
  border-radius: 999px;
  background: var(--flaeche2);
  border: 1px solid var(--linie);
  overflow: hidden;
}
.fortschritt-balken i {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: var(--verlauf-balken);
  /* Der Balken wandert, er springt nicht: der Server meldet alle drei
     Sekunden, und ein Sprung sieht aus wie ein Ruck statt wie Arbeit. */
  transition: width .6s linear;
}
.fortschritt-zahl { flex: none; color: var(--schrift); font-weight: 600; }
.fortschritt-satz { overflow-wrap: anywhere; }

/* ── Klappblock ──────────────────────────────────────────────────────────────
   <details class="klapp"> — der Weg, auf dem diese Oberflaeche dichter wird,
   ohne dass etwas verschwindet. Was selten gebraucht wird, ist zu, nicht weg.
   static/app.js merkt sich je Block, wie er zuletzt stand. */

.klapp {
  border: 1px solid var(--linie);
  border-radius: 10px;
  background: var(--flaeche2);
}
.klapp + .klapp { margin-top: 8px; }
.klapp > summary {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 14px;
  cursor: pointer;
  list-style: none;
  font-size: 13.5px;
  color: #c9cfda;
  font-weight: 600;
  border-radius: 10px;
  user-select: none;
}
.klapp > summary::-webkit-details-marker { display: none; }
.klapp > summary::before {
  content: "›";
  font-size: 15px;
  line-height: 1;
  color: var(--leise);
  transition: transform .15s ease;
  flex: none;
}
.klapp[open] > summary::before { transform: rotate(90deg); }
.klapp > summary:hover { color: var(--schrift); background: rgba(255, 255, 255, .035); }
.klapp > summary:focus-visible { outline: 2px solid var(--blau); outline-offset: -2px; }
/* Die Zahl neben der Ueberschrift sagt, ob sich das Aufklappen lohnt. */
.klapp-zahl { margin-left: auto; color: var(--leise); font-weight: 500; font-size: 12.5px; }
.klapp-koerper { padding: 2px 12px 12px; }
.klapp-koerper > .tabelle { margin-top: 4px; }
@media (prefers-reduced-motion: reduce) { .klapp > summary::before { transition: none; } }

/* Ein Klappblock, der eine ganze Karte ist — auf den Uebersichtsseiten. */
.karte > .klapp { background: transparent; border: 0; }
.karte > .klapp > summary { padding-left: 0; padding-right: 0; }
.karte > .klapp > .klapp-koerper { padding-left: 0; padding-right: 0; }

/* Fertige Komplettaufnahmen im Bausteine-Menue. Eine ruhige, einspaltige
   Bibliothek: Der native Player bleibt tastaturbedienbar und laedt dank
   preload="none" erst beim Abspielen Daten. */
.aufnahme-liste { display: grid; gap: 8px; margin-top: 8px; }
.aufnahme-zeile {
  display: grid;
  grid-template-columns: minmax(190px, 1fr) minmax(260px, 420px);
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  border: 1px solid var(--linie);
  border-radius: 10px;
  background: var(--flaeche2);
}
.aufnahme-meta { display: grid; gap: 3px; min-width: 0; overflow-wrap: anywhere; }
.aufnahme-zeile audio { display: block; width: 100%; min-height: 44px; }
@media (max-width: 720px) {
  .aufnahme-zeile { grid-template-columns: minmax(0, 1fr); }
}

/* ── Schrittkette ────────────────────────────────────────────────────────────
   Wo die Idee auf ihrem Weg steht — angelegt, gerendert, geplant, draussen.
   Vier Woerter statt eines Rohwerts aus der Datenbank. */

.schritte { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin: 10px 0 0; }
.schritt {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--leise);
  padding: 3px 11px 3px 9px;
  border-radius: 999px;
  border: 1px solid var(--linie);
  background: var(--flaeche2);
}
.schritt-punkt {
  width: 8px; height: 8px; border-radius: 50%; flex: none;
  background: var(--flaeche2); border: 1px solid var(--linie);
}
.schritt.erledigt { color: var(--schrift); border-color: rgba(79, 209, 151, .3); }
.schritt.erledigt .schritt-punkt { background: var(--gut); border-color: var(--gut); }
.schritt.jetzt { color: var(--blau-hell); font-weight: 600; border-color: rgba(33, 150, 243, .5); background: var(--blau-grund); }
.schritt.jetzt .schritt-punkt { background: var(--blau); border-color: var(--blau); }

/* ── Neues Video (Seite /neu) ────────────────────────────────────────────────
   Die vier Schritte des Weges von Hand. Der Zeichnungswaehler ist bewusst eine
   Bilderreihe und keine Tabelle: man erkennt eine Zeichnung am Bild, nicht an
   ihrer Nummer. */

.schritte-gross { gap: 8px; margin: 0 0 2px; }
.schritte-gross .schritt { font-size: 13px; padding: 5px 14px 5px 10px; }
.schritte-gross .schritt-punkt { width: 9px; height: 9px; }

.waehler {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(124px, 1fr));
  gap: 10px;
}
.waehler-karte {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  padding: 8px 6px 9px;
  border: 1px solid var(--linie);
  border-radius: 10px;
  background: var(--flaeche2);
  color: var(--schrift);
  text-align: center;
  min-width: 0;
  transition: transform .12s ease, border-color .12s ease, box-shadow .12s ease;
}
.waehler-karte:hover { border-color: var(--blau); text-decoration: none; transform: translateY(-2px); box-shadow: 0 12px 22px -14px rgba(33, 150, 243, .8); }
.waehler-karte:focus-visible { outline: 2px solid var(--blau); outline-offset: 2px; }
.waehler-karte b { font-size: 13px; font-weight: 600; overflow-wrap: anywhere; }
/* Die gewaehlte Karte traegt den Ton der Auswahl — sonst sucht man in einer
   Reihe von vierundzwanzig Bildern, welches man gerade angeklickt hat. */
.waehler-karte.gewaehlt {
  border-color: var(--blau);
  background: var(--blau-grund);
  box-shadow: inset 0 0 0 1px var(--blau);
}

.vorschlag { display: grid; grid-template-columns: 168px 1fr; gap: 16px; align-items: start; }
.vorschlag-bild { display: flex; flex-direction: column; gap: 6px; align-items: center; text-align: center; }
.vorschlag-text { min-width: 0; }
.vorschlag-kopf { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
/* Die Texttabelle des Vorschlags ist ein Lesetext, keine Datenliste: kein
   Kopf, weiche Trennlinien, und die linke Spalte bleibt schmal. */
.vorschlag-text .tabelle td { border-bottom-color: rgba(42, 45, 49, .4); vertical-align: top; }

@media (max-width: 760px) {
  .vorschlag { grid-template-columns: 1fr; }
}

/* Die eine Zeile ganz oben auf der Uebersicht: wann geht das naechste Video
   raus? Sie ist absichtlich eine Zeile und keine Kachel — eine Kachel liest
   man als Zahl, diesen Satz liest man als Satz. */
.naechste-zeile { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; font-size: 14px; }
.naechste-marke {
  font-size: 11px; text-transform: uppercase; letter-spacing: .08em;
  color: var(--leise); flex: none;
}

/* ── Ein Schalter ────────────────────────────────────────────────────────────
   Oben steht, was er TUT ("Veroeffentlichen erlaubt"), darunter die Folge, und
   erst in einem Klappblock der Schluesselname samt Pruefspur.

   Der Schluessel ist nicht verschwunden und darf es nicht: nach ihm wird im
   Log, in der Datenbank und in der Dokumentation gesucht. Er steht nur nicht
   mehr als Ueberschrift da, wo ein Name hingehoert. */

.schalter-zeile {
  display: grid;
  grid-template-columns: minmax(240px, 1fr) 210px;
  gap: 10px 16px;
  align-items: start;
  padding: 11px 0;
  border-top: 1px solid var(--linie);
}
.schalter-zeile:first-of-type { border-top: none; }
.schalter-kopf { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.schalter-name { font-size: 14px; font-weight: 600; }
.schalter-satz { color: var(--leise); font-size: 12.5px; margin-top: 3px; max-width: 62ch; }
.schalter-satz.folge { color: #f0d9a8; }
.schalter-wert { display: flex; align-items: center; gap: 7px; }
.schalter-wert .eingabe, .schalter-wert select { flex: 1; }
.schalter-einheit { color: var(--leise); font-size: 12px; white-space: nowrap; }
/* Der Klappblock mit dem Schluessel. Kleiner als ein gewoehnlicher, weil er
   in einer Zeile steht und nicht auf einer Seite. */
.schalter-technik { margin-top: 6px; }
.schalter-technik > summary {
  font-size: 11.5px;
  color: var(--leise);
  cursor: pointer;
  list-style: none;
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.schalter-technik > summary::-webkit-details-marker { display: none; }
.schalter-technik > summary::before { content: "›"; transition: transform .15s ease; }
.schalter-technik[open] > summary::before { transform: rotate(90deg); }
.schalter-technik > summary:hover { color: var(--schrift); }
.schalter-technik > summary:focus-visible { outline: 2px solid var(--blau); outline-offset: 2px; border-radius: 4px; }
.schalter-technik-koerper { margin-top: 5px; font: var(--schrift-mono); color: var(--leise); }
.schalter-technik-koerper b { color: var(--schrift); font-weight: 650; }
@media (prefers-reduced-motion: reduce) { .schalter-technik > summary::before { transition: none; } }

/* Der Kasten der vier gefaehrlichen Schalter. */
.karte.gefahr { border-color: rgba(240, 101, 92, .38); background: linear-gradient(180deg, rgba(226, 86, 77, .07), transparent 120px); }
.warnsatz { font-size: 13px; color: #f0a49d; margin: 0 0 10px; max-width: 78ch; }
.sicher { display: flex; gap: 7px; align-items: center; font-size: 13px; color: #f3b8b2; cursor: pointer; }
.sicher input { accent-color: var(--schlecht); }
.karten-fuss {
  display: flex; gap: 12px; align-items: center; flex-wrap: wrap;
  margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--linie);
}
ol.reihenfolge { margin: 0 0 12px; padding-left: 1.4em; font-size: 12.5px; color: var(--leise); line-height: 1.55; max-width: 78ch; }
ol.reihenfolge li { margin-bottom: 4px; }
ol.reihenfolge b { color: var(--schrift); }

/* Die Ueberschrift einer Seite mit einem Halbsatz daneben. Vorher baute sich
   jede pages2-Seite dafuer eine eigene `.kopfzeile`-Regel — elfmal dieselbe. */
.seitenkopf { display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap; }
.seitenkopf h2 { font-size: 17px; }
.seitenkopf .knopfreihe { margin-left: auto; }

/* ── Gefahrenzone ────────────────────────────────────────────────────────────
   Abgesetzt und ganz unten: wer die Seite wegen eines Schalters aufruft, soll
   hier nicht versehentlich landen. Im einfachen Modus steht sie gar nicht da. */

.gefahrenzone {
  margin-top: 34px;
  padding: 16px 18px;
  border: 1px solid rgba(240, 101, 92, .38);
  border-radius: var(--r);
  background: linear-gradient(180deg, rgba(226, 86, 77, .06), transparent 160px);
}
.gefahrenzone h3 { margin: 0 0 8px; font-size: 15px; color: #f3b8b2; text-transform: none; letter-spacing: 0; }
.gefahrenzone p { margin: 0 0 12px; max-width: 74ch; line-height: 1.5; }
.gz-tabelle { border-collapse: collapse; margin: 0 0 12px; min-width: 280px; }
.gz-tabelle td { padding: 3px 14px 3px 0; font-size: 12.5px; border-bottom: 1px solid var(--linie); }
.gz-tabelle td.rechts { font-variant-numeric: tabular-nums; }
.gz-tabelle tr.summe td { font-weight: 650; border-bottom: none; padding-top: 6px; }
.gz-form { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin: 0 0 10px; }
.gz-haken { display: flex; align-items: center; gap: 7px; font-size: 13px; cursor: pointer; }
.gz-haken input { cursor: pointer; accent-color: var(--schlecht); }
.gefahrenzone .knopf.gefahr[disabled] { opacity: .45; cursor: not-allowed; }

/* Der Rumpf einer Seite. Vorher hiess er auf jeder pages2-Seite anders
   (.s-set, .s-vo, .s-mu, .s-ana …) und stand elfmal mit denselben drei
   Eigenschaften da. */
.seite { display: flex; flex-direction: column; gap: 14px; max-width: 1180px; }
.seite.breit { max-width: none; }

/* ── Audio: Raster und Laufanzeige ───────────────────────────────────────────
   Gemeinsam fuer /voices und /musik. Beide zeigen dasselbe: viele Kaestchen,
   in denen ein Balken sagt, wie weit etwas fertig ist. Vorher stand die Regel
   zweimal da — einmal unter .s-vo, einmal unter .s-mu — und die Kaestchen
   sahen deshalb schon leicht verschieden aus. */

.matrix { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 12px; }
.zelle {
  border: 1px solid var(--linie);
  border-radius: var(--r);
  padding: 12px 14px;
  background: var(--flaeche2);
}
.zelle-titel { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; margin-bottom: 6px; }
.zelle-titel b { font-size: 13.5px; }
.zelle-balken {
  display: flex;
  height: 9px;
  border-radius: 5px;
  overflow: hidden;
  background: var(--flaeche);
  border: 1px solid var(--linie);
  margin: 7px 0;
}
.zelle-balken i { display: block; height: 100%; background: var(--gut); }
/* Die Segmente eines mehrfarbigen Balkens (fertig / fehlt / Fehler / veraltet). */
.zelle-balken i.st-fertig { background: var(--gut); }
.zelle-balken i.st-warte  { background: var(--blau); }
.zelle-balken i.st-alt    { background: var(--warn); }
.zelle-balken i.st-fehler { background: var(--schlecht); }
.zelle-balken i.st-fehlt  { background: var(--aus-grund); }
.zelle-wann { font-size: 12px; color: var(--leise); line-height: 1.45; margin: 0 0 7px; }
.zelle-fuss { font-size: 11.5px; color: var(--leise); overflow-wrap: anywhere; }

/* Ein laufender Erzeugungslauf. Blau, weil auf dieser Oberflaeche blau
   "arbeitet gerade" heisst — dieselbe Bedeutung wie bei der laufenden Pille. */
.karte.lauf { border-color: rgba(33, 150, 243, .35); background: linear-gradient(180deg, rgba(33, 150, 243, .07), transparent 120px); }
.lauf-kopf { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.lauf-balken { height: 10px; border-radius: 5px; overflow: hidden; background: var(--flaeche2); border: 1px solid var(--linie); margin: 8px 0; }
.lauf-balken i { display: block; height: 100%; background: var(--blau); transition: width .4s ease; }
@media (prefers-reduced-motion: reduce) { .lauf-balken i { transition: none; } }

/* Eine lange Liste, die nicht die ganze Seite lang werden soll. */
.rollkasten { max-height: 520px; overflow: auto; border: 1px solid var(--linie); border-radius: var(--r); }
.rollkasten .tabelle th { position: sticky; top: 0; background: var(--flaeche); z-index: 1; }

/* Eine Karte, die warnt, ohne ein Hinweiskasten zu sein — sie hat eine
   Ueberschrift und Inhalt, nur einen anderen Rand. */
.karte.warn { border-color: rgba(240, 176, 74, .36); background: linear-gradient(180deg, rgba(224, 161, 58, .06), transparent 140px); }

/* Zwei Kaesten nebeneinander, die im schmalen Fenster untereinander rutschen.
   Stand vorher als `.paar` in vier Seiten, viermal gleich. */
.paar { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; align-items: start; }
.paar > div, .paar > section { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
@media (max-width: 1100px) { .paar { grid-template-columns: 1fr; } }

/* Ein Raster gleich grosser Kaesten (Systemwerte, Plattformkonten). Stand
   vorher als `.gitter` in accounts und system. */
.gitter { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 12px; }

/* Beschreibungslisten in den Kaesten von /system und /accounts. */
.karte dl { margin: 0; display: grid; grid-template-columns: auto 1fr; gap: 3px 12px; }
.karte dt { color: var(--leise); font-size: 12.5px; }
.karte dd { margin: 0; font-size: 13px; overflow-wrap: anywhere; }

/* Ein waagerechter Balken mit Ampelfarbe (Last, Plattenbelegung). */
.ampel { height: 8px; border-radius: 999px; background: var(--flaeche2); border: 1px solid var(--linie); overflow: hidden; margin: 6px 0; }
.ampel i { display: block; height: 100%; background: var(--gut); }
.ampel i.warn { background: var(--warn); }
.ampel i.schlecht { background: var(--schlecht); }
.ampel i.aus { background: var(--leise); }

/* ── Diagramme (static/charts.js) ────────────────────────────────────────────
   Stand vorher zweimal identisch da — einmal in analytics.ejs, einmal in
   scheduler.ejs. Ein Diagramm, das auf zwei Seiten verschieden aussieht, ist
   zweimal dasselbe Diagramm und einmal zu viel Pflege. */

.diagramm { margin: 0; }
.diagramm svg { display: block; width: 100%; height: auto; }
.diagramm figcaption { font-size: 12px; color: var(--leise); margin-top: 6px; }
.diagramm-zahlen summary { font-size: 12px; color: var(--leise); cursor: pointer; margin-top: 8px; }

/* ── Protokoll ───────────────────────────────────────────────────────────────
   Die Zaehlerleiste, die Stufenwahl und der Livestrom. */

.zaehler-leiste { display: flex; gap: 8px; flex-wrap: wrap; }
.zaehler-leiste .z {
  background: var(--flaeche2);
  border: 1px solid var(--linie);
  border-radius: 999px;
  padding: 3px 11px;
  font-size: 12px;
  color: var(--leise);
}
.zaehler-leiste .z b { color: var(--schrift); font-variant-numeric: tabular-nums; }
.zaehler-leiste .z.DEBUG b { color: var(--leise); }
.zaehler-leiste .z.INFO b { color: var(--blau-hell); }
.zaehler-leiste .z.WARNING b { color: var(--warn); }
.zaehler-leiste .z.ERROR b, .zaehler-leiste .z.CRITICAL b { color: var(--schlecht); }

.stufenwahl { display: flex; gap: 12px; flex-wrap: wrap; }
.stufenwahl label { display: inline-flex; align-items: center; gap: 5px; font-size: 12.5px; cursor: pointer; }
.stufenwahl input { accent-color: var(--blau); }

.stromreihe { display: flex; align-items: center; gap: 8px; margin-left: auto; }
.stand { font-size: 12px; color: var(--leise); }
.stand[data-zustand="gut"] { color: var(--gut); }
.stand[data-zustand="warn"] { color: var(--warn); }

.lg-text { overflow-wrap: anywhere; max-width: 70ch; }
/* Eine Zeile, die gerade per Livestrom hereingekommen ist. */
.tabelle tr.lg-neu td { background: rgba(33, 150, 243, .09); }
.tabelle tr[data-stufe="WARNING"] td { background: rgba(224, 161, 58, .06); }
.tabelle tr[data-stufe="ERROR"] td, .tabelle tr[data-stufe="CRITICAL"] td { background: rgba(226, 86, 77, .07); }

/* Die handgebaute Blaetterleiste von /logs und /comments. Sie heisst weiter
   `.blaettern`, sieht aber jetzt aus wie partials/pager.ejs — ein Blaetterer,
   der auf zwei Seiten anders aussieht, ist zweimal derselbe und einmal zu viel. */
.blaettern {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--linie);
  color: var(--leise); font-size: 12.5px;
}

/* ── Konten ──────────────────────────────────────────────────────────────────
   Kartengitter statt Tabelle: acht Kanaele mit je fuenf Angaben lesen sich als
   Karten besser als als Zeilen. */

.karten-kopf { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 6px; }
.kanal { font-size: 15px; font-weight: 650; }
.handle { color: var(--leise); font-size: 12.5px; margin: 0 0 10px; overflow-wrap: anywhere; }
.fehlertext { color: #f3b8b2; font-size: 12.5px; margin: 8px 0 0; overflow-wrap: anywhere; }
.karte.aus { opacity: .62; }
.karte.warnung { border-color: rgba(240, 176, 74, .36); }
.karte.fehler { border-color: rgba(240, 101, 92, .38); }

/* ── Kommentare ──────────────────────────────────────────────────────────────
   Ein Balken aus drei Toenen: richtig, falsch, unklar. */

.verteilung { display: flex; height: 8px; border-radius: 999px; overflow: hidden; background: var(--flaeche2); border: 1px solid var(--linie); min-width: 90px; }
.verteilung i { display: block; height: 100%; }
.verteilung .r { background: var(--gut); }
.verteilung .f { background: var(--schlecht); }
.verteilung .u { background: var(--warn); }
.einordnen { display: flex; gap: 6px; align-items: center; }
.einordnen select { min-width: 130px; }
/* Der normalisierte Text unter dem Kommentar — Rohstoff der Einordnung. */
.roh { color: var(--leise); font-size: 11.5px; font: var(--schrift-mono); overflow-wrap: anywhere; }
.tabelle td.text { max-width: 46ch; overflow-wrap: anywhere; }

/* ── Gewichte (Rezepte und Textbausteine) ────────────────────────────────────
   Der Regler, mit dem man ein gelerntes Gewicht von Hand ueberschreibt. Er
   steht in einer Tabellenzeile, deshalb ist er schmal und die Zahl daneben
   feststehend breit — sonst wackelt die Spalte bei jedem Ziehen. */

.regler { display: flex; align-items: center; gap: 7px; }
.regler input[type="range"] { width: 88px; accent-color: var(--blau); }
.reglerwert { min-width: 2.6em; text-align: right; font-variant-numeric: tabular-nums; font-size: 12.5px; }
.balkenzelle { min-width: 96px; }
.gewichtbalken { display: block; height: 6px; border-radius: 999px; background: var(--flaeche2); border: 1px solid var(--linie); overflow: hidden; }
.gewichtbalken i { display: block; height: 100%; background: var(--verlauf-balken); }
/* Eine abgeschaltete Zeile bleibt lesbar, tritt aber zurueck. */
.tabelle tr.aus td { opacity: .5; }
.gruppenkopf { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin-bottom: 8px; }
.satz { color: var(--leise); font-size: 12.5px; line-height: 1.55; max-width: 78ch; }
/* Die Felderreihe im Formular "Neues Rezept" und in "neue Version". */
.rezeptfelder, .anlegen { display: flex; gap: 10px; flex-wrap: wrap; align-items: flex-end; }

/* ── Auswertung ──────────────────────────────────────────────────────────────
   Die Zeitraumwahl (7 / 30 / 90 Tage) als Knopfreihe: drei Werte, zwischen
   denen man hin und her springt — dafuer ist ein Auswahlfeld zu langsam. */

.zeitwahl { display: flex; gap: 4px; margin-left: auto; }
.zeitwahl .knopf[aria-pressed="true"] { border-color: var(--blau); color: var(--schrift); background: var(--blau-grund); }
/* Die Kacheln dieser Seite tragen eigene Namen, weil sie eine Zeile mehr
   haben als die der Uebersicht. */
.kachel .name { font-size: 11px; text-transform: uppercase; letter-spacing: .07em; color: var(--leise); }
.kachel .wert { font-size: 26px; font-weight: 700; line-height: 1.1; }
.kachel .neben { font-size: 12px; color: var(--leise); overflow-wrap: anywhere; }
.schluessel { font: var(--schrift-mono); overflow-wrap: anywhere; }

/* ── Wochenraster der Sendezeiten ────────────────────────────────────────────
   Sieben Zeilen, vierundzwanzig Spalten, 168 Knoepfe. Die groesste Tabelle der
   Anwendung — und die einzige, in der eine Zelle ein Knopf ist. */

.raster { border-collapse: collapse; }
.raster th { font-size: 10px; color: var(--leise); font-weight: 600; padding: 2px 3px; text-align: center; }
.raster th.tag { text-align: right; padding-right: 7px; white-space: nowrap; }
.raster td { padding: 1px; }
.raster-zelle {
  position: relative;
  display: block;
  width: 26px;
  height: 20px;
  border: 1px solid var(--linie);
  border-radius: 4px;
  background: var(--flaeche2);
  cursor: pointer;
  padding: 0;
  overflow: hidden;
}
.raster-zelle:hover { border-color: var(--blau); }
.raster-zelle:focus-visible { outline: 2px solid var(--blau); outline-offset: 1px; }
.raster-zelle[disabled] { cursor: default; }
.raster-zelle.manuell { background: var(--blau-grund); border-color: rgba(33, 150, 243, .5); }
.raster-zelle.auto { background: var(--gut-grund); border-color: rgba(78, 201, 138, .4); }
.raster-zelle.aus { opacity: .45; }
.raster-zelle.taeglich { box-shadow: inset 0 0 0 1px var(--cyan); }
/* Der Hintergrund zeigt die gemessene Leistung dieses Sendeplatzes. Er liegt
   UNTER der Marke, damit "hier steht eine Regel" nie von "hier war es gut"
   verdeckt wird. */
.raster-zelle .hitze { position: absolute; inset: 0; background: var(--warn); }
.raster-zelle .marke {
  position: absolute; right: 2px; top: 2px;
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--schrift);
}
.raster-zelle.auto .marke { background: var(--gut); }
.raster-zelle.manuell .marke { background: var(--blau); }

.legende { display: flex; gap: 16px; flex-wrap: wrap; font-size: 12px; color: var(--leise); margin-top: 10px; }
.legende > span { display: inline-flex; align-items: center; gap: 6px; }
.legende .probe { width: 14px; height: 12px; border: 1px solid var(--linie); border-radius: 3px; background: var(--flaeche2); flex: none; }
.legende .probe.manuell { background: var(--blau-grund); border-color: rgba(33, 150, 243, .5); }
.legende .probe.auto { background: var(--gut-grund); border-color: rgba(78, 201, 138, .4); }
.legende .probe.taeglich { box-shadow: inset 0 0 0 1px var(--cyan); }
.legende .probe.hitze { background: var(--warn); opacity: .55; }
.schalterreihe { display: flex; gap: 14px; align-items: flex-end; flex-wrap: wrap; justify-content: space-between; }

/* ── Pausen einstellen (/voices) ─────────────────────────────────────────────
   Zwei Balken uebereinander: oben die Aufnahme, wie sie kam, unten die Fassung
   mit den geaenderten Pausen. Jede Pause hat einen Griff, an dem man sie zieht;
   die Zahl im Feld daneben und der Griff sind dieselbe Groesse, nur zweimal
   bedienbar. static/app.js rechnet beim Ziehen mit, ohne die Seite neu zu laden.

   Der Streifenhintergrund ist kein Schmuck: eine Pause ist NICHTS, und eine
   Flaeche, die nichts zeigt, muss anders aussehen als eine, die etwas zeigt. */

.stern { color: var(--blau); }
.pausen-leiste { margin: 4px 0 16px; }
.pl-zeile { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; }
.pl-name { width: 58px; font-size: 12px; color: var(--leise); text-align: right; flex: none; }
.pl-dauer { width: 64px; font-size: 12px; flex: none; font-variant-numeric: tabular-nums; }
.pl-balken {
  flex: 1;
  display: flex;
  height: 26px;
  border-radius: 6px;
  overflow: hidden;
  background: var(--flaeche2);
  border: 1px solid var(--linie);
}
.pl-balken i { display: block; height: 100%; position: relative; }
.pl-balken i.sprache { background: linear-gradient(180deg, #3f7fb2, #31688f); }
.pl-balken i.pause { background: repeating-linear-gradient(45deg, var(--linie-stark), var(--linie-stark) 5px, #31363c 5px, #31363c 10px); }
.pl-balken i.gedehnt { background: repeating-linear-gradient(45deg, #5a4a27, #5a4a27 5px, #6b5730 5px, #6b5730 10px); }
.pl-balken i.gekuerzt { background: repeating-linear-gradient(45deg, #4a2f2c, #4a2f2c 5px, #5a3a36 5px, #5a3a36 10px); }
.pl-griff {
  position: absolute; top: 0; right: -6px;
  width: 12px; height: 100%;
  cursor: ew-resize; z-index: 2; touch-action: none; display: block;
}
.pl-griff::after {
  content: ''; position: absolute; top: 3px; bottom: 3px; left: 5px; width: 2px;
  background: var(--schrift); opacity: .55; border-radius: 1px;
}
.pl-griff:hover::after { opacity: 1; background: var(--blau); }
.pl-balken.zieht { cursor: ew-resize; user-select: none; }
.pl-balken.zieht .pl-griff::after { opacity: 1; background: var(--blau); }
.pl-legende { display: flex; align-items: center; gap: 7px; margin: 0; font-size: 12px; color: var(--leise); }
.pl-legende i { display: inline-block; width: 15px; height: 11px; border-radius: 3px; vertical-align: middle; }
.pl-legende i.pl-sprache { background: #3f7fb2; }
.pl-legende i.pl-pause { background: var(--linie-stark); margin-left: 9px; }
.pl-diff { margin-left: 9px; font-variant-numeric: tabular-nums; }
.pl-diff.laenger { color: var(--warn); }
.pl-diff.kuerzer { color: var(--gut); }

/* Die grosse Zahl in den Systemkaesten (Last, Belegung). */
.gross { font-size: 24px; font-weight: 700; line-height: 1.15; font-variant-numeric: tabular-nums; }

/* Eine Zahlenspalte. Rechtsbuendig und mit gleich breiten Ziffern, damit
   Tausender untereinander stehen und man Groessen vergleichen kann, ohne zu
   lesen. Stand vorher in sechs Seiten, sechsmal gleich. */
.zahl { text-align: right; font-variant-numeric: tabular-nums; font: var(--schrift-mono); }
th.zahl { text-align: right; }

/* Die Flaeche, in die static/charts.js sein SVG haengt. Die Daten daneben
   stehen in einem <script type="application/json"> und sind ohnehin unsichtbar
   — die Regel steht trotzdem hier, damit klar ist, dass sie es sein SOLL. */
.diagramm-flaeche { min-height: 40px; }
.diagramm-daten { display: none; }

/* Eine Zeile im Protokoll. Die Faerbung nach Stufe steht weiter oben. */
.lg-zeile td { vertical-align: top; }

/* ══ Studio (pages/studio.ejs) ═══════════════════════════════════════════════
   Der ganze Weg eines Videos als Fliessband: vier Stationen nebeneinander,
   von links nach rechts zu lesen. Die Seite nimmt die volle Breite — sie ist
   kein Dokument, sondern ein Arbeitstisch. */

.inhalt.inhalt-studio { max-width: none; padding: 18px 22px 110px; gap: 16px; }

/* Die Lage in einem Satz, darueber steht nichts. Wer die Seite oeffnet, liest
   zuerst, ob etwas auf ihn wartet. */
.lage {
  display: flex;
  align-items: center;
  gap: 18px;
  flex-wrap: wrap;
  padding: 18px 22px;
  border-radius: 18px;
  border: 1px solid rgba(108, 184, 255, .22);
  background:
    linear-gradient(100deg, rgba(33, 150, 243, .16), rgba(156, 39, 176, .12) 70%, transparent),
    var(--flaeche);
  box-shadow: var(--schatten-hoch);
}
.lage-satz { flex: 1 1 380px; font-size: 15px; color: #c9cfda; line-height: 1.5; }
.lage-satz b { display: block; font-size: 22px; font-weight: 700; letter-spacing: -.02em; color: var(--schrift); }
.lage-rechts { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.lage-chip {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 6px 12px;
  border-radius: 999px;
  font-size: 12.5px; font-weight: 600;
  background: var(--flaeche2);
  border: 1px solid var(--linie-stark);
  color: var(--schrift);
  white-space: nowrap;
}
.lage-chip::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--leise); }
.lage-chip.gut::before { background: var(--gut); box-shadow: 0 0 0 3px rgba(79, 209, 151, .18); }
.lage-chip.warn::before { background: var(--warn); }
.lage-chip.schlecht::before { background: var(--schlecht); }
.lage-chip.schlecht { border-color: rgba(240, 101, 92, .45); }
a.lage-chip:hover { text-decoration: none; border-color: var(--schlecht); }

.band {
  display: grid;
  grid-template-columns: minmax(300px, 1.25fr) minmax(210px, .6fr) minmax(300px, 1.25fr) minmax(260px, 1fr);
  gap: 14px;
  align-items: start;
}
.station {
  position: relative;
  display: flex;
  flex-direction: column;
  min-width: 0;
  border-radius: 16px;
  border: 1px solid var(--linie);
  background: var(--flaeche);
  box-shadow: var(--schatten);
}
/* Der Pfeil zur naechsten Station. Er ist das einzige Zeichen, das sagt
   "es geht hier nach rechts weiter" — ohne ihn waeren es vier Kaesten. */
.station:not(:last-child)::after {
  content: "›";
  position: absolute;
  right: -13px; top: 22px;
  width: 22px; height: 22px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--flaeche3);
  border: 1px solid var(--linie-stark);
  color: var(--leise);
  font-size: 15px; line-height: 1;
  z-index: 2;
}
/* Station 3 ist die, an der ein Mensch gebraucht wird. Sie traegt als einzige
   den Markenrand. */
.station.betont { border-color: rgba(108, 184, 255, .45); box-shadow: 0 0 0 1px rgba(108, 184, 255, .12), var(--schatten-hoch); }

.st-kopf { display: flex; align-items: flex-start; gap: 12px; padding: 14px 14px 12px; border-bottom: 1px solid var(--linie); }
.st-kopf h2 { font-size: 16px; font-weight: 700; display: flex; align-items: center; gap: 8px; }
.st-kopf p { margin: 3px 0 0; font-size: 12.5px; line-height: 1.45; color: var(--leise); }
.st-kopf p b { color: var(--schrift); font-weight: 600; }
.st-kopf > div { flex: 1; min-width: 0; }
.st-nr {
  width: 30px; height: 30px; flex: none;
  display: grid; place-items: center;
  border-radius: 10px;
  background: var(--flaeche3);
  border: 1px solid var(--linie-stark);
  font-weight: 700; font-size: 15px;
}
.station.betont .st-nr { background: var(--verlauf); border-color: transparent; color: #fff; }
.st-zahl { font-size: 12.5px; font-weight: 600; color: var(--leise); background: var(--flaeche3); border-radius: 999px; padding: 1px 9px; }
.st-alle {
  flex: none;
  background: transparent;
  border: 1px solid var(--linie-stark);
  border-radius: 999px;
  padding: 3px 10px;
  font-size: 12px; color: var(--leise);
  cursor: pointer;
}
.st-alle:hover { color: var(--schrift); border-color: #4a5366; }

.st-liste { padding: 12px; display: flex; flex-direction: column; gap: 8px; max-height: calc(100vh - 290px); min-height: 180px; overflow-y: auto; }
.st-liste.raster { display: grid; grid-template-columns: repeat(auto-fill, minmax(128px, 1fr)); align-content: start; gap: 10px; }
.st-liste.raster.hoch { grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); }
.st-liste > .leer, .st-liste > .st-rest, .st-zwischen { grid-column: 1 / -1; }
.st-zwischen { margin: 6px 0 0; font-size: 11.5px; text-transform: uppercase; letter-spacing: .07em; color: var(--leise); font-weight: 600; }
.st-zwischen:first-child { margin-top: 0; }
.st-zwischen.fehler { color: var(--schlecht); }
.st-zwischen.warn { color: var(--warn); }
.st-karte.wartet { border-color: rgba(240, 176, 74, .4); }
.st-grund { display: block; margin-top: 6px; font-size: 12px; line-height: 1.4; color: #f6c2bd; white-space: normal; }
.st-rest { margin: 0; }
.st-rest b { color: var(--schrift); font-weight: 600; }

/* Eine Karte ist ein <label> um ihren Haken: ein Klick irgendwo auf die Karte
   waehlt sie aus. Der Haken selbst ist unsichtbar klein in der Ecke — sichtbar
   ist der Rahmen der Karte, und der traegt die Auswahl. */
.st-karte {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 7px 7px 9px;
  border-radius: 12px;
  border: 1.5px solid var(--linie);
  background: var(--flaeche2);
  cursor: pointer;
  min-width: 0;
  user-select: none;
  transition: transform .1s ease, border-color .1s ease, box-shadow .1s ease;
}
.st-karte:hover { border-color: var(--linie-stark); transform: translateY(-1px); }
.st-karte.gewaehlt {
  border-color: var(--blau);
  background: var(--blau-grund);
  box-shadow: 0 0 0 3px rgba(33, 150, 243, .25);
}
.st-karte.erledigt { opacity: .35; }
.st-karte.fehler { border-color: rgba(240, 101, 92, .4); }
.st-haken {
  position: absolute;
  top: 10px; left: 10px;
  width: 18px; height: 18px;
  z-index: 2;
  opacity: 0;
  cursor: pointer;
}
.st-karte:hover .st-haken, .st-karte.gewaehlt .st-haken, .st-haken:focus-visible { opacity: 1; }
.st-bild {
  display: grid; place-items: center;
  border-radius: 8px;
  background: var(--canvas);
  overflow: hidden;
  position: relative;
}
.st-bild .zeichnung { width: 100%; height: auto; background: transparent; }
.st-bild.hochkant { aspect-ratio: 9 / 16; background: #07080b; }
.st-bild.hochkant img { width: 100%; height: 100%; object-fit: cover; display: block; }
.st-abspielen {
  position: absolute;
  inset: auto 6px 6px auto;
  width: 34px; height: 34px;
  border-radius: 50%;
  border: 0;
  background: rgba(10, 12, 17, .78);
  color: #fff;
  font-size: 13px;
  cursor: pointer;
  box-shadow: 0 0 0 1.5px rgba(255, 255, 255, .5);
}
.st-abspielen:hover { background: var(--blau); box-shadow: 0 0 0 1.5px #fff; }
.st-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; padding: 0 2px; }
.st-text b { font-size: 13px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.st-karte.zeile { padding: 10px 12px 10px 34px; }
.st-karte.zeile .st-haken { opacity: 1; top: 12px; }
.st-fassung { display: flex; align-items: center; gap: 8px; margin-top: 4px; flex-wrap: wrap; }
.st-fassung .fortschritt { flex: 1; min-width: 0; }

/* Die Auswahlleiste. Sie schwebt unten in der Mitte und ist das Einzige, was
   sich auf dieser Seite hereinbewegt — sie soll gesehen werden. */
.auswahl-leiste {
  position: fixed;
  left: 50%; bottom: 22px;
  transform: translateX(-50%);
  z-index: 40;
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  justify-content: center;
  max-width: calc(100vw - 28px);
  padding: 12px 14px 12px 20px;
  border-radius: 18px;
  background: #1b202b;
  border: 1px solid rgba(108, 184, 255, .5);
  box-shadow: 0 24px 50px -12px rgba(0, 0, 0, .9), 0 0 0 4px rgba(33, 150, 243, .12);
  animation: leiste-ein .18s ease-out;
}
.auswahl-leiste[hidden] { display: none; }
/* `hidden` muss gegen `.knopf { display: inline-block }` gewinnen. Ohne diese
   Regel standen ALLE zehn Knoepfe in der Leiste, auch die, die zur Auswahl
   gar nicht passen — static/studio.js blendet sie ueber das Attribut aus,
   und das Attribut allein verliert gegen jede display-Angabe. */
.auswahl-leiste [hidden] { display: none !important; }
.auswahl-leiste .knopf { flex: none; }
@keyframes leiste-ein { from { opacity: 0; transform: translate(-50%, 14px); } to { opacity: 1; transform: translate(-50%, 0); } }
@media (prefers-reduced-motion: reduce) { .auswahl-leiste { animation: none; } }
.auswahl-zahl { font-size: 14px; margin-right: 6px; white-space: nowrap; }
.auswahl-zahl b { font-size: 18px; font-variant-numeric: tabular-nums; }
.auswahl-leiste .knopf { padding: 9px 16px; font-size: 14px; }
.knopf.leise-knopf { background: transparent; border-color: transparent; color: var(--leise); box-shadow: none; }
.knopf.leise-knopf:hover { color: var(--schrift); background: rgba(255, 255, 255, .05); }

/* Die Durchsicht: ein Video, drei Tasten, sonst nichts. */
html.ds-offen { overflow: hidden; }
.durchsicht {
  position: fixed; inset: 0;
  z-index: 60;
  display: grid; place-items: center;
  padding: 16px;
  background: rgba(5, 6, 9, .9);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
}
.durchsicht[hidden] { display: none; }
.ds-kasten { display: flex; flex-direction: column; gap: 12px; align-items: center; width: min(560px, 100%); max-height: 100%; }
.ds-kopf { display: flex; align-items: center; gap: 12px; width: 100%; }
.ds-kopf b { font-size: 20px; letter-spacing: -.02em; }
.ds-sprachen { display: flex; gap: 4px; margin-left: auto; }
.ds-sprachen .knopf.an { border-color: var(--blau); background: var(--blau-grund); }
.ds-video {
  height: min(64vh, 720px);
  aspect-ratio: 9 / 16;
  max-width: 100%;
  border-radius: 18px;
  background: #000;
  border: 1px solid var(--linie-stark);
  box-shadow: 0 30px 80px -20px rgba(33, 150, 243, .45);
}
.ds-knoepfe { display: grid; grid-template-columns: 1fr auto 1fr; gap: 10px; width: 100%; }
.ds-knoepfe .knopf { text-align: center; padding: 14px 10px; font-size: 16px; }
.ds-knoepfe kbd {
  margin-left: 6px; padding: 1px 6px;
  border-radius: 5px;
  background: rgba(0, 0, 0, .28);
  font: 600 12px/1.5 var(--familie-mono);
}
.ds-hinweis { margin: 0; text-align: center; min-height: 1.4em; }

/* ══ Mehr (pages/mehr.ejs) ════════════════════════════════════════════════════
   Alles, was selten gebraucht wird, als Kacheln mit je einem Satz. */
.mehr-gruppe { display: flex; flex-direction: column; gap: 8px; margin-top: 6px; }
.mehr-gruppe h2 { font-size: 17px; font-weight: 700; }
.mehr-gruppe > p { margin: -4px 0 2px; }
.mehr-kacheln { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 10px; }
.mehr-kachel {
  display: flex; flex-direction: column; gap: 3px;
  padding: 14px 16px;
  border-radius: 13px;
  border: 1px solid var(--linie);
  background: var(--flaeche);
  color: var(--schrift);
  box-shadow: var(--schatten);
  transition: transform .12s ease, border-color .12s ease;
}
.mehr-kachel:hover { text-decoration: none; border-color: var(--blau); transform: translateY(-2px); }
.mehr-kachel b { font-size: 15px; font-weight: 650; }
.mehr-kachel span { font-size: 12.5px; color: var(--leise); line-height: 1.4; }
.mehr-kachel.technik { border-style: dashed; }

@media (max-width: 1250px) {
  /* Zwei mal zwei: die Reihenfolge bleibt lesbar (1 2 / 3 4), der Pfeil nach
     rechts stimmt dann nur noch in jeder zweiten Station und entfaellt. */
  .band { grid-template-columns: 1fr 1fr; }
  .station:not(:last-child)::after { display: none; }
  .st-liste { max-height: 520px; }
}
@media (max-width: 720px) {
  .band { grid-template-columns: 1fr; }
  .inhalt.inhalt-studio { padding: 12px 12px 130px; }
  .lage { padding: 14px; }
  .lage-satz b { font-size: 19px; }
  .ds-knoepfe { grid-template-columns: 1fr 1fr; }
  .ds-knoepfe .knopf:nth-child(2) { grid-column: 1 / -1; order: 3; }
}

/* ══ Authenticator einrichten (pages/authenticator.ejs) ════════════════════ */
.karte > h2 .st-nr { width: 26px; height: 26px; font-size: 13px; border-radius: 8px; }
.totp-scan { display: flex; gap: 22px; align-items: flex-start; flex-wrap: wrap; margin-top: 6px; }
/* Der QR-Code steht auf Weiss mit Rand: auf dunklem Grund erkennt ihn keine
   Kamera, und ohne die helle Ruhezone darum auch nicht. */
.totp-qr { width: 200px; height: 200px; padding: 10px; border-radius: 12px; background: #fff; flex: none; }
.totp-qr svg { width: 100%; height: 100%; display: block; }
.totp-schluessel { font-size: 17px; letter-spacing: .06em; margin: 8px 0; color: var(--schrift); overflow-wrap: anywhere; user-select: all; }
.totp-form { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin-top: 10px; }
.totp-code { width: 150px; font-size: 22px; letter-spacing: .18em; text-align: center; padding: 9px 10px; }
.anmeldung-rueckweg { text-align: center; }
