/* PulsQuiz - gemeinsames Design für Beamer und Handy
 * ---------------------------------------------------
 * Die Schriften liegen im Projekt und kommen vom eigenen Server. Im
 * Behördennetz ist ein Abruf bei Google Fonts ein Datenschutzproblem
 * und im Klassenraum ohne Netz wäre die Seite ohne ihn kahl.
 *
 * Ein Akzent: das Rettungsrot aus notsanwissen. Es trägt Hauptaktion,
 * Fokus und aktuellen Zustand. Gefahr, Richtig und Warnung sind
 * Statusfarben und keine zweite Aktionsfarbe.
 * Die sechs Antwortfarben sind kein Schmuck, sondern die Zuordnung
 * zwischen Beamer und Handy. Sie stehen nie allein: der Buchstabe
 * A bis F trägt dieselbe Information, damit auch bei Farbenblindheit
 * eindeutig bleibt, welche Kachel gemeint ist.
 *
 * Alle Antwortfarben sind gegen weißen Text auf mindestens 4.5:1
 * gerechnet. Die Startfassung lag bei Rot, Gold und Türkis darunter.
 */

/* Die Schriften liegen im Projekt und kommen vom eigenen Server. Ein
 * <link> auf Google überträgt die IP jedes Azubi-Handys an einen
 * US-Anbieter, und der Klassenraum muss ohne Netz laufen. Es sind
 * variable Schriften: eine Datei trägt alle Gewichte, zusammen 88 KB.
 * "swap" statt "block", damit die Folie auch dann steht, wenn eine Datei
 * hängt. */
@font-face {
  font-family: 'Inter'; src: url('/schriften/Inter.woff2') format('woff2');
  font-weight: 100 900; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'JetBrains Mono'; src: url('/schriften/JetBrainsMono.woff2') format('woff2');
  font-weight: 100 800; font-style: normal; font-display: swap;
}

/* ---------- Farben ----------
 *
 * Die Werte kommen aus notsanwissen (`src/app/globals.css`), damit Lennys
 * Lernwerkzeuge zusammengehören: Rettungsrot als einziger Akzent, weisser
 * Grund, Inter und JetBrains Mono.
 *
 * Es gibt zwei Fassungen, hell und dunkel, umschaltbar mit der Taste D
 * oder dem Knopf im Fuss. Der Grund ist kein Geschmack, sondern der Raum:
 * Ein abgedunkelter Klassenraum mit lichtstarkem Beamer will Dunkel, ein
 * heller Raum mit schwachem Beamer will Hell. Beide Fassungen sind gegen
 * ihren jeweiligen Grund gerechnet, die Zahl in Klammern ist der gemessene
 * Kontrast.
 *
 * Ein Akzent, und das ist das Rot. Es trägt Hauptaktion, Fokusring und
 * aktuellen Zustand. Die Statusfarben sind keine zweite Aktionsfarbe.
 */
:root {
  /* Grund, helle Fassung */
  --ink: #1A1A2E;      /* 17.06:1 auf Grund */
  --paper: #FFFFFF;
  --panel: #F8F9FA;
  --line: #E5E7EB;
  --mut: #4B5563;      /* 7.56:1 */

  /* Akzent und Status */
  --akzent: #C8102E;       /* 5.88:1 */
  --akzent-tief: #A50D24;  /* 7.83:1, für Text auf heller Fläche */
  --akzent-hell: #E8304A;
  --auf-akzent: #FFFFFF;   /* 5.88:1 auf der Akzentfläche */
  --gefahr: #B91C1C;
  --gut: #15803D;      /* 5.02:1, nicht #16A34A: das lag bei 3.30:1 */
  --mittel: #B45309;   /* 5.02:1, nicht #D97706: das lag bei 3.19:1 */

  /* Marken auf einem Bild. Sie liegen auf der Abbildung, und eine
   * Abbildung dreht sich nicht mit der Fassung: Sie bleibt hell, auch
   * wenn der Beamer auf dunkel steht. Deshalb sind diese Werte in beiden
   * Fassungen dieselben, wie die sechs Antwortfarben.
   *
   * Gemessen: der helle Akzent #FF5C70 der dunklen Fassung kommt auf dem
   * weissen Bildgrund auf 2.99:1. Genau dieser Fehler stand schon einmal
   * siebzehnmal auf dem Weiter-Knopf. */
  --marke: #C8102E;        /* 5.88:1 gegen den weissen Bildgrund */
  --auf-marke: #FFFFFF;    /* 5.88:1 auf der Marke */
  --schild: #FFFFFF;
  --schild-ink: #1A1A2E;   /* 17.06:1 auf dem Schild */
  --schild-mut: #4B5563;   /* 7.56:1 */

  /* Die abgeblendete Kachel in der Auflösung. Sie trägt weissen Text und
   * bleibt deshalb in beiden Fassungen derselbe Wert, aus demselben Grund
   * wie die sechs Antwortfarben. Vorher stand hier ein fest geschriebenes
   * Graugrün (#626F68) aus dem alten grünen Design und in der dunklen
   * Fassung ein Blaugrau (#4A545F): zwei Farbfamilien für dieselbe Rolle,
   * beide ausserhalb der Palette. */
  --blass: #4B5563;  /* weisser Text 7.56:1 */

  /* Antwortfarben, gemessen gegen weissen Text */
  --a: #C62828;  /* 5.62:1 */
  --b: #1D5480;  /* 7.98:1 */
  --c: #8A6510;  /* 5.32:1 */
  --d: #1E7857;  /* 5.41:1 */
  --e: #71429C;  /* 7.09:1 */
  --f: #0C7A84;  /* 5.08:1 */

  /* Maße. Die Inhaltsbreite steht genau hier, damit Beamer- und
   * Handyansicht nicht auseinanderdriften. */
  --breite: 1280px;
  --rand: max(20px, env(safe-area-inset-left));
  --radius: 12px;
  --radius-klein: 8px;
  --schatten: 0 1px 2px rgba(26, 26, 46, .06), 0 8px 24px rgba(26, 26, 46, .05);
  --schatten-tief: 0 4px 12px rgba(26, 26, 46, .10), 0 16px 44px rgba(26, 26, 46, .10);

  --sans: 'Inter', system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
  --mono: 'JetBrains Mono', ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  color-scheme: light;
}

/* Dunkle Fassung. Der Akzent wird heller, weil #C8102E auf dunklem Grund
 * absäuft: gemessen 1.87:1 gegen den Grund, also unlesbar. */
:root[data-dunkel] {
  --ink: #EDEFF3;      /* 16.01:1 auf Grund */
  --paper: #11141B;
  --panel: #1A1E27;
  --line: #2E3440;
  --mut: #A7B0BE;      /* 8.42:1 */

  --akzent: #FF5C70;       /* 6.16:1 auf Grund, 5.57:1 auf Fläche */
  --akzent-tief: #FF7085;  /* 6.94:1 */
  --akzent-hell: #FF8496;
  --auf-akzent: #11141B;   /* 6.16:1 auf der Akzentfläche */
  --gefahr: #FF6B5E;
  --gut: #4ADE80;      /* 10.57:1 */
  --mittel: #FBBF24;   /* 11.04:1 */

  /* Die Antwortfarben bleiben unverändert. Sie tragen weissen Text, und
   * das ist die harte Anforderung: alle sechs liegen über 5:1 gegen ihn.
   * Ein Aufhellen für den dunklen Grund brach genau das, drei von sechs
   * fielen unter 4.5:1. Gegen den dunklen Grund liegen sie bei 2.3 bis
   * 3.6:1; damit die Kachel trotzdem klar als Fläche endet, bekommt sie
   * unten eine feine helle Kante. Die Zuordnung trägt ohnehin doppelt,
   * über die Farbe und über den Buchstaben A bis F. */

  --schatten: 0 1px 2px rgba(0, 0, 0, .4), 0 8px 24px rgba(0, 0, 0, .35);
  --schatten-tief: 0 4px 12px rgba(0, 0, 0, .5), 0 16px 44px rgba(0, 0, 0, .45);

  color-scheme: dark;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  min-height: 100%;
  font-family: var(--sans);
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  -webkit-text-size-adjust: 100%;
}
body { overflow-x: hidden; }

