/* Aufsichtenplanung WIAI — Basis-Stil.
   Eine Datei, kein Build-Step, keine Frameworks (PRD §8.3).

   Herkunft der Gestaltung: das Design-System des WIAI-Neubaus
   (~/Desktop/wiai-webseiten-analyse/neubau/designsystem). Übernommen sind
   Palette, Kantenführung (1 px Haarlinie statt Schatten), quadratische
   Kästen, eine führende linke Kante und die Regel „höchstens zwei
   Flächenfarben je Seite".

   Zwei bewusste Abweichungen, beide begründet:
   1. Systemschriften statt der CD-Webfonts Open Sans und Copse — Webfonts
      wären ein zusätzlicher Auslieferungsweg ohne fachlichen Gewinn.
   2. Meldungen tragen eine einheitliche graue Kante statt einer Kante in der
      Signalfarbe: Gelb (1,44:1) und Grün (2,15:1) erreichen auf Weiß die für
      Bedienelemente geforderten 3:1 nicht (WCAG 1.4.11). Die Bedeutung trägt
      ohnehin die Textmarke, nicht die Farbe (WCAG 1.4.1).

   --- Werkzeug, nicht Webseite (GUI-Umbau) ---------------------------------

   Drei Regeln, die seit dem GUI-Umbau überall gelten. Sie stehen hier oben,
   weil jede von ihnen sonst an genau einer Stelle wieder aufgeweicht wird:

   1. KANTEN SIND ENTWEDER VOLLSTÄNDIG ODER GAR NICHT. Eine Fläche trägt
      ringsum dieselbe Kante; Bedeutung kommt aus Kantenfarbe, Fläche und
      Text, nie aus einer einzelnen angesetzten Kante. Eine Haarlinie
      ZWISCHEN gestapelten Geschwistern (Tabellenzeile, Listentrenner,
      Kartenkopf) ist davon nicht betroffen — sie trennt, sie schmückt nicht.
      Eine einzige Ausnahme, bewusst: `.feld--fehlerhaft` (siehe dort).

   2. EIN GEFÜLLTER KNOPF JE ANSICHT. `.knopf--primaer` ist die eine Aufgabe
      der Seite. Alles Zweitrangige ist `.knopf` (Kontur), alles Beiläufige —
      Exporte, Navigationswege, „Zurück“ — ist ein Textlink in `.wege` oder
      ein `.knopf--leise`. Vier gleich große Konturknöpfe nebeneinander sind
      keine Rangfolge, sondern eine Parade.

   3. ZUSAMMENGEHÖRIGES SITZT IN EINER GEMEINSAMEN FLÄCHE. `.karte` mit
      `.karte__kopf` ist der Baustein dafür, `.kartenraster` die Anordnung.
      Abstand innerhalb einer Gruppe ist klein (raum-2/3), zwischen Gruppen
      groß (raum-6/7) — daran erkennt man die Gruppe, nicht an einer
      Überschrift allein.
   ========================================================================== */

/* --- Merkmale (Tokens) ---------------------------------------------------- */

:root {
  /* Palette der Universität Bamberg. Nur diese Werte plus Weiß und Schwarz —
     kein eigenes Farbvokabular (Vorgabe des Design-Systems). */
  --uni-blau: #00457d;
  --uni-blau-80: #336a97;
  --uni-blau-40: #99b5cb;
  --uni-blau-20: #ccdae5;
  --uni-gelb-20: #fff6cc;
  --uni-gruen-20: #eaf2cf;
  --uni-rot: #e6444f;
  --uni-rot-20: #fadadc;
  --uni-grau: #878783;
  --uni-grau-40: #cfcfce;
  --uni-grau-20: #e7e7e6;

  /* Rollen. Textstufen als Schwarz mit Alpha statt als Grautöne — so halten
     sie ihren Kontrast auch auf dem Flächenton. */
  --grund: #ffffff;
  --flaeche-ton: #e8eef3; /* Blau-20 zu 45 % in Weiß */
  --text: #000000;
  --text-zweit: rgba(0, 0, 0, 0.72);
  --text-leise: rgba(0, 0, 0, 0.55);
  --akzent: var(--uni-blau);

  /* Haarlinie schmückt, Kante bedient: Grau-40 ist als Trennstrich gedacht,
     Grau (3,61:1) trägt jede Kante, die ein Bedienelement begrenzt. */
  --linie: var(--uni-grau-40);
  --kante: var(--uni-grau);

  --schrift: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue",
    Arial, sans-serif;
  /* Ersatz für Copse. Wie dort gilt: ausschließlich h1, sonst nichts —
     die Anzeige-Schrift soll sich nicht ausbreiten. */
  --schrift-anzeige: Georgia, "Iowan Old Style", "Times New Roman", Times, serif;

  /* Der Seitentitel ist eine Beschriftung, kein Plakat. Vorher lief er bis
     2,9 rem und schob den eigentlichen Inhalt unter die Falz — auf einer Seite,
     die man zweimal im Semester zum Arbeiten öffnet und nicht zum Lesen. */
  --fs-anzeige: clamp(1.6rem, 1.25rem + 1.1vw, 2.05rem);
  --fs-h2: 1.3rem;
  --fs-h3: 1.1rem;
  --fs-lead: 1.0625rem;
  --fs-body: 1.0625rem; /* 17 px */
  --fs-klein: 0.95rem;
  --fs-mikro: 0.8rem;

  --raum-1: 0.25rem;
  --raum-2: 0.5rem;
  --raum-3: 0.75rem;
  --raum-4: 1rem;
  --raum-5: 1.5rem;
  --raum-6: 2rem;
  --raum-7: 3rem;
  --raum-8: 4.5rem;

  --breite: 1200px;
  /* Zeilenlänge: die px-Grenze gewinnt auf schmalen Schirmen, die ch-Grenze
     bei großer Schrift — so hält die Grenze in beide Richtungen. */
  --mass: min(680px, 72ch);
  --mass-weit: min(980px, 96ch);

  --radius-kasten: 0; /* Kästen sind quadratisch, ausnahmslos */
  --radius-steuer: 4px; /* Rundung gibt es nur für Bedienelemente */
  --uebergang: 0.2s ease;

  /* Bauhöhe des klebenden Kopfbereichs. Sie steuert nur, wie weit ein
     angesprungenes Ziel vom oberen Rand wegrückt (`scroll-padding-top`) —
     nicht das Layout. Deshalb ist ein zu großer Wert harmlos (das Ziel sitzt
     etwas tiefer) und ein zu kleiner die einzige Gefahr.

     Der Wert ist absichtlich großzügig: Gemessen wurden 115 px bei 1440 px und
     152 px bei 900 px (dort bricht die Kopfzeile um). 9,5 rem deckt beide ab.
     Genau diese Schwankung ist der Grund, warum der Kopf `sticky` ist und nicht
     `fixed` — ein `padding-top` am `body` müsste den richtigen Wert treffen,
     dieses `scroll-padding` darf ihn überschätzen. */
  --kopfhoehe: 9.5rem;
}

/* --- Grundlagen ----------------------------------------------------------- */

*,
*::before,
*::after {
  box-sizing: border-box;
}

/* Ohne das setzt jede Autorenregel mit `display` das UA-`[hidden]` außer
   Kraft, und per JS gesetztes `hidden` bleibt wirkungslos. */
[hidden] {
  display: none !important;
}

html {
  color-scheme: light;
  /* Der Kopfbereich klebt oben und liegt damit über allem, was man anspringt:
     `#inhalt`, die Fehlerübersicht, ein Slot nach einer Aktion. Ohne diese
     Zeile landet jedes Sprungziel unter dem Kopf — das Fokusziel wäre fokussiert
     und unsichtbar (WCAG 2.4.7, 2.4.11). Ein Wert am Wurzelelement gilt für
     Ankersprünge, `focus()` und `scrollIntoView()` gleichermaßen; einzelne
     `scroll-margin-top`-Regeln wären dieselbe Zusage an fünfzehn Stellen. */
  scroll-padding-top: var(--kopfhoehe);
}

/* Spaltenaufbau, damit das Fußband auch auf kurzen Seiten unten sitzt statt
   mitten im Bild zu enden. */
body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100dvh;
  margin: 0;
  background: var(--grund);
  color: var(--text);
  font-family: var(--schrift);
  font-size: var(--fs-body);
  line-height: 1.6;
  -webkit-text-size-adjust: 100%;
}

/* Spalte, damit ein Kind sich per `margin-block: auto` im freien Raum
   ausrichten kann (siehe `.tuerseite`). Ohne freien Raum ändert sich nichts. */
main {
  display: flex;
  flex-direction: column;
  flex: 1 0 auto;
}

/* Fließtext darf trennen (deutsche Komposita), Überschriften nicht. */
p,
li,
dd {
  hyphens: auto;
  text-wrap: pretty;
}

h1,
h2,
h3,
h4 {
  margin: 0 0 var(--raum-3);
  line-height: 1.2;
  letter-spacing: -0.01em;
  hyphens: manual;
  overflow-wrap: break-word;
  text-wrap: balance;
}

/* Hierarchie kommt aus der Größe, nicht aus dem Fettgrad. */
h1 {
  margin-bottom: var(--raum-5);
  font-family: var(--schrift-anzeige);
  font-size: var(--fs-anzeige);
  font-weight: 400;
  color: var(--uni-blau);
  line-height: 1.12;
}

h2 {
  font-size: var(--fs-h2);
  font-weight: 400;
  color: var(--uni-blau);
}

h3 {
  font-size: var(--fs-h3);
  font-weight: 400;
  color: var(--uni-blau);
}

h4 {
  font-size: var(--fs-body);
  font-weight: 600;
  color: var(--uni-blau);
}

p {
  margin: 0 0 var(--raum-4);
}

ul,
ol {
  margin: 0 0 var(--raum-4);
  padding-left: 1.3rem;
}

li + li {
  margin-top: var(--raum-1);
}

a {
  color: var(--uni-blau);
  text-decoration: underline;
  text-underline-offset: 2px;
}

a:hover {
  color: var(--uni-blau-80);
  text-decoration-thickness: 2px;
}

img {
  display: block;
  max-width: 100%;
  height: auto;
}

/* --- Fokus und Sprungmarke ------------------------------------------------ */

/* Ein Ring für alles. Auf dem blauen Band wäre Blau unsichtbar — dort
   überschreibt `.kopfband` die Farbe auf Weiß. */
:focus-visible {
  outline: 2px solid var(--akzent);
  outline-offset: 2px;
}

/* `main` ist nur Sprungziel, kein Bedienelement. Ein Ring um die halbe Seite
   hilft niemandem; die Ansage der Landmarke leistet die Rückmeldung. */
main:focus {
  outline: none;
}

.sprungmarke {
  position: absolute;
  left: var(--raum-4);
  top: -100vh;
  z-index: 100;
  padding: var(--raum-3) var(--raum-5);
  background: var(--grund);
  color: var(--uni-blau);
  border: 2px solid var(--uni-blau);
  border-radius: 0 0 var(--radius-steuer) var(--radius-steuer);
  font-weight: 600;
  text-decoration: none;
}

.sprungmarke:focus {
  top: 0;
}

/* Die Marke liegt immer über dem blauen Band — ein blauer Ring wäre dort
   unsichtbar. Weiß mit Versatz ergibt eine erkennbare Doppellinie. */
