/* ===========================================================================
   ZEUGNIS – Oberfläche

   Gestaltungsrichtung: **amtliches Papier, neu gesetzt** – seit dem
   6. August 2026 in den warmen Neutraltönen der Claude-App: Cremeweiß als
   Grund, ein fast schwarzes Anthrazit als Tinte, Terrakotta als einziger
   Markenton.

   ⚠️ **Warum der Wechsel: damit Rot und Grün wieder etwas bedeuten.**
   Vorher war das Markenrot (Siegelrot) dem Fehlerrot so ähnlich, dass eine
   rote Zeile in der Klassenübersicht neben roten Überschriften, roten
   Marken und roten Trennlinien unterging – und genau diese Zeile ist die
   eine, die auffallen muss. Jetzt gilt:

     · Terrakotta  = Marke und Anklickbares. Keine Aussage über ein Kind.
     · Grün        = erfüllt.
     · Bernstein   = gefährdet (Halbjahr).
     · Rot         = nicht versetzt (Jahreszeugnis).

   Die drei Aussagefarben stehen **gefüllt** – weiße Schrift auf sattem
   Grund – und nicht als zarte Tönung. Eine Aussage über ein Kind darf nicht
   aussehen wie eine Verzierung.

   Konventionen:
   – Alle Farben stehen als Token unter :root. Sonst steht keine Farbe
     irgendwo im Quelltext, und JavaScript setzt keine Inline-Stile
     (KI/04 § D8).
   – Keine externen Schriften: Die CSP erlaubt nur `self`, und eine
     eingefrorene Zeugnisausgabe darf ohnehin von keinem fremden Server
     abhängen. Die Stapel unten bestehen aus Schriften, die auf Windows und
     macOS vorhanden sind, mit ehrlichem Rückfall.
   =========================================================================== */

:root {
  /* ---- Schrift ------------------------------------------------------- */
  /* Überschriften und Marke: die Urkunden-Lage. */
  --schrift-display: "Palatino Linotype", Palatino, "Book Antiqua",
                     "Iowan Old Style", Georgia, "Times New Roman", serif;
  /* Oberfläche: humanistische Grotesk mit echten Tabellenziffern. Corbel und
     Candara setzen Ziffern von Haus aus als Mediävalziffern – für ein
     Notenraster falsch. `font-variant-numeric` unten stellt sie um. */
  --schrift-ui: Corbel, Candara, "Segoe UI", "Helvetica Neue", Helvetica, sans-serif;
  --schrift-mono: "Cascadia Mono", Consolas, "SF Mono", "DejaVu Sans Mono", monospace;

  /* ---- Papier und Tinte ---------------------------------------------- */
  --papier:        #faf9f5;   /* Cremeweiß – der Grund der Claude-App */
  --flaeche:       #ffffff;   /* der beschriebene Bogen */
  --flaeche-tief:  #f2f0ea;
  --tinte:         #141413;
  --tinte-matt:    #5d5c55;
  --tinte-fern:    #8f8d85;
  --linie:         #e6e4dc;
  --linie-stark:   #cbc8bd;

  /* ---- Akzente -------------------------------------------------------- */
  /* Terrakotta: Marke UND alles Anklickbare. Ein Akzent, nicht zwei –
     zwei Markenfarben nebeneinander lassen die dritte (die Aussagefarbe)
     nicht mehr durch. Nie für eine Aussage über ein Kind. */
  --amt:        #b8543a;
  --amt-hell:   #fbeee9;
  --amt-tief:   #96412c;
  /* Dasselbe Terrakotta trägt das Siegel. Die Token bleiben getrennt,
     damit Marke und Bedienung später wieder auseinandergehen können. */
  --siegel:     #b8543a;
  --siegel-hell:#fbeee9;

  /* ---- Die zwei Zuständigkeitsfarben ---------------------------------
     Terrakotta sagt „anklickbar", die drei Aussagefarben sagen etwas über
     ein Kind. Beides taugt nicht, um zu zeigen, WER gerade handelt. Dafür
     diese zwei – sie stehen nie in einer Notenzelle:

     `--amtsblau`  Verwaltung, Archiv, Technik: die Bereiche der Schulleitung.
                   Wer beides ist – Klassenleitung und Schuladmin –, hat in
                   derselben Kopfzeile beide Rollen stehen.
     `--leitung`   die eigene Klassenleitung: Petrol, weil es neben dem
                   Terrakotta eindeutig eine andere Farbe ist und nicht mit
                   Grün („gut") oder Rot („gefährdet") verwechselt wird.

     ⚠️ Beide tragen nie eine Aussage allein. Neben der Farbe steht immer das
     Wort – „Klassenleitung" an der Kachel, der Name des Bereichs im Reiter. */
  --amtsblau:      #4a5484;
  --amtsblau-hell: #ecedf7;
  --leitung:       #1c6a74;
  --leitung-hell:  #e3f1f2;
  --leitung-rand:  #9ac8cd;

  /* ---- Die drei Aussagefarben ----------------------------------------
     Je Farbe drei Werte: `-fest` ist der gefüllte Grund (weiße Schrift),
     die Grundvariante ist die Schriftfarbe auf hellem Grund, `-hell` die
     Zeilentönung, `-rand` die Linie. Die Tönungen sind bewusst kräftiger
     als zuvor: Bei 5 % Deckung sah eine gefährdete Zeile aus wie ein
     Papierfleck. */
  --gut:        #0f7145;
  --gut-fest:   #147a4c;
  --gut-hell:   #e0f2e7;
  --gut-rand:   #9ed0b5;

  --warn:       #96650a;
  --warn-fest:  #b8800f;
  --warn-hell:  #fdf0cd;
  --warn-rand:  #e8c66d;

  --fehler:     #b32316;
  --fehler-fest:#c62a1c;
  --fehler-hell:#fde3df;
  --fehler-rand:#f0a79c;

  /* Die Fläche einer 5 oder 6 im Notenraster.
     ⚠️ **Dieselben zwei Töne stehen in `app/druck.php`** (§ td.kritisch) – das
     gedruckte Übersichtsblatt färbte die auffälligen Noten schon, der
     Bildschirm nicht. Wer einen Ton hier ändert, muss den anderen mitziehen;
     `bin/selftest.php` § Auffällige Noten vergleicht beide und meldet, wenn
     sie auseinanderlaufen. Der zweite Ton ist kräftiger, damit die Note auch
     auf einer rot getönten Zeile („nicht versetzt") stehen bleibt. */
  --note-kritisch:      #f3c8c0;
  --note-kritisch-tief: #eeb3a8;

  /* Höhe der klebenden Kopfzeile – Bezugspunkt für alles, was darunter
     kleben soll (derzeit der Kopf der Zuordnungsmatrix). */
  --kopf-hoehe: 3.7rem;

  --radius: 3px;          /* fast eckig – Formular, nicht App */
  --kante: 1px solid var(--linie);
  --spur: .08em;          /* Laufweite für Versalien */
}

/* ---------------------------------------------------------------------------
   ⚠️ Die einzige Stelle mit !important – und sie muss hier stehen.

   Der Ansichtswechsel setzt das Attribut `hidden`. Sichtbar wird eine Ansicht
   dadurch aber nur, wenn keine eigene Regel `display` überschreibt: Das
   `display: none`, das der Browser für `[hidden]` mitbringt, steht im
   Standard-Stylesheet – und JEDE Autorenregel schlägt es, egal wie niedrig
   ihre Spezifität ist.

   Real passiert: `.anmeldung { display: flex }` ließ die Anmeldekarte nach
   dem Anmelden stehen, während das Grundgerüst darunter schon geladen war.
   Das Attribut war korrekt gesetzt – nur wirkungslos. Ein Test, der
   `element.hidden` abfragt, bestätigt so etwas fröhlich (KI/04 § D6:
   „Prüfen statt hinsehen").

   `bin/check-api-urls.mjs` prüft, dass die Regel da ist.
   --------------------------------------------------------------------------- */
[hidden] { display: none !important; }

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  font-family: var(--schrift-ui);
  font-variant-numeric: lining-nums;
  font-size: 15.5px;
  line-height: 1.55;
  color: var(--tinte);
  background-color: var(--papier);
  /* Papierkorn: eine winzige SVG-Textur als data:-URI. Die CSP erlaubt
     `img-src 'self' data:` – kein fremder Server, keine zusätzliche Anfrage. */
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23n)' opacity='.035'/%3E%3C/svg%3E");
  background-attachment: fixed;
}