button, input { font-family: inherit; font-size: inherit; color: inherit; }
.mono { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.hidden { display: none !important; }
.mitte { text-align: center; }
.mut { color: var(--mut); }
.klein { font-size: .9rem; }
.stark { font-weight: 700; color: var(--ink); }
.warn { color: var(--gefahr); }
.voll { width: 100%; }

/* Sichtbarer Fokus überall. Ohne ihn ist die Seite mit der Tastatur
 * nicht bedienbar, und am Beamer wird oft nur mit Tasten gesteuert. */
:where(button, input, a):focus-visible {
  outline: 3px solid var(--akzent);
  outline-offset: 3px;
}

/* ---------- Gerüst ---------- */
.wrap { min-height: 100vh; min-height: 100dvh; display: flex; flex-direction: column; }

/* ---------- Kopfleiste ----------
 * Eine durchgehende Zone über die ganze Breite, kein Streifen mit
 * schwebenden Teilen darin. Links der Markenblock als Farbfläche, daneben
 * der Name der Stunde, rechts der Zähler, auf der Unterkante der
 * Fortschritt. Der alte Kopf bestand aus einer Pille links und einem
 * Kicker rechts, die nichts miteinander zu tun hatten, und man konnte
 * nirgends ablesen, wie weit die Stunde ist. */
.bar-top {
  display: flex; align-items: stretch; gap: 0;
  padding: 0; width: 100%; margin: 0;
  height: 60px; position: relative;
  background: var(--paper); border-bottom: 1px solid var(--line);
}
.brand {
  display: flex; align-items: center; flex: 0 0 auto;
  background: var(--akzent); color: var(--auf-akzent);
  padding: 0 clamp(18px, 2vw, 28px);
  font-weight: 800; letter-spacing: .015em; text-transform: uppercase;
  font-size: clamp(14px, 1.5vw, 17px);
}
/* Die zweite Hälfte der Wortmarke ist abgesetzt, aber nicht abgeblendet.
 * Mit "opacity: .7" kam sie auf 3.42:1 in der hellen und 3.90:1 in der
 * dunklen Fassung, und keine Messung hat das gemeldet: Deckkraft ändert
 * die dargestellte Farbe, nicht die gemessene. Gefunden hat es erst
 * durchspielen.mjs, nachdem es die Deckkraft einrechnet.
 * Gemischt sind es 4.62:1 hell und 5.20:1 dunkel. */
.brand b { color: var(--auf-akzent); font-weight: 800; }
.brand b { color: color-mix(in srgb, var(--auf-akzent) 86%, var(--akzent)); }
.kopf-stunde {
  display: flex; align-items: center; min-width: 0;
  padding-left: clamp(14px, 1.6vw, 24px);
  font-weight: 700; font-size: clamp(14px, 1.5vw, 17px); letter-spacing: -.012em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.kopf-zaehler {
  display: flex; align-items: center; margin-left: auto; flex: 0 0 auto;
  padding-right: clamp(14px, 1.6vw, 24px);
  font-size: clamp(12px, 1.2vw, 14px); font-weight: 600; color: var(--mut);
}
/* Der Fortschritt sitzt auf der Unterkante der Leiste und legt sich über
 * deren Rahmen, damit er nicht als zweite Linie danebensteht. */
.fortschritt-spur, .fortschritt {
  position: absolute; left: 0; bottom: -1px; height: 3px;
}
.fortschritt-spur { right: 0; background: var(--line); }
/* Der Balken läuft über scaleX, nicht über width. Eine Breitenanimation
 * rechnet in jedem Bild das Layout neu; auf dem Beamer neben einer
 * laufenden Uhr ist das die eine Stelle, an der es ruckelt. Die Regel
 * steht in DESIGN.md und galt hier als einziger Stelle noch nicht. */
.fortschritt {
  width: 100%; background: var(--akzent); z-index: 1;
  border-radius: 0 2px 2px 0;
  transform: scaleX(0); transform-origin: left center;
  transition: transform .35s cubic-bezier(.2, .7, .2, 1);
}
.ecg { display: none; }

.pill {
  font-family: var(--mono); font-size: 14px; color: var(--mut);
  white-space: nowrap; margin: 0;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: 999px; padding: 6px 14px;
  max-width: 46vw; overflow: hidden; text-overflow: ellipsis; min-width: 0;
}
/* Der Raumcode in der Kopfleiste steht am rechten Rand und richtet sich
 * an deren Mitte aus, nicht am Text daneben. */
.bar-top .pill { align-self: center; margin-right: clamp(14px, 1.6vw, 24px); }

/* ---------- Bühne ----------
 * Die Auswahl, die Lobby und der Endstand richten sich weiter mittig aus,
 * das sind einzelne Bildschirme. Die Erklärseite und die Frage schlagen
 * oben an: Jede Folie beginnt an derselben Kante, und genau das ist der
 * Unterschied zwischen einer Website und einer Unterrichtsfolie. */
.stage {
  flex: 1; min-height: 0;
  display: flex; flex-direction: column; justify-content: center;
  gap: 20px;
  padding: clamp(18px, 2.6vh, 30px) clamp(24px, 3vw, 44px) 0;
  width: 100%; max-width: var(--breite); margin: 0 auto;
}
.stage > section { display: flex; flex-direction: column; gap: 18px; }
.stage > #info { grid-template-rows: auto 1fr auto; }
.stage > #question { grid-template-rows: auto auto 1fr auto; }
.stage > #reveal { grid-template-rows: auto 1fr auto; }
.stage > #info, .stage > #question, .stage > #reveal {
  flex: 1; min-height: 0; gap: 0; display: grid;
  /* Ohne diese Spalte ist das Raster so breit wie sein breitestes Kind.
   * Auf einer Folie, die nur ein hochformatiges Bild trägt, schrumpfte
   * damit auch die Steuerleiste mit: Die Trennlinie endete bei 1030 statt
   * bei 1396, und der Weiter-Knopf stand mitten im Bild statt an der
   * rechten Kante. Aus zehn Metern sieht das aus, als sei die Folie
   * abgeschnitten. */
  grid-template-columns: minmax(0, 1fr);
}
/* Die Zeilen werden ausdrücklich zugewiesen. Ein Element mit display:none
 * belegt keine Grid-Zeile, und weil die alte Kopfzeile der Erklärseite
 * genau das ist, rutschte die Folie in die erste Zeile und die
 * Steuerleiste bekam das 1fr. Sichtbar war eine Folie, die oben klebte,
 * und ein Weiter-Knopf, der in einer riesigen leeren Zone schwamm.
 *
 * Dieselbe Falle stand danach in #question, nur unbemerkt: fünf Kinder
 * bei drei Zeilen, und das 1fr fiel auf den acht Punkte hohen
 * Zeitbalken. Gemessen 251 Punkte Leere über der Frage, während unten
 * Kacheln, Knöpfe und Fusszeile mit null Abstand aneinanderklebten.
 * Wer hier eine Zeile ergänzt, weist sie zu. */
#info .folie { grid-row: 2; }
#info .steuer { grid-row: 3; }
#question .qmeta { grid-row: 1; }
#question .zeitbalken { grid-row: 2; }
#question .qmitte { grid-row: 3; }
#question .steuer { grid-row: 4; }
#reveal .qmeta { grid-row: 1; }
#reveal .qmitte { grid-row: 2; }
#reveal .steuer { grid-row: 3; }
/* Frage und Kacheln stehen zusammen in der Mitte des freien Raums,
 * genau wie die Folie. Der Abstand nach unten hält die Trennlinie der
 * Steuerleiste von den Kacheln weg, die vorher direkt anschloss. */
#question .qmitte, #reveal .qmitte {
  display: flex; flex-direction: column; justify-content: center;
  gap: clamp(14px, 2.6vh, 30px); min-height: 0;
  padding-bottom: clamp(12px, 2vh, 24px);
}
/* Die Auflösung trägt mehr Zeilen als die Frage: Fragetext, Kacheln,
 * Erklärkasten und Rangliste. Deshalb dort ein knapperer Abstand, sonst
 * schiebt sie sich auf einem flachen Beamerbild aus dem Bild. */
#reveal .qmitte { gap: clamp(8px, 1.6vh, 18px); }
/* Der Inhalt steht senkrecht in der Mitte des freien Raums, aber jede
 * Zeile beginnt an derselben linken Kante. Oben angeschlagen liess bei
 * einer kurzen Folie dreihundert Punkte Luft darunter stehen, mittig
 * zentriert ohne linke Kante sah aus wie eine Website. Das hier ist
 * beides: ruhig im Bild, ausgerichtet am Rand. */
/* justify-content, nicht align-content: Die Folie ist eine Flexbox in
 * Spaltenrichtung, und dort richtet align-content erst bei umbrechenden
 * Zeilen etwas aus. Mit align-content blieb der Inhalt oben kleben und
 * dreihundert Punkte darunter leer. */
#info .folie { justify-content: center; }

.foot {
  display: flex; justify-content: space-between; align-items: center;
  gap: 12px; flex-wrap: wrap;
  padding: 8px clamp(24px, 3vw, 44px) calc(10px + env(safe-area-inset-bottom));
  width: 100%; max-width: var(--breite); margin: 0 auto;
  font-family: var(--mono); font-size: 12px; color: var(--mut);
}
.fussrechts { display: flex; align-items: center; gap: 14px; }
/* Der Umschalter steht im Fuss, weil er im Unterricht einmal gedrückt wird
 * und danach nie wieder. Die Tastatur kann es auch, mit D. */
.lichtknopf {
  font-family: var(--mono); font-size: 12px; font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase;
  /* Die Schrift des Knopfs steht auf --ink, nicht auf --mut: Er ist eine
   * Aktion, keine Nebeninformation, und in der dunklen Fassung kam die
   * gedämpfte Farbe auf 3.53:1. */
  background: var(--panel); color: var(--ink);
  border: 1px solid var(--line); border-radius: 999px;
  /* 44 px, wie jede Tippfläche im Projekt. Mit 32 px war er kleiner als
   * die Regel erlaubt, und am Beamer wird oft mit dem Finger auf einem
   * Touchmonitor bedient. */
  padding: 12px 18px; min-height: 44px; cursor: pointer;
  transition: border-color .15s ease, color .15s ease;
}
.lichtknopf:hover { border-color: var(--akzent); color: var(--akzent); }
.foot p { margin: 0; }

/* Am Handy sitzt der Lichtknopf in der Kopfleiste, weil es dort keine
 * Fusszeile gibt. Er bleibt bei 44 px Tippfläche, wird aber schmaler:
 * Bei 375 px Gerätebreite teilen sich Marke, Name und Knopf eine Zeile.
 * Der Name schrumpft zuerst, der Knopf nie, sonst trifft ihn der Daumen
 * nicht mehr. */
.handy .bar-top .lichtknopf {
  align-self: center; flex: 0 0 auto;
  margin-left: auto; margin-right: max(12px, env(safe-area-inset-right));
  padding: 12px 14px; font-size: 11px;
}
.handy .bar-top .pill {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  margin-right: 10px;
}
/* Vor dem Beitreten steht in der Namenspille nichts. Eine leere Kapsel
 * neben der Marke sieht aus, als fehle etwas. */
.handy .bar-top .pill:empty { display: none; }

h1 { font-size: clamp(30px, 4.6vw, 60px); line-height: 1.04; letter-spacing: -.025em; margin: 0; font-weight: 800; }
h2 { font-size: clamp(22px, 3vw, 38px); line-height: 1.1; letter-spacing: -.02em; margin: 0; font-weight: 800; }
h3 { font-size: clamp(16px, 1.6vw, 20px); margin: 0; font-weight: 800; }
/* Fachbegriffe im Rettungsdienst sind lang und haben keine Trennstellen.
 * Ohne Umbruchreserve schiebt "Sinusknoten-Reentry-Tachykardie" die
 * Kachel über den Rand, statt in der Zeile zu bleiben. */
h1, h2, h3, .qtext, .pfrage, .kacheltext, .ptext, .awfrage, .rname {
  overflow-wrap: anywhere; min-width: 0;
}
p { margin: 0; line-height: 1.5; }

.eyebrow {
  font-family: var(--mono); font-size: 13px; letter-spacing: .12em;
  text-transform: uppercase; color: var(--gefahr); font-weight: 700; margin: 0;
}
.fehler { color: var(--gefahr); font-weight: 600; min-height: 1.4em; margin: 0; }
/* Getönte Flächen werden aus ihrer Statusfarbe und dem Grund gemischt,
 * nicht fest hingeschrieben. Ein fester Hellwert bleibt in der dunklen
 * Fassung hell, und der Text darauf dreht sich mit: Im Zwischenstand stand
 * der Name des Führenden weiss auf creme und war unlesbar. Kennt ein
 * Browser color-mix nicht, greift die Deklaration davor. */
.warnung {
  color: var(--mittel); font-weight: 600; margin: 0;
  background: var(--panel); border: 1px solid var(--line);
  background: color-mix(in srgb, var(--mittel) 12%, var(--paper));
  border-color: color-mix(in srgb, var(--mittel) 34%, var(--paper));
  border-radius: var(--radius-klein); padding: 10px 14px;
}
kbd {
  font-family: var(--mono); background: var(--panel); border: 1px solid var(--line);
  border-bottom-width: 2px; border-radius: 6px; padding: 1px 7px; font-size: 11px;
}

/* ---------- Knöpfe ---------- */
.btn {
  font-family: var(--mono); font-size: 15px; letter-spacing: .05em;
  text-transform: uppercase; font-weight: 700;
  /* Nicht fest weiss: In der dunklen Fassung ist der Akzent hell, und
   * weisser Text darauf kam auf 2.99:1. Die Textfarbe hängt deshalb am
   * Token, das je Fassung mitwechselt. */
  color: var(--auf-akzent); background: var(--akzent);
  border: 2px solid transparent; border-radius: 12px;
  padding: 15px 26px; min-height: 48px;
  cursor: pointer; box-shadow: var(--schatten);
  transition: transform .12s ease, background-color .15s ease;
}
.btn:hover { transform: translateY(-2px); }
.btn:active { transform: translateY(0); }
.btn:disabled { opacity: .5; cursor: not-allowed; transform: none; }
.btn.gross { font-size: 18px; padding: 19px 34px; min-height: 60px; }
.btn.leise { background: transparent; color: var(--mut); border-color: var(--line); box-shadow: none; }
.btn.leise:hover { color: var(--ink); border-color: var(--mut); }
.btn.bereit { background: var(--gefahr); }

.steuer { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; }
/* Zurück ist die leise Variante und steht links, abgesetzt von der
 * Hauptaktion rechts. In einer nach rechts ausgerichteten Leiste schiebt
 * die automatische rechte Aussenkante den Knopf an den linken Rand. */
.steuer .zurueck { margin-right: auto; }
/* Auf einer Folie sitzt der Weiter-Knopf fest unten rechts über einer
 * Trennlinie, wie in einem Präsentationsprogramm. Vorher schwebte er
 * mittig unter dem Inhalt und wanderte mit dessen Höhe. */
/* Die Auflösung bekommt dieselbe Steuerleiste wie Folie und Frage: unten
 * rechts über einer Trennlinie. Vorher schwebte der Weiter-Knopf dort
 * mittig unter der Rangliste und wanderte mit deren Höhe. Der Dozent
 * sucht ihn auf jedem Bildschirm an derselben Stelle, sonst zielt er im
 * abgedunkelten Raum daneben. Dafür muss #reveal die Höhe füllen, sonst
 * hat "margin-top: auto" nichts, wovon es sich abstossen kann. */