.sprungmarke:focus-visible {
  outline-color: #ffffff;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* --- Aufbau --------------------------------------------------------------- */

/* Vollbreite Bänder sind außen Fläche, innen Container — nie ein Container,
   der selbst blutet. Alle Container teilen sich eine linke Kante. */
/* `width: 100%` ist nicht überflüssig: `main` ist eine Flex-Spalte, und dort
   hebelt ein `margin-inline: auto` das `align-items: stretch` aus — der
   Container schrumpfte sonst auf seine Inhaltsbreite und die linke Kante
   wanderte weg vom Wortzeichen. */
.container {
  width: 100%;
  max-width: var(--breite);
  margin-inline: auto;
  padding-inline: var(--raum-5);
}

.band--ton {
  background: var(--flaeche-ton);
}

.abschnitt {
  padding-block: var(--raum-7);
}

.abschnitt--weit {
  padding-block: var(--raum-8);
}

/* Türseiten tragen wenig Inhalt. Statt ihn oben kleben und darunter ein
   totes Feld entstehen zu lassen, richtet er sich im freien Raum aus; auf
   schmalen Schirmen gibt es keinen freien Raum und nichts passiert. */
.tuerseite {
  margin-block: auto;
}

.fliesstext {
  max-width: var(--mass);
}

.fliesstext--weit {
  max-width: var(--mass-weit);
}

/* --- Kopfbereich ----------------------------------------------------------- */

/* Kopfband und Kontextleiste sind ein Bauteil und bleiben zusammen oben stehen:
   „welches Semester, welche Phase" ist die Angabe, die jede Entscheidung auf
   jeder Seite bindet, und sie war nach dem ersten Bildlauf weg.

   `sticky` und nicht `fixed`, und das ist eine Entscheidung und kein Versehen:
   Die Höhe dieses Bauteils ist nicht bekannt. Die Kontextleiste steht nur auf
   Semesterseiten, die Nutzerkennung ist eine Mailadresse beliebiger Länge, und
   beides bricht je nach Fläche um. `fixed` nimmt den Kopf aus dem Fluss und
   verlangt dafür ein `padding-top` am `body`, das genau seiner Höhe entspricht —
   diesen Wert kann CSS nicht ausrechnen. Ein zu kleiner Wert verdeckt Inhalt
   dauerhaft, ein zu großer reißt ein Loch. `sticky` hat diesen Fehlerfall
   nicht: Der Kopf bleibt im Fluss, das Ergebnis für die Bedienung ist dasselbe,
   und die einzige verbleibende Folgekosten-Stelle — angesprungene Ziele unter
   dem Kopf — löst `scroll-padding-top` am Wurzelelement. */
.kopfbereich {
  position: sticky;
  top: 0;
  /* Über der Auswahlleiste des Boards (5) und der Erklärungsblase (2). */
  z-index: 20;
}

/* Auf schmalen Schirmen scrollt der Kopf mit. Zwei Bänder übereinander sind
   dort rund ein Viertel der sichtbaren Höhe — ein Werkzeug, das ein Viertel
   seiner Fläche für die Angabe belegt, in welchem Semester man ist, hat die
   Rangfolge verloren. Die Angabe steht weiterhin am Seitenanfang. */
@media (max-width: 48rem) {
  .kopfbereich {
    position: static;
  }
}

.kopfband {
  background: var(--uni-blau);
  color: #ffffff;
}

.kopfband :focus-visible {
  outline-color: #ffffff;
}

/* Eine Zeile, eine Mittelachse. Vorher trafen sich hier fünf Elemente mit drei
   verschiedenen Ausrichtungen (`center` außen, `baseline` innen), und das
   Sitzungspaket rutschte auf eine zweite Zeile mit eigener Höhe — das war das
   „chaotisch" am Kopfband. Jetzt richtet sich alles an derselben Mittelachse
   aus, und das Umbrechen ist ein Fall und nicht der Normalfall. */
.kopfzeile {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--raum-3) var(--raum-6);
  padding-block: var(--raum-3);
}

.marke {
  margin: 0;
  margin-right: auto;
}

/* Sitzung und Sprache: ein Paket, leiser als alles andere im Band. Die
   trennende Haarlinie ist weg — sie war eine einseitige Kante an einem Kasten
   ohne Fläche und trennte etwas, das der Abstand schon trennt. */
.kopfzeile__rechts {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--raum-2) var(--raum-4);
  font-size: var(--fs-klein);
}

.marke a {
  display: block;
  color: inherit;
  text-decoration: none;
}

.marke a:hover .marke__name {
  text-decoration: underline;
  text-underline-offset: 3px;
}

.marke__traeger {
  display: block;
  font-size: var(--fs-mikro);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--uni-blau-20);
}

.marke__name {
  display: block;
  font-size: 1.15rem;
  font-weight: 400;
}

/* Hauptnavigation im Kopfband. Wenige Ziele, deshalb eine Reihe ohne
   Aufklappmenü: Ein Menü, das man erst öffnen muss, ist auf jedem Gerät ein
   Klick mehr und mit der Tastatur zwei. */
.hauptnav ul {
  display: flex;
  flex-wrap: wrap;
  gap: var(--raum-2) var(--raum-4);
  margin: 0;
  padding: 0;
  list-style: none;
}

.hauptnav li + li {
  margin-top: 0;
}

.hauptnav a {
  display: block;
  padding: var(--raum-1) 0;
  color: #ffffff;
  text-decoration: none;
  font-weight: 600;
}

.hauptnav a:hover {
  color: #ffffff;
  text-decoration: underline;
  text-underline-offset: 4px;
}

/* Die aktuelle Rubrik trägt eine Unterkante — die Ansage `aria-current`
   erledigt dasselbe für die Sprachausgabe. */
.hauptnav a[aria-current] {
  border-bottom: 2px solid #ffffff;
}

/* Wer angemeldet ist und wie man das beendet — im Kopfband, weil es auf jeder
   Seite gilt. Die Kennung ist eine Angabe, keine Ansage: Sie steht in Blau-20
   wie die Trägerzeile der Marke und nicht in Weiß. */
.nutzerband {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--raum-2) var(--raum-3);
  margin: 0;
}

.nutzerband__name {
  color: var(--uni-blau-20);
}

/* „Abmelden" und die zweite Sprache sind beiläufige Aktionen und sehen jetzt
   auch so aus: unterstrichener Text statt Kasten. Vorher standen im Band drei
   umrandete Schaltflächen (Abmelden, Deutsch, English) plus eine versale Marke
   „SPRACHE" — vier Konturen, die um dieselbe Aufmerksamkeit stritten wie der
   Name der Anwendung. */
.kopflink {
  padding: 0;
  border: 0;
  background: transparent;
  color: #ffffff;
  font-family: inherit;
  font-size: inherit;
  line-height: 1.4;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: rgba(255, 255, 255, 0.6);
  cursor: pointer;
}

.kopflink:hover {
  color: #ffffff;
  text-decoration-color: #ffffff;
  text-decoration-thickness: 2px;
}

.sprachwahl {
  margin: 0;
}

.sprachwahl__gruppe {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--raum-2) var(--raum-3);
}

/* Unterkante wie bei `.hauptnav a[aria-current]`: Die Bedeutung trägt
   `aria-current`, sie hängt also nicht an der Auszeichnung (WCAG 1.4.1). */
.sprachwahl__aktiv {
  border-bottom: 2px solid #ffffff;
  color: #ffffff;
  font-weight: 600;
  line-height: 1.4;
}

/* --- Kontextleiste -------------------------------------------------------- */

/* Der Dauerplatz für „welches Semester, welche Phase, welcher Saldo". Diese
   Anwendung befindet sich immer in einem Semester und in einer Phase — das
   ist die eine Angabe, die auf jeden Bildschirm gehört. Bis Welle 3 gibt es
   nichts zu füllen; der Block bleibt leer statt zu erfinden. */
/* Der Flächenton bindet die Leiste an das blaue Band darüber: Beides ist
   Werkzeugrahmen und nicht Inhalt. Auf Weiß sah sie aus wie die erste Zeile der
   Seite und stritt mit der Überschrift darunter. */
.kontextleiste {
  border-bottom: 1px solid var(--linie);
  background: var(--flaeche-ton);
}

/* Semester und Phase stehen links beieinander, ein etwaiger Riegel rechts —
   deshalb `flex-start` plus `margin-left: auto` am Riegel und nicht
   `space-between`, das die beiden Angaben auseinanderzöge. */
.kontextleiste .container {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-start;
  gap: var(--raum-1) var(--raum-5);
  padding-block: var(--raum-2);
  font-size: var(--fs-klein);
  color: var(--text-zweit);
}

.kontextleiste__teil {
  display: inline-flex;
  align-items: center;
  gap: var(--raum-2);
  margin: 0;
}

.kontextleiste__teil--riegel {
  margin-left: auto;
  color: var(--text);
  font-weight: 600;
}

/* Die Marke benennt, was die Zahl daneben ist — ohne sie wäre „4 von 7" eine
   Zahl ohne Gegenstand. */
.kontextleiste__marke {
  font-size: var(--fs-mikro);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-leise);
}

.kontextleiste__phase {
  font-variant-numeric: tabular-nums;
  color: var(--text);
}

/* --- Unternavigation ------------------------------------------------------ */

/* Die Arbeitsbereiche eines Semesters. Steht unter der Überschrift, weil sie
   zum Gegenstand der Seite gehört und nicht zur Anwendung. */
.unternav {
  margin-bottom: var(--raum-6);
  border-bottom: 1px solid var(--linie);
}

/* Dieselbe Markierung wie in der Hauptnavigation: Unterkante plus fettere
   Schrift, damit die aktuelle Rubrik nicht allein an der Farbe hängt
   (WCAG 1.4.1, 2.4.8). */
.unternav a[aria-current] {
  font-weight: 700;
  text-decoration: none;
  box-shadow: inset 0 -3px 0 var(--akzent);
}

.unternav ul {
  display: flex;
  flex-wrap: wrap;
  gap: var(--raum-2) var(--raum-5);
  margin: 0;
  padding: 0;
  list-style: none;
}

/* EINE Zeile statt drei benannter Gruppen.

   Die Gruppen waren die Antwort auf fünfzehn Ziele nebeneinander. Seit die
   Leiste nur noch zeigt, was in dieser Phase dran ist, sind es höchstens
   sieben — und für sieben ist eine Gruppierung mehr Struktur als Inhalt.

   Der Rest ist Umbruchverhalten: `flex-wrap` auf der Liste (oben) trägt die
   Zeile bis 320 px, ohne die Seite waagerecht aufzuschieben (WCAG 1.4.10). */
.unternav--zeile {
  padding-bottom: var(--raum-1);
}

/* Die Nachweise stehen in jeder Phase, sind aber in keiner die Aufgabe. Sie
   bekommen deshalb den leisen Ton und einen Abstand, der sie vom Ablauf
   absetzt — sichtbar, ohne mitzureden. Kein `aria`-Unterschied: Für die
   Sprachausgabe sind es dieselben Links, nur später in der Liste. */
.unternav__nachweis {
  color: var(--text-leise);
}

.unternav__nachweis a {
  font-weight: 500;
  color: var(--text-leise);
}

/* Der Übergang vom Ablauf zu den Nachweisen ist ein Abstand und keine Kante:
   Eine senkrechte Einzelkante wäre genau die Form, gegen die der Stilwächter
   in `test_stil.py` steht. `:first-of-type` träfe hier ohnehin das erste `li`
   überhaupt, weil alle Kinder `li` sind. */
.unternav li:not(.unternav__nachweis) + .unternav__nachweis {
  margin-inline-start: var(--raum-5);
}

.unternav li + li {
  margin-top: 0;
}

.unternav a {
  display: block;
  padding-bottom: var(--raum-2);
  font-size: var(--fs-klein);
  font-weight: 600;
  text-decoration: none;
}

.unternav a:hover {
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* --- Meldungen ------------------------------------------------------------ */

.meldungen {
  padding-top: var(--raum-5);
}

.meldung {
  max-width: var(--mass-weit);
  margin: 0 0 var(--raum-3);
  padding: var(--raum-3) var(--raum-4);
  border: 1px solid var(--kante);
  border-radius: var(--radius-kasten);
  background: var(--uni-grau-20);
  color: var(--text-zweit);
}

/* Die Farbe verstärkt nur — gelesen wird die Textmarke. */
.meldung__art {
  font-weight: 700;
  color: var(--text);
}

.meldung--success {
  background: var(--uni-gruen-20);
}

.meldung--info,
.meldung--debug {
  background: var(--flaeche-ton);
}

.meldung--warning {
  background: var(--uni-gelb-20);
}

.meldung--error {
  background: var(--uni-rot-20);
  border-color: var(--uni-rot);
}

/* --- Typografische Hilfsklassen ------------------------------------------- */

/* Höchstens ein bis zwei Vorzeilen je Seite — eine über jedem Abschnitt ist
   Füllmaterial und flacht die Hierarchie ab. */
.vorzeile {
  margin: 0 0 var(--raum-2);
  font-size: var(--fs-mikro);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--uni-blau);
}