::selection { background: var(--siegel); color: #fff; }

/* -------------------------------------------------------------- Typografie */

h1, h2, h3 { font-family: var(--schrift-display); font-weight: 400; }
h1 { font-size: 1.85rem; line-height: 1.2; margin: 0 0 .2rem; letter-spacing: -.005em; }
h2 {
  font-size: .82rem; font-family: var(--schrift-ui); font-weight: 700;
  text-transform: uppercase; letter-spacing: var(--spur); color: var(--tinte-matt);
  margin: 2rem 0 .7rem; padding-bottom: .35rem; border-bottom: 1px solid var(--linie);
}
h3 { font-size: 1.02rem; margin: 1.4rem 0 .4rem; }
a { color: var(--amt); text-underline-offset: .18em; text-decoration-thickness: 1px; }
a:hover { color: var(--siegel); }

.unterzeile { color: var(--tinte-matt); margin: 0 0 1.3rem; }
.klein { font-size: .84rem; }
.zeit  { color: var(--tinte-fern); font-size: .78rem; font-variant-numeric: tabular-nums; }
code   { font-family: var(--schrift-mono); font-size: .86em; }

.visuell-versteckt {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

/* -------------------------------------------------------------- Siegelmotiv */

/* Das Erkennungszeichen des Moduls: ein Stempel, leicht schief, wie von Hand
   aufgedrückt. Er taucht an genau zwei Stellen auf – Marke und Anmeldekarte –
   und nirgends sonst, damit er ein Zeichen bleibt und keine Verzierung wird. */
.siegel {
  display: block; width: 74px; height: 74px; margin: 0 auto 1.4rem;
  border: 2px solid var(--siegel); border-radius: 50%;
  display: grid; place-items: center; transform: rotate(-7deg);
  opacity: .85; position: relative;
}
.siegel::before {
  content: ""; position: absolute; inset: 5px;
  border: 1px solid var(--siegel); border-radius: 50%; opacity: .55;
}
.siegel-innen {
  font-family: var(--schrift-display); font-size: .62rem; color: var(--siegel);
  text-transform: uppercase; letter-spacing: .18em; text-indent: .18em;
}

/* ------------------------------------------------------------------- Kopf */

.kopf {
  background: var(--flaeche);
  border-bottom: 1px solid var(--linie-stark);
  position: sticky; top: 0; z-index: 20;
}
/* Feine Siegel-Linie unter dem Kopf – das Band, das ein Formular oben trägt. */
.kopf::after {
  content: ""; display: block; height: 2px;
  background: linear-gradient(90deg, var(--siegel) 0 22%, transparent 22%);
  opacity: .7;
}
.kopf-innen {
  max-width: 1560px; margin: 0 auto; padding: .55rem 1.4rem;
  display: flex; align-items: center; gap: 1.1rem; flex-wrap: wrap;
}

.marke { display: flex; align-items: center; gap: .5rem; text-decoration: none; }
.marke-siegel {
  width: 19px; height: 19px; border: 1.5px solid var(--siegel);
  border-radius: 50%; transform: rotate(-7deg); position: relative; flex: none;
}
.marke-siegel::after {
  content: ""; position: absolute; inset: 3.5px;
  border-radius: 50%; background: var(--siegel); opacity: .8;
}
.marke-text {
  font-family: var(--schrift-display); font-size: 1.2rem; color: var(--tinte);
  letter-spacing: .01em;
}
.marke:hover .marke-text { color: var(--siegel); }

.kopf-schule {
  font-size: .8rem; color: var(--tinte-matt);
  text-transform: uppercase; letter-spacing: var(--spur);
  padding-left: 1.1rem; border-left: 1px solid var(--linie);
}
.kopf-schulwahl-huelle { padding-left: 1.1rem; border-left: 1px solid var(--linie); }
.kopf-schulwahl {
  font-family: var(--schrift-ui); font-size: .82rem; color: var(--tinte);
  background: var(--siegel-hell); border: 1px solid var(--siegel);
  border-radius: var(--radius); padding: .2rem 1.6rem .2rem .5rem;
  max-width: 15rem;
}

.kopf-nav { display: flex; gap: .1rem; margin-left: auto; }
.kopf-nav a {
  position: relative; padding: .45rem .8rem .5rem; text-decoration: none;
  color: var(--tinte-matt); font-size: .88rem;
  border-bottom: 2px solid transparent;
}
.kopf-nav a:hover { color: var(--tinte); background: var(--flaeche-tief); }
.kopf-nav a.aktiv { color: var(--tinte); border-bottom-color: var(--siegel); font-weight: 600; }

/* Verwaltung · Archiv · Technik – die Bereiche der Schulleitung.
   Getönt statt nur eingefärbt: Eine reine Schriftfarbe fiele in einer Reihe
   aus sieben Reitern nicht auf, und genau darum geht es hier (app.js §
   navFuer, `amt: true`). */
.kopf-nav a.nav-amt {
  color: var(--amtsblau); background: var(--amtsblau-hell);
  border-radius: var(--radius) var(--radius) 0 0;
}
.kopf-nav a.nav-amt:hover { color: var(--amtsblau); background: #dfe1f1; }
.kopf-nav a.nav-amt.aktiv { color: var(--amtsblau); border-bottom-color: var(--amtsblau); }

.kopf-person { display: flex; flex-direction: column; line-height: 1.25; text-align: right; }
.kopf-name  { font-size: .85rem; }
.kopf-rolle {
  font-size: .68rem; color: var(--tinte-fern);
  text-transform: uppercase; letter-spacing: var(--spur);
}

main { max-width: 1560px; margin: 0 auto; padding: 2rem 1.4rem 5rem; }

/* ⚠️ Die Klassenübersicht darf breiter werden als der Rest.
   1560px sind für Fließtext richtig und für ein Notenraster mit neunzehn
   Fächern zu wenig – dort entscheidet jede Spalte darüber, ob die Klasse ohne
   Seitwärtsrollen auf den Bildschirm passt. `app.js` setzt die Klasse am
   <body>; es gibt keinen Inline-Stil (KI/04 § D8). */
body.in-klasse main { max-width: 2200px; }

/* -------------------------------------------------------------- Anmeldung */

.anmeldung { display: flex; justify-content: center; padding-top: 4vh; }
.anmeldekarte {
  background: var(--flaeche); padding: 2.6rem 2.4rem 2rem;
  border: 1px solid var(--linie-stark); border-radius: var(--radius);
  width: 100%; max-width: 27rem; text-align: center;
  box-shadow: 0 1px 0 var(--linie), 0 14px 40px -28px rgba(34, 32, 28, .5);
}
.anmelde-ueber {
  margin: 0 0 .3rem; font-size: .7rem; color: var(--tinte-fern);
  text-transform: uppercase; letter-spacing: .14em;
}
.anmeldekarte h1 { font-size: 1.5rem; }
.anmeldekarte .unterzeile { margin-bottom: 1.6rem; font-size: .9rem; }
.anmeldekarte form { text-align: left; }
.anmeldekarte label {
  display: block; margin: 1.05rem 0 .28rem; font-size: .74rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: var(--spur); color: var(--tinte-matt);
}
.anmeldekarte input, .anmeldekarte select { width: 100%; }
.anmeldekarte .knopf { width: 100%; margin-top: 1.5rem; }
.willkommen {
  background: var(--amt-hell); padding: .75rem .9rem; border-radius: var(--radius);
  font-size: .9rem; text-align: left;
}
.hinweis {
  margin: 1.8rem 0 0; padding-top: 1.1rem; border-top: 1px solid var(--linie);
  font-size: .78rem; color: var(--tinte-fern); text-align: left;
}

/* ---------------------------------------------------- Felder und Schalter */

input[type="text"], input[type="email"], input[type="password"], input[type="date"],
input[type="number"], input[type="search"], select, textarea {
  font: inherit; font-variant-numeric: lining-nums; padding: .42rem .6rem;
  border: 1px solid var(--linie-stark); border-radius: var(--radius);
  background: var(--flaeche); color: var(--tinte);
  transition: border-color .12s, box-shadow .12s;
}
input:hover, select:hover, textarea:hover { border-color: var(--tinte-fern); }
input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: none; border-color: var(--amt);
  box-shadow: 0 0 0 3px var(--amt-hell);
}
textarea { resize: vertical; }

.knopf {
  font: inherit; font-size: .88rem; padding: .42rem .95rem; cursor: pointer;
  border: 1px solid var(--linie-stark); border-radius: var(--radius);
  background: var(--flaeche); color: var(--tinte);
  transition: background .12s, border-color .12s, color .12s;
}
.knopf:hover { background: var(--amt-hell); border-color: var(--amt); color: var(--amt); }
.knopf:active { transform: translateY(1px); }
.knopf.haupt {
  background: var(--amt); color: #fff; border-color: var(--amt); font-weight: 600;
}
.knopf.haupt:hover { background: var(--amt-tief); color: #fff; }
.knopf.schlicht { background: transparent; border-color: transparent; color: var(--tinte-matt); }
.knopf.schlicht:hover { background: var(--flaeche-tief); color: var(--tinte); }
.knopf.klein { padding: .28rem .65rem; font-size: .82rem; }
.knopf.mini  { padding: .06rem .4rem; font-size: .74rem; line-height: 1.5; }
/* Der zweite Knopf einer Gruppe, wenn er der seltenere und folgenreichere
   ist: „zurückziehen" neben „Kinder ändern". Gleich laut wären beide eine
   Einladung, sie für dasselbe zu halten. Im Hover ist er wieder voll da –
   leise heißt zurückhaltend, nicht versteckt. */
.knopf.leise { border-color: transparent; color: var(--tinte-fern); }
.knopf.leise:hover { border-color: var(--amt); color: var(--amt); }
.knopf:focus-visible { outline: 2px solid var(--amt); outline-offset: 2px; }

.raster, .leiste {
  display: flex; gap: .9rem; flex-wrap: wrap; align-items: flex-end;
}
.raster { margin-top: 1.2rem; }
.leiste { margin-bottom: 1.4rem; }
.raster label, .leiste label {
  display: flex; flex-direction: column; gap: .25rem;
  font-size: .72rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: var(--spur); color: var(--tinte-matt);
}

/* ------------------------------------------------------------- Bausteine */

.block {
  background: var(--flaeche); padding: 1.4rem 1.5rem 1.5rem;
  border: 1px solid var(--linie); border-radius: var(--radius);
  margin-bottom: 1.2rem;
}
.block h2:first-child { margin-top: 0; }

.unternav {
  display: flex; gap: 0; flex-wrap: wrap; margin-bottom: 1.4rem;
  border-bottom: 1px solid var(--linie);
}
.unternav a {
  padding: .45rem .95rem; text-decoration: none; color: var(--tinte-matt);
  font-size: .87rem; border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.unternav a:hover { color: var(--tinte); }
.unternav a.aktiv { color: var(--tinte); border-bottom-color: var(--siegel); font-weight: 600; }

.kacheln { display: flex; gap: .7rem; flex-wrap: wrap; }
.kachel {
  display: block; padding: 1rem 1.5rem; background: var(--flaeche);
  border: 1px solid var(--linie-stark); border-radius: var(--radius);
  text-decoration: none; color: var(--tinte);
  font-family: var(--schrift-display); font-size: 1.3rem;
  min-width: 5.5rem; text-align: center; line-height: 1.2;
  transition: border-color .12s, background .12s, transform .12s;
}
.kachel:hover {
  border-color: var(--amt); background: var(--amt-hell);
  color: var(--amt); transform: translateY(-1px);
}
/* Die eigene Klassenleitung – siehe app.js § zeichneStart.
   ⚠️ Der Hover darf sie nicht einebnen: Die Grundregel `.kachel:hover` färbt
   auf Terrakotta um, und ohne die Regel darunter sähe die Leitungsklasse beim
   Darüberfahren aus wie jede andere. */
.kachel-kl {
  border-color: var(--leitung-rand); border-left: 3px solid var(--leitung);
  background: var(--leitung-hell);
}
.kachel-kl .kachel-rolle { color: var(--leitung); font-weight: 600; }
.kachel-kl:hover {
  border-color: var(--leitung); background: #d5eaec; color: var(--leitung);
}
.kachel-rolle {
  display: block; font-family: var(--schrift-ui); font-size: .64rem;
  text-transform: uppercase; letter-spacing: var(--spur); color: var(--tinte-fern);
  margin-top: .25rem;
}

.liste { list-style: none; padding: 0; margin: 0; }
.liste li { padding: .45rem 0; border-bottom: 1px solid var(--linie); }
.liste li:last-child { border-bottom: none; }

.probleme { margin: .6rem 0; padding-left: 1.1rem; }
.probleme li { margin: .25rem 0; }

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

.tabelle { width: 100%; border-collapse: collapse; background: var(--flaeche); }
.tabelle th, .tabelle td {
  padding: .45rem .65rem; text-align: left;
  border-bottom: 1px solid var(--linie); vertical-align: middle;
}
.tabelle thead th {
  font-size: .7rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: var(--spur); color: var(--tinte-matt);
  border-bottom: 1px solid var(--linie-stark);
  position: sticky; top: 0; background: var(--flaeche); z-index: 3;
}
.tabelle tbody tr:hover { background: var(--flaeche-tief); }
.tabelle.schmal th[scope="row"] {
  width: 13rem; font-weight: 400; color: var(--tinte-matt);
}
.tabelle .aktionen { white-space: nowrap; text-align: right; }
.tabelle-rollt {
  overflow-x: auto; border: 1px solid var(--linie); border-radius: var(--radius);
  background: var(--flaeche);
}

/* ------------------------------------------------------------ Notenraster */
/* Der Ort, an dem stundenlang gearbeitet wird. Beide Achsen bleiben stehen,
   die Ziffern laufen tabellarisch, und ein Eingabefeld sieht erst dann wie
   eines aus, wenn man es berührt – bis dahin ist es eine beschriebene Zeile. */

/* ⚠️ Alle Maße hier sind knapp – und zwar mit Absicht. Eine Realschulklasse
   hat gut zwanzig Fächer; jede eingesparte Zehntel-rem je Spalte entscheidet
   mit, ob die Klasse ohne Seitwärtsrollen auf den Bildschirm passt. Wer hier
   großzügiger wird, schiebt die Spalte „Versetzung" aus dem Bild. */
.tabelle.noten { font-variant-numeric: tabular-nums lining-nums; font-size: .9rem; }
.tabelle.noten th, .tabelle.noten td { padding: .3rem .35rem; }
.tabelle.noten th.fest {
  position: sticky; left: 0; z-index: 2; background: var(--flaeche);
  width: 10.5rem; min-width: 10.5rem; font-weight: 400;
  border-right: 1px solid var(--linie-stark);
  padding-left: .6rem; white-space: nowrap;
}
.tabelle.noten thead th.fest { z-index: 4; }
.tabelle.noten tbody tr:hover th.fest { background: var(--flaeche-tief); }
.tabelle.noten thead th:not(.fest) {
  text-align: center; padding-left: .15rem; padding-right: .15rem;
  writing-mode: horizontal-tb;
}
.tabelle.noten thead th { padding-top: .45rem; padding-bottom: .45rem; }

/* Alle Notenspalten gleich breit – die Tabelle soll ein Raster sein, kein
   Flickenteppich aus Spalten, deren Breite vom Zufall der Kurzform abhängt.
   Der Kurzname steht deshalb in einem <span> mit eigener Grenze; ohne ihn
   würde ein langes Kürzel genau seine Spalte aufziehen. */
.tabelle.noten th.fach, .tabelle.noten td.feld { width: 2.75rem; min-width: 2.75rem; }
.tabelle.noten th.fach > span {
  display: block; max-width: 2.6rem; margin: 0 auto;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tabelle.noten th.niv { width: 2.1rem; min-width: 2.1rem; }
.tabelle.noten th.schnitt-kopf { width: 3.4rem; min-width: 3.4rem; font-size: .95rem; }
.tabelle.noten th.stand-kopf { width: 6.5rem; }
.tabelle.noten th.versetzung-kopf { width: 10.5rem; }
.tabelle.noten td.stand, .tabelle.noten td.versetzung { white-space: nowrap; }

/* Das eigene Fach steht vorn und trägt zusätzlich eine Marke – „vorn" allein
   sagt nicht, wo die eigenen Spalten aufhören. */
.tabelle.noten th.fach.eigenes {
  color: var(--amt); border-bottom-color: var(--amt);
  box-shadow: inset 0 -2px 0 var(--amt);
}

/* Knopf „Hauptfächer vorn" über der Tabelle. */
.spaltenordnung {
  display: flex; align-items: baseline; gap: .55rem;
  margin: 0 0 .8rem; color: var(--tinte-matt);
}

/* Dieselbe Überlegung wie bei der Marke am eigenen Fach: Sind die
   Hauptfächer nach vorn geholt, muss man sehen, wo sie AUFHÖREN – sonst
   zählt man in einer Tabelle mit zwanzig Spalten mit. Ein Strich statt einer
   Färbung, weil die Zellen ihre Farben schon vergeben haben (kritisch,
   fremd, abgeschlossen) und eine weitere Fläche mit ihnen streiten würde. */
.tabelle.noten th.fach.blockende,
.tabelle.noten td.feld.blockende,
.tabelle.noten td.fach-schnitt.blockende {
  border-right: 2px solid var(--linie-stark);
}

/* ---- Durchschnitt ------------------------------------------------------- */
/* Grundstärke 600, nicht 700 – aus demselben Grund wie beim Notenfeld: Ein
   Schnitt ab 4,5 steht fett, und das kann er nur, wenn die übrigen es nicht
   sind. Er darf trotzdem etwas kräftiger stehen als eine einzelne Note; die
   Spalte ist die Zusammenfassung der Zeile. */
.tabelle.noten td.schnitt {
  text-align: center; font-weight: 600; color: var(--tinte-matt);
  border-left: 1px solid var(--linie-stark);
  font-variant-numeric: tabular-nums lining-nums;
}
/* Ab 4,5 zusätzlich in der Tinte statt im matten Ton – Gewicht allein reicht
   bei 0,82 rem Schriftgröße in der Fußzeile nicht. Wieder: kein Rot. */
.tabelle.noten td.schnitt .kritisch { font-weight: 800; color: var(--tinte); }
.kein-schnitt { color: var(--tinte-fern); font-weight: 400; }

.tabelle.noten tfoot th, .tabelle.noten tfoot td {
  border-top: 2px solid var(--linie-stark); border-bottom: none;
  background: var(--flaeche-tief); font-size: .82rem;
}
.tabelle.noten tfoot th.fest {
  background: var(--flaeche-tief); font-weight: 700; font-size: .72rem;
  text-transform: uppercase; letter-spacing: var(--spur); color: var(--tinte-matt);
}
.tabelle.noten tfoot td.schnitt { color: var(--tinte); border-left: none; }
.tabelle.noten tfoot td.gesamt { border-left: 1px solid var(--linie-stark); }

/* Was sich nach einer Eingabe mitbewegt hat, leuchtet kurz auf. Ohne das
   übersieht man, dass rechts gerade der Schnitt und die Ampel gewechselt
   haben – die Aufmerksamkeit liegt beim Tippen auf dem Feld. */
.frisch { animation: aufleuchten 1.2s ease-out; }
@keyframes aufleuchten {
  0%   { background: var(--gut-hell); box-shadow: inset 0 0 0 2px var(--gut); }
  100% { background: transparent; box-shadow: none; }
}

.tabelle.noten td.feld { text-align: center; padding: .1rem .1rem; }

/* ⚠️ Ein Notenfeld sieht aus wie ein Feld – immer, nicht erst beim Berühren.
   Vorher war der Rahmen durchsichtig, bis die Maus darüberfuhr; auf dem
   Bildschirm stand dann eine fette Ziffer, die man für Text hielt. Wer nicht
   sieht, dass etwas ein Eingabefeld ist, klickt auch nicht hinein. */
/* ⚠️ **Grundstärke 500, nicht 700 – damit fett etwas bedeuten kann.**
   Bis zum 7. August 2026 stand jede Note im Raster in 700; „fett" war der
   Normalfall und konnte deshalb nichts hervorheben. Seither ist eine **5 oder
   6** fett und alles andere nicht (§ .kritisch weiter unten). Die Ziffer bleibt
   gut lesbar – sie steht mittig in einem Feld mit sichtbarem Rahmen, und der
   Rahmen war es, an dem es vorher fehlte (readme/02 § Ein Notenfeld sieht aus
   wie ein Feld). */
.tabelle.noten input.note {
  width: 2.5rem; text-align: center; padding: .22rem .05rem;
  font-weight: 500; font-size: .95rem;
  border: 1px solid var(--linie-stark); background: var(--flaeche);
  border-radius: var(--radius);
}
.tabelle.noten input.note:hover { border-color: var(--tinte-fern); background: #fff; }
.tabelle.noten input.note:focus-visible {
  border-color: var(--amt); background: #fff; box-shadow: 0 0 0 3px var(--amt-hell);
}
.tabelle.noten input.note::placeholder { color: var(--tinte-fern); font-weight: 400; }
.tabelle.noten input.note.gespeichert {
  border-color: var(--gut); background: var(--gut-hell);
  transition: background .5s ease-out, border-color .5s ease-out;
}
.tabelle.noten input.note.ungueltig { border-color: var(--fehler); background: var(--fehler-hell); }
/* Freigegeben: änderbar, aber jede Änderung ist eine begründete Korrektur. */
.tabelle.noten input.note.korrektur { border-style: dashed; border-color: var(--siegel); }

/* Fremdes Fach, aber änderbar (Klassenleitung, Schuladmin): Die Schraffur
   bleibt, damit man sieht, dass die Note jemand anderem gehört – das Feld ist
   trotzdem ein Feld. */
.tabelle.noten td.fremd-feld {
  background: repeating-linear-gradient(
    -45deg, transparent 0 5px, rgba(148, 141, 128, .09) 5px 6px);
}

/* ⚠️ „Abgeschlossen" ist eine **Fertigmeldung, keine Sperre**. Deshalb zart
   hinterlegt und nicht ausgegraut: Ein Feld, das gesperrt aussieht, hält
   Lehrkräfte davon ab, ihren eigenen Fehler zu berichtigen – und genau das
   war der häufigste Fall (readme/06 § Z19). */
.tabelle.noten td.abgeschlossen input.note {
  border-color: var(--gut); background: color-mix(in srgb, var(--gut-hell) 60%, transparent);
}
.tabelle.noten td.abgeschlossen input.note:focus-visible {
  border-color: var(--amt); background: #fff;
}

/* Fremde Fachnote OHNE Änderungsrecht: bewusst KEIN gesperrtes Feld, sondern
   Text. Ein deaktiviertes Feld lädt zum Versuch ein; Text sagt, dass hier
   nichts zu holen ist (readme/02 § Rollenmatrix). */
.tabelle.noten td.fremd {
  color: var(--tinte-fern); background: repeating-linear-gradient(
    -45deg, transparent 0 5px, rgba(148, 141, 128, .06) 5px 6px);
}
.tabelle.noten td.fest-wert { font-weight: 500; }

/* ------------------------------------------------- Die auffälligen Zahlen

   Eine **5 oder 6** und ein **Durchschnitt ab 4,5** stehen fett – überall im
   Modul, am Bildschirm wie auf Papier. Die Schwelle steht nicht hier, sondern
   in `app/helpers.php` (§ NOTE_KRITISCH_AB); das Stylesheet setzt nur um, was
   der Server als `kritisch` mitliefert.

   Im **Notenraster** bekommt die 5 und die 6 zusätzlich eine Fläche.

   ⚠️ **Das war bis zum 10.09.2026 anders**, und die alte Begründung stand
   genau hier: „Kein Rot – Rot ist die Aussage «nicht versetzt», eine Fünf ist
   eine Note, keine Entscheidung über ein Kind." Der Einwand stimmt, aber er
   war nur halb durchgehalten: Das **gedruckte** Übersichtsblatt färbt die
   auffälligen Noten seit jeher (`app/druck.php` § td.kritisch), und zwar aus
   einem handfesten Grund – bei 5 mm Zeilenhöhe ist eine fette Ziffer aus einem
   Meter Entfernung nicht von einer normalen zu unterscheiden. Am Bildschirm
   gilt dasselbe, sobald jemand mit zwanzig Spalten vor sich sucht, wo die
   Fünfen sitzen. Zwei Ansichten derselben Klasse, die verschieden aussehen,
   sind die schlechtere Lösung.

   Aufgelöst wird der alte Einwand nicht durch Verzicht, sondern durch
   **Abstand**: Die Zeilentönung bleibt die Aussage über das Kind (blass, ganze
   Zeile), die Feldfläche ist die Aussage über die Note (kräftiger, nur das
   Feld). Deshalb der tiefere Ton auf einer roten Zeile – sonst verschwände die
   Note in der Zeile, die sie verursacht hat. Genauso macht es der Druck.

   ⚠️ Beim Tippen wird das Feld weiß: Eine Fläche hinter dem Textcursor macht
   die eigene Eingabe schlechter lesbar, und wer gerade tippt, weiß ohnehin,
   welche Zahl er schreibt. */
.kritisch, .tabelle.noten input.note.kritisch,
.tabelle.noten td.fest-wert.kritisch, .tabelle.noten td.fremd.kritisch {
  font-weight: 800;
}

/* Das beschreibbare Feld. Die Auswahl muss `td.abgeschlossen input.note`
   (grün hinterlegt) schlagen, sonst bliebe die Fünf einer fertiggemeldeten
   Lehrkraft grün – und das ist der Normalfall, nicht die Ausnahme. */
.tabelle.noten td.feld input.note.kritisch,
.tabelle.noten td.abgeschlossen input.note.kritisch {
  background: var(--note-kritisch);
  border-color: var(--fehler-rand);
}
.tabelle.noten tr.ampel-nicht_versetzt td.feld input.note.kritisch,
.tabelle.noten tr.ampel-gefaehrdet td.feld input.note.kritisch {
  background: var(--note-kritisch-tief);
}
/* Beim Tippen weiß – siehe oben. Steht nach den beiden Regeln, damit es sie
   schlägt, ohne die Auswahl weiter aufzublähen. */
/* ⚠️ `tr` gehört in die Auswahl, auch wenn es nichts einschränkt. Ohne das
   steht die Regel bei 6 Klassen/2 Elementen und verliert gegen den tiefen Ton
   der getönten Zeile (6/3) – ausgerechnet dort, wo am ehesten jemand eine Fünf
   korrigiert. Nachgerechnet, nicht geraten. */
.tabelle.noten tr td.feld input.note.kritisch:focus-visible,
.tabelle.noten tr td.abgeschlossen input.note.kritisch:focus-visible {
  background: #fff;
}

/* ⚠️ **Die beiden Rückmeldungen müssen die Fläche schlagen, nicht umgekehrt.**
   „Gespeichert" (grün, eine Sekunde) und „ungültig" (rot umrandet) sind die
   einzige Antwort, die die Lehrkraft auf ihre Eingabe bekommt. Ohne diese zwei
   Regeln verschluckt die Fläche der Fünf sie beide – und ausgerechnet die Fünf
   ist die Note, bei der man wissen will, ob sie angekommen ist. Die Auswahl
   nennt `tr` mit, damit sie auch auf einer getönten Zeile gewinnt. */
.tabelle.noten tr td.feld input.note.kritisch.gespeichert,
.tabelle.noten tr td.abgeschlossen input.note.kritisch.gespeichert {
  background: var(--gut-hell); border-color: var(--gut);
}
.tabelle.noten tr td.feld input.note.kritisch.ungueltig,
.tabelle.noten tr td.abgeschlossen input.note.kritisch.ungueltig {
  background: var(--fehler-hell); border-color: var(--fehler);
}

/* Die nur lesbaren Zellen: eigene, aber gesperrte Note (`fest-wert`) und
   fremde Fachnote (`fremd`). Bei `fremd` bleibt die Schraffur erhalten – sie
   sagt „gehört jemand anderem" und wäre sonst weg. Ein Farbverlauf mit
   durchsichtigen Anteilen legt sich dafür über die Fläche. */
.tabelle.noten td.feld.fest-wert.kritisch {
  background: var(--note-kritisch);
}
.tabelle.noten td.feld.fremd.kritisch {
  background: repeating-linear-gradient(
    -45deg, transparent 0 5px, rgba(148, 141, 128, .09) 5px 6px), var(--note-kritisch);
}
.tabelle.noten tr.ampel-nicht_versetzt td.feld.fest-wert.kritisch,
.tabelle.noten tr.ampel-gefaehrdet td.feld.fest-wert.kritisch {
  background: var(--note-kritisch-tief);
}
.tabelle.noten tr.ampel-nicht_versetzt td.feld.fremd.kritisch,
.tabelle.noten tr.ampel-gefaehrdet td.feld.fremd.kritisch {
  background: repeating-linear-gradient(
    -45deg, transparent 0 5px, rgba(148, 141, 128, .09) 5px 6px),
    var(--note-kritisch-tief);
}

/* „Dieses Fach hat der Schüler nicht" – Punkt auf grauer Fläche.
   ⚠️ Die Fläche war am 6. August 2026 kurz entfernt, weil drei
   Religionsspalten nebeneinander einen grauen Block ergeben, der breiter
   aussieht als die übrigen Spalten. Er ist es nicht – alle Fachspalten sind
   auf die Zehntel gleich breit (54,8 px, nachgemessen). Zurückgenommen: Die
   Fläche trennt „hat das Fach nicht" von „hat noch keine Note" auf einen
   Blick, und das wiegt schwerer als der Blockeindruck. */
.tabelle.noten td.leer { color: var(--tinte-fern); background: var(--flaeche-tief); }
.tabelle.noten td.niveau {
  text-align: center; font-size: .76rem; color: var(--tinte-fern);
  font-variant: small-caps; letter-spacing: .04em;
}
/* Zwei zusammengehörige Felder nebeneinander im Dialog (Fehltage). */
.feldpaar { display: flex; gap: .9rem; }
.feldpaar label { flex: 1 1 0; }

.tabelle.noten .knopf.mini { padding: .04rem .3rem; font-size: .7rem; }
.tabelle.noten th.fest .knopf.mini { padding: .04rem .28rem; }

/* ---- Enge Bildschirme: noch eine Stufe schmaler -------------------------
   Bei 1280 px fehlten mit zwanzig Fächern rund fünfzig Pixel – und fünfzig
   Pixel entscheiden darüber, ob die Spalte „Versetzung" sichtbar ist oder
   nicht. Die Zeile bleibt lesbar; abgeschnitten wird nichts, nur enger
   gesetzt. Darunter greift weiterhin `overflow-x` – lieber rollen als
   verstecken. */
@media (max-width: 1400px) {
  body.in-klasse main { padding-left: .6rem; padding-right: .6rem; }
  .tabelle.noten { font-size: .86rem; }
  .tabelle.noten th.fest { width: 9.5rem; min-width: 9.5rem; padding-left: .4rem; }
  .tabelle.noten th.fach, .tabelle.noten td.feld { width: 2.55rem; min-width: 2.55rem; }
  .tabelle.noten th.fach > span { max-width: 2.4rem; }
  .tabelle.noten input.note { width: 2.3rem; font-size: .9rem; }
  .tabelle.noten th.schnitt-kopf { width: 3.1rem; min-width: 3.1rem; }
  .tabelle.noten th.stand-kopf { width: 6rem; }
  .tabelle.noten th.versetzung-kopf { width: 9.4rem; }
  .schalter { width: 1.3rem; height: 1.3rem; font-size: .88rem; }
}

/* -------------------------------------------------------------- Ampelfarben */
/* Drei Aussagen, drei Farben – und jede zusätzlich in Worten in der Spalte
   „Versetzung": Auf Farbe allein darf keine Aussage über ein Kind beruhen.
   Eine vierte Lage gibt es bewusst NICHT: Die Zuordnung zu Niveau G ist keine
   Gefährdung (siehe `.ampelmarke-zuordnung` weiter unten) und trägt deshalb
   keine Zeilenfarbe.

   ⚠️ Die Tönung ist kräftiger als üblich, und das ist der Zweck. In der
   Halbjahresinformation muss die **gefährdete** Zeile ins Auge springen, im
   Jahreszeugnis die **nicht versetzte** – das sind die beiden Zeilen, wegen
   derer man die Liste überhaupt durchgeht. Dazu ein 5 px breiter Balken vorn:
   Er bleibt beim seitlichen Rollen stehen, die Tönung der Notenspalten läuft
   dabei aus dem Bild. */

.tabelle.noten tr.ampel-nicht_versetzt > td,
.tabelle.noten tr.ampel-nicht_versetzt > th.fest { background: var(--fehler-hell); }
.tabelle.noten tr.ampel-gefaehrdet > td,
.tabelle.noten tr.ampel-gefaehrdet > th.fest { background: var(--warn-hell); }

.tabelle.noten tbody tr.ampel-nicht_versetzt:hover > td,
.tabelle.noten tbody tr.ampel-nicht_versetzt:hover > th.fest { background: #fbd2cb; }
.tabelle.noten tbody tr.ampel-gefaehrdet:hover > td,
.tabelle.noten tbody tr.ampel-gefaehrdet:hover > th.fest { background: #fbe5ab; }

/* Die Zeilenfarbe darf das Notenfeld nicht schlucken – es bleibt ein Feld. */
.tabelle.noten tr.ampel-nicht_versetzt input.note,
.tabelle.noten tr.ampel-gefaehrdet input.note { background: #fff; }

/* Der Name des Kindes trägt die Aussage mit: Wer die Zeile links liest,
   soll sie nicht erst rechts bestätigt bekommen. */
.tabelle.noten th.fest { border-left: 5px solid transparent; }
.tabelle.noten tr.ampel-nicht_versetzt > th.fest {
  border-left-color: var(--fehler-fest); font-weight: 700; color: var(--fehler);
}
.tabelle.noten tr.ampel-gefaehrdet > th.fest {
  border-left-color: var(--warn-fest); font-weight: 700; color: var(--warn);
}

/* ---- Die Marke in der Spalte „Versetzung" -------------------------------
   Gefüllt, nicht getönt. Eine Aussage über ein Kind soll wie eine Aussage
   aussehen und nicht wie eine Hintergrundfarbe. */
.ampelmarke {
  display: inline-block; padding: .1rem .42rem; border-radius: 3px;
  font-size: .68rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .045em; border: 1px solid transparent; white-space: nowrap;
}
.ampelmarke-ok {
  background: var(--gut-fest); color: #fff; border-color: var(--gut);
}
.ampelmarke-gefaehrdet {
  background: var(--warn-fest); color: #fff; border-color: var(--warn);
}
.ampelmarke-nicht_versetzt {
  background: var(--fehler-fest); color: #fff; border-color: var(--fehler);
}
/* Zuordnung zu einem Niveau ist ein **Ergebnis**, keine Warnung: Am Ende der
   Klasse 5 wird nicht versetzt, sondern zugeordnet. Bis zum 6. August 2026
   trug „Zuordnung zu Niveau G" dieselbe Warnfarbe wie eine drohende
   Nichtversetzung – in einer 5. Klasse stand damit die halbe Liste in
   Alarmfarbe, und die Farbe sagte nichts mehr. */
.ampelmarke-zuordnung {
  background: var(--flaeche); color: var(--tinte-matt); border-color: var(--linie-stark);
}
.ampelmarke-offen {
  background: var(--flaeche-tief); color: var(--tinte-fern); border-color: var(--linie);
}

/* Eine **bestätigte** Entscheidung trägt dieselbe Farbe wie das Ergebnis – nur
   mit Ring. Die Farbe gehört zur Aussage („nicht versetzt" ist rot), der Ring
   dazu, dass ein Mensch sie getroffen hat. */
.ampelmarke.entschieden {
  box-shadow: 0 0 0 2px var(--flaeche), 0 0 0 3px currentColor;
}
.ampelmarke-zuordnung.entschieden { box-shadow: none; border-width: 2px; }

.tabelle.noten .marke { font-size: .66rem; padding: .06rem .32rem; letter-spacing: .03em; }
.warnzeichen { width: .95rem; height: .95rem; line-height: .95rem; font-size: .66rem; }

/* Der Zählstreifen über der Tabelle: wie viele Kinder gefährdet sind bzw.
   nicht versetzt werden. Er beantwortet die Frage, wegen der man die Liste
   öffnet, ohne dass man sie durchsehen muss. */
.ampelbilanz {
  display: flex; gap: .5rem; flex-wrap: wrap; align-items: center;
  margin: 0 0 .9rem;
}
.bilanz {
  display: inline-flex; align-items: baseline; gap: .4rem;
  padding: .3rem .7rem; border-radius: var(--radius);
  border: 1px solid var(--linie-stark); background: var(--flaeche);
  font-size: .82rem;
}
.bilanz b { font-size: 1.05rem; font-variant-numeric: tabular-nums; }
.bilanz-gefaehrdet {
  border-color: var(--warn-rand); background: var(--warn-hell); color: var(--warn);
}
.bilanz-nicht_versetzt {
  border-color: var(--fehler-rand); background: var(--fehler-hell); color: var(--fehler);
}
.bilanz-ok { border-color: var(--gut-rand); background: var(--gut-hell); color: var(--gut); }

/* ---- Der Schalter für die Versetzungsentscheidung ------------------------
   Er läuft im Kreis: ○ keine → + versetzt → − nicht versetzt → wieder frei.
   Er zeigt immer den **aktuellen** Zustand, nicht den nächsten – ein Knopf,
   der etwas anderes anzeigt als das, was gilt, wird falsch gelesen. Die
   Beschriftung daneben nennt den Zustand zusätzlich in Worten; auf Zeichen
   allein darf keine Aussage über ein Kind beruhen. */
.schalter {
  font: inherit; font-size: .95rem; line-height: 1; font-weight: 700;
  width: 1.45rem; height: 1.45rem; padding: 0; cursor: pointer;
  display: inline-grid; place-items: center; vertical-align: middle;
  border: 1px solid var(--linie-stark); border-radius: 50%;
  background: var(--flaeche); color: var(--tinte-fern);
  transition: background .12s, border-color .12s, color .12s;
}
.schalter:hover { border-color: var(--amt); color: var(--amt); background: var(--amt-hell); }
.schalter:focus-visible { outline: 2px solid var(--amt); outline-offset: 2px; }
.schalter[disabled] { opacity: .5; cursor: progress; }
.schalter-versetzt { background: var(--gut-hell); border-color: var(--gut); color: var(--gut); }
.schalter-nicht_versetzt {
  background: var(--fehler-hell); border-color: var(--fehler); color: var(--fehler);
}
.schalter-sonstige { background: var(--amt-hell); border-color: var(--amt); color: var(--amt); }

.vorlaeufig {
  font-size: .66rem; text-transform: uppercase; letter-spacing: .03em;
  color: var(--tinte-fern); border-bottom: 1px dotted var(--tinte-fern);
}
.fehlt { color: var(--fehler); font-style: italic; }
.ohne-leitung td { background: var(--warn-hell); }

/* ---------------------------------------------------------------- Legende */
/* Eine Spaltenüberschrift, die erklärt werden muss, braucht die Erklärung auf
   derselben Seite. „Stand" und „Versetzung" sahen nebeneinander wie dasselbe
   aus – das war der häufigste Rückfrage-Anlass. */

.legende {
  margin-top: 1.2rem; padding: 1rem 1.3rem 1.2rem;
  background: var(--flaeche); border: 1px solid var(--linie);
  border-left: 3px solid var(--linie-stark); border-radius: var(--radius);
  font-size: .88rem;
}
.legende h3 {
  margin: 0 0 .7rem; font-family: var(--schrift-ui); font-size: .72rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: var(--spur); color: var(--tinte-matt);
}
.legende-liste { margin: 0; display: grid; grid-template-columns: 11rem 1fr; gap: .55rem 1.1rem; }
.legende-liste dt {
  font-weight: 700; color: var(--tinte-matt); font-size: .78rem;
  text-transform: uppercase; letter-spacing: var(--spur);
}
.legende-liste dd { margin: 0; color: var(--tinte-matt); }
.legende-ampel { list-style: none; margin: 0; padding: 0; }
.legende-ampel li { margin: .25rem 0; }

/* ---------------------------------------------------- Schritte im Deputat */
/* Klasse, Fach, Umfang und der Knopf standen vorher gleichrangig nebeneinander.
   Daraus war nicht ablesbar, dass ein Entwurf nichts bewirkt und die
   Bestätigung der eigentliche Vorgang ist. Jetzt: drei benannte Schritte. */

.schritt {
  display: flex; gap: 1rem; align-items: flex-start;
  padding: 1.1rem 0; border-top: 1px solid var(--linie);
}
.schritt:first-child { border-top: none; padding-top: .3rem; }
.schritt-nr {
  flex: none; width: 1.75rem; height: 1.75rem; border-radius: 50%;
  background: var(--amt-hell); color: var(--amt); border: 1px solid var(--amt);
  display: grid; place-items: center;
  font-family: var(--schrift-display); font-size: .95rem;
}
.schritt-inhalt { flex: 1 1 auto; min-width: 0; }
.schritt-inhalt h3 { margin: .05rem 0 .6rem; font-size: 1rem; }
.schritt-inhalt .raster { margin-top: 0; }

.wahlfeld { display: flex; flex-direction: column; gap: .4rem; }
.wahl {
  display: flex; align-items: flex-start; gap: .55rem; cursor: pointer;
  padding: .55rem .75rem; border: 1px solid var(--linie); border-radius: var(--radius);
  transition: border-color .12s, background .12s;
}
.wahl:hover { border-color: var(--linie-stark); background: var(--flaeche-tief); }
.wahl:has(input:checked) { border-color: var(--amt); background: var(--amt-hell); }
.wahl input { margin-top: .28rem; flex: none; }

.zusammenfassung {
  margin: 0 0 .9rem; padding: .65rem .85rem;
  background: var(--flaeche-tief); border-radius: var(--radius);
  border-left: 3px solid var(--linie-stark);
}
/* Die Liste über dem Knopf in Schritt 3: Text links, „entfernen" rechts.
   ⚠️ Der Knopf hängt an der Zeile, zu der er gehört – eine gemeinsame
   Sammelaktion („alles verwerfen") wäre hier das Falsche: Wer sich verklickt
   hat, will eine Zeile los, nicht seine ganze Arbeit. */
.zusammenfassung .probleme li {
  display: flex; align-items: baseline; justify-content: space-between; gap: .6rem;
}

/* ---------------------------------------------------- Schritte im Deputat */
/* ⚠️ Bewusst dieselbe Formsprache wie der Rest: fast eckig (var(--radius)),
   Haarlinien, keine Schatten. Am 6. August 2026 war das hier einmal runder
   gesetzt – weichere Kanten, pillenförmige Knöpfe, ein klebender Balken am
   unteren Rand. Es wurde zurückgenommen: Eine Ansicht, die anders aussieht
   als die vier daneben, sieht nicht moderner aus, sondern fremd. */

/* Kopf der Seite: Titel links, der Merksatz rechts daneben. */
.seitenkopf {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 1.5rem; flex-wrap: wrap;
}
.seitenkopf-text { flex: 1 1 22rem; min-width: 0; }
.seitenkopf h1 { margin-bottom: .2rem; }
.seitenkopf .unterzeile { margin: 0 0 .15rem; }
.hinweiskasten {
  flex: 0 1 auto; margin: .4rem 0 0;
  display: flex; align-items: flex-start; gap: .55rem;
  padding: .7rem .9rem; border-radius: var(--radius);
  background: var(--flaeche-tief); border: 1px solid var(--linie);
  font-size: .82rem; color: var(--tinte-matt); line-height: 1.35;
}
.hinweiskasten-zeichen { color: var(--amt); font-size: 1rem; line-height: 1.1; }

/* Überschrift eines Schrittes mit den Sammelaktionen rechts. */
.schritt-kopf {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: .8rem; flex-wrap: wrap; margin-bottom: .35rem;
}
.schritt-kopf h3 { margin: 0; }
.schritt-aktionen { display: flex; align-items: center; gap: .5rem; }
/* „zurücksetzen" ist der leisere der beiden – er nimmt weg, er baut nicht. */
.knopf.rueckgaengig { color: var(--amt); text-decoration: underline; }
.knopf.rueckgaengig:hover { background: var(--amt-hell); }

.tipp {
  display: flex; align-items: flex-start; gap: .5rem;
  margin: .9rem 0 0; font-size: .8rem; color: var(--tinte-matt);
}
.tipp-zeichen {
  flex: none; display: grid; place-items: center;
  width: 1.05rem; height: 1.05rem; border-radius: 50%;
  background: var(--flaeche-tief); border: 1px solid var(--linie-stark);
  font-size: .7rem; font-style: normal; color: var(--tinte-matt);
}

.aktionen-rechts {
  display: flex; align-items: center; justify-content: flex-end;
  gap: .7rem; flex-wrap: wrap; margin-top: .9rem;
}
.zusammenzaehler { margin-right: auto; font-size: .85rem; }
.knopf[disabled] { opacity: .45; cursor: not-allowed; }
.knopf[disabled]:hover { background: var(--flaeche); border-color: var(--linie-stark);
  color: var(--tinte); }
.knopf.haupt[disabled]:hover { background: var(--amt); color: #fff; }

.fachwahl { display: flex; flex-wrap: wrap; gap: .4rem; margin-bottom: .3rem; }
/* ⚠️ Das angekreuzte Fach ist **gefüllt**, nicht nur getönt. In einer Reihe
   aus einundzwanzig Kästchen muss man die sechs eigenen auf einen Blick
   sehen; eine helle Tönung verschwindet zwischen den weißen. Der Haken steht
   trotzdem daneben – die Farbe allein trägt die Aussage nicht. */
.fachhaken {
  display: inline-flex; align-items: center; gap: .45rem; cursor: pointer;
  padding: .38rem .8rem; border-radius: var(--radius); font-size: .88rem;
  border: 1px solid var(--linie-stark); background: var(--flaeche);
  transition: border-color .12s, background .12s, color .12s;
}
.fachhaken:hover { border-color: var(--amt); background: var(--amt-hell); }
.fachhaken input { accent-color: var(--amt); cursor: pointer; }
.fachhaken.an {
  border-color: var(--amt); background: var(--amt); color: #fff; font-weight: 600;
}
.fachhaken.an:hover { background: var(--amt-tief); border-color: var(--amt-tief); }
.fachhaken.an input { accent-color: #fff; }

/* ---------------------------------------------- Die Zuordnungsmatrix
   Klassen als Zeilen, die eigenen Fächer als Spalten.

   ⚠️ Vorher stand hier eine Karte je Klasse (`.klassenraster`). Das las sich
   gut bei fünf Klassen und schlecht bei einundzwanzig: „In welchen Klassen
   habe ich Deutsch?" hieß, einundzwanzig Karten durchzusehen, weil dieselbe
   Auskunft in jeder Karte an einer anderen Stelle stand. In einer Tabelle
   ist es eine Spalte. */

/**
 * ⚠️ **Diese Hülle ist absichtlich KEIN Scrollcontainer.**
 *
 * Sie hieß einmal `overflow-x: auto` – und damit klebte der Tabellenkopf
 * nicht mehr. `position: sticky` misst sich am nächsten scrollbaren
 * Vorfahren; ist das eine Hülle, die nur waagerecht rollt, gibt es senkrecht
 * nichts, woran der Kopf kleben könnte. Er scrollte stumm mit hinaus, ohne
 * dass an der Regel etwas falsch aussah (readme/06 § Z45).
 *
 * Waagerecht rollen tut die Hülle deshalb erst auf schmalen Geräten – siehe
 * den Medienabschnitt am Ende. Dort ist der klebende Kopf ohnehin der
 * kleinere Gewinn, und lieber rollen als verstecken.
 */
.tabelle-huelle { }

/* Mehr Platz für die Spalten – dieselbe Ausnahme wie in der
   Klassenübersicht, aus demselben Grund: Je Fach eine Spalte. */
body.in-deputat main { max-width: 2200px; }

/**
 * ⚠️ **Die Spaltenköpfe laufen mit, solange noch eine Klasse zu sehen ist.**
 *
 * Einundzwanzig Klassen passen nicht auf den Bildschirm. Wer zur 9c scrollt,
 * sieht sechs Spalten mit Kästchen und keine Überschrift mehr dazu – und
 * kreuzt Gemeinschaftskunde an, wo er Geschichte meinte. Der Kopf klebt
 * deshalb unter der Seitenkopfzeile (`.kopf` ist selbst `sticky`, darum der
 * Versatz) und verschwindet erst, wenn die Tabelle ganz vorbei ist: Genau
 * das tut ein `sticky` Tabellenkopf von allein – er bleibt innerhalb seines
 * Elternelements, und das ist die Tabelle.
 *
 * ⚠️ `position: sticky` an `<thead>` greift nicht überall; gesetzt wird es
 * deshalb an den Zellen selbst. Und sie brauchen einen eigenen Hintergrund –
 * ohne den scheinen die Zeilen darunter hindurch.
 *
 * ⚠️ **Der Versatz ist gemessen, nicht gerechnet, und steht als Token da.**
 * `.kopf` ist 59 px hoch (gemessen am 12.09.2026, 16 px Grundschrift = 3,7 rem).
 * Ihn per JavaScript auszumessen und als Inline-Stil zu setzen wäre genauer –
 * und verstieße gegen die Regel, dass JavaScript in diesem Modul keine
 * Inline-Stile setzt (KI/04 § D8). Wer die Kopfzeile höher macht, zieht
 * `--kopf-hoehe` mit; auf schmalen Geräten bricht die Navigation um, dort
 * steht der Wert im Medienabschnitt weiter unten.
 */
.tabelle.deputatsraster thead th {
  position: sticky; top: var(--kopf-hoehe); z-index: 3;
  background: var(--flaeche);
  box-shadow: inset 0 -1px 0 var(--linie-stark);
}

.tabelle.deputatsraster { table-layout: auto; }
.tabelle.deputatsraster th.sp-fach {
  text-align: center; vertical-align: bottom; color: var(--amt);
  font-size: .78rem; line-height: 1.25; min-width: 6.5rem;
}
.tabelle.deputatsraster th.sp-klasse { text-align: left; }
.tabelle.deputatsraster td.sp-schueler,
.tabelle.deputatsraster th.sp-schueler {
  text-align: right; color: var(--tinte-fern); font-size: .8rem;
  white-space: nowrap; padding-right: 1rem;
}
.tabelle.deputatsraster tbody th.sp-klasse {
  font-family: var(--schrift-display); font-size: 1.05rem; font-weight: 400;
  text-align: left; white-space: nowrap;
}

/* Der Sortierknopf sieht aus wie die Überschrift, die er ist. */
.spaltenknopf {
  font: inherit; color: inherit; background: none; border: none; padding: 0;
  cursor: pointer; display: inline-flex; align-items: center; gap: .3rem;
}
.spaltenknopf:hover { color: var(--amt); }
.spaltenknopf:focus-visible { outline: 2px solid var(--amt); outline-offset: 2px; }
.sortzeichen { color: var(--tinte-fern); font-size: .8em; }

/* ---- Die Zelle ------------------------------------------------------
   Fünf Lagen, und keine verlässt sich auf ihre Farbe allein: Jede trägt
   einen `title`, und die beiden angehakten tragen zusätzlich eine Zeile
   mit der Zahl der Kinder. */
.tabelle.deputatsraster td.zelle {
  text-align: center; vertical-align: middle; padding: .3rem .4rem;
}
.zelle-haken { display: inline-flex; margin: 0; cursor: pointer; }
.zelle-haken input { width: 1.05rem; height: 1.05rem; cursor: pointer; }

/* Eingetragen: grün wie überall in diesem Modul, wo etwas gilt. */
td.zelle.eingetragen { background: var(--gut-hell); }
td.zelle.eingetragen .zelle-haken input { accent-color: var(--gut-fest); }

/* Ausgewählt, aber noch nicht gespeichert: die Bedienfarbe, nicht die
   Aussagefarbe. Der Unterschied zu Grün ist der ganze Zweck. */
td.zelle.gewaehlt { background: var(--amt-hell); }
td.zelle.gewaehlt .zelle-haken input { accent-color: var(--amt); }

/* „alle 25" / „12 von 25" – der Weg zur Teilgruppe. */
.zelle-umfang {
  display: block; margin: .1rem auto 0; padding: 0 .2rem;
  font: inherit; font-size: .68rem; line-height: 1.3;
  background: none; border: none; cursor: pointer;
  color: var(--tinte-matt); text-decoration: underline dotted;
}
.zelle-umfang:hover { color: var(--amt); }
.zelle-umfang:focus-visible { outline: 2px solid var(--amt); outline-offset: 1px; }
td.zelle.eingetragen .zelle-umfang { color: var(--gut); }

.zelle-rest { display: block; font-size: .66rem; color: var(--warn); margin-top: .1rem; }
.zelle-entwurf {
  display: block; font-size: .62rem; color: var(--tinte-fern);
  text-transform: uppercase; letter-spacing: var(--spur); margin-top: .1rem;
}

/* Vergeben: kein Kästchen. Ein abgeschaltetes Kästchen lädt zum Versuch
   ein, ein Name beantwortet die Frage, die man dann hat. */
td.zelle.belegt { background: var(--flaeche-tief); }
.zelle-fremd {
  display: block; font-size: .68rem; color: var(--tinte-fern);
  font-style: italic; line-height: 1.25;
}

/* Nicht in der Stundentafel. ⚠️ Das ist der Fall, den es in der
   Kartenansicht gar nicht gab – dort fiel die Zeile einfach weg. In einer
   Tabelle gibt es die Zelle trotzdem, und sie darf nicht wie ein leeres
   Kästchen aussehen: Sonst kreuzt jemand ein Fach an, das diese Klasse
   nicht führt. */
td.zelle.nicht-in-tafel { color: var(--linie-stark); background: var(--papier); }

/* Die Zeile, auf der der Blick liegt. Bei sechs Spalten und einundzwanzig
   Klassen verrutscht man sonst eine Zeile – und kreuzt die 7b an, wo die 7a
   stehen sollte. */
.tabelle.deputatsraster tbody tr:hover td,
.tabelle.deputatsraster tbody tr:hover th { background-color: var(--flaeche-tief); }
.tabelle.deputatsraster tbody tr:hover td.zelle.eingetragen { background-color: #cfe9da; }
.tabelle.deputatsraster tbody tr:hover td.zelle.gewaehlt { background-color: #f6e0d7; }

.lagemarke {
  font-size: .76rem; color: var(--tinte-matt);
  margin-left: auto; text-align: right; max-width: 100%;
}
.lagemarke.lage-eigen { white-space: nowrap; }
.lagemarke.lage-belegt { color: var(--fehler); font-style: italic; }
.lagemarke.lage-teilweise { color: var(--warn); }
.lagemarke.lage-eigen { color: var(--gut); font-weight: 600; }

.umfang {
  margin: .35rem 0 .5rem; padding: .5rem .7rem;
  border-left: 3px solid var(--amt); background: var(--amt-hell);
  border-radius: 0 var(--radius) var(--radius) 0;
}
.umfang .wahl { background: transparent; border: none; padding: .1rem 0; }
.umfang .wahl:hover { background: transparent; }
.umfang .schuelerliste { columns: 1; margin-top: .4rem; max-height: 15rem; overflow-y: auto; }
.umfang .aktionen-links { margin-top: .3rem; }
.umfang p:last-child { margin-bottom: 0; }

/* Die Knopfzeile beim nachträglichen Ändern einer bestehenden Zuordnung.
   Abgesetzt, damit „Änderung übernehmen" nicht mit „Alle freien auswählen"
   in einer Reihe steht – das eine ändert die Auswahl, das andere schreibt
   sie fest (deputat.js § umfangswahl). */
.umfang .umfang-aendern {
  margin-top: .6rem; padding-top: .5rem; border-top: 1px solid var(--linie-stark);
}
.umfang .umfang-aendern .unterzeile { flex: 1 1 14rem; }

/* ---------------------------------------------------- Meine Klassenleitung
   Ein Feld je Klasse: Name, wer sie leitet, ein Knopf. Die eigene ist in der
   Leitungsfarbe getönt – dieselbe wie die Kachel auf der Startseite, damit
   „meine Klasse" überall gleich aussieht. */
.kl-raster {
  display: grid; gap: .5rem;
  grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
}
.kl-feld {
  display: flex; align-items: center; gap: .5rem;
  padding: .45rem .6rem; background: var(--flaeche);
  border: 1px solid var(--linie-stark); border-radius: var(--radius);
}
.kl-feld.meine {
  border-color: var(--leitung-rand); border-left: 3px solid var(--leitung);
  background: var(--leitung-hell);
}
.kl-name { font-family: var(--schrift-display); font-size: 1.05rem; }
.kl-wer {
  flex: 1 1 auto; font-size: .76rem; color: var(--tinte-matt);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.kl-feld.meine .kl-wer { color: var(--leitung); }

.aktionen-links { display: flex; gap: .6rem; flex-wrap: wrap; align-items: center; }
.kopplung { margin-top: .9rem; padding-top: .9rem; border-top: 1px solid var(--linie); }
.kacheln-fuss { margin: .9rem 0 0; }

/* ------------------------------------------------------------- Kopfnoten

   Zwei Tabellen, zwei Zwecke:

   `.kopfnotentabelle`  die Eingabe der Fachlehrkraft – zwei Spalten, sonst
                        nichts. Sie ist schmal und darf es sein.
   `.schnitttabelle`    die Ansicht der Klassenleitung – vier Spalten je
                        Kopfnote (Ø, Vorschlag, im Zeugnis, in Worten).

   ⚠️ Die Spalte **„im Zeugnis"** ist die einzige, die etwas entscheidet.
   Sie ist deshalb die einzige mit einem Feld; Ø und Vorschlag stehen als
   Text. Wer alle vier gleich aussehen ließe, lüde dazu ein, in den Schnitt
   zu schreiben. */

.tabelle.kopfnotentabelle, .tabelle.schnitttabelle {
  font-variant-numeric: tabular-nums lining-nums;
}
.tabelle.kopfnotentabelle { max-width: 34rem; }
.tabelle.kopfnotentabelle th.fest { text-align: left; font-weight: 500; }
.tabelle.kopfnotentabelle td.feld, .tabelle.schnitttabelle td.feld {
  text-align: center; padding: .18rem .25rem; width: 5.5rem;
}
/* Ohne Änderungsrecht steht dort **Text**, kein gesperrtes Feld – dieselbe
   Regel wie im Notenraster (readme/02 § Grundsätze). */
.tabelle.kopfnotentabelle td.fest-wert, .tabelle.schnitttabelle td.fest-wert {
  font-weight: 700;
}
.tabelle.kopfnotentabelle th:not(.fest), .tabelle.schnitttabelle thead th {
  text-align: center;
}

/* Dasselbe Feld wie im Notenraster – ein Eingabefeld sieht überall gleich
   aus, sonst hält man es an einer der beiden Stellen für Text. */
input.kopfnote {
  width: 2.5rem; text-align: center; padding: .22rem .05rem;
  font-weight: 700; font-size: .95rem;
  border: 1px solid var(--linie-stark); background: var(--flaeche);
  border-radius: var(--radius);
}
input.kopfnote:hover { border-color: var(--tinte-fern); background: #fff; }
input.kopfnote:focus-visible {
  border-color: var(--amt); background: #fff; box-shadow: 0 0 0 3px var(--amt-hell);
}
input.kopfnote.gespeichert {
  border-color: var(--gut); background: var(--gut-hell);
  transition: background .5s ease-out, border-color .5s ease-out;
}
input.kopfnote.fehlerhaft { border-color: var(--fehler); background: var(--fehler-hell); }

.tabelle.schnitttabelle td.mittelwert { text-align: center; font-weight: 600; }
.tabelle.schnitttabelle td.vorschlag {
  text-align: center; color: var(--tinte-matt); background: var(--flaeche-tief);
}
.tabelle.schnitttabelle td.wortspalte { color: var(--tinte-matt); font-size: .85rem; }
.tabelle.schnitttabelle th.fest { text-align: left; font-weight: 500; white-space: nowrap; }

/* Die Matrix Schüler × Fach. Schmale Fachspalten wie im Notenraster – bei
   zwanzig Fächern entscheidet jede Spalte darüber, ob die vier Spalten rechts
   noch im Bild sind. */
.tabelle.schnitttabelle th.fach { width: 2.6rem; min-width: 2.6rem; }
.tabelle.schnitttabelle th.fach > span {
  display: block; max-width: 2.5rem; margin: 0 auto;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* ⚠️ Ein Strich, kein leeres Feld: „hat noch nichts eingetragen" ist eine
   Aussage, und sie muss von „hat eine 1 gegeben" unterscheidbar sein. Die
   Füllung trennt beides auf einen Blick – dieselbe Überlegung wie bei den
   leeren Zellen der Klassenübersicht (readme/07). */
.tabelle.schnitttabelle td.ohne-eingabe {
  background: var(--flaeche-tief); color: var(--tinte-fern);
}
/* Die Trennlinie vor Ø: Was links davon steht, sind Einzelmeinungen; was rechts
   steht, ist das Ergebnis. */
.tabelle.schnitttabelle .trennlinie { border-left: 2px solid var(--linie-stark); }

.leerwert { color: var(--tinte-fern); }
.aktionen-reihe { margin: 1.1rem 0 .4rem; }
.umschalter { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; margin: 1rem 0; }
.klassentitel { margin-top: 1.6rem; }

/* ------------------------------------------------- Klassen-Ampel (Kopfnoten)

   ⚠️ **Die Farbe steht nie allein.** Auf jeder Kachel steht zusätzlich in
   Worten, was sie bedeutet – „vollständig", „7 offen", „nichts eingetragen".
   Dieselbe Regel wie bei der Versetzungsampel (readme/02). */

.klassenampel { display: flex; flex-wrap: wrap; gap: .6rem; margin: .9rem 0 1.4rem; }
.ampelkachel {
  display: flex; flex-direction: column; gap: .2rem; align-items: flex-start;
  min-width: 8.5rem; padding: .6rem .8rem; cursor: pointer; text-align: left;
  font: inherit; border: 1px solid var(--linie-stark); border-radius: var(--radius);
  background: var(--flaeche); color: var(--tinte);
  transition: border-color .12s, background .12s, box-shadow .12s;
}
.ampelkachel:hover { border-color: var(--tinte-fern); }
.ampelkachel-name { font-family: var(--schrift-display); font-size: 1.15rem; }
.ampelkachel-stand { font-size: .75rem; text-transform: uppercase; letter-spacing: var(--spur); }
.ampelkachel-vollstaendig {
  background: var(--gut-hell); border-color: var(--gut-rand); color: var(--gut);
}
.ampelkachel-teilweise {
  background: var(--warn-hell); border-color: var(--warn-rand); color: var(--warn);
}
.ampelkachel-leer {
  background: var(--fehler-hell); border-color: var(--fehler-rand); color: var(--fehler);
}
.ampelkachel.aktiv { box-shadow: inset 0 0 0 2px var(--amt); border-color: var(--amt); }

/* ---------------------------------------------------------- Druckvorschau */

.vorschau { margin-top: 1.6rem; }
.vorschau-kopf {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 1rem; flex-wrap: wrap; margin-bottom: .8rem;
}
.vorschau-kopf h2 { margin: 0; }
/* Die Übersicht ist quer (A4: 297 × 210), das Infoblatt hoch (210 × 297). Der
   Rahmen bekommt deshalb je nach Bogen ein anderes Seitenverhältnis – sonst
   rollt man im Rahmen statt zu sehen, was auf das Blatt passt. */
.vorschau-rahmen {
  display: block; width: 100%; aspect-ratio: 297 / 210; border: 1px solid var(--linie-stark);
  border-radius: var(--radius); background: #fff;
}
.vorschau-hoch .vorschau-rahmen { aspect-ratio: 210 / 297; max-height: 70vh; }

/* ---------------------------------------------------------------- Drucken */

/* ⚠️ `align-items: stretch` (die Vorgabe) statt `flex-start`: Die beiden Karten
   sind **gleich hoch**, egal wie lang ihr Erklärungstext ist. Mit `flex-start`
   endete die kürzere mitten in der Zeile und das Feld sah aus, als fehlte etwas.
   Die Knopfreihe wird dabei nach unten geschoben, damit beide auf derselben
   Linie stehen – dafür ist die Karte selbst ein Flex-Container. */
.druckkarten { display: flex; gap: 1rem; flex-wrap: wrap; }
.druckkarte {
  flex: 1 1 22rem; margin-top: 0;
  display: flex; flex-direction: column;
}
.druckkarte .wahlreihe { margin-top: auto; padding-top: .6rem; }
.wahlreihe { margin-bottom: 0; }
kbd {
  font-family: var(--schrift-mono); font-size: .82em; padding: .05rem .3rem;
  border: 1px solid var(--linie-stark); border-radius: 2px; background: var(--flaeche-tief);
}

/* ---------------------------------------------------------------- Marken */

.marke-entwurf, .marke-offen, .marke-vorbereitung, .marke-bestaetigt,
.marke-freigegeben, .marke-vollstaendig, .marke-ausgegeben, .marke-vorgelegt,
.marke-zurueckgezogen, .marke-gesperrt, .marke-archiviert, .marke-hinweis {
  display: inline-block; padding: .09rem .45rem; border-radius: 2px;
  font-size: .7rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .05em; white-space: nowrap;
  border: 1px solid transparent;
}
.marke-entwurf, .marke-offen, .marke-vorbereitung {
  background: var(--warn-hell); color: var(--warn); border-color: var(--warn-rand);
}
.marke-bestaetigt, .marke-vollstaendig {
  background: var(--gut-hell); color: var(--gut); border-color: var(--gut-rand);
}
.marke-vorgelegt { background: var(--amt-hell); color: var(--amt); border-color: var(--amt); }
/* Freigegeben und ausgegeben tragen das Siegel – der Zustand, um den es geht. */
.marke-freigegeben, .marke-ausgegeben {
  background: var(--siegel-hell); color: var(--siegel); border-color: var(--siegel);
}
.marke-zurueckgezogen, .marke-gesperrt, .marke-archiviert {
  background: var(--flaeche-tief); color: var(--tinte-fern); border-color: var(--linie);
}
/* „abweichend": ein Hinweis, keine Aussage über ein Kind – deshalb Bernstein
   und nicht Rot. Dass eine Kopfnote vom gerundeten Schnitt abweicht, ist
   erlaubt; es soll nur sichtbar sein. */
.marke-hinweis {
  background: var(--warn-hell); color: var(--warn); border-color: var(--warn-rand);
}
.warnzeichen {
  display: inline-block; width: 1.05rem; height: 1.05rem; line-height: 1.05rem;
  text-align: center; border-radius: 50%; background: var(--warn);
  color: #fff; font-size: .72rem; font-weight: 700;
}

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

.meldung {
  padding: .8rem 1rem; border-radius: var(--radius); margin: 1rem 0;
  border-left: 3px solid transparent; font-size: .92rem;
}
.meldung.info    { background: var(--amt-hell);    border-left-color: var(--amt); }
.meldung.erfolg  { background: var(--gut-hell);    border-left-color: var(--gut);   color: var(--gut); }
.meldung.warnung { background: var(--warn-hell);   border-left-color: var(--warn);  color: var(--warn); }
.meldung.fehler  { background: var(--fehler-hell); border-left-color: var(--fehler); color: var(--fehler); }

/* Notenvorschläge aus einem externen Programm (readme/NOTENWEB_IMPORT.md).
   Bewusst NICHT „erfolg": Ein Vorschlag ist noch keine Zeugnisnote. Er soll
   auffallen und zugleich nicht so aussehen, als wäre schon etwas erledigt. */
.meldung.vorschlaege {
  background: var(--amt-hell); border-left-color: var(--amt);
  display: flex; flex-wrap: wrap; align-items: center; gap: .6rem;
}
.meldung.vorschlaege .klein { font-size: .84rem; opacity: .75; }

/* Der Vorschlag steht als Platzhalter im leeren Feld – grau und kursiv, damit
   er auf einen Blick von einer eingetragenen Note zu unterscheiden ist. Wer
   das verwechselt, hält ein leeres Zeugnis für vollständig. */
td.feld input.note::placeholder {
  color: var(--amt); opacity: .55; font-style: italic;
}

.hinweisleiste {
  position: fixed; left: 50%; bottom: 1.6rem; transform: translateX(-50%);
  padding: .7rem 1.3rem; border-radius: var(--radius);
  box-shadow: 0 8px 26px -12px rgba(34, 32, 28, .55);
  z-index: 60; max-width: 90vw; background: var(--tinte); color: var(--papier);
  font-size: .9rem;
  animation: einblenden .18s ease-out;
}
.hinweisleiste.erfolg  { background: var(--gut); color: #fff; }
.hinweisleiste.fehler  { background: var(--fehler); color: #fff; }
.hinweisleiste.warnung { background: var(--warn); color: #fff; }

.ladebalken {
  position: fixed; top: 0; left: 0; height: 2px; width: 100%; z-index: 70;
  background: linear-gradient(90deg, transparent, var(--siegel), transparent);
  background-size: 40% 100%; background-repeat: no-repeat;
  animation: laden 1s linear infinite;
}
@keyframes laden { from { background-position: -40% 0; } to { background-position: 140% 0; } }
@keyframes einblenden { from { opacity: 0; transform: translate(-50%, 6px); }
                        to   { opacity: 1; transform: translate(-50%, 0); } }

/* --------------------------------------------------------- Schülerliste */

.schuelerliste { list-style: none; padding: 0; columns: 2; column-gap: 2.5rem; }
.schuelerliste li { padding: .22rem 0; break-inside: avoid; }
.schuelerliste li.belegt { color: var(--tinte-fern); }
.belegt-von { font-size: .8rem; font-style: italic; color: var(--siegel); }

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

dialog {
  border: 1px solid var(--linie-stark); border-radius: var(--radius);
  padding: 1.8rem; max-width: 46rem; width: 92vw;
  box-shadow: 0 24px 70px -30px rgba(34, 32, 28, .7);
  color: var(--tinte); background: var(--flaeche);
}
dialog::backdrop { background: rgba(34, 32, 28, .42); }
dialog h2 {
  margin-top: 0; font-family: var(--schrift-display); font-size: 1.3rem;
  text-transform: none; letter-spacing: 0; font-weight: 400; color: var(--tinte);
}
dialog label {
  display: block; margin: .95rem 0 .25rem; font-size: .72rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: var(--spur); color: var(--tinte-matt);
}
dialog input, dialog select, dialog textarea { width: 100%; }

/* ⚠️ **Ein Kästchen im Dialog ist kein Feldname.**
   Zwei Regeln darüber trafen es trotzdem, und zusammen zerlegten sie den
   Dialog „Demoschule neu aufbauen":

   1. `dialog label` setzt VERSALIEN, 0,72 rem und fette Schrift. Das ist die
      Beschriftung ÜBER einem Eingabefeld. Ein Kästchen steht DANEBEN und trägt
      Fließtext – aus dem Erklärungssatz wurde eine schreiende Kurzfassung.
   2. `dialog input { width: 100% }` blies das Kästchen auf die volle
      Dialogbreite auf. Der Text daneben rutschte in eine drei Zentimeter
      schmale Spalte, die Kachel wurde vierhundert Pixel hoch, und der Dialog
      rollte waagerecht.

   Beides galt für **alle drei** Kästchen des Moduls – auch für „Freigabe
   ausdrücklich zurücknehmen", an dem schon § Z29 hing. Gemeldet aus dem
   laufenden Betrieb, nicht gefunden von fünf Prüfläufen: Ein Stylesheet-Fehler
   sieht in keinem Testlauf anders aus als eine richtige Seite (readme/06 § Z32). */
dialog label:has(input[type="checkbox"]),
dialog label:has(input[type="radio"]) {
  display: flex; align-items: flex-start; gap: .55rem; cursor: pointer;
  text-transform: none; letter-spacing: 0;
  font-size: .9rem; font-weight: 400; color: var(--tinte);
}
dialog input[type="checkbox"], dialog input[type="radio"] {
  width: auto; flex: none; margin-top: .2rem;
}
dialog menu {
  display: flex; gap: .6rem; justify-content: flex-end;
  margin: 1.8rem 0 0; padding: 1.1rem 0 0; border-top: 1px solid var(--linie);
}
.befund { font-size: 1.1rem; font-family: var(--schrift-display); }

.aktionsleiste {
  display: flex; gap: .6rem; flex-wrap: wrap; margin-top: 1.4rem;
  padding-top: 1.2rem; border-top: 1px solid var(--linie);
}

/* ------------------------------------------------ Einblenden beim Laden */
/* Eine einzige, gestaffelte Bewegung beim Aufbau – nicht überall ein Zappeln. */

#ansicht-start > *, #ansicht-deputat > *, #ansicht-klasse > *,
#ansicht-verwaltung > *, #ansicht-archiv > *, #ansicht-system > * {
  animation: aufblenden .34s cubic-bezier(.2, .7, .3, 1) backwards;
}
#ansicht-start > :nth-child(2), #ansicht-deputat > :nth-child(2),
#ansicht-klasse > :nth-child(2), #ansicht-verwaltung > :nth-child(2),
#ansicht-archiv > :nth-child(2), #ansicht-system > :nth-child(2) { animation-delay: .05s; }
#ansicht-start > :nth-child(3), #ansicht-deputat > :nth-child(3),
#ansicht-klasse > :nth-child(3), #ansicht-verwaltung > :nth-child(3),
#ansicht-archiv > :nth-child(3), #ansicht-system > :nth-child(3) { animation-delay: .1s; }
#ansicht-start > :nth-child(n+4) { animation-delay: .15s; }

@keyframes aufblenden { from { opacity: 0; transform: translateY(7px); } }

.anmeldekarte { animation: aufblenden .45s cubic-bezier(.2, .7, .3, 1) backwards; }

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

/* ------------------------------------------------------------ Schmale Geräte */

@media (max-width: 900px) {
  /* Die Navigation bricht hier in eine eigene Zeile um – der Kopf wird höher,
     und alles, was darunter klebt, muss mit. */
  :root { --kopf-hoehe: 6.4rem; }
  /* Hier darf die Matrix waagerecht rollen; der klebende Kopf entfällt dabei
     (siehe § .tabelle-huelle). */
  .tabelle-huelle { overflow-x: auto; }
  .kopf-innen { gap: .6rem; padding: .5rem .9rem; }
  .kopf-nav { margin-left: 0; width: 100%; overflow-x: auto; }
  .kopf-person { display: none; }
  .kopf-schule, .kopf-schulwahl-huelle { border-left: none; padding-left: 0; }
  .schuelerliste { columns: 1; }
  main { padding: 1.2rem .9rem 4rem; }
  .anmeldekarte { padding: 2rem 1.4rem 1.6rem; }
  .tabelle.noten th.fest { min-width: 9.5rem; }
}