#info .steuer, #question .steuer, #reveal .steuer {
  justify-content: flex-end; align-items: center;
  border-top: 1px solid var(--line);
  padding: clamp(10px, 1.5vh, 16px) 0 clamp(10px, 1.5vh, 16px);
  margin-top: auto;
}
#info .btn.gross, #question .btn.gross, #reveal .btn.gross { padding: 13px 32px; }

/* ---------- Felder ---------- */
.feldlabel { display: block; font-family: var(--mono); font-size: 13px; color: var(--mut); margin-bottom: -8px; }
.feld {
  width: 100%; font-size: 19px; padding: 15px 18px; min-height: 54px;
  border: 2px solid var(--line); border-radius: 14px;
  background: var(--panel); color: var(--ink);
}
.feld:focus { outline: none; border-color: var(--akzent); box-shadow: 0 0 0 3px rgba(21, 94, 68, .18); }
.code-feld { text-align: center; letter-spacing: .3em; text-transform: uppercase; font-size: 26px; font-weight: 700; }
.schmal { max-width: 380px; margin: 0 auto; display: flex; flex-direction: column; gap: 14px; text-align: left; }

/* ---------- Quizauswahl ---------- */
.liste { display: grid; gap: 10px; max-width: 620px; margin: 0 auto; width: 100%; }
.quizrow {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  width: 100%; min-height: 62px; text-align: left;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 14px 20px; cursor: pointer;
  transition: border-color .15s ease, transform .12s ease;
}
.quizrow::after {
  content: "▸"; color: var(--akzent); font-size: 22px; line-height: 1;
  flex: 0 0 auto; transition: transform .15s ease;
}
.quizrow:hover:not(:disabled) { border-color: var(--akzent); transform: translateY(-2px); }
.quizrow:hover:not(:disabled)::after { transform: translateX(3px); }
.quizrow:disabled::after { color: var(--mut); }
.quizrow:disabled { opacity: .55; cursor: not-allowed; }
.quizrow > span:first-child { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.quiztitel { font-weight: 800; font-size: 19px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.quizsub {
  font-size: 13px; color: var(--mut);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.quizzahl { font-size: 14px; color: var(--akzent); font-weight: 700; white-space: nowrap; }
.quizzahl.warn { color: var(--gefahr); }

/* Auf schmalen Fenstern rutscht die Zahlenspalte unter den Titel. Sie hat
 * "nowrap" und schrumpft deshalb nicht: Als aus "12 Fragen" ein
 * "13 Fragen · 13 Erklärseiten" wurde, schob sie die Zeile auf 547 px in
 * einem 390 px breiten Fenster. Der Beamer läuft zwar am grossen Bild, die
 * Auswahl ruft aber auch mal jemand am Handy auf. */
@media (max-width: 560px) {
  .quizrow { flex-wrap: wrap; row-gap: 6px; }
  .quizrow > span:first-child { flex: 1 1 100%; }
  .quizzahl { white-space: normal; flex: 1 1 auto; min-width: 0; }
}

/* ---------- Lobby ---------- */
.lobby { display: grid; grid-template-columns: minmax(260px, 400px) 1fr; gap: 40px; align-items: center; width: 100%; }
@media (max-width: 860px) { .lobby { grid-template-columns: 1fr; } }

.joincard {
  background: var(--panel); border: 1px solid var(--line); border-radius: 22px;
  padding: 24px; box-shadow: var(--schatten); text-align: center;
  display: flex; flex-direction: column; gap: 10px; align-items: center;
}
.joincard img { width: 100%; max-width: 320px; border-radius: 12px; display: block; }
.joincard .code {
  font-size: clamp(34px, 4vw, 54px); font-weight: 800; letter-spacing: .22em;
  color: var(--gefahr); margin: 0; padding-left: .22em;
}
.joincard .url { font-size: 13px; color: var(--mut); word-break: break-all; margin: 0; }
/* Zeigt die Beitrittsadresse auf den eigenen Rechner, kommt kein Handy in den
   Raum. Das muss der Dozent sehen, bevor die Klasse davorsteht, nicht danach.
   Die Farbe trägt nicht allein, der Satz sagt es aus. */
.joincard .urlWarnung { font-size: 13px; line-height: 1.4; color: var(--mittel);
  border-left: 3px solid var(--mittel); padding-left: 8px; text-align: left;
  margin: 8px 0 0; }

.lobbyText { display: flex; flex-direction: column; gap: 14px; align-items: flex-start; }
.lobbyText .btn { align-self: stretch; }
.roster { display: flex; flex-wrap: wrap; gap: 9px; align-content: flex-start; min-height: 44px; width: 100%; }
.chip {
  display: inline-flex; align-items: center;
  background: var(--panel); border: 1px solid var(--line); border-radius: 999px;
  padding: 10px 18px; min-height: 44px; font-weight: 600;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: clamp(15px, 1.4vw, 18px); cursor: pointer;
  animation: auftauchen .25s ease;
  transform-origin: center;
  transition: border-color .15s ease, color .15s ease;
}
.chip:hover { border-color: var(--gefahr); color: var(--gefahr); }
.chip.fort { opacity: .5; border-style: dashed; }
@keyframes auftauchen { from { transform: translateY(6px); opacity: 0; } to { transform: none; opacity: 1; } }

/* ---------- Frage ---------- */
.qmeta { display: flex; justify-content: space-between; align-items: center; gap: 16px; width: 100%; }
.antwortzahl { font-size: clamp(15px, 1.6vw, 20px); color: var(--mut); margin: 0; }

.uhr {
  display: flex; align-items: center; justify-content: center;
  min-width: 92px; height: 68px; padding: 0 18px;
  background: var(--panel); border: 3px solid var(--akzent); border-radius: 18px;
  font-weight: 800; font-size: clamp(26px, 3vw, 40px); color: var(--akzent);
}
.uhr.knapp { border-color: var(--gefahr); color: var(--gefahr); animation: pochen 1s ease-in-out infinite; }
@keyframes pochen { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.06); } }

.zeitbalken { height: 8px; background: var(--line); border-radius: 999px; overflow: hidden; width: 100%; }
.zeitbalken-fuell {
  height: 100%; width: 100%; background: var(--akzent); border-radius: 999px;
  transform-origin: left center; transform: scaleX(1);
  transition: transform .25s linear;
}

/* Alles auf einer Beamerseite beginnt an derselben linken Kante, auch
 * die Frage. Gemessen hatte die Auflösung vier: Kacheln bei 204, der
 * Erklärkasten bei 275, der Fragetext bei 439, die Rangliste bei 490.
 * Aus zehn Metern liest sich das wie vier lose Zettel statt wie eine
 * Seite. Die Zeilenbreite bleibt begrenzt, nur die Zentrierung fällt weg. */
.qtext {
  font-size: clamp(24px, 3.2vw, 44px); font-weight: 800; line-height: 1.14;
  text-align: left; max-width: 26ch; margin: 0;
}

.answers { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; width: 100%; }
.answers.n2 { grid-template-columns: 1fr 1fr; }
.answers.n3, .answers.n5, .answers.n6 { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 760px) { .answers, .answers.n3, .answers.n5, .answers.n6 { grid-template-columns: 1fr; } }

.ans {
  --col: var(--a);
  position: relative; overflow: hidden;
  display: flex; align-items: center; gap: 14px;
  background: var(--col); color: #fff;
  border-radius: var(--radius); padding: 20px 22px; min-height: 76px;
  font-size: clamp(17px, 1.9vw, 23px); font-weight: 700;
  text-align: left; box-shadow: var(--schatten);
  transition: filter .2s ease, outline-color .2s ease;
}
/* Der Anteil der Stimmen als eigener Streifen am unteren Rand. Als
 * Aufhellung der ganzen Kachel sah es aus, als sei die Kachel halb
 * kaputt gerendert, statt nach einem Diagramm. */
.kachelfuell {
  position: absolute; inset: auto 0 0 0; height: 7px; width: 100%;
  background: rgba(255, 255, 255, .85);
  transform-origin: left center; transform: scaleX(0);
  transition: transform .4s cubic-bezier(.2, .7, .3, 1);
}
.ans > :not(.kachelfuell) { position: relative; }
.ans .sym {
  font-weight: 800; background: rgba(0, 0, 0, .24); border-radius: 9px;
  width: 44px; height: 44px; display: flex; align-items: center; justify-content: center;
  flex: 0 0 auto; font-size: 21px;
}
.kacheltext { flex: 1; }
.kachelzahl { margin-left: auto; font-size: 18px; opacity: .92; flex: 0 0 auto; }
.ans.blass { background: var(--blass); box-shadow: none; }   /* weisser Text: 7.56:1 */
.ans.blass .kachelfuell { background: rgba(255, 255, 255, .62); }
.ans.richtig { outline: 4px solid var(--ink); outline-offset: 4px; box-shadow: var(--schatten-tief); }
/* Ein Etikett statt nur einer Farbe. Wer rot und grün nicht
 * unterscheidet, liest trotzdem, welche Antwort stimmt. */
.ans.richtig::before {
  content: "Richtig";
  position: absolute; top: 0; right: 0; z-index: 1;
  /* Grund und Schrift kommen aus den Tokens und drehen sich mit der
   * Fassung um: hell ist --ink dunkel und --paper weiss, dunkel genau
   * andersherum. Fest weisser Text stand in der dunklen Fassung weiss auf
   * fast weiss. Gemeldet hat das kein Werkzeug, weil dieses Etikett nur in
   * der Auflösung erscheint und folien.mjs nur die Erklärseiten prüft. */
  background: var(--ink); color: var(--paper);
  font-family: var(--mono); font-size: 12px; font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase;
  padding: 5px 12px; border-bottom-left-radius: var(--radius-klein);
}

.quote { font-size: clamp(16px, 1.8vw, 22px); font-weight: 700; color: var(--mut); margin: 0; }
.quote.gut { color: var(--gut); }
.quote.schwach { color: var(--gefahr); }

.explain {
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius-klein);
  padding: 15px 20px; font-size: clamp(16px, 1.7vw, 21px);
  max-width: 70ch; margin: 0 auto; line-height: 1.45;
}
/* Am Beamer an der linken Kante, am Handy weiter mittig: dort ist die
 * Spalte so schmal, dass eine Kante keine Rolle spielt. */
.beamer .explain, .beamer #board { margin-left: 0; margin-right: 0; }