/* Der Vorspann trennt nicht: Trennstriche in einer hervorgehobenen Zeile
   lesen sich als Fehler, nicht als Satz. */
.lead {
  max-width: var(--mass);
  margin-bottom: var(--raum-5);
  font-size: var(--fs-lead);
  line-height: 1.55;
  color: var(--text-zweit);
  hyphens: manual;
}

.leise {
  color: var(--text-leise);
  font-size: var(--fs-klein);
}

/* Soll, Ist, Saldo. Tabellenziffern, damit Spalten stellenweise fluchten —
   das ist der Grund, warum diese Anwendung überhaupt gelesen wird. */
.zahl {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

/* Bewusst keine dicktengleiche Schrift: die Systemschrift setzt mit
   `tabular-nums` bereits stellengleich, und ein Wechsel der Schriftfamilie
   mitten in einer Zahlenspalte fällt als Bruch auf. */
.saldo {
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Das Vorzeichen trägt die Aussage, nicht die Farbe (WCAG 1.4.1). */
.saldo--unterdeckt {
  font-weight: 700;
}

/* Kleine Sach-Etiketten in Tabellen (zentral/dezentral, lange Dauer, …).
   Text trägt die Aussage, die Kontur nur die Gruppierung (WCAG 1.4.1). */
.etikett {
  display: inline-block;
  padding: 0.05rem 0.4rem;
  margin-inline-end: 0.25rem;
  border: 1px solid var(--linie, currentColor);
  border-radius: 0.25rem;
  font-size: 0.85em;
  white-space: nowrap;
}

/* --- Tabellen ------------------------------------------------------------- */

/* Die Hülle scrollt, nicht die Seite. `tabindex="0"`, `role="region"` und
   ein `aria-label` gehören ins Markup: ein scrollbarer Bereich muss mit der
   Tastatur erreichbar sein (WCAG 2.1.1).

   `position: relative` ist keine Kosmetik: `.sr-only` steht auf
   `position: absolute` ohne Versatz. Ohne positionierten Vorfahren ist sein
   Containing Block der Seitenkasten — die 1-px-Marke landet dann an der
   Stelle, an der sie *in der breiten Tabelle* stünde, wird von der Hülle nicht
   beschnitten und schiebt die ganze Seite waagerecht auf. In der Abnahme auf
   vier Seiten gefunden (Fristen, Lehreinheiten, Nicht-Melder, Zuweisung), je
   rund 140 px Bildlauf am `body` (WCAG 1.4.10). */
.tabelle-huelle {
  position: relative;
  max-width: 100%;
  overflow-x: auto;
  margin-bottom: var(--raum-5);
}

table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-klein);
  font-variant-numeric: tabular-nums;
}

caption {
  margin-bottom: var(--raum-2);
  text-align: left;
  font-weight: 600;
  color: var(--text-zweit);
}

th,
td {
  padding: var(--raum-2) var(--raum-3);
  text-align: left;
  vertical-align: top;
  border-bottom: 1px solid var(--linie);
}

thead th {
  border-bottom: 1.5px solid var(--uni-blau-40);
  font-size: var(--fs-mikro);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--uni-blau);
}

/* Kein `white-space: nowrap` an der Kopfzeile. Es stand hier, und ein einziger
   langer Kopf hat damit die ganze Tabelle in den Bildlauf geschoben: „Teilnehmende
   Vorjahr" verlangte 208 px für eine dreistellige Zahl, und die Meldungsübersicht
   lief um 33 px aus ihrem Container, obwohl die Summe der Mindestbreiten
   hineinpasste (gemessen bei 1440 px, Befund DH). Die Kopfzeile ist Mikrotypografie
   in Versalien; zwei Zeilen sind dort normal, ein waagerechter Bildlauf über der
   ganzen Tabelle ist es nicht. Der Bildlauf der `.tabelle-huelle` bleibt für die
   Fälle, in denen er wirklich nötig ist. */

tbody tr:hover {
  background: var(--flaeche-ton);
}

.spalte-zahl {
  text-align: right;
}

/* --- Formulare ------------------------------------------------------------ */

.feld {
  margin-bottom: var(--raum-5);
  max-width: var(--mass);
}

.feld > label,
.feld-legende {
  display: block;
  margin-bottom: var(--raum-1);
  font-weight: 600;
}

.feld-hilfe {
  margin: 0 0 var(--raum-2);
  font-size: var(--fs-klein);
  color: var(--text-leise);
}

/* Der Fehler steht über dem Feld, damit er beim Vorlesen vor der Eingabe
   kommt; er wird zusätzlich per `aria-describedby` verknüpft. */
.feld-fehler {
  margin: 0 0 var(--raum-2);
  font-size: var(--fs-klein);
  font-weight: 600;
  color: var(--text);
}

/* DIE EINE AUSNAHME von Regel 1 (vollständige Kanten), bewusst getroffen und
   hier begründet: Diese Kante ist keine Auszeichnung, sondern eine Zuordnung.
   Sie klammert Fehlermeldung und Eingabefeld zu einem Block, damit der Fehler
   nicht optisch am gefüllten Feld DARÜBER klebt — er gehört zu dem darunter.
   Ein voller Rahmen leistet das nicht: Er umschlösse auch die Beschriftung und
   die Hilfe und sähe aus wie eine zweite Feldgruppe; und ein Feld trägt bereits
   einen eigenen Rahmen, der bei `aria-invalid` rot und 2 px breit wird — zwei
   volle rote Rahmen ineinander sind Lärm.

   Die Bedeutung trägt ohnehin die Textmarke „Fehler" im Markup, nicht die
   Kante (WCAG 1.4.1). Sie ist im Kontrastmodus verzichtbar und darf dort
   verschwinden. */
.feld--fehlerhaft {
  padding-left: var(--raum-3);
  border-left: 3px solid var(--uni-rot);
}

/* Fehlerübersicht über dem Formular — Zähler, Anker, Fokusziel. Voller Rahmen
   statt angesetzter Kante: Sie ist ein Kasten und hat eine eigene Fläche.
   `scroll-margin-top` gibt es nicht einzeln — `scroll-padding-top` am
   Wurzelelement gilt für jedes Sprung- und Fokusziel der Anwendung. */
.fehleruebersicht {
  max-width: var(--mass);
  margin-bottom: var(--raum-5);
  padding: var(--raum-3) var(--raum-4);
  border: 1px solid var(--uni-rot);
  background: var(--uni-rot-20);
}

.fehleruebersicht__titel {
  margin: 0;
}

.fehleruebersicht ul {
  margin: var(--raum-2) 0 0;
  padding-left: var(--raum-5);
}

/* Maschinenlesbare Eingaben (JSON-Zuordnung des PA-Imports): In der
   Proportionalschrift sind Spaltenbuchstaben und Klammern nicht abzuzählen. */
.feld--maschine {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

/* Ein Zusatz im Spaltenkopf steht auf eigener Zeile und nicht fett — sonst
   liest sich der Kopf als Satz und die Spalte wird breiter als ihre Zahlen. */
.th-zusatz {
  display: block;
  font-weight: 400;
}

/* Schalter: Kästchen und Beschriftung in einer Zeile, die Beschriftung ist
   Teil der Klickfläche. */
.feld--schalter > label,
.feld-schalter label {
  display: inline;
  font-weight: 400;
}

.feld-schalter {
  display: flex;
  align-items: baseline;
  gap: var(--raum-2);
  margin: 0;
}

/* Zahlenfelder in Tabellenzellen: nur so breit wie nötig, damit die Spalte
   nicht die Tabelle auseinanderzieht. */
td input[type="text"],
td input[type="date"] {
  max-width: 9rem;
}

input[type="text"],
input[type="email"],
input[type="number"],
input[type="date"],
input[type="search"],
input[type="password"],
select,
textarea {
  width: 100%;
  padding: 0.45rem 0.6rem;
  border: 1px solid var(--kante);
  border-radius: var(--radius-steuer);
  background: var(--grund);
  color: var(--text);
  font-family: inherit;
  font-size: var(--fs-body);
  line-height: 1.5;
}

/* Ein Auswahlfeld ist so breit wie sein längster Eintrag, nicht so breit wie
   sein Container. Über die volle Spaltenbreite gezogen behauptet „ohne
   Vorlage, mit Standardwerten" eine Eingabemenge, die es nicht gibt, und in
   einer Tabellenzeile zieht es die Spalte auseinander (Befund DH). Die
   Obergrenze hält das Feld unter 320 px im Kasten (WCAG 1.4.10); die Marken
   der Optionen kürzt der Browser dann selbst. */
select {
  width: max-content;
  max-width: 100%;
}

input[type="number"],
input[type="date"] {
  font-variant-numeric: tabular-nums;
}

textarea {
  min-height: 7rem;
  resize: vertical;
}

input:hover,
select:hover,
textarea:hover {
  border-color: var(--uni-blau);
}

[aria-invalid="true"] {
  border-color: var(--uni-rot);
  border-width: 2px;
}

fieldset {
  margin: 0 0 var(--raum-5);
  padding: var(--raum-4);
  border: 1px solid var(--linie);
  border-radius: var(--radius-kasten);
}

legend {
  padding-inline: var(--raum-2);
  font-weight: 600;
  color: var(--uni-blau);
}

/* Radiogruppe: Die Gruppe ist das Feld, deshalb ohne Rahmen und Innenabstand —
   ein Kasten je Auswahlfrage zerlegte das Formular optisch in Bausteine. */
.feld-gruppe {
  margin: 0;
  padding: 0;
  border: 0;
}

.feld-gruppe > .feld-legende {
  padding-inline: 0;
  color: var(--text);
}

.feld-gruppe label {
  display: inline;
  font-weight: 400;
}

.feld-gruppe input[type="radio"] {
  margin-right: var(--raum-1);
}

/* --- Listen und Hinweise -------------------------------------------------- */

/* Eine Liste von Verweisen ohne Aufzählungszeichen: Die Einträge sind Wege,
   keine Aufzählung. */
.liste-klar {
  margin: 0 0 var(--raum-5);
  padding: 0;
  list-style: none;
}

.liste-klar li {
  padding: var(--raum-2) 0;
  border-bottom: 1px solid var(--linie);
}

.liste-klar .leise {
  margin-left: var(--raum-2);
}

/* Ein Weg, der schreiben muss, steht als Formular in der Zeile (der xlsx-Export
   protokolliert und darf deshalb kein GET sein). Ohne diese Zeile bräche das
   Block-Formular die Zeile um und der Halbsatz dahinter stünde allein. */
.liste-klar form {
  display: inline;
}

/* Ein stehender Hinweis zum Zustand der Seite — anders als `.meldung`, die auf
   eine gerade ausgeführte Aktion antwortet. Die Fläche allein trägt ihn: Sie
   ist eine vollständige Region, die angesetzte 4-px-Kante war eine zweite
   Auszeichnung für dieselbe Aussage. */
.hinweis {
  max-width: var(--mass-weit);
  margin: 0 0 var(--raum-5);
  padding: var(--raum-3) var(--raum-4);
  background: var(--flaeche-ton);
}

/* Bearbeiten und Löschen nebeneinander; die Spalte soll nicht umbrechen.

   Kein `display: flex` auf der Zelle: Das nimmt sie aus dem Tabellenlayout,
   sie wächst nicht mehr auf Zeilenhöhe, und ihre Unterkante steht über der
   der Zeile — sichtbar als Treppe in der Trennlinie, auf Papier deutlicher
   als am Bildschirm. Nebeneinander stehen die beiden auch so: Das `form` ist
   das einzige Blockelement darin und wird inline gesetzt. */
.spalte-aktion {
  white-space: nowrap;
  text-align: right;
}

.spalte-aktion > form {
  display: inline-block;
}

.spalte-aktion > * + * {
  margin-left: var(--raum-2);
}

/* Ein Formular, das in eine Tabellenzeile passen muss: Auswahl und Knopf
   nebeneinander statt untereinander. Ohne diese Regel steht das `select` als
   Block über dem Knopf und zieht mit `width: 100%` die Spalte auf. */
.formular-zeile {
  display: flex;
  flex-wrap: wrap;
  gap: var(--raum-2);
  align-items: center;
}

/* --- Knöpfe --------------------------------------------------------------- */

.knopf {
  display: inline-block;
  padding: 0.55rem 1.4rem;
  border: 1px solid var(--uni-blau);
  border-radius: var(--radius-steuer);
  background: var(--grund);
  color: var(--uni-blau);
  font-family: inherit;
  font-size: var(--fs-body);
  font-weight: 600;
  line-height: 1.5;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--uebergang), color var(--uebergang);
}

.knopf:hover {
  background: var(--flaeche-ton);
  color: var(--uni-blau);
  text-decoration: none;
}

.knopf--primaer {
  background: var(--uni-blau);
  color: #ffffff;
}

.knopf--primaer:hover {
  background: var(--uni-blau-80);
  border-color: var(--uni-blau-80);
  color: #ffffff;
}

/* Ein Knopf, der IN einer Tabellenzeile oder einer Wiederhol-Liste steht.

   Die Anwendung ist ein Werkzeug für den Schreibtisch, und ein Knopf mit
   Touch-Maßen in jeder Zeile macht aus einer Tabelle mit dreißig Zeilen eine
   Tabelle mit sechzig Zeilen Höhe. Er wird deshalb kleiner — aber nicht
   beliebig klein: Die Zielfläche bleibt über den 24 × 24 px, die WCAG 2.5.8
   (AA) verlangt. Nachgerechnet mit der Grundschrift 16 px:
   0,85 rem × 1,5 Zeilenhöhe = 20,4 px, dazu zweimal 0,25 rem Innenabstand
   (8 px) und zweimal 1 px Kante — 30,4 px hoch. In der Breite trägt jeder
   dieser Knöpfe ein Wort und liegt weit darüber. `test_bediendichte.py`
   rechnet das aus dem Stylesheet nach.

   Formulare AUSSERHALB von Tabellen behalten ihre Größe: Dort ist der Knopf
   der Abschluss einer Eingabe und nicht die dreißigste Wiederholung. */
.knopf--zeile {
  padding: 0.25rem 0.7rem;
  font-size: 0.85rem;
}

/* In einer Wiederhol-Liste (Personenliste des Boards) stehen die Knöpfe
   enger beieinander als in einer Knopfreihe unter einem Formular. */
.knopfreihe--zeile {
  gap: var(--raum-2);
  margin-bottom: 0;
}

/* Dritte Stufe: eine Aktion, die zum Kasten gehört, in dem sie steht —
   „Parameter bearbeiten" neben den Parametern. Sie soll auffindbar sein und
   nicht werben, deshalb Haarlinie statt Akzentkante und kleine Schrift. */
.knopf--leise {
  padding: 0.3rem 0.8rem;
  border-color: var(--kante);
  color: var(--uni-blau);
  font-size: var(--fs-klein);
  font-weight: 600;
}

.knopf--leise:hover {
  border-color: var(--uni-blau);
}

.knopf[disabled],
.knopf[aria-disabled="true"] {
  opacity: 0.4;
  cursor: not-allowed;
}

.knopfreihe {
  display: flex;
  flex-wrap: wrap;
  gap: var(--raum-3);
  align-items: center;
  margin-bottom: var(--raum-4);
}

/* --- Nebenwege -------------------------------------------------------------

   Vierte Stufe und das Gegenstück zur Knopfreihe: Exporte, Rücksprünge,
   Nachschlagewege. Sie sind Ziele, keine Aufgaben. Als gleich große
   Konturknöpfe nebeneinander behaupteten vier Exporte denselben Rang wie der
   Phasenwechsel — vier Knöpfe in einer Reihe sind keine Rangfolge, sondern eine
   Parade (Befund DH).

   Kein Trennzeichen zwischen den Einträgen: Der Abstand trennt, und ein „·" im
   Markup wäre Text in der Vorlesereihe. Unterstrichen sind sie ohnehin. */
.wege {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--raum-2) var(--raum-5);
  margin: 0 0 var(--raum-4);
  padding: 0;
  list-style: none;
  font-size: var(--fs-klein);
}

.wege li + li {
  margin-top: 0;
}

/* Ein Weg, der schreibt, muss ein `button` in einem Formular sein (der
   xlsx-Export protokolliert). Er soll aber aussehen wie seine Nachbarn —
   dieselbe Zeile, dieselbe Rolle, derselbe Rang. */
.textknopf {
  padding: 0;
  border: 0;
  background: none;
  color: var(--uni-blau);
  font: inherit;
  text-align: left;
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}

.textknopf:hover {
  color: var(--uni-blau-80);
  text-decoration-thickness: 2px;
}

/* --- Seitenkopf ----------------------------------------------------------- */

/* Der Kopf einer Arbeitsseite: Vorzeile, Titel und die eine Hauptaktion in
   EINER Zeile, darunter eine Haarlinie.

   Vorher stand auf jeder Seite eine große Überschrift, darunter ein
   Vorspann-Absatz, darunter irgendwann der Inhalt — der Aufbau einer Webseite.
   Ein Werkzeug beginnt mit dem Gegenstand und der Aufgabe; alles Erklärende
   steht weiter unten oder in einem Aufklapper. */
.seitenkopf {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--raum-3) var(--raum-5);
  margin-bottom: var(--raum-6);
  padding-bottom: var(--raum-3);
  border-bottom: 1px solid var(--linie);
}

.seitenkopf__titel {
  min-width: 0;
  flex: 1 1 20rem;
}

.seitenkopf h1 {
  margin-bottom: 0;
}

/* Ein Satz, nicht ein Vorspann: Er steht neben dem Titel im selben Block und
   ist auf eine Zeilenlänge begrenzt. */
.seitenkopf__satz {
  margin: var(--raum-2) 0 0;
  max-width: var(--mass);
  color: var(--text-zweit);
}

/* Die eine Hauptaktion sitzt rechts auf der Grundlinie des Titels. */
.seitenkopf__aktion {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--raum-3);
  margin-left: auto;
}

/* Unter 40 rem steht die Aktion unter dem Titel und über die volle Breite —
   dieselbe Regel wie in der Knopfreihe. */
@media (max-width: 40rem) {
  .seitenkopf__aktion {
    width: 100%;
  }

  .seitenkopf__aktion .knopf {
    width: 100%;
  }
}

/* --- Karten: die gemeinsame Region ---------------------------------------- */

/* Der Baustein gegen „unaufgeräumt": Was zusammengehört, steht in einer
   gemeinsamen, begrenzten Fläche mit einer Beschriftung am Kopf. Eine
   Überschrift allein leistet das nicht — sie sagt, wo etwas anfängt, aber
   nicht, wo es aufhört.

   Zwei Flächenfarben, wie im Regelwerk: Weiß für den Leib, der Flächenton für
   den Kopf. Kante ringsum, keine angesetzte Akzentkante. */
.karte {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--linie);
  border-radius: var(--radius-kasten);
  background: var(--grund);
}

.karte__kopf {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--raum-1) var(--raum-4);
  padding: var(--raum-2) var(--raum-4);
  border-bottom: 1px solid var(--linie);
  background: var(--flaeche-ton);
}

.karte__titel {
  margin: 0;
  font-size: var(--fs-h3);
  font-weight: 600;
  color: var(--uni-blau);
}

/* Eine Zusatzangabe am Kartenkopf — „5 von 5 besetzt", „Stand: eingereicht".
   Rechtsbündig, leise, in derselben Zeile wie der Titel. */
.karte__marke {
  font-size: var(--fs-klein);
  color: var(--text-zweit);
}

.karte__leib {
  padding: var(--raum-4);
}

/* Der Fuß trägt die Aktion, die zu dieser Karte gehört. `margin-top: auto`
   hält ihn im Raster unten, auch wenn die Nachbarkarte höher ist. */
.karte__fuss {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--raum-2) var(--raum-4);
  margin-top: auto;
  padding: var(--raum-3) var(--raum-4);
  border-top: 1px solid var(--linie);
}

/* Der letzte Absatz einer Karte braucht seinen Abstand nach unten nicht — den
   trägt der Innenrand. */
.karte__leib > :last-child,
.karte__fuss > :last-child {
  margin-bottom: 0;
}

/* Eine Zwischenüberschrift innerhalb einer Karte — für die eine Karte, die
   mehrere Listen führt (der Index der Übersicht). Kleiner als der Kartentitel
   und im Fließtext-Ton: Sie ordnet, sie kündigt keinen neuen Bereich an. */
.karte__untertitel {
  margin: 0 0 var(--raum-2);
  font-size: var(--fs-mikro);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-leise);
}

/* Nebeneinander, solange der Platz reicht; darunter gestapelt. `auto-fit` mit
   Mindestbreite statt einer festen Spaltenzahl, damit bei 320 px nichts
   waagerecht überläuft (WCAG 1.4.10). */
.spaltenpaar {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
  gap: var(--raum-4) var(--raum-6);
}

/* Eine Tabelle füllt ihre Karte bis an die Kante; der Innenrand käme sonst
   zweimal (Karte und Zelle) und die Spaltenköpfe stünden eingerückt. */
.karte__leib--tabelle {
  padding: 0;
}

.karte__leib--tabelle .tabelle-huelle {
  margin-bottom: 0;
}

/* Zwei Tabellen in einer Karte (Rechenregeln und Vergleichswert): Die zweite
   bekommt eine Beschriftung mit Luft darüber, sonst liest sie sich als
   Fortsetzung der ersten — und genau das soll sie nicht. */
.karte__leib--tabelle caption {
  padding: var(--raum-3) var(--raum-4) var(--raum-1);
  font-size: var(--fs-mikro);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-leise);
}

.karte__leib--tabelle .tabelle-huelle + .tabelle-huelle {
  border-top: 1px solid var(--linie);
}

.karte__leib--tabelle th:first-child,
.karte__leib--tabelle td:first-child {
  padding-left: var(--raum-4);
}

.karte__leib--tabelle th:last-child,
.karte__leib--tabelle td:last-child {
  padding-right: var(--raum-4);
}

.karte__leib--tabelle tbody tr:last-child > * {
  border-bottom: 0;
}

/* Karten nebeneinander statt untereinander. Auf 1440 px lag rechts neben jedem
   Kasten die halbe Seite brach, während der Inhalt nach unten weglief —
   dieselbe Beobachtung, die schon die Kennzahlenliste zum Raster gemacht hat. */
/* Ohne `align-items: start` sind die Karten einer Zeile gleich hoch. Das ist
   hier gewollt und nicht Zufall: Der Kartenfuß trägt die Aktion, und Aktionen
   sollen auf einer Linie stehen. Die Höhe entsteht ohnehin aus dem Inhalt der
   höchsten Karte, nicht aus einer gesetzten Zahl. */
.kartenraster {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(24rem, 100%), 1fr));
  gap: var(--raum-5);
  margin-bottom: var(--raum-7);
}

/* Grid-Kinder stehen auf `min-width: auto`; ohne diese Zeile schiebt ein
   breites Kind die Seite bei 320 px waagerecht auf (WCAG 1.4.10). */
.kartenraster > * {
  min-width: 0;
}

/* Karten ohne Fuß richten sich oben aus. Die Gleichhöhe von oben ist die Regel,
   weil sie Aktionen auf eine Linie bringt; wo es keine Aktion gibt, erzeugt sie
   nur ein Loch unter der kürzeren Karte (Board: der Fortschrittsbalken neben der
   fünfzeiligen Bilanz). */