/* ---------- Rangliste ---------- */
.board { display: grid; gap: 8px; width: 100%; max-width: 620px; margin: 0 auto; }
.board .row {
  display: flex; align-items: center; gap: 14px;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius-klein);
  padding: 11px 18px; font-size: clamp(16px, 1.7vw, 21px);
}
.board .row {
  position: relative; overflow: hidden;
}
.board .row > * { position: relative; z-index: 1; }
.board .row .rank {
  font-family: var(--mono); font-weight: 800; color: var(--mut);
  width: 34px; flex: 0 0 auto; font-variant-numeric: tabular-nums;
}
.board .row .rname { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
.board .row .sc {
  margin-left: auto; font-family: var(--mono); font-weight: 800;
  color: var(--ink); flex: 0 0 auto; font-variant-numeric: tabular-nums;
}

/* Die ersten drei Plätze tragen ihre Farbe, das ist Status und keine Deko.
 * Gold, Silber, Bronze, gemischt aus dem jeweiligen Grund, damit sie in
 * beiden Fassungen tragen. */
.board .row.top1 {
  border-color: var(--mittel);
  background: color-mix(in srgb, var(--mittel) 13%, var(--paper));
}
.board .row.top1 .rank, .board .row.top1 .sc { color: var(--mittel); }
.board .row.top2 { border-color: color-mix(in srgb, var(--mut) 46%, var(--paper)); }
.board .row.top2 .rank { color: var(--mut); }
.board .row.top3 { border-color: color-mix(in srgb, var(--gefahr) 34%, var(--paper)); }
.board .row.top3 .rank { color: var(--gefahr); }

/* Die eigene Zeile am Handy. Der Akzent trägt sie, nicht eine eigene Farbe. */
.board .row.ich {
  border-color: var(--akzent);
  background: color-mix(in srgb, var(--akzent) 10%, var(--paper));
}
.board .row.ich .rname { font-weight: 800; }

/* Der Anteil am Punktestand des Führenden als Füllung hinter der Zeile.
 * Sie zeigt auf einen Blick, ob das Feld eng beieinander liegt oder
 * auseinandergeht, und macht aus einer Liste eine Rangfolge. */
.board .row .rfuell {
  position: absolute; inset: 0 auto 0 0; z-index: 0;
  background: color-mix(in srgb, var(--akzent) 12%, transparent);
  transform-origin: left center; transform: scaleX(var(--anteil, 0));
  transition: transform .5s cubic-bezier(.2, .7, .2, 1);
}
.board .row.top1 .rfuell { background: color-mix(in srgb, var(--mittel) 20%, transparent); }

/* ---------- Auswertung am Ende ---------- */
.endspalten { display: grid; grid-template-columns: 1fr 1fr; gap: 34px; align-items: start; width: 100%; }
/* Der Endstand ist der einzige Bildschirm, der lang werden kann.
 * Er beginnt deshalb oben, statt sich in der Mitte auszurichten. */
#ended, #info { justify-content: flex-start; }
#ended .auswertung { display: grid; gap: 10px; }
@media (max-width: 860px) { .endspalten { grid-template-columns: 1fr; } }
.spaltenkopf { margin-bottom: 12px; color: var(--mut); text-transform: uppercase; letter-spacing: .08em; font-family: var(--mono); font-size: 13px; }
.auswertung { display: grid; gap: 12px; }
.awrow { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius-klein); padding: 12px 16px; display: grid; gap: 8px; }
.awkopf { display: flex; align-items: baseline; gap: 10px; }
.awnr { color: var(--mut); font-size: 13px; flex: 0 0 auto; }
.awfrage { flex: 1; font-size: 15px; line-height: 1.35; }
.awproz { font-weight: 800; font-size: 17px; flex: 0 0 auto; white-space: nowrap; }
.awproz.gut, .awfuell.gut { color: var(--gut); }
.awproz.mittel, .awfuell.mittel { color: var(--mittel); }
.awproz.schwach, .awfuell.schwach { color: var(--gefahr); }
.awbalken { height: 7px; background: var(--line); border-radius: 999px; overflow: hidden; }
.awfuell {
  height: 100%; width: 100%; border-radius: 999px; background: currentColor;
  transform-origin: left center; transform: scaleX(0);
  transition: transform .5s ease;
}

/* ---------- Handy ---------- */
/* "safe center": mittig, solange der Inhalt passt, und oben angeschlagen,
 * sobald er überläuft. Mit "flex-start" allein klebte jeder kurze
 * Handybildschirm oben und liess die untere Hälfte leer, mit "center"
 * allein wäre bei einer langen Erklärseite der Anfang über den oberen
 * Rand hinausgeschoben und nicht mehr erreichbar. Die Deklaration davor
 * ist der Rückfall für Browser, die "safe" nicht kennen. */
.handy .stage { justify-content: flex-start; padding-top: 10px; }
.handy .stage { justify-content: safe center; }
.phone { max-width: 520px; margin: 0 auto; width: 100%; display: flex; flex-direction: column; gap: 15px; }
/* Bildschirme mit eigener Kopfzeile füllen die Bühne, damit die Kopfzeile
 * oben bleibt. Ohne das schwamm auf der Erklärseite auch "19 von 30"
 * mittig, mit einer handbreiten Lücke zur Kopfleiste darüber. Zentriert
 * wird nur der Inhalt darunter, genau wie am Beamer die Folie in ihrer
 * mittleren Rasterzeile. */
#answering, #pinfo { flex: 1; }
#pinfo .pfolie { flex: 1; justify-content: safe center; }
.phonekopf { display: flex; justify-content: space-between; align-items: center; gap: 12px; }
.uhrklein { font-weight: 800; font-size: 16px; color: var(--akzent); border-color: var(--akzent); }
.uhrklein.knapp { color: var(--gefahr); border-color: var(--gefahr); }

.pfrage { font-size: clamp(18px, 5vw, 23px); font-weight: 700; line-height: 1.28; text-align: center; margin: 4px 0; }

.pgrid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; flex: 1; align-content: stretch; }
.pgrid.eins { grid-template-columns: 1fr; }
@media (max-width: 420px) { .pgrid, .pgrid.drei { grid-template-columns: 1fr; } }

.pbtn {
  --col: var(--a);
  display: flex; align-items: center; gap: 12px;
  min-height: 84px; padding: 14px 16px;
  border: 3px solid transparent; border-radius: 18px;
  background: var(--col); color: #fff;
  font-weight: 700; font-size: 17px; text-align: left;
  cursor: pointer; box-shadow: var(--schatten);
  transition: transform .08s ease, opacity .2s ease;
  touch-action: manipulation;
}
.pbtn:active { transform: scale(.97); }
.pbtn:disabled { cursor: default; }
.pbtn:disabled:not(.gewaehlt) { opacity: .4; }
.pbtn.gewaehlt { border-color: var(--ink); transform: scale(.99); }
.psym {
  font-weight: 800; font-size: 22px; background: rgba(0, 0, 0, .24);
  border-radius: 9px; width: 46px; height: 46px; flex: 0 0 auto;
  display: flex; align-items: center; justify-content: center;
}
.ptext { flex: 1; line-height: 1.25; }

.status { font-size: clamp(24px, 7vw, 34px); font-weight: 800; padding: 18px 8px 4px; margin: 0; }
.status.gut { color: var(--gut); }
.status.schwach { color: var(--gefahr); }
/* Neutral, nicht blau. Hier stand die Antwortfarbe B, und die ist dafür
 * gerechnet, weissen Text zu TRAGEN, nicht selbst Text zu sein: Auf dem
 * dunklen Grund kam sie auf 2.31:1. Gefunden wurde es erst, als
 * durchspielen.mjs das Handy auch in der dunklen Fassung fotografierte.
 * "Antwort ist raus" ist ohnehin weder gut noch schlecht, sondern
 * erledigt, und genau das sagt die neutrale Farbe. */
.status.warte { color: var(--ink); }
.big-score { font-size: 44px; font-weight: 800; margin: 0; }

/* Zeigt, dass die Verbindung steht, ohne dass etwas zu tun wäre. */
.pulsring {
  width: 54px; height: 54px; margin: 20px auto 0; border-radius: 50%;
  border: 4px solid var(--line); border-top-color: var(--akzent);
  animation: drehen 1.4s linear infinite;
}
@keyframes drehen { to { transform: rotate(360deg); } }

/* ---------- Erklärseite am Beamer ----------
 *
 * Neun Formen, ein System. Die Regel, die alles andere bestimmt: Eine Folie
 * muss samt Weiter-Knopf in ein Beamerbild passen, ohne zu scrollen. Deshalb
 * hängen die Schriftgrößen hier an der Bildhöhe (vh) und nicht nur an der
 * Breite. Ein Beamer ist 16 zu 9 und oft nur 900 Punkte hoch: Was nach der
 * Breite bemessen ist, wird auf einem breiten Bild zu groß und schiebt den
 * Knopf hinaus. Genau das ist zweimal passiert.
 *
 * Kein seitlicher Farbbalken an einer Karte. Der Kartentitel trägt den
 * Akzent, klein und gesperrt, wie eine Beschriftung im Anatomieatlas.
 * Zahlen und Nummern stehen in der Monospace: Sie sind der Zug, der eine
 * Unterrichtsfolie medizinisch aussehen lässt und nicht dekorativ.
 */

.folie {
  display: flex; flex-direction: column; gap: clamp(10px, 1.7vh, 20px);
  width: 100%; min-width: 0;
}

/* Der Kopf einer Folie: Der Abschnittsname steht klein über dem Titel,
 * nicht rechts daneben. Alles beginnt an derselben linken Kante. Zentriert
 * sah jede Folie aus wie eine eigene kleine Website. */
/* Die alte Kopfzeile der Erklärseite entfällt: Zähler und Abschnittsname
 * stehen jetzt in der Kopfleiste beziehungsweise in der Folie selbst. */
#info .qmeta { display: none; }
.f-kicker {
  font-family: var(--mono); font-size: clamp(11px, 1.4vh, 14px); font-weight: 700;
  letter-spacing: .13em; text-transform: uppercase; color: var(--akzent);
  text-align: left; margin: 0 0 clamp(-4px, -0.4vh, -2px);
}

/* Kopf jeder Folie. Zentriert, weil eine Folie ohne rechte Hälfte
 * unfertig aussieht und der Blick von zehn Metern die Mitte sucht. */
/* Der Titel einer Erklärseite ist so gross wie eine Frage. Vorher war er
 * kleiner, und damit sah die Hälfte der Stunde aus wie das Vorprogramm
 * der anderen Hälfte. Aus zehn Metern trägt eine Überschrift die Folie,
 * und eine Erklärseite ist genauso Unterricht wie eine Abfrage.
 * Die Grenze bleibt dieselbe: Die Folie muss samt Weiter-Knopf ins
 * Beamerbild passen, gemessen von werkzeug/folien.mjs bei 1600 mal 900. */
.f-titel {
  font-size: clamp(28px, 5vh, 58px); font-weight: 800; line-height: 1.06;
  letter-spacing: -.03em; text-align: left; max-width: 24ch;
  margin: 0; text-wrap: balance;
}
.f-titel.gross { font-size: clamp(34px, 6.2vh, 72px); max-width: 18ch; }
.f-titel.frage { max-width: 22ch; }
.f-titel.mitte { max-width: 22ch; }

.f-lead {
  font-size: clamp(15px, 2.2vh, 24px); line-height: 1.38; color: var(--mut);
  max-width: 78ch; margin: 0; text-align: left; text-wrap: pretty;
}
.f-lead.mitte { max-width: 72ch; }

/* Die Leitfrage. Sie wird vorgelesen, also steht sie allein und bekommt
 * Luft nach unten. Zwei feine Linien statt Anführungszeichen: Die Zeichen
 * hätte der Beamer je nach Schrift anders gesetzt. */
.f-leitfrage { display: flex; flex-direction: column; gap: 8px; }

/* ---------- Karten ----------
 * Die Spaltenzahl richtet sich nach der Menge, nicht nach einem festen
 * Raster. Zwei Punkte nebeneinander, drei zu dritt, ab vier zu zweit auf
 * zwei Reihen: So bleibt jede Karte lesbar, statt bei sechs Punkten auf
 * Streifen zusammenzuschrumpfen. */
.f-raster {
  display: grid; gap: clamp(8px, 1.3vh, 15px);
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  width: 100%;
}
.f-raster.ziele { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }

/* Die Spaltenzahl folgt der Kartenzahl, nicht dem verfügbaren Platz. Sonst
 * legt "auto-fit" vier Karten als drei plus eine allein darunter um, und
 * fünf als drei plus zwei versetzt. Beides sieht aus wie ein Fehler.
 *
 * Drei Karten nebeneinander sind laut Gestaltungsregel sonst verboten. Hier
 * bleiben sie: Es sind keine drei austauschbaren Merkmalskacheln, sondern
 * die Kernpunkte eines Unterrichtsgesprächs in der Zahl, die der Stoff
 * vorgibt. Die Abweichung steht in DESIGN.md. */