.kartenraster--stand {
  align-items: start;
}

/* Eine Karte, die über die ganze Rasterbreite läuft — die Fristentabelle
   neben zwei schmalen Karten sähe sonst gequetscht aus. */
.kartenraster__weit {
  grid-column: 1 / -1;
}

/* Eine Karte außerhalb eines Rasters steht allein und braucht ihren eigenen
   Abstand nach unten. In einem Raster trägt den Abstand die Rasterlücke —
   sonst schöbe der Außenabstand die zweite Karte einer Zeile um seine Höhe nach
   unten, und zwei nebeneinanderstehende Karten begännen auf verschiedenen
   Höhen (in der Abnahme auf /hilfe/ gemessen: 24 px Versatz). */
.karte {
  margin-bottom: var(--raum-5);
}

.kartenraster > .karte,
.hilfe-wege > .karte {
  margin-bottom: 0;
}

/* Die Karte, die die Aufgabe trägt: Ihr Kopf ist die einzige Stelle, an der
   das Kartenraster eine Rangfolge kennt. Eine kräftigere Kante statt einer
   dritten Fläche — die Aufgabe ist wichtiger als der Stand daneben, und das
   soll man sehen, bevor man liest. */
.karte--aufgabe {
  border-color: var(--uni-blau);
}

.karte--aufgabe .karte__kopf {
  border-bottom-color: var(--uni-blau);
}

/* Frist und Datum als Paare nebeneinander statt als lange Säule aus
   dt/dd-Zeilen: Auf 1440 px waren zwei Fristen sechs Zeilen hoch. */
.fristenpaare {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(14rem, 100%), 1fr));
  gap: var(--raum-2) var(--raum-5);
  margin: 0 0 var(--raum-4);
}

.fristenpaare__paar {
  min-width: 0;
}

.fristenpaare dt {
  font-size: var(--fs-klein);
  color: var(--text-zweit);
}

.fristenpaare dd {
  margin: 0;
  font-weight: 600;
}

/* --- Kästen --------------------------------------------------------------- */

/* Struktur trägt die Kante, nicht der Schatten. Keine farbige Kante, keine
   Rundung — beides liest sich sofort als Baukasten von der Stange. */
.kasten {
  padding: 1.25rem 1.4rem;
  border: 1px solid var(--linie);
  border-radius: var(--radius-kasten);
  background: var(--grund);
}

/* Merkmalsliste im Kasten: Begriff über Wert, nicht nebeneinander — bei
   langen Werten (mehrere Lehreinheiten) bricht das sauber um. */
dl.kasten {
  margin: 0 0 var(--raum-5);
  max-width: var(--mass);
}

dl.kasten dt {
  font-size: var(--fs-mikro);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-leise);
}

dl.kasten dd {
  margin: 0 0 var(--raum-3);
}

/* Die Phasenzeile trägt jetzt zwei Sätze: „Wer tut was“ und den nächsten
   Schritt. Der zweite steht als eigener Absatz im `dd` und braucht seinen
   Abstand nach oben, nicht den vollen Absatzabstand nach beiden Seiten. */
dl.kasten dd p {
  margin: var(--raum-2) 0 0;
}

/* Ein Etikett im `dt` — „nächste Frist“, „verstrichen“ — erbt sonst
   Versalien und Sperrung der Merkmalsbeschriftung und wird unlesbar. */
dl.kasten dt .etikett {
  text-transform: none;
  letter-spacing: normal;
  font-weight: 400;
}

/* Kennzahlenkasten als Raster: Sieben Werte untereinander ergaben eine
   halbbreite Säule von sieben Zeilen; die Tabelle, um die es auf der Seite
   geht, begann erst weit darunter — obwohl man Kennzahlen und Zeilen
   gegeneinander liest (Gesamtbedarf gegen Σ Soll, Faktor gegen die Soll-Spalte).
   `auto-fit` mit Mindestbreite: Auf 1440 px drei bis vier Spalten, bei 320 px
   eine — ohne einen zweiten Umbruchpunkt zu pflegen. `dt`/`dd` bleiben als Paar
   zusammen, weil jedes Paar eine eigene Rasterzelle bekommt. */
dl.kasten--kennzahlen {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: var(--raum-2) var(--raum-5);
  max-width: var(--mass-weit);
}

/* Ein `div` je Paar (in einer `dl` erlaubt und schon das Muster von
   `.begriffe`): Ohne Wrapper wären dt und dd eigene Rasterzellen, und ein
   Begriff könnte am Zeilenende stehen, sein Wert am Anfang der nächsten. */
dl.kasten--kennzahlen .kasten__paar {
  min-width: 0;
}

dl.kasten--kennzahlen dd {
  margin-bottom: 0;
}

dl.kasten dd:last-child {
  margin-bottom: 0;
}

/* --- Fußband -------------------------------------------------------------- */

.fussband {
  margin-top: var(--raum-8);
  border-top: 1px solid var(--linie);
  background: var(--flaeche-ton);
  color: var(--text-zweit);
  font-size: var(--fs-klein);
}

.fussband .container {
  padding-block: var(--raum-5);
}

.fussband p {
  margin: 0 0 var(--raum-1);
  max-width: var(--mass-weit);
}

.fussband .leise {
  font-variant-numeric: tabular-nums;
}

/* Der Dev-User-Switch (PRD §8.4). Er soll erkennbar ein Werkzeug sein und
   nicht wie Teil der Anwendung aussehen — deshalb die gestrichelte Kante. */
.devleiste {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--raum-2);
  margin-top: var(--raum-4);
  padding: var(--raum-3);
  border: 1px dashed var(--linie);
}

.devleiste select {
  width: auto;
  min-width: 0;
  max-width: 100%;
  flex: 1 1 18rem;
}

/* --- Besetzungsboard (Welle 5) --------------------------------------------- */

/* Zwei Spalten ab mittlerer Breite: links Personen, rechts Slots (PRD §6.6).
   Auf schmalen Schirmen stapeln sie — die Personenliste zuerst, weil die
   Auswahl der Person der erste Schritt der Selection-first-Bedienung ist. */
.board-spalten {
  display: grid;
  gap: var(--raum-6);
  align-items: start;
}

/* Grid-Kinder stehen auf `min-width: auto` und können nicht unter die
   min-content-Breite ihres Inhalts schrumpfen. Ohne diese Zeile reicht ein
   einziges breites Element in einer Spalte, um die Seite bei 320 px waagerecht
   scrollen zu lassen (WCAG 1.4.10). */
.board-spalten > * {
  min-width: 0;
}

@media (min-width: 56rem) {
  .board-spalten {
    grid-template-columns: minmax(16rem, 1fr) 2fr;
  }
}

.personenliste,
.slotliste {
  list-style: none;
  margin: 0;
  padding: 0;
}

.personenliste .person,
.slotliste .slot {
  border: 1px solid var(--linie);
  border-radius: 0.25rem;
  padding: var(--raum-3) var(--raum-4);
  margin-block-end: var(--raum-3);
}

/* Der Füllstand färbt den ganzen Rahmen und nicht mehr eine angesetzte linke
   Kante: dieselbe Aussage, vollständige Kante. Er wiederholt ohnehin nur, was
   der Satz „besetzt" / „offen" im Slot sagt (WCAG 1.4.1). */
.slotliste .slot[data-status="besetzt"] {
  border-color: var(--uni-blau);
}

/* Fokusziel nach jeder Aktion: Der Slot bekommt den Fokus, damit die
   Sprachausgabe den geänderten Eintrag als Ganzes liest. Der Abstand hält ihn
   beim Anspringen frei vom klebenden Kopfbereich und von der Auswahlleiste;
   er addiert sich zum `scroll-padding-top` des Wurzelelements. */
.slotliste .slot {
  scroll-margin-top: var(--raum-5);
}

.slotliste .slot:focus-visible {
  outline: 2px solid var(--akzent);
  outline-offset: 2px;
}

.person__name {
  font-weight: 600;
  display: block;
}

.person__status {
  display: block;
  color: var(--text-leise);
}

.slot__kopf {
  margin-block-end: var(--raum-1);
}

.besetzen-formular {
  display: flex;
  flex-wrap: wrap;
  gap: var(--raum-2);
  align-items: center;
  margin-block-start: var(--raum-2);
}

/* Hier stand eine Ausnahme: Der Absendeknopf des Slot-Formulars war gefüllt
   und wurde erst bei aktivem JavaScript auf Kontur zurückgenommen
   (`[data-js]`, UX-Befund P9) — ohne JavaScript blieb er der Hauptweg, der er
   dann ist. Bei der Abnahme des GUI-Umbaus gemessen: Das ergibt ohne
   JavaScript siebzehn gefüllte Knöpfe untereinander, einen je Slot. „Ein
   gefüllter Knopf je Ansicht" heißt aber nicht „einer je Entscheidung"; wo es
   siebzehn gleichrangige gibt, ist keiner der eine. Der Knopf trägt jetzt in
   beiden Fällen Kontur (die Klasse steht in `board.html`), und diese Regel
   entfällt ersatzlos. */

/* Der Satz gehört zur Auswahlliste und nicht in die Knopfreihe: Er erklärt,
   was die Wahl einer fremden Person bedeutet (UX-Befund P1). */
.slot__fremdhinweis {
  flex-basis: 100%;
}

/* `min-width: 0` statt eines Mindestmaßes: Ein `select` zieht seine
   min-content-Breite aus der längsten Option („Bea Semamann (Wissenschaft-
   liche:r Mitarbeiter:in)") und schiebt sonst die ganze Seite über 320 px
   hinaus — WCAG 1.4.10. Die Wunschbreite trägt weiterhin die flex-basis. */
.besetzen-formular select {
  width: auto;
  min-width: 0;
  max-width: 100%;
  flex: 1 1 12rem;
}

/* Finalisierungs-Arbeitsliste (PRD §6.6): die beiden Entscheidungswege je
   Slot nebeneinander, gleichwertig — keiner ist der Hauptweg. `min-width: 0`
   aus demselben Grund wie bei .board-spalten (WCAG 1.4.10). */
.entscheidungswege {
  display: grid;
  gap: var(--raum-6);
  align-items: start;
}

.entscheidungswege > * {
  min-width: 0;
}

@media (min-width: 56rem) {
  .entscheidungswege {
    grid-template-columns: 1fr 1fr;
  }
}

/* --- Fortschritt ---------------------------------------------------------- */

.fortschritt-zeile {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--raum-2) var(--raum-4);
}

/* Ein Balken ohne UA-Verlauf: dieselbe Kantenführung wie alles andere. */
progress.fortschritt {
  flex: 0 0 auto;
  width: min(18rem, 100%);
  height: 0.85rem;
  appearance: none;
  border: 1px solid var(--kante);
  border-radius: 0;
  background: var(--grund);
}

progress.fortschritt::-webkit-progress-bar {
  background: var(--grund);
}

progress.fortschritt::-webkit-progress-value {
  background: var(--uni-blau);
}

progress.fortschritt::-moz-progress-bar {
  background: var(--uni-blau);
}

/* --- Selection-first (nur mit JavaScript) --------------------------------- */

/* Alles darunter erscheint erst, wenn das Board-Modul die Seite verbessert
   hat. Ohne JavaScript bleibt die Seite so, wie der Server sie ausliefert. */

.personensuche {
  margin-block-end: var(--raum-4);
}

.personensuche label {
  display: block;
  margin-block-end: var(--raum-1);
  font-weight: 600;
}

.personensuche__treffer {
  margin: var(--raum-1) 0 0;
  font-size: var(--fs-klein);
  color: var(--text-leise);
}

/* Der Name ist die Schaltfläche: ein Ziel statt „Eintrag plus Knopf daneben"
   (WCAG 2.5.5, größere Trefferfläche). */
.person__waehlen {
  display: block;
  width: 100%;
  margin: 0 0 var(--raum-1);
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

/* Der Name muss als Bedienelement zu erkennen sein — sonst sieht die
   Personenliste aus wie eine Liste und niemand klickt sie an. */
.person__waehlen .person__name {
  color: var(--uni-blau);
  text-decoration: underline;
  text-decoration-color: var(--uni-blau-40);
  text-underline-offset: 3px;
}

.person__waehlen:hover .person__name {
  text-decoration-color: currentColor;
  text-decoration-thickness: 2px;
}

/* Die Textmarke trägt die Auswahl; Kante und Fläche verstärken sie nur. */
.person__marke {
  display: none;
}

.person__waehlen[aria-pressed="true"] .person__marke {
  display: inline-block;
  margin-block-start: var(--raum-1);
  padding: 0.05rem 0.4rem;
  border: 1px solid var(--uni-blau);
  border-radius: 0.25rem;
  font-size: var(--fs-mikro);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--uni-blau);
}

/* Die gewählte Person: voller Rahmen in Blau plus Fläche. Die angesetzte
   linke Kante war dieselbe Aussage in schwächerer Form. */
.personenliste .person:has(.person__waehlen[aria-pressed="true"]) {
  border-color: var(--uni-blau);
  background: var(--flaeche-ton);
}

.person--fremd .person__status {
  font-size: var(--fs-klein);
}

/* Die Auswahl bleibt beim Scrollen sichtbar — sonst wählt man eine Person und
   verliert auf dem Weg zum Slot die Rückmeldung, wen man eigentlich setzt.

   Sie liegt seit dem klebenden Kopfbereich ÜBER ihm (z-index 30 gegen 20) und
   nicht darunter. Zwei Gründe: Erstens gibt es keinen verlässlichen Versatz,
   unter den sie sich hängen könnte — die Kopfhöhe schwankt mit dem Umbruch der
   Kopfzeile (115 px bei 1440, 152 px bei 900). Zweitens ist die Rangfolge in
   genau diesem Moment eindeutig: Wer eine Person gewählt hat und zum Slot
   scrollt, braucht „wen setze ich" und nicht „welches Semester". Die Leiste ist
   `hidden`, solange nichts gewählt ist (besetzungsboard.js), verdeckt den Kopf
   also nur während des Einteilens. */
.auswahlleiste {
  position: sticky;
  top: 0;
  z-index: 30;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--raum-3);
  margin-block-end: var(--raum-4);
  padding: var(--raum-2) var(--raum-3);
  /* 2 px, weil sie über dem blauen Band schwebt: Eine Haarlinie auf Uni-Blau
     ist keine Kante mehr, sondern ein Farbwechsel. */
  border: 2px solid var(--uni-blau);
  background: var(--flaeche-ton);
}

.auswahlleiste__name {
  font-weight: 600;
}

.auswahlleiste .knopf {
  padding: 0.25rem 0.8rem;
  font-size: var(--fs-klein);
}

/* Der Knopf ist nie wirklich deaktiviert: Ohne gewählte Person sagt er beim
   Auslösen, was fehlt. Ausgegraut wäre er ein bedienbares Element unterhalb
   des geforderten Kontrasts — die Beschriftung trägt den Zustand. */
.slot__zuweisen[aria-disabled="true"] {
  opacity: 1;
  cursor: pointer;
}

/* Drop-Ziel und Tastaturziel sind dasselbe Element und sehen gleich aus. */
.slot--zielaktiv {
  outline: 2px dashed var(--uni-blau);
  outline-offset: 2px;
  background: var(--flaeche-ton);
}

.slot__meldungen:empty {
  display: none;
}

.slot__meldung {
  margin: var(--raum-2) 0 0;
  padding: var(--raum-2) var(--raum-3);
  border: 1px solid var(--kante);
  font-size: var(--fs-klein);
}

.slot__meldung--warnung {
  background: var(--uni-gelb-20);
}

.slot__meldung--fehler {
  background: var(--uni-rot-20);
  border-color: var(--uni-rot);
}

.slot__meldung__art {
  font-weight: 700;
}

/* --- Schmale Schirme ------------------------------------------------------ */

/* Ohne klebenden Kopf braucht ein Sprungziel auch keinen Platz über sich; der
   großzügige Wert von oben schöbe hier nur Inhalt aus dem Bild. */
@media (max-width: 48rem) {
  :root {
    --kopfhoehe: var(--raum-4);
  }
}

@media (max-width: 40rem) {
  :root {
    --raum-7: 2.25rem;
    --raum-8: 3rem;
  }

  .container {
    padding-inline: var(--raum-4);
  }

  .kopfzeile {
    align-items: flex-start;
  }

  .marke {
    margin-right: 0;
    width: 100%;
  }

  /* Handlungsknöpfe laufen unter 560 px über die volle Breite. */
  .knopfreihe .knopf {
    width: 100%;
  }

  /* Nebenwege nicht: Sie sind Textlinks und sollen keine Knopfreihe werden.
     Zeilenknöpfe auch nicht: Sie gehören zu einem Eintrag der Liste, in der
     sie stehen, und über die volle Breite gezogen sähen sie aus wie die
     Aktion der ganzen Seite. */
  .wege .knopf,
  .wege .textknopf,
  .knopfreihe .knopf--zeile {
    width: auto;
  }
}

/* --- Bewegung, Druck, Kontrastmodus --------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* Belegliste der Transparenz-Ansicht: aufklappbar, weil sie der Nachweis der
   Zahl daneben ist und nicht das, was man zuerst liest. Voller Rahmen statt
   angesetzter Kante — ein Aufklapper ist ein Kasten mit einem Deckel. */
details.beleg,
details.aufklapp {
  max-width: var(--mass-weit);
  margin-block: var(--raum-4);
  padding: 0 var(--raum-3);
  border: 1px solid var(--linie);
}

/* Nebeneingang eines Formulars: die Spaltenzuordnung des PA-Imports ändert man
   nur bei einer Formatumstellung, sehen muss man sie trotzdem. `details`
   bringt die Tastaturbedienung mit, ohne eine Zeile JavaScript. */
details.aufklapp {
  max-width: var(--mass);
}

details.beleg > summary,
details.aufklapp > summary {
  cursor: pointer;
  padding-block: var(--raum-2);
  font-weight: 600;
}

/* Der aufgeklappte Inhalt braucht den Abstand zum Deckel; zugeklappt soll der
   Kasten so hoch sein wie seine Zeile. */
details.beleg[open] > :not(summary):last-child,
details.aufklapp[open] > :not(summary):last-child {
  margin-bottom: var(--raum-3);
}

/* Konsistenz-Selbstcheck: eine Ampel-Liste. Die Farbe steht am linken Rand,
   die Stufe zusätzlich als Wort — Farbe allein ist kein Merkmal (WCAG 1.4.1). */
.pruefliste {
  list-style: none;
  margin: var(--raum-4) 0 0;
  padding: 0;
}

/* Die Stufe färbt den ganzen Rahmen, nicht eine 6-px-Kante an der linken Seite.
   Die Stufe steht zusätzlich als Wort in `.pruefung__stufe` — Farbe allein ist
   kein Merkmal (WCAG 1.4.1). */
.pruefung {
  margin-block: var(--raum-3);
  padding: var(--raum-3);
  border: 1px solid var(--kante);
  background: var(--grund);
}

.pruefung--ok {
  border-color: var(--uni-blau);
}

/* Ausgefallener Prüfschritt: ausdrücklich neutral, damit er nicht wie ein
   bestandener aussieht. Die Kante bleibt das Grau der Grundregel. */
.pruefung--nicht_anwendbar {
  border-color: var(--uni-grau);
}

.pruefung--warnung {
  border-color: var(--uni-grau);
  background: var(--uni-gelb-20);
}

.pruefung--fehler {
  border-color: var(--uni-rot);
  background: var(--uni-rot-20);
}

.pruefung__titel {
  margin: 0 0 var(--raum-2);
  font-size: var(--fs-h3);
}

.pruefung__stufe {
  display: inline-block;
  margin-right: var(--raum-2);
  padding: 0.1em 0.5em;
  border: 1px solid var(--kante);
  background: var(--grund);
  font-size: var(--fs-klein);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* Filterleiste der Historie: die Felder nebeneinander, solange Platz ist. */
.filterleiste {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--raum-3);
  margin-block: var(--raum-4);
}

.filterleiste .feld {
  margin: 0;
}

.blaettern {
  display: flex;
  gap: var(--raum-3);
  margin-block: var(--raum-4);
}

/* --- Symbole (Heroicons, inline) ------------------------------------------ */

/* Ein Symbol steht immer neben Text, nie an seiner Stelle (WCAG 1.4.1) —
   deshalb bemisst es sich an der Schrift und nicht an einer festen Größe. */
.ikone {
  width: 1.15em;
  height: 1.15em;
  /* Ohne die Korrektur sitzt das Quadrat auf der Grundlinie und damit optisch
     zu hoch neben Ziffern. */
  vertical-align: -0.2em;
  flex: 0 0 auto;
}

/* --- Inline-Erklärung am Ort der Zahl ------------------------------------- */

/* Aufklappbar per `details`: nativ mit der Tastatur bedienbar, ohne eine Zeile
   Skript, und dasselbe Muster wie die Belegliste der Transparenz-Ansicht. */
.erklaerung {
  display: inline-block;
  position: relative;
  /* Die Blase liegt über allem, was danach kommt — auch über der nächsten
     Tabellenzeile. */
  z-index: 2;
}

.erklaerung__knopf {
  display: inline-flex;
  align-items: center;
  cursor: help;
  color: var(--akzent);
  /* Die Fläche muss die 24-px-Marke erreichen (WCAG 2.5.8), ohne die Zeile
     auseinanderzuziehen. */
  padding: 0.15rem;
  margin: -0.15rem;
  border-radius: var(--radius-steuer);
  /* Der Dreiecks-Marker von `summary` würde neben dem (i) ein zweites Symbol
     setzen. */
  list-style: none;
}

.erklaerung__knopf::-webkit-details-marker {
  display: none;
}

.erklaerung__knopf:hover {
  color: var(--uni-blau-80);
}

.erklaerung__blase {
  position: absolute;
  /* Rechts ausgerichtet: In den Zahlenspalten steht das (i) am rechten Rand,
     eine linksbündige Blase liefe aus der Tabelle heraus. */
  right: 0;
  top: calc(100% + var(--raum-1));
  width: min(30rem, 78vw);
  padding: var(--raum-4);
  border: 1px solid var(--kante);
  background: var(--grund);
  /* Ohne Schatten (Regelwerk); getrennt wird über die Haarlinie und die
     Fläche. Die Blase liegt auf Weiß, damit sie auch über dem Flächenton
     lesbar bleibt. */
  font-size: var(--fs-klein);
  font-weight: 400;
  text-align: left;
  white-space: normal;
  color: var(--text);
}

.erklaerung__wort {
  margin: 0;
  font-weight: 700;
}

.erklaerung__formel {
  margin: var(--raum-2) 0 0;
  font-variant-numeric: tabular-nums;
  color: var(--text-zweit);
}

.erklaerung__text {
  margin: var(--raum-2) 0 0;
}

.erklaerung__mehr {
  margin: var(--raum-3) 0 0;
  font-size: var(--fs-mikro);
}

/* In einer Kopfzelle klebt die Blase sonst an der Zellgrenze. */
th .erklaerung,
td .erklaerung {
  position: static;
}

th .erklaerung__blase,
td .erklaerung__blase {
  /* Bezug ist dann die Zelle; sie braucht dafür einen Positionskontext. */
  top: auto;
}

th:has(.erklaerung),
td:has(.erklaerung) {
  position: relative;
}

/* --- Offengelegte Rechnung ------------------------------------------------ */

/* Soll, Ist und Saldo nebeneinander sind irreführend, solange der Übertrag
   fehlt: Ein Ist unter dem Soll liest sich als Rückstand, obwohl der Saldo
   positiv sein kann. Deshalb steht die Rechnung als Rechnung da — mit den
   Operatoren zwischen den Gliedern. */