.f-raster.n1 { grid-template-columns: minmax(0, 620px); justify-content: center; }
.f-raster.n2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.f-raster.n3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.f-raster.n4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.f-raster.n5,
.f-raster.n6 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 900px) {
  .f-raster.n2, .f-raster.n3, .f-raster.n4, .f-raster.n5, .f-raster.n6 {
    grid-template-columns: 1fr;
  }
}
.f-raster.schmal { max-width: 760px; margin: 0 auto; }
.f-raster.sop { grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); }

.f-karte {
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius-klein);
  padding: clamp(9px, 1.35vh, 15px) clamp(12px, 1.3vw, 17px);
  display: flex; flex-direction: column; gap: 4px; min-width: 0;
}
.f-karte-titel {
  margin: 0; font-size: clamp(11px, 1.5vh, 14px); font-weight: 700;
  letter-spacing: .07em; text-transform: uppercase; color: var(--akzent);
}
.f-karte-text {
  margin: 0; font-size: clamp(13px, 1.85vh, 19px); line-height: 1.33;
  overflow-wrap: anywhere;
}
/* Bild auf einer Karte. "contain" auf weissem Grund, nicht "cover": Ein
 * beschnittenes Anatomiebild zeigt am Ende genau die Stelle nicht mehr,
 * um die es geht. Der weisse Grund gehört zum Bild und ist in beiden
 * Fassungen derselbe, wie bei jeder Abbildung im Projekt. */
.f-karte.mitbild { padding-top: clamp(7px, 1vh, 11px); }
/* Trägt eine Karte ein Bild, gehört Urheber und Lizenz darunter. Eine
 * Karte hat keine eigene Bildunterschrift, deshalb sammelt eine Zeile
 * unter dem Raster, was die Karten mitbringen. */
.f-rasterblock { display: flex; flex-direction: column; gap: clamp(5px, .8vh, 9px); width: 100%; }
.f-kartenquellen {
  margin: 0; text-align: center; color: var(--mut);
  font-size: clamp(9px, 1.25vh, 12px); line-height: 1.3;
}
.pf-kartenquellen { margin: 8px 0 0; color: var(--mut); font-size: 11px; line-height: 1.35; }
/* Ohne grosses Bild daneben haben die Kartenbilder mehr Platz. Aus der
 * letzten Reihe zählt jeder Punkt Höhe. */
.f-raster.gross .f-karte-bild { height: clamp(76px, 13vh, 150px); }
/* Vier bebilderte Karten stehen in einer Reihe, nicht als 2x2. Zwei Reihen
 * mit je einem Bild darüber standen 86 px aus dem Beamerbild, gemessen mit
 * werkzeug/folien.mjs. In einer Reihe trägt jede Karte ihr Bild und die
 * Folie bleibt drin. */
.f-raster.gross.n4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 1100px) { .f-raster.gross.n4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.f-karte-bild {
  width: 100%; height: clamp(58px, 9.5vh, 112px); object-fit: contain;
  background: #FFFFFF; border-radius: calc(var(--radius-klein) - 3px);
  border: 1px solid var(--line); margin-bottom: 3px;
}

/* Die Lernziele der Titelfolie werden gezählt, das gibt der Stunde einen
 * Anfang. Die Nummer kommt aus dem Zähler, nicht aus dem Inhalt. */
.f-raster.ziele { counter-reset: ziel; }
.f-raster.ziele .f-karte { counter-increment: ziel; }
.f-raster.ziele .f-karte-titel::before {
  content: counter(ziel, decimal-leading-zero) " · ";
  font-family: var(--mono); letter-spacing: 0;
}
/* Ein erledigtes Lernziel. Der grüne Haken sagt aus zehn Metern, was die
 * Stunde schon abgearbeitet hat. Grün ist hier Status (geschafft), keine
 * Deko, und darf deshalb neben den einen Akzent treten, wie "Richtig". Die
 * getönte Fläche wird gemischt, nicht als Hellwert hingeschrieben, sonst
 * bliebe sie in der dunklen Fassung falsch stehen. */
.f-raster.ziele .f-karte { position: relative; }
.f-karte.erledigt {
  border-color: color-mix(in srgb, var(--gut) 40%, var(--line));
  background: var(--panel);
  background: color-mix(in srgb, var(--gut) 11%, var(--panel));
}
.f-karte.erledigt .f-karte-titel { color: var(--gut); }
.f-ziel-haken {
  position: absolute; top: clamp(8px, 1.1vh, 13px); right: clamp(10px, .9vw, 15px);
  width: clamp(20px, 2.5vh, 26px); height: clamp(20px, 2.5vh, 26px);
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--gut); color: var(--paper); border-radius: 50%;
  font-size: clamp(12px, 1.6vh, 16px); font-weight: 700; line-height: 1;
}

/* ---------- Kette ----------
 * Ein Weg mit Stationen. Die Pfeile sind Deko und aria-hidden, sonst liest
 * ein Screenreader zwischen jeder Station "Rechtspfeil" vor. */
.f-kette {
  display: flex; flex-wrap: wrap; align-items: stretch;
  justify-content: center; gap: clamp(5px, .8vh, 9px);
  margin: 0; padding: 0; list-style: none;
  counter-reset: station;
}
/* Eine zugedeckte Station behält ihre Nummer. Ohne sie standen auf der
 * Folie elf leere Kapseln mit Pfeilen dazwischen, und das sah nicht nach
 * "gleich kommt hier etwas" aus, sondern nach einem Ladefehler. Die
 * Nummer sagt: der Platz ist vergeben, der Name kommt gleich.
 *
 * Nur die waagerechte Kette braucht das. Die senkrechte trägt ihre Nummer
 * ohnehin in einem eigenen ::before, und dort stand die Nummer dadurch
 * kurzzeitig zweimal: einmal richtig und einmal als "00", weil
 * "counter-increment" nur einmal gesetzt werden kann und die
 * stapel-Regel den zweiten Zähler still überschrieb. */
.f-kette:not(.stapel) > .f-station { counter-increment: station; }
.markengefuehrt .f-kette:not(.stapel) > .f-station[data-nr]:not(.auf) .f-station-name::before {
  content: counter(station, decimal-leading-zero);
  visibility: visible; color: var(--akzent); font-family: var(--mono);
}
.f-station {
  display: flex; flex-direction: column; gap: 2px; justify-content: center;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: 999px; padding: clamp(7px, 1.1vh, 12px) clamp(13px, 1.3vw, 20px);
  text-align: center; min-width: 0;
}
.f-station-name {
  font-weight: 700; font-size: clamp(13px, 1.95vh, 20px); line-height: 1.15;
}
.f-station-zusatz {
  font-family: var(--mono); font-size: clamp(10px, 1.35vh, 13px);
  color: var(--mut); line-height: 1.2;
}
.f-pfeil {
  align-self: center; color: var(--akzent);
  font-size: clamp(14px, 2vh, 21px); line-height: 1;
}
/* Ein Pfeil am Ende einer umbrechenden Zeile zeigt nach rechts ins Leere,
 * während es links unten weitergeht. Welcher Pfeil das trifft, weiss erst
 * der fertige Umbruch, deshalb setzt JS diese Klasse nach dem Zeichnen. */
.f-pfeil.am-rand { visibility: hidden; }

/* ---------- Bild mit Aufdeckkarten ---------- */
/* Das Bild bekommt die größere Spalte. Eine Abbildung, die aus zehn Metern
 * gelesen werden soll, verträgt keine Halbierung, und die Karten daneben
 * tragen kurze Fragen. */
.f-bildspalten {
  display: grid; grid-template-columns: minmax(0, 1.32fr) minmax(0, 1fr);
  gap: clamp(14px, 1.9vw, 28px); align-items: start; width: 100%;
}
/* Ohne Karten daneben steht das Bild allein und darf hoch sein. Die Breite
 * wird trotzdem begrenzt, sonst zieht ein Querformat die Zeilen der
 * Bildunterschrift auf die volle Bühne. */
.f-bildspalten.nurbild {
  grid-template-columns: minmax(0, 1fr); justify-items: center;
}
/* Eine Folie, die nur aus einer Abbildung besteht, gibt ihr allen Platz,
 * den der Kopf übrig lässt. Ein EKG-Streifen, dessen Ableitungen man nicht
 * mehr lesen kann, ist keine Abbildung mehr, sondern Dekoration. */
.f-bildspalten.nurbild .f-figur { max-width: 100%; }
.f-bildspalten.nurbild .f-bild { max-height: 55vh; }
.f-bildspalten.nurbild ~ .f-fuss { margin-top: 0; }
.art-bild .f-titel { max-width: 30ch; }

/* Bild neben dem Inhalt bei den Formen ohne eigenen Bildplatz. Der Inhalt
 * steht links, die Abbildung rechts, beide senkrecht mittig. Die Höhe ist
 * knapper als bei der reinen Bildfolie, weil über dem Bild noch Titel und
 * Lead stehen und der Weiter-Knopf ins Beamerbild passen muss. Die genauen
 * Grenzen sind mit werkzeug/folien.mjs gemessen, nicht geschätzt. */
.f-mitbild {
  display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, .92fr);
  gap: clamp(16px, 2.4vw, 36px); align-items: center; width: 100%;
}
.f-mitbildtext { display: flex; flex-direction: column; gap: clamp(9px, 1.6vh, 18px); min-width: 0; }
.f-mitbild > .f-figur { align-self: center; }
.art-titel .f-mitbild .f-bild { max-height: 48vh; }
.art-gespraech .f-mitbild .f-bild { max-height: 28.5vh; }
.art-einsatz .f-bild.einsatzbild { max-height: 16vh; align-self: flex-start; }
@media (max-width: 900px) {
  .f-mitbild { grid-template-columns: 1fr; }
}

/* Kette mit Abbildung: Bild links, der Weg daneben. */
.f-kettenspalten {
  display: grid; grid-template-columns: minmax(0, .78fr) minmax(0, 1.22fr);
  gap: clamp(16px, 2.2vw, 32px); align-items: start; width: 100%;
}
.f-kettentext { display: flex; flex-direction: column; gap: clamp(9px, 1.4vh, 16px); min-width: 0; }
.f-kettentext .f-lead.links { text-align: left; margin: 0; max-width: none; }
.f-bild.hoch { max-height: 46vh; }

/* Neben einem Bild wird aus der Kette eine Liste. Pfeile nach rechts
 * ergeben dort keinen Sinn mehr, die Reihenfolge trägt die Nummer. */
.f-kette.stapel {
  flex-direction: column; align-items: stretch; justify-content: flex-start;
  gap: clamp(4px, .7vh, 7px); counter-reset: station;
}
.f-kette.stapel .f-station {
  flex-direction: row; align-items: baseline; gap: 9px;
  border-radius: var(--radius-klein); text-align: left;
  padding: clamp(5px, .85vh, 9px) clamp(11px, 1.1vw, 15px);
  counter-increment: station;
}
.f-kette.stapel .f-station::before {
  content: counter(station, decimal-leading-zero);
  font-family: var(--mono); font-weight: 700; color: var(--akzent);
  font-size: clamp(11px, 1.5vh, 14px); flex: 0 0 auto;
}
.f-kette.stapel .f-station-zusatz { margin-left: auto; text-align: right; }
.f-kette.stapel .f-pfeil { display: none; }
.f-figur { margin: 0; display: flex; flex-direction: column; gap: 8px; min-width: 0; }
/* Breite auto, nicht 100 Prozent: Der weisse Rahmen gehört zum Bild und
 * soll so breit sein wie das Bild. Bei "width: 100%" spannte er sich über
 * die ganze Spalte, und ein hochformatiges Röntgenbild sass in einer
 * leeren weissen Fläche. */
.f-bild {
  width: auto; max-width: 100%; max-height: 49.5vh; object-fit: contain;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 10px;
}
.f-figur { align-items: center; }
.f-bild.rechts { max-height: 42vh; }
.f-bildunter {
  font-size: clamp(11px, 1.5vh, 14px); color: var(--mut); text-align: center;
  line-height: 1.3;
}

/* ---------- Marken auf dem Bild ----------
 *
 * Die Fläche ist genau so gross wie das Bild, sonst zeigen die
 * Prozentkoordinaten daneben. Deshalb "inline-block" und kein Block: der
 * Kasten schrumpft auf das Bild, statt die Spalte auszufüllen. Dasselbe
 * Argument wie beim weissen Rahmen eine Regel weiter oben. */
.f-bildflaeche { position: relative; display: inline-block; line-height: 0; max-width: 100%; }
.f-bildflaeche > .f-bild { display: block; }
/* Ein Bild mit Marken darf höher sein als eines ohne. Auf ihm wird
 * getippt, und ein Punkt von 30 Punkten auf einem 430 Punkte breiten Bild
 * ist am Touchmonitor kein Ziel. Die Grenze ist gemessen, nicht geschätzt:
 * werkzeug/folien.mjs meldet jede Folie, die aus dem Beamerbild ragt. */
.f-bildflaeche.hatmarken > .f-bild { max-height: 53vh; }
/* Traegt ein Bild zugleich Marken und Aufdeckkarten daneben, fehlt die
 * Hoehe, die ein Bild mit Marken sonst haben darf: neben den Karten muss
 * der Bild-mit-Zaehler-Stapel in dieselbe Hoehe wie die Karten passen.
 * Deshalb hier zurueck auf die Kartengrenze. Gemessen mit folien.mjs, sonst
 * ragt die Folie 18 px aus dem Beamerbild. */
.f-bildspalten:not(.nurbild) .f-bildflaeche.hatmarken > .f-bild { max-height: 49.5vh; }

.f-marke {
  position: absolute; transform: translate(-50%, -50%);
  display: flex; align-items: center; gap: 10px;
  background: none; border: 0; padding: 0; cursor: pointer;
  line-height: 1; z-index: 2;
}
/* Der Punkt sitzt auf dem Bild und ist die Tippfläche. 44 px, wie überall,
 * denn am Touchmonitor tippt der Dozent mit dem Finger. Sichtbar ist er
 * kleiner: die Fläche liegt aussen herum. */
.f-marke-punkt {
  display: flex; align-items: center; justify-content: center;
  width: clamp(30px, 3.4vh, 40px); height: clamp(30px, 3.4vh, 40px);
  border-radius: 999px; flex: 0 0 auto;
  background: var(--marke); color: var(--auf-marke);
  font-weight: 700; font-size: clamp(14px, 1.8vh, 19px);
  box-shadow: 0 0 0 3px rgba(255, 255, 255, .92), 0 2px 8px rgba(0, 0, 0, .28);
  transition: transform .18s ease;
}
.f-marke::before {
  /* Unsichtbare Tippfläche um den Punkt herum, damit die 44 px stehen,
   * ohne dass der Punkt auf dem Bild so gross werden muss. */
  content: ''; position: absolute; left: 50%; top: 50%;
  width: 44px; height: 44px; transform: translate(-50%, -50%);
}
.f-marke:hover .f-marke-punkt { transform: scale(1.12); }

/* Auf dem Bild steht nur die Nummer, nie ein Name.
 *
 * Ein Schild am Punkt war die erste Fassung. Sie ist an der Geometrie
 * gescheitert: Auf der Herzanatomie liegen acht Marken auf gut 430 Punkten
 * Bildbreite, ein Schild misst rund 200, und werkzeug/schilder.mjs hat
 * gemessen, dass 13 von 16 Schildern eine andere Marke verdecken. Auf
 * keiner der vier Seiten ist Platz, also hilft auch kein Ausweichen. Eine
 * verdeckte Marke ist für die Klasse nicht da: Sie sucht dann eine Zahl,
 * die auf dem Bild nicht zu finden ist. Die Namen stehen jetzt in der
 * Liste daneben (.markenliste), verbunden über dieselbe Nummer.
 *
 * Eine aufgedeckte Marke bleibt markiert, sonst weiss niemand mehr,
 * welche Punkte schon dran waren. Die zuletzt aufgedeckte trägt zusätzlich
 * den vollen Ring: Sie sagt, von welchem Punkt gerade die Rede ist. */
.f-marke.auf .f-marke-punkt {
  box-shadow: 0 0 0 3px rgba(255, 255, 255, .92), 0 0 0 6px var(--marke), 0 2px 8px rgba(0, 0, 0, .28);
}
.f-marke.zuletzt { z-index: 3; }
.f-marke.zuletzt .f-marke-punkt {
  transform: scale(1.18);
  box-shadow: 0 0 0 4px rgba(255, 255, 255, .96), 0 0 0 9px var(--marke), 0 3px 12px rgba(0, 0, 0, .34);
}
@keyframes markeAuf { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }

/* Rechts neben dem Bild stehen Aufdeckkarten und Namensliste untereinander.
 * Auf der Anatomiefolie sind es vier Karten und acht Namen, und beide
 * zusammen müssen in dieselbe Höhe passen wie das Bild links. */
.f-bildneben {
  display: flex; flex-direction: column; gap: clamp(9px, 1.4vh, 16px); min-width: 0;
}
/* Ohne Aufdeckkarten steht rechts nur die Namensliste. Oben angeschlagen
 * sah sie neben einem hohen Bild verloren aus, also sitzt sie mittig auf
 * Bildhöhe und nimmt nur die Breite, die ihre Namen brauchen. */
.f-bildneben.nurliste { justify-content: center; height: 100%; align-items: stretch; }
/* Stehen Aufdeckkarten und Namensliste in derselben Spalte, wird es eng:
 * vier Karten und acht Namen neben einem Bild in voller Höhe. Die Karten
 * geben nach, nicht das Bild, denn ein kleineres Bild lässt seine eigenen
 * Punkte überlappen (gemessen mit schilder.mjs). */
.f-bildneben:has(.markenliste) .f-deck { padding: clamp(6px, .95vh, 11px) clamp(11px, 1.1vw, 15px); }
.f-bildneben:has(.markenliste) .f-deck-frage { font-size: clamp(12px, 1.7vh, 17px); }
.f-bildneben:has(.markenliste) .f-deck-antwort { font-size: clamp(11px, 1.55vh, 16px); }
/* Ab fünf Karten zweispaltig, und die Kartenspalte bekommt mehr Breite:
 * sechs aufgeklappte Karten untereinander standen 170 px aus dem Bild. */
.f-bildspalten.vielekarten { grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr); }
.f-bildspalten.vielekarten .f-decks {
  display: grid; grid-template-columns: 1fr 1fr; align-content: start;
  gap: clamp(6px, 1vh, 10px);
}
@media (max-width: 1100px) {
  .f-bildspalten.vielekarten .f-decks { grid-template-columns: 1fr; }
}
.f-bildneben.nurliste .markenliste { max-width: 26ch; width: 100%; align-self: center; }
/* Ohne Karten bekommt das Bild mehr von der Breite. Höher darf es trotzdem
 * nicht werden: bei 53vh stand das hochformatige Röntgenbild 18 px aus dem
 * Beamerbild, gemessen mit werkzeug/folien.mjs. */
.f-bildspalten.mitliste { grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr); align-items: stretch; }

/* Die Namen der Marken. Aufgebaut wie eine Kette im Stapel, weil es
 * dieselbe Sache ist: eine nummerierte Liste, die sich Zeile für Zeile
 * aufdeckt. Sie erbt damit auch die Aufdeckregel von .markengefuehrt. */
.f-kette.stapel.markenliste { align-self: stretch; }
/* Ab fünf Namen zweispaltig. Acht Zeilen unter vier Aufdeckkarten schoben
 * die Folie sonst aus dem Beamerbild, gemessen mit werkzeug/folien.mjs. */
.f-kette.stapel.markenliste.eng {
  display: grid; grid-template-columns: 1fr 1fr;
  column-gap: clamp(5px, .7vw, 9px); row-gap: clamp(2px, .35vh, 4px);
}
/* Im engen Raster steht die Nummer neben dem Namen und der Zusatz darunter,
 * genau wie in der Liste am Handy. Die Nummer in eine eigene Zeile zu setzen
 * kostete je Reihe 18 px, und damit stand die Folie 48 px zu hoch im
 * Beamerbild. Gemessen mit werkzeug/folien.mjs. */
.f-kette.stapel.markenliste.eng .f-station {
  display: grid; grid-template-columns: auto minmax(0, 1fr);
  align-items: baseline; column-gap: 7px; row-gap: 0;
  padding: clamp(2px, .38vh, 5px) clamp(8px, .8vw, 11px);
}
.f-kette.stapel.markenliste.eng .f-station-name,
.f-kette.stapel.markenliste.eng .f-station-zusatz { grid-column: 2; }
.f-kette.stapel.markenliste.eng .f-station-zusatz { margin-left: 0; text-align: left; }

.f-markenzaehler {
  font-size: clamp(11px, 1.5vh, 14px); color: var(--mut); text-align: center; margin: 0;
}
.f-markenzaehler.fertig { color: var(--gut); }

/* Führen die Marken durch die Liste daneben, startet sie zugedeckt: Sonst
 * steht die Antwort schon da, während die Klasse den Punkt auf dem Bild
 * noch sucht. Der Platz bleibt stehen, damit beim Aufdecken nichts springt. */
.markengefuehrt .f-station[data-nr]:not(.auf) .f-station-name,
.markengefuehrt .f-station[data-nr]:not(.auf) .f-station-zusatz { visibility: hidden; }
.markengefuehrt .f-station[data-nr] { transition: border-color .2s ease, background-color .2s ease; }
.markengefuehrt .f-station[data-nr].auf {
  border-color: color-mix(in srgb, var(--akzent) 45%, var(--line));
  background: color-mix(in srgb, var(--akzent) 7%, var(--panel));
}

.f-decks { display: flex; flex-direction: column; gap: clamp(5px, .85vh, 9px); min-width: 0; }

/* Eine Karte, die erst auf Klick antwortet. Der Sinn ist didaktisch: Die
 * Klasse soll erst selbst denken. Geschlossen liegt die Antwort auf null
 * Deckkraft und ist aus dem Fluss genommen, damit die geschlossene Karte
 * nicht die Höhe der offenen beansprucht. */
.f-deck {
  position: relative; text-align: left; width: 100%;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius-klein);
  padding: clamp(8px, 1.2vh, 13px) 56px clamp(8px, 1.2vh, 13px) clamp(12px, 1.2vw, 16px);
  cursor: pointer; display: flex; flex-direction: column; gap: 5px;
  transition: border-color .18s ease, box-shadow .18s ease;
}
.f-deck:hover { border-color: var(--akzent); }
.f-deck.offen { border-color: var(--akzent); box-shadow: var(--schatten); }
.f-deck-frage {
  margin: 0; font-weight: 700; font-size: clamp(13px, 1.9vh, 19px);
  line-height: 1.28; overflow-wrap: anywhere;
}
.f-deck-antwort {
  margin: 0; font-size: clamp(12px, 1.8vh, 18px); line-height: 1.34;
  color: var(--mut); overflow-wrap: anywhere;
  display: none; opacity: 0; transform: translateY(-3px);
  transition: opacity .2s ease, transform .2s ease;
}
.f-deck.offen .f-deck-antwort { display: block; opacity: 1; transform: none; }
/* Der Hinweis war ein Wort und stand rechts neben dem Fragetext. Bei einer
 * Frage über zwei Zeilen liefen beide ineinander. Jetzt ist es ein Zeichen
 * in fester Breite, und die Karte hält den Platz dafür frei. */