.bilanz {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--raum-2) var(--raum-3);
  margin-block: var(--raum-3);
}

.bilanz__glied {
  display: inline-flex;
  align-items: baseline;
  gap: 0.35rem;
  white-space: nowrap;
  color: var(--text-zweit);
}

.bilanz__glied .zahl {
  color: var(--text);
}

/* Das Ergebnis hebt sich über Schriftfarbe und -stärke ab, nicht über eine
   zusätzliche Kante: Neben dem „=" las sich die 3-px-Kante wie ein
   versehentlicher Strich. Das Gleichheitszeichen markiert das Ergebnis schon. */
.bilanz__glied--ergebnis {
  color: var(--text);
  font-weight: 600;
}

.bilanz__zeichen {
  font-variant-numeric: tabular-nums;
  color: var(--text-leise);
}

/* --- Begriffsliste unter einer Zahlentabelle ------------------------------ */

/* Auf 1440 px lag rechts neben jeder Tabelle die halbe Seitenbreite brach; die
   Liste füllt sie, statt die Seite länger zu machen. */
.begriffe {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr));
  gap: var(--raum-4) var(--raum-6);
  margin-block: var(--raum-5);
  max-width: var(--mass-weit);
  font-size: var(--fs-klein);
}

.begriffe__paar {
  border-top: 1px solid var(--linie);
  padding-top: var(--raum-2);
}

.begriffe dt {
  font-weight: 700;
}

.begriffe dd {
  margin: var(--raum-1) 0 0;
  color: var(--text-zweit);
}

/* Die Formel gehört zum Begriff, trägt aber nicht dessen Gewicht. */
.begriffe__formel {
  font-weight: 400;
  font-variant-numeric: tabular-nums;
  color: var(--text-leise);
  white-space: nowrap;
}

/* Die längste Formel („Restbedarf = Soll − zugeteilt − Anrechnung −
   Übertrag") ist rund 395 px breit und schob mit `nowrap` die Zuweisungsseite
   bei 320 px waagerecht auf (WCAG 1.4.10, in der Abnahme gefunden). Oberhalb
   dieser Schwelle passt sie in eine Zeile und bleibt dort; darunter darf sie
   umbrechen. `normal` erzwingt keinen Umbruch, es erlaubt ihn nur. */
@media (max-width: 30rem) {
  .begriffe__formel {
    white-space: normal;
  }
}

.begriffe__paar--mehr {
  border-top: 0;
  align-self: end;
}

/* --- Glossarseite --------------------------------------------------------- */

.glossar {
  margin: var(--raum-5) 0 0;
  max-width: var(--mass-weit);
}

/* Themengruppe: eine Zwischenüberschrift, kein neues Farbvokabular. Die
   Gruppen sind die Antwort darauf, dass eine Nachschlageseite mit 35 Einträgen
   am Stück nicht mehr durchsucht, sondern gescrollt wird. */
.glossar__gruppe {
  margin-top: var(--raum-7);
  font-size: var(--fs-klein);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-leise);
}

.glossar__eintrag {
  padding-block: var(--raum-4);
  border-top: 1px solid var(--linie);
}

.glossar__eintrag:last-child {
  border-bottom: 1px solid var(--linie);
}

/* Angesprungener Eintrag: Wer aus einer (i)-Erklärung hierher kommt, soll ohne
   Suchen sehen, welcher Begriff gemeint war. */
.glossar__eintrag:target {
  background: var(--flaeche-ton);
  box-shadow: -0.75rem 0 0 var(--flaeche-ton), 0.75rem 0 0 var(--flaeche-ton);
}

.glossar dt {
  font-weight: 700;
}

.glossar dd {
  margin: var(--raum-2) 0 0;
  max-width: var(--mass);
}

.glossar dd p {
  margin: 0;
}

.glossar__formel {
  margin-bottom: var(--raum-2) !important;
  font-variant-numeric: tabular-nums;
  color: var(--text-zweit);
}

.glossar-phasen {
  list-style: none;
  margin: var(--raum-5) 0 0;
  padding: 0;
  max-width: var(--mass-weit);
}

/* Acht Stufen als acht vollständig gerahmte Kästen. Vorher trug jede eine
   angesetzte linke Kante — dieselbe Form, die die Fehlerzuordnung im Formular
   benutzt, hier aber ohne deren Aufgabe. */
.glossar-phasen__stufe {
  margin-block: var(--raum-3);
  padding: var(--raum-3) var(--raum-4);
  border: 1px solid var(--linie);
}

.glossar-phasen__stufe:target {
  border-color: var(--akzent);
  background: var(--flaeche-ton);
}

.glossar-phasen__name {
  margin: 0;
  font-weight: 700;
}

.glossar-phasen__nummer {
  display: inline-block;
  min-width: 1.6em;
  margin-right: var(--raum-2);
  padding: 0.05em 0.35em;
  border: 1px solid var(--kante);
  font-variant-numeric: tabular-nums;
  text-align: center;
}

.glossar-phasen__text {
  margin: var(--raum-1) 0 0;
  max-width: var(--mass);
  color: var(--text-zweit);
}

/* --- Prozessdoku (/hilfe/) ------------------------------------------------ */

/* Die Doku benutzt kein eigenes Formvokabular: Kante statt Schatten, quadrat,
   höchstens zwei Flächenfarben (Weiß und der Flächenton). Neu ist allein das
   Phasenband weiter unten — und das ist neu, weil es etwas zeigt, das keine
   Liste zeigen kann. */

/* Die beiden Wege des Einstiegs. `auto-fit` statt zweier fester Spalten: Für
   einen Melder gibt es nur einen Kasten, und der soll nicht als halbe Seite
   dastehen.

   `min(20rem, 100%)` und nicht bloß `20rem`: Eine Spur von 20rem ist bei 320 px
   genau die Fensterbreite — zusammen mit dem Innenrand des Containers schob sie
   die Seite um 16 px nach rechts und erzwang den Querlauf, den WCAG 1.4.10
   ausschließt. Das `min` lässt die Spur unter der Schwelle mitschrumpfen. */
.hilfe-wege {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(20rem, 100%), 1fr));
  gap: var(--raum-5);
  margin-block: var(--raum-5) var(--raum-7);
  max-width: var(--mass-weit);
}

/* Den abgesetzten Fuß bringt `.karte` mit (`margin-top: auto` am `karte__fuss`):
   Nebeneinander stehen die beiden Knöpfe auf einer Linie, auch wenn der eine
   Text eine Zeile länger ist. */
.hilfe-weg p {
  max-width: none;
}

/* Sprungliste am Seitenkopf. Die Doku ist lang, und wer mitten im Semester
   herkommt, sucht eine Phase und nicht den Anfang. */
.hilfe-inhalt {
  margin-block: var(--raum-5);
  padding: var(--raum-3) 0;
  border-block: 1px solid var(--linie);
}

/* `align-items: baseline` und der Entzug des Listenabstands sind hier kein
   Feinschliff, sondern der Fehler selbst: Ohne beides erbt jedes Element ab dem
   zweiten das globale `li + li { margin-top: 0.25rem }`. In einer Flex-Zeile
   mit `stretch` wird der erste Eintrag dadurch 4 px höher als seine Nachbarn
   und seine Schrift sitzt 4 px weiter oben — die Leiste sprang auf der
   Grundlinie (Befund DH). Dieselbe Vorsorge steht bei `.hauptnav`, `.unternav`
   und `.wege`. */
.hilfe-inhalt ul {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--raum-2) var(--raum-5);
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: var(--fs-klein);
}

.hilfe-inhalt li + li {
  margin-top: 0;
}

/* Eine Marke vor einer Aussage: „Frist", „Am Zug", „Vor dem Weiterschalten".
   Dasselbe Muster wie die Merkmalsliste im Kasten — versale Mikroschrift, die
   die Zeile einordnet, ohne ihr Gewicht zu nehmen. */
.hilfe-marke,
.phasenband__marke {
  display: inline-block;
  margin-right: var(--raum-2);
  font-size: var(--fs-mikro);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-leise);
}

/* Ein Phasenabschnitt der beiden Leitfäden. Vollständig gerahmt wie die Stufen
   auf der Glossarseite: Beide Seiten reden über dieselben acht Zustände, und
   ein Abschnitt einer Checkliste hat einen Anfang und ein Ende. */
.hilfe-phase {
  margin-block: var(--raum-5);
  padding: var(--raum-4) var(--raum-5);
  border: 1px solid var(--linie);
  max-width: var(--mass-weit);
}

.hilfe-phase:target {
  border-color: var(--akzent);
  background: var(--flaeche-ton);
}

.hilfe-phase__kopf {
  display: flex;
  align-items: baseline;
  gap: var(--raum-3);
  margin: 0;
  font-size: var(--fs-h3);
}

.hilfe-phase__nummer,
.phasenband__nummer {
  flex: none;
  min-width: 1.7em;
  padding: 0.05em 0.35em;
  border: 1px solid var(--kante);
  font-size: var(--fs-klein);
  font-variant-numeric: tabular-nums;
  text-align: center;
}

/* Der Satz aus kern/glossar.py — er ordnet ein, er ist nicht die Anweisung.
   Deshalb zweite Textstufe und kursiv gegen den Rest abgesetzt. */
.hilfe-phase__satz {
  margin: var(--raum-2) 0 var(--raum-4);
  max-width: var(--mass);
  color: var(--text-zweit);
  font-style: italic;
}

.hilfe-phase__rolle,
.hilfe-phase__frist,
.hilfe-phase__pruefen {
  margin: var(--raum-4) 0 0;
  max-width: var(--mass);
}

.hilfe-phase__frist,
.hilfe-phase__pruefen {
  padding: var(--raum-3) var(--raum-4);
  background: var(--flaeche-ton);
}

/* Der Riegel ist die schwerste Aussage einer Phase: ab hier gibt es kein
   Zurück. Er trägt deshalb eine volle Kante statt einer Fläche — und das Wort
   „Kein Zurück" daneben, weil eine Kante allein keine Bedeutung trägt. */
.hilfe-phase__riegel {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--raum-2);
  margin: var(--raum-4) 0 0;
  padding: var(--raum-3) var(--raum-4);
  border: 2px solid var(--text);
  max-width: var(--mass);
}

.hilfe-phase__riegel .ikone {
  align-self: center;
}

.hilfe-schritte {
  margin: var(--raum-3) 0 0;
  padding-left: 1.4rem;
  max-width: var(--mass);
}

.hilfe-schritte li {
  margin-bottom: var(--raum-3);
}

/* Der Weg in die Maske steht am Ende des Schritts und sieht aus wie ein Ziel,
   nicht wie ein Wort im Satz. Kein Knopf: Es sind bis zu vier je Abschnitt, und
   vier Knöpfe nebeneinander sind keine Anleitung mehr, sondern ein Menü. */
/* Kein `nowrap`: „→ Aufsichtenliste für das Prüfungsamt" ist bei 320 px breiter
   als die Seite und schob sie waagerecht auf (WCAG 1.4.10, in der Abnahme
   gemessen). Der Pfeil bleibt am Zeilenanfang stehen, der Rest darf umbrechen. */
.hilfe-maske {
  display: inline-block;
  margin-top: var(--raum-1);
  font-size: var(--fs-klein);
  font-weight: 600;
  overflow-wrap: break-word;
}

.hilfe-maske::before {
  content: "→ ";
}

.hilfe-fall {
  margin-block: var(--raum-5);
  padding-bottom: var(--raum-4);
  border-bottom: 1px solid var(--linie);
  max-width: var(--mass-weit);
}

.hilfe-fall h3 {
  margin-top: 0;
}

/* --- Mails: was das System schickt, was das Dekanat schreibt --------------- */

.mailkasten {
  margin-top: var(--raum-5);
  padding: var(--raum-4);
  border: 1px solid var(--linie);
  max-width: var(--mass-weit);
}

.mailkasten__titel {
  margin: 0 0 var(--raum-3);
  font-size: var(--fs-klein);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-leise);
}