.f-deck-hinweis {
  position: absolute; top: 50%; right: 12px; transform: translateY(-50%);
  width: 32px; height: 32px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  border: 1.5px solid var(--line); color: var(--akzent);
  font-family: var(--mono); font-size: 19px; font-weight: 700; line-height: 1;
}
.f-deck.offen .f-deck-hinweis { color: var(--mut); border-color: var(--line); }

/* ---------- Formel ----------
 * Die Gleichung ist die Aussage der Folie, also bekommt sie die Größe einer
 * Überschrift und die Schrift der Zahlen. */
.f-formel {
  margin: 0; text-align: center; font-family: var(--mono);
  font-size: clamp(19px, 3.5vh, 40px); font-weight: 700; letter-spacing: -.01em;
  color: var(--akzent); line-height: 1.2;
  padding: clamp(10px, 1.6vh, 18px) 16px;
  border-top: 2px solid var(--akzent); border-bottom: 2px solid var(--akzent);
  overflow-wrap: anywhere;
}

/* ---------- Einsatz ----------
 * Links die Lage, rechts die Reihenfolge. Die Werte stehen als Chips in der
 * Monospace, weil sie vom Monitor kommen und untereinander vergleichbar
 * bleiben sollen. */
.f-einsatzspalten {
  display: grid; grid-template-columns: minmax(0, .92fr) minmax(0, 1.08fr);
  gap: clamp(16px, 2.2vw, 34px); align-items: start; width: 100%;
}
.f-lage { display: flex; flex-direction: column; gap: clamp(9px, 1.3vh, 15px); min-width: 0; }
.f-lage .f-lead { text-align: left; margin: 0; max-width: none; color: var(--ink); }

.f-werte { display: flex; flex-wrap: wrap; gap: clamp(7px, 1.1vh, 11px); }
.f-wert {
  display: flex; flex-direction: column; gap: 1px;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius-klein);
  padding: clamp(7px, 1.1vh, 11px) clamp(11px, 1.1vw, 16px); min-width: 0;
}
.f-wert-name {
  font-size: clamp(10px, 1.3vh, 12px); font-weight: 700; letter-spacing: .07em;
  text-transform: uppercase; color: var(--akzent);
}
.f-wert-zahl {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: clamp(15px, 2.3vh, 24px); font-weight: 700; line-height: 1.15;
}
/* Ein ganzer Satz statt eines Messwerts: normale Schrift, und der Chip darf
 * die Zeile für sich nehmen. In der Monospace las er sich wie ein Ausdruck
 * aus dem Drucker. */
.f-wert.breit { flex: 1 1 100%; }
.f-wert-satz { font-size: clamp(13px, 1.85vh, 19px); line-height: 1.33; overflow-wrap: anywhere; }

.f-schritte {
  display: flex; flex-direction: column; gap: clamp(6px, 1vh, 10px);
  margin: 0; padding: 0; list-style: none; min-width: 0;
}
.f-schritt {
  display: flex; gap: clamp(9px, 1vw, 14px); align-items: baseline;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius-klein);
  padding: clamp(7px, 1.05vh, 11px) clamp(11px, 1.15vw, 15px); min-width: 0;
}
.f-schritt-nr {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: clamp(13px, 1.9vh, 19px); font-weight: 700; color: var(--akzent);
  flex: 0 0 auto;
}
.f-schritt-inhalt { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.f-schritt-titel { margin: 0; font-weight: 700; font-size: clamp(13px, 1.8vh, 18px); line-height: 1.25; }
.f-schritt-text { margin: 0; font-size: clamp(12px, 1.6vh, 16px); line-height: 1.3; color: var(--mut); overflow-wrap: anywhere; }

/* ---------- Merksätze ----------
 * Zwei Spalten zu je drei Sätzen, gross, mit feinen Linien dazwischen und
 * ohne Kästen. Eine Spalte über die ganze Bühne wäre zu lang zum Lesen,
 * eine schmale Spalte in der Mitte stünde nicht an derselben linken Kante
 * wie der Titel darüber. */
.f-merk {
  display: grid; grid-auto-flow: column;
  grid-template-columns: 1fr 1fr; grid-template-rows: repeat(3, auto);
  column-gap: clamp(26px, 3.4vw, 62px); row-gap: 0;
  margin: 0; padding: 0; list-style: none; width: 100%;
}
/* Spaltenweise, nicht zeilenweise: 01 bis 03 links, 04 bis 06 rechts. Wer
 * eine Liste liest, liest sie von oben nach unten. */
@media (max-width: 900px) { .f-merk { grid-auto-flow: row; grid-template-columns: 1fr; grid-template-rows: none; } }
/* Kein Kasten, nur eine feine Linie zwischen zwei Sätzen. Sechs graue
 * Kästen in zwei Reihen waren die schwächste Folie der Stunde (Lenny,
 * 29.08.2026): Sie sahen aus wie eine Tabelle und lasen sich aus zehn
 * Metern nicht. Ein Merksatz ist keine Zelle. */
.f-merk-satz {
  display: flex; gap: clamp(14px, 1.5vw, 22px); align-items: baseline;
  padding: clamp(7px, 1.5vh, 18px) 0; min-width: 0;
  border-top: 1px solid var(--line);
}
/* Oben in jeder Spalte keine Linie: sie hätte nichts, wovon sie trennt. */
.f-merk-satz:nth-child(3n + 1) { border-top: 0; padding-top: 0; }
@media (max-width: 900px) {
  .f-merk-satz { border-top: 1px solid var(--line); padding-top: clamp(7px, 1.15vh, 15px); }
  .f-merk-satz:first-child { border-top: 0; padding-top: 0; }
}
/* Die Nummer ist gross, weil sie zählt: sechs Sätze, und die Klasse soll
 * beim Wiederholen wissen, wie viele es waren. */
.f-merk-nr {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: clamp(18px, 3.1vh, 34px); font-weight: 700; color: var(--akzent);
  flex: 0 0 auto; line-height: 1.05;
}
.f-merk-text {
  margin: 0; font-size: clamp(15px, 2.8vh, 30px); line-height: 1.28;
  overflow-wrap: anywhere; font-weight: 500;
}

/* ---------- Abschluss ----------
 * Ein Satz, sonst nichts. Wer hier noch Stichpunkte unterbringt, hat den
 * Zweck der Folie verfehlt. */
.f-schluss {
  font-size: clamp(18px, 3.1vh, 34px); line-height: 1.32; text-align: left;
  max-width: 42ch; margin: 0; text-wrap: pretty;
}

/* ---------- Fußzeile der Folie ---------- */
.f-fuss {
  margin: 0; text-align: left; font-size: clamp(12px, 1.7vh, 17px);
  color: var(--mut); line-height: 1.35; max-width: 86ch; text-wrap: pretty;
}

/* ---------- Schlichte Erklärseite ----------
 * Das Verhalten der ersten Fassung, für Quizdateien ohne Formangabe. */
.f-schlichtspalten {
  display: grid; grid-template-columns: 1fr 1fr; gap: clamp(18px, 2.4vw, 36px);
  align-items: center; width: 100%;
}
.f-schlichtspalten.einspaltig { grid-template-columns: 1fr; max-width: 62ch; margin: 0 auto; }
.f-textteil { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.f-textteil .f-lead { text-align: left; margin: 0; max-width: none; color: var(--ink); }
.f-liste { display: flex; flex-direction: column; gap: 10px; margin: 0; padding: 0; list-style: none; }
.f-liste li {
  font-size: clamp(14px, 2vh, 21px); line-height: 1.3;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius-klein); padding: 10px 15px; overflow-wrap: anywhere;
}

/* Schmale Bildschirme: alles untereinander. Das gilt für die Vorschau am
 * Rechner, nicht für den Beamer. */
@media (max-width: 900px) {
  .f-bildspalten, .f-einsatzspalten, .f-schlichtspalten,
  .f-kettenspalten { grid-template-columns: 1fr; }
  .f-bild, .f-bild.hoch { max-height: 34vh; }
}


/* ---------- Erklärseite am Handy ----------
 * Die kurze Fassung dessen, was vorne steht. Sie wird gelesen, nicht
 * bedient: keine Tippflächen, deshalb auch keine 44-Punkte-Regel. Der
 * Inhalt darf hier scrollen, anders als am Beamer. Das Bild bekommt eine
 * Höhengrenze, sonst schiebt es alles andere unter den Rand. */
.pfolie { display: flex; flex-direction: column; gap: 13px; width: 100%; min-width: 0; }
/* Der Abschnittsname stand in der Kopfpille und wurde dort abgeschnitten
 * ("Anatomie · Bild …"). Über dem Titel hat er die ganze Breite. */
.pf-kicker {
  margin: 0 0 -7px; font-size: 12px; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--akzent); line-height: 1.3;
}
.pf-titel {
  font-size: clamp(19px, 5.4vw, 25px); font-weight: 800; line-height: 1.2;
  letter-spacing: -.018em; margin: 0; text-wrap: balance;
}
.pf-text { margin: 0; font-size: 16px; line-height: 1.45; color: var(--mut); }
.pf-bild {
  width: 100%; max-height: 42vh; object-fit: contain;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 8px;
}
.pf-bildunter { margin: 0; font-size: 12px; color: var(--mut); text-align: center; line-height: 1.3; }

/* ---------- Marken am Handy ----------
 *
 * Auf dem Bild stehen nur die Nummern, aufgedeckt werden sie vorne. Die
 * Namen darunter tragen den gleichen Stand: aufgedeckt oder zugedeckt.
 * Der Platz einer zugedeckten Zeile bleibt stehen, damit die Liste beim
 * Aufdecken nicht springt und niemand mitten im Lesen die Zeile verliert. */
.pf-bildflaeche { position: relative; display: block; line-height: 0; }
.pf-bildflaeche.hatmarken { display: inline-block; max-width: 100%; align-self: center; }
.pf-marke {
  position: absolute; transform: translate(-50%, -50%);
  display: flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; border-radius: 999px;
  background: var(--marke); color: var(--auf-marke);
  font-weight: 700; font-size: 13px; line-height: 1;
  box-shadow: 0 0 0 2px rgba(255, 255, 255, .92), 0 1px 4px rgba(0, 0, 0, .3);
}
.pf-marken {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-direction: column; gap: 6px;
}
.pf-markenzeile {
  display: grid; grid-template-columns: 26px 1fr; gap: 2px 10px;
  align-items: baseline;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius-klein); padding: 9px 12px;
  min-height: 44px;
}
.pf-markennr { color: var(--akzent-tief); font-weight: 700; font-size: 14px; }
.pf-markenname, .pf-markenzusatz { grid-column: 2; }
.pf-markenname { font-weight: 700; font-size: 15px; }
.pf-markenzusatz { color: var(--mut); font-size: 13px; line-height: 1.35; }
/* Zugedeckt: der Text wird ausgeblendet, nicht gelöscht. Deshalb
 * visibility und nicht display, sonst fällt die Zeilenhöhe zusammen und
 * die Liste springt beim Aufdecken. Die Nummer bleibt sichtbar, damit man
 * am Bild abzählen kann, was noch kommt. */
.pf-markenzeile:not(.auf) .pf-markenname,
.pf-markenzeile:not(.auf) .pf-markenzusatz { visibility: hidden; }
.pf-markenzeile:not(.auf)::after {
  content: 'noch zugedeckt'; grid-column: 2; grid-row: 1;
  color: var(--mut); font-size: 13px; font-style: normal;
}
.pf-markenzeile.auf { border-color: color-mix(in srgb, var(--akzent) 40%, var(--line)); }
/* Die Punkte auf dem Bild bleiben in voller Farbe, auch solange sie
 * zugedeckt sind. Ein Abblenden über Deckkraft würde die weisse Ziffer
 * mit dem Bildgrund mischen und unter AA drücken, ohne dass eine
 * CSS-Messung das meldet. Diese Falle steht dreimal in DESIGN.md. */

.pf-punkte, .pf-kette { display: flex; flex-direction: column; gap: 9px; margin: 0; padding: 0; list-style: none; }
.pf-punkt, .pf-kettenglied {
  display: flex; flex-direction: column; gap: 3px;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius-klein); padding: 11px 14px; min-width: 0;
}
.pf-punkt-titel, .pf-kettenname {
  font-size: 11px; font-weight: 700; letter-spacing: .07em;
  text-transform: uppercase; color: var(--akzent);
}
.pf-kettenname { font-size: 15px; letter-spacing: 0; text-transform: none; color: var(--ink); }
.pf-punkt-text { font-size: 15px; line-height: 1.4; overflow-wrap: anywhere; }
/* Dasselbe Bild in der Hand. Aus der letzten Reihe ist die Leinwand zehn
 * Meter weg, deshalb liegt jede Abbildung auch auf dem Handy. */
.pf-punkt-bild {
  width: 100%; height: 108px; object-fit: contain;
  background: #FFFFFF; border-radius: calc(var(--radius-klein) - 3px);
  border: 1px solid var(--line); margin-bottom: 2px;
}
/* Erledigtes Lernziel am Handy, wie am Beamer: grüner Haken als Status. */
.pf-punkt.erledigt {
  position: relative; padding-right: 42px;
  border-color: color-mix(in srgb, var(--gut) 40%, var(--line));
  background: var(--panel);
  background: color-mix(in srgb, var(--gut) 11%, var(--panel));
}
.pf-punkt.erledigt .pf-punkt-titel { color: var(--gut); }
.pf-ziel-haken {
  position: absolute; top: 10px; right: 12px;
  width: 22px; height: 22px;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--gut); color: var(--paper); border-radius: 50%;
  font-size: 14px; font-weight: 700; line-height: 1;
}
/* Die Zahlenschrift trägt Messwerte, keine Sätze. Ohne die zweite Regel
 * stand am Handy jeder Schritt eines Einsatzes in der Monospace und las
 * sich wie ein Ausdruck aus dem Drucker. Am Beamer entscheidet dieselbe
 * Länge, siehe presenter.html in der Form "einsatz". */
.pf-kettenzusatz { font-family: var(--mono); font-size: 12px; color: var(--mut); line-height: 1.3; }
.pf-kettenzusatz.satz { font-family: var(--sans); font-size: 13px; }

/* Die Kette bekommt am Handy Nummern statt Pfeile. Untereinander gestapelt
 * zeigt ein Pfeil nach rechts in die falsche Richtung. */
.pf-kette { counter-reset: glied; }
.pf-kettenglied { counter-increment: glied; }
.pf-kettenglied .pf-kettenname::before {
  content: counter(glied) " · "; font-family: var(--mono); color: var(--akzent);
}

/* Führt eine Kette sich selbst (kein Bild mit Marken, das die Stationen
 * aufdeckt), starten ihre Glieder zugedeckt und decken sich Zeile für Zeile
 * im Gleichschritt mit dem Beamer auf. Der Platz bleibt stehen: visibility,
 * nicht display, sonst fällt die Höhe zusammen und die Liste springt beim
 * Aufdecken. Die Nummer bleibt, damit die Klasse abzählen kann, was noch
 * kommt. Der Akzentrahmen des aufgedeckten Glieds ist derselbe wie am
 * Beamer, siehe .markengefuehrt .f-station.auf. */
.pf-kette.laeuft .pf-kettenglied[data-nr]:not(.auf) .pf-kettenname,
.pf-kette.laeuft .pf-kettenglied[data-nr]:not(.auf) .pf-kettenzusatz { visibility: hidden; }
.pf-kette.laeuft .pf-kettenglied[data-nr]:not(.auf) .pf-kettenname::before {
  content: counter(glied); visibility: visible;
}
.pf-kette.laeuft .pf-kettenglied[data-nr] { transition: border-color .2s ease, background-color .2s ease; }
.pf-kette.laeuft .pf-kettenglied[data-nr].auf {
  border-color: color-mix(in srgb, var(--akzent) 45%, var(--line));
  background: color-mix(in srgb, var(--akzent) 7%, var(--panel));
}

.pf-formel {
  margin: 0; text-align: center; font-size: 17px; font-weight: 700;
  color: var(--akzent); line-height: 1.3;
  padding: 12px 10px; border-top: 2px solid var(--akzent); border-bottom: 2px solid var(--akzent);
  overflow-wrap: anywhere;
}
.pf-fuss { margin: 0; font-size: 13px; color: var(--mut); line-height: 1.4; }


/* ---------- Dunkle Fassung, Nachzieher ----------
 * Was sich nicht allein über die Farbwerte regeln lässt. */

/* Die Antwortkachel hebt sich auf dunklem Grund nur mit 2.3 bis 3.6:1 ab.
 * Eine feine helle Kante macht klar, wo sie endet, ohne die Farbe selbst
 * anzufassen. */
:root[data-dunkel] .ans { box-shadow: inset 0 0 0 1px rgba(255,255,255,.18), var(--schatten); }
/* Gegen den dunklen Grund liegt die blasse Kachel bei 2.44:1, genau wie
 * die sechs Antwortfarben. Die feine helle Kante zeigt deshalb auch
 * hier, wo die Fläche endet. Die Farbe selbst bleibt dieselbe. */
:root[data-dunkel] .ans.blass { box-shadow: inset 0 0 0 1px rgba(255,255,255,.14); }

/* Eine Abbildung mit weissem Grund knallt im dunklen Raum. Sie bekommt
 * ihren eigenen hellen Rahmen und bleibt damit lesbar, aber der Rahmen
 * schliesst bündig ab statt zu leuchten. */
:root[data-dunkel] .f-bild { background: #F4F5F7; border-color: #39414F; }
:root[data-dunkel] .pf-bild { background: #F4F5F7; border-color: #39414F; }

/* ---------- Karteikarten fürs Selbststudium ---------- */
#karte { flex: 1; }
.karteflaeche {
  flex: 1; min-height: 320px; width: 100%;
  display: flex; align-items: center; justify-content: center;
  background: var(--panel); border: 1px solid var(--line); border-radius: 22px;
  padding: 28px 24px; cursor: pointer; box-shadow: var(--schatten);
  text-align: center;
  transition: border-color .15s ease;
}
.karteflaeche:hover { border-color: var(--akzent); }
.karteseite { display: flex; flex-direction: column; align-items: center; gap: 14px; width: 100%; }
.kartelabel {
  font-size: 12px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--mut); font-weight: 700;
}
.kartetext {
  font-size: clamp(20px, 5.5vw, 27px); font-weight: 800; line-height: 1.25;
  overflow-wrap: anywhere;
}
.kartetext.gut { color: var(--gut); }
/* Mehrzeiliger Stoff auf der Rückseite liest sich linksbündig besser
 * als zentriert, eine einzelne Antwort dagegen zentriert. */
.kartetext.links { text-align: left; font-size: clamp(17px, 4.4vw, 21px); font-weight: 600; white-space: pre-line; }
.karteerklaerung {
  font-size: 15px; line-height: 1.5; color: var(--mut);
  border-top: 1px solid var(--line); padding-top: 14px; margin-top: 4px; width: 100%;
}

/* ---------- Zuordnung der Antwortfarben ----------
 * Steht bewusst am Ende der Datei. A bis F müssen auf Beamer und
 * Handy dieselbe Farbe haben, sonst zeigt der Azubi auf eine andere
 * Kachel als die, die er vorne sieht. Weiter oben würde jede spätere
 * Regel mit gleicher Spezifität diese Zuordnung überholen.
 */
.a0 { --col: var(--a); } .a1 { --col: var(--b); } .a2 { --col: var(--c); }
.a3 { --col: var(--d); } .a4 { --col: var(--e); } .a5 { --col: var(--f); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important; animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}

/* Beamer im Vollbild: alles eine Spur größer, der Raum ist dunkel
 * und die hinterste Reihe sitzt zehn Meter weg. */
/* Die Frage steht in der Auflösung genauso gross und in derselben Farbe
 * wie beim Fragen. Vorher war sie klein und gedämpft, als blosse
 * Erinnerung. Sie ist aber der Satz, um den es auf dem Bildschirm geht,
 * und wer beim Antworten aufs Handy geschaut hat, liest sie hier zum
 * ersten Mal richtig. */
#rFrage { font-size: clamp(22px, 2.9vw, 40px); max-width: 30ch; color: var(--ink); font-weight: 800; }

@media (min-width: 1400px) {
  /* Lennys Ansage am 29.08.2026: die Frage und ihre Antworten sollen
   * mittig, gross und präsent stehen. Sie sind der Grund, warum die Klasse
   * überhaupt nach vorne schaut, und standen mit 27 px Schrift in 100 px
   * hohen Kacheln kleiner da als der Stoff auf den Erklärseiten. Unter den
   * Kacheln lagen dabei 120 px Leere. Gemessen: die Kachel trägt jetzt
   * 34 px Schrift auf 128 px Höhe, und die Seite bleibt im Beamerbild. */
  .beamer .qtext { font-size: 60px; max-width: 20ch; }
  .beamer #rFrage { font-size: 48px; max-width: 24ch; }
  /* Ein Fallbeispiel über vier Zeilen kann nicht so gross stehen wie eine
   * Frage über eine. Die Stufe setzt der Beamer als Klasse, weil CSS Text
   * nicht zählen kann; siehe textStufe() in presenter.html. */
  .beamer .qtext.lang { font-size: 46px; max-width: 26ch; }
  .beamer .qtext.sehrlang { font-size: 38px; max-width: 34ch; }
  .beamer #rFrage.lang { font-size: 38px; max-width: 30ch; }
  .beamer #rFrage.sehrlang { font-size: 32px; max-width: 38ch; }
  /* Dasselbe für die Kacheln: die längste Antwort entscheidet. */
  .beamer .answers.lang .ans { font-size: 27px; min-height: 104px; }
  .beamer .answers.sehrlang .ans { font-size: 24px; min-height: 92px; }
  .beamer #reveal .answers.lang .ans { font-size: 23px; min-height: 74px; }
  .beamer #reveal .answers.sehrlang .ans { font-size: 21px; min-height: 68px; }
  .beamer .ans { font-size: 32px; min-height: 118px; padding: 20px 26px; gap: 16px; }
  .beamer .ans .sym { width: 58px; height: 58px; font-size: 28px; }
  .beamer .kachelzahl { font-size: 29px; }
  /* In der Auflösung stehen unter denselben Kacheln noch der Erklärkasten
   * und die Rangliste. Mit der Fragegrösse stand die Seite dort bis zu
   * 1026 px hoch, bei 900 px Bild; gemessen über alle 13 Fragen des Herz-
   * Quiz. Beim Fragen ist die Kachel die Hauptsache, in der Auflösung nur
   * noch der Beleg, deshalb tritt sie hier zurück. */
  .beamer #reveal .ans { font-size: 25px; min-height: 78px; padding: 15px 22px; gap: 13px; }
  .beamer #reveal .ans .sym { width: 48px; height: 48px; font-size: 23px; }
  .beamer #reveal .kachelzahl { font-size: 23px; }
  .beamer #reveal .explain { font-size: 22px; padding: 15px 22px; }
  .beamer #reveal .board .row { font-size: 21px; padding: 10px 18px; }
  .beamer .board .row { font-size: 24px; padding: 14px 22px; }
  .beamer .explain { font-size: 24px; padding: 20px 26px; }
  .beamer .quote { font-size: 26px; }
  .beamer .uhr { min-width: 118px; height: 86px; font-size: 46px; }
  .beamer .joincard .code { font-size: 60px; }
  .beamer .stage { gap: 26px; }
}