.mailkasten__liste {
  margin: 0;
  font-size: var(--fs-klein);
}

.mailkasten__liste dt {
  font-weight: 700;
}

.mailkasten__liste dd {
  margin: 0 0 var(--raum-3);
  color: var(--text-zweit);
}

.mailkasten__liste dd:last-child {
  margin-bottom: 0;
}

.mailvorlage {
  margin-top: var(--raum-5);
  max-width: var(--mass-weit);
}

.mailvorlage__titel {
  margin: 0 0 var(--raum-2);
  font-size: var(--fs-h3);
}

.mailvorlage__wann,
.mailvorlage__betreff {
  margin: 0 0 var(--raum-2);
  font-size: var(--fs-klein);
}

.mailvorlage__betreff {
  font-weight: 600;
}

/* `pre` wegen des Zeilenfalls, nicht wegen der Schreibmaschine: Es ist ein
   Anschreiben und kein Programm — deshalb die Grundschrift und nicht die
   dicktengleiche. `pre-wrap` samt Wortumbruch hält die Vorlage bei 320 px im
   Kasten (WCAG 1.4.10); `user-select: all` wäre hier falsch, weil man in aller
   Regel nur einen Absatz übernimmt. */
.mailvorlage__text {
  margin: 0;
  /* Der Kasten legt sich um die längste Zeile statt über die halbe Seite: Der
     Zeilenfall ist auf 78 Zeichen gesetzt, und ein Kasten mit 300 px leerem
     Rand rechts sieht aus, als fehlte dort etwas. */
  width: fit-content;
  max-width: 100%;
  padding: var(--raum-4);
  border: 1px solid var(--linie);
  background: var(--flaeche-ton);
  font-family: inherit;
  font-size: var(--fs-klein);
  line-height: 1.55;
  white-space: pre-wrap;
  overflow-wrap: break-word;
  tab-size: 2;
}

.mailvorlage__hinweis {
  margin: var(--raum-2) 0 0;
  max-width: var(--mass);
  font-size: var(--fs-klein);
}

/* --- Das Phasenband (/hilfe/schaubild/) ----------------------------------- */

/* Zwei Spuren: links das Dekanat, rechts die Lehreinheiten. Die Bewegung
   zwischen den Spuren ist die Aussage des Bildes — sie zeigt, dass die Arbeit
   den Träger wechselt und nicht nur weiterläuft (PRD §1.2). Die Position trägt
   die Bedeutung nie allein: Jede Station nennt den Handelnden als Text
   (WCAG 1.3.1, 1.4.1). */
.phasenband-spuren {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--raum-4);
  margin: var(--raum-6) 0 var(--raum-2);
  max-width: var(--mass-weit);
}

.phasenband-spuren__kopf {
  padding-bottom: var(--raum-2);
  border-bottom: 2px solid var(--uni-blau);
  font-size: var(--fs-mikro);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-zweit);
}

/* Der Mittelstrich als Hintergrund und nicht als Element: Er ist die Achse, an
   der die Stationen hängen, und darf im Umbruch auf eine Spalte rückstandslos
   verschwinden. */
.phasenband {
  display: grid;
  grid-template-columns: 1fr 1fr;
  /* Ohne `start` zöge eine Station ihre Zeilennachbarin auf die eigene Höhe —
     die Vorbereitung bekäme den leeren Fuß der Meldephase, die eine Frist trägt
     und sie nicht. Kästen sollen so hoch sein wie ihr Inhalt. */
  align-items: start;
  gap: var(--raum-4);
  margin: 0 0 var(--raum-6);
  padding: var(--raum-4) 0;
  max-width: var(--mass-weit);
  list-style: none;
  background: linear-gradient(var(--uni-blau-40), var(--uni-blau-40)) center / 1px 100%
    no-repeat;
}

/* Vollständige Kante, keine angesetzte. Vorher trug jede Station eine 3-px-Kante
   auf der Seite, die zur Achse zeigt — als Bild schlüssig, im Ergebnis aber ein
   Kasten mit drei dünnen und einer dicken Seite, und je nach Spur mal links,
   mal rechts, mal beidseitig. Was die Station der Achse zuordnet, ist ihre
   Spalte, die Achse selbst und der Satz „Am Zug: …" in ihrem Text (WCAG 1.3.1).
   Die Kantenfarbe unterscheidet nur noch, ob eine Station einer Spur gehört
   (Haarlinie) oder beiden (Blau, volle Breite). */
.phasenband__station {
  padding: var(--raum-3) var(--raum-4);
  border: 1px solid var(--linie);
  background: var(--grund);
}

.phasenband__station--dekanat {
  grid-column: 1;
}

.phasenband__station--lehreinheiten {
  grid-column: 2;
}

.phasenband__station--beide {
  grid-column: 1 / -1;
  border-color: var(--uni-blau);
}

.phasenband__station:target {
  background: var(--flaeche-ton);
}

.phasenband__kopf {
  display: flex;
  align-items: baseline;
  gap: var(--raum-2);
  margin: 0;
  font-weight: 700;
}

.phasenband__akteur {
  margin: var(--raum-2) 0 0;
  font-size: var(--fs-klein);
}

.phasenband__text {
  margin: var(--raum-2) 0 0;
  font-size: var(--fs-klein);
  color: var(--text-zweit);
}

.phasenband__frist {
  margin: var(--raum-3) 0 0;
  padding-top: var(--raum-2);
  border-top: 1px solid var(--linie);
  font-size: var(--fs-klein);
}

/* Der Riegel liegt quer über beide Spuren: Er gehört keiner Phase, sondern dem
   Übergang zwischen zweien. Er ist das schwerste Element des Bildes und trägt
   dafür die schwerste Kante — aber ringsum. Ein Paar aus Ober- und Unterkante
   war zwar symmetrisch, aber immer noch ein halber Rahmen; mit dem vollen
   liest er sich weiterhin als Schlagbaum, und der Text daneben sagt dasselbe
   noch einmal. */
.phasenband__riegel {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--raum-1) var(--raum-3);
  padding: var(--raum-3) var(--raum-4);
  border: 3px solid var(--text);
  background: var(--flaeche-ton);
}

.phasenband__riegel .ikone {
  align-self: center;
}

.phasenband__riegel-marke {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.phasenband__riegel-text {
  flex: 1 1 18rem;
  font-size: var(--fs-klein);
  color: var(--text-zweit);
}

/* Unter zwei lesbaren Spalten fällt das Band auf eine zurück: Zwei Spuren à
   150 px sind keine zwei Spuren mehr, sondern zwei Spalten Silbentrennung. Der
   Text jeder Station nennt den Handelnden ohnehin. */
@media (max-width: 52rem) {
  .phasenband-spuren {
    display: none;
  }

  .phasenband {
    grid-template-columns: 1fr;
    background: none;
  }

  .phasenband__station--dekanat,
  .phasenband__station--lehreinheiten,
  .phasenband__station--beide {
    grid-column: 1;
  }
}

/* Druckansichten sind laut PRD §8.2 der Weg zu PDF — deshalb sind sie hier
   Grundausstattung und keine Nacharbeit. */
@media print {
  /* Ein klebender Kopf auf Papier klebt an der ersten Seite und deckt dort den
     Anfang des Textes zu. Auf Papier gibt es keinen Bildlauf und damit keinen
     Grund für die Klebrigkeit; `static` gilt für den Rahmen, den Inhalt des
     Kopfbands blendet die Regel darunter ohnehin aus. */
  .kopfbereich {
    position: static;
  }

  .sprungmarke,
  .kopfband,
  .sprachwahl,
  .unternav,
  .nicht-drucken,
  .knopfreihe,
  .erklaerung,
  /* Die Sprungliste der Prozessdoku ist ein Bedienelement: Auf Papier führen
     ihre Anker nirgendwohin, die Überschriften stehen ohnehin darunter. */
  .hilfe-inhalt {
    display: none !important;
  }

  /* Die Prozessdoku ist zum Ausdrucken gebaut (Abnahmekriterium): Sie ist das,
     was ein Sekretariat neben die Tastatur legt. Deshalb hier drei Zusagen. */

  /* Erstens: Eine Mailvorlage wird nicht über zwei Seiten zerrissen, und sie
     wird vollständig gesetzt — `pre-wrap` bleibt, ein abgeschnittener Satz
     wäre eine unbrauchbare Vorlage. */
  .mailvorlage,
  .mailkasten,
  .hilfe-phase__riegel,
  .phasenband__station,
  .phasenband__riegel {
    break-inside: avoid;
  }

  .mailvorlage__text {
    white-space: pre-wrap;
    overflow: visible;
    border: 1pt solid #000;
    background: #fff;
    font-size: 9.5pt;
  }

  /* Zweitens: Ein Phasenabschnitt beginnt möglichst auf einer Seite und nicht
     mit der Überschrift am Fuß der vorigen. */
  .hilfe-phase {
    break-inside: avoid;
  }

  .hilfe-phase__kopf,
  .mailvorlage__titel {
    break-after: avoid;
  }

  /* Drittens das Phasenband. Es braucht hier keine eigene Umbruchregel: Die
     Seitenbreite ist im Druck die Breite des Papiers, und die 52-rem-Schwelle
     oben entscheidet damit von selbst richtig — A4 quer (rund 70 rem) behält
     die beiden Spuren, A4 hochkant (rund 50 rem) fällt auf die einspaltige
     Liste zurück. Beides ist eine gültige Fassung des Bildes.

     Was hier steht, ist nur die Umstellung auf Schwarz-Weiß: Fläche und
     Blauton verschwinden auf einem Laserdrucker in dasselbe Grau, und der
     Riegel verlöre genau die Auszeichnung, die ihn ausmacht. */
  .phasenband {
    background: none;
    gap: 6pt;
  }

  .phasenband__station {
    border-color: #000;
    background: #fff;
  }

  .phasenband__riegel {
    border-block-color: #000;
    background: #fff;
  }

  .hilfe-phase__frist,
  .hilfe-phase__pruefen {
    border: 0.5pt solid #000;
    background: #fff;
  }

  /* Die Tabellen der Druckfassungen (PA-Plan, Einsatzplan, Versandfassung)
     sollen aufs Papier passen, nicht in einen Bildlaufkasten: Der Rahmen mit
     `overflow` ist eine Bildschirmhilfe. */
  .tabelle-huelle {
    overflow: visible !important;
    border: 0;
  }

  .drucktabelle {
    font-size: 9pt;
  }

  /* Aufgeklappte Belege drucken mit; ein `details` ohne `open` bliebe sonst
     leer auf dem Papier. */
  details.beleg > summary {
    font-weight: 700;
  }

  body {
    font-size: 10.5pt;
    color: #000;
    background: #fff;
  }

  h1,
  h2,
  h3,
  h4,
  a {
    color: #000;
  }

  .fussband,
  .kontextleiste {
    background: #fff;
    border-color: #000;
  }

  th,
  td {
    border-bottom: 0.5pt solid #000;
  }

  tr,
  .kasten,
  .karte {
    break-inside: avoid;
  }

  /* Der Kartenkopf verliert auf dem Laserdrucker seinen Flächenton und damit
     die Trennung zum Leib; die Haarlinie darunter trägt sie dann allein. */
  .karte__kopf {
    background: #fff;
    border-bottom-color: #000;
  }

  .karte,
  .karte__fuss {
    border-color: #000;
  }
}

/* Im Windows-Kontrastmodus verschwinden Flächen; die Kanten müssen bleiben. */
@media (forced-colors: active) {
  .kasten,
  .karte,
  .meldung,
  .knopf,
  .slot__meldung,
  progress.fortschritt,
  input,
  select,
  textarea {
    border: 1px solid CanvasText;
  }

  /* Auswahl- und Drop-Zustand hängen im Kontrastmodus sonst an Flächen, die
     dort verschwinden. */
  .personenliste .person:has(.person__waehlen[aria-pressed="true"]),
  .slot--zielaktiv {
    outline: 2px solid Highlight;
  }

  :focus-visible {
    outline-color: Highlight;
  }
}
