/*
 * assets/css/stil.css
 * ---------------------------------------------------------------------------
 * Grundstil des Kachel-Dashboards. Bewusst schlicht und ohne externes
 * CSS-Framework - wird in den nächsten Bauschritten um das eigentliche
 * Kachel-Grid, die Formatierungsleiste usw. ergänzt.
 * ---------------------------------------------------------------------------
 */

:root {
    --farbe-hintergrund: #f4f5f7;
    --farbe-flaeche: #ffffff;
    --farbe-rand: #dfe3e8;
    --farbe-text: #1f2430;
    /* Bauschritt 20: bis hierhin eine fest verdrahtete, von der
       eingestellten Schriftfarbe unabhängige Nebenfarbe (siehe die
       ausführliche Rückfrage/Antwort dazu und den jetzt veralteten
       Kommentar bei seiteSchriftVariablenStil() in includes/
       seiteneinstellungen.php - "wirklich alles umstellen", nicht nur die
       Haupttextfarbe). color-mix() mit "currentColor" statt eines zweiten,
       eigenen Farbwerts: "currentColor" liefert an JEDER Stelle, an der
       diese Variable tatsächlich verwendet wird (color: var(--farbe-text-
       gedaempft) an all den ~40 Stellen in dieser Datei), die dort gerade
       GÜLTIG VERERBTE Textfarbe zurück - ob das nun die globale Standard-
       Schriftfarbe ist, eine in den Seiteneinstellungen eigens gewählte,
       oder (perspektivisch) eine Kachel-eigene direkt gesetzte Farbe -,
       ganz ohne diese ~40 Stellen einzeln anfassen zu müssen. Der Browser
       mischt sie mit 30 % Transparenz statt mit einer zweiten festen
       Farbe - das ergibt gegenüber der bisherigen Standardkombination
       (dunkler Text auf hellem Kachel-Hintergrund) optisch ungefähr
       denselben gedämpften Grauton wie zuvor, bleibt aber unabhängig vom
       tatsächlichen Hintergrund immer eine abgeschwächte Version GENAU
       DER Farbe, die an dieser Stelle sonst für normalen Text gelten
       würde. Voraussetzung: ein Browser mit color-mix()-Unterstützung
       (alle gängigen Browser seit 2023) - in einem älteren Browser bleibt
       die betroffene "color"-Angabe ungültig und es greift einfach die
       normal vererbte (nicht gedämpfte) Textfarbe weiter, kein Bruch. */
    --farbe-text-gedaempft: color-mix(in srgb, currentColor 70%, transparent);
    --farbe-akzent: #2f5fdd;
    --farbe-akzent-dunkel: #1e40af;
    --farbe-fehler: #b3261e;
    --farbe-fehler-flaeche: #fdecea;
    --schrift-anzeige: 'Fjalla One', sans-serif;
    --schrift-text: 'Karla', sans-serif;
    --schrift-mono: 'JetBrains Mono', monospace;
    --radius: 12px;
    --schatten: 0 1px 3px rgba(20, 24, 33, 0.08), 0 1px 2px rgba(20, 24, 33, 0.06);
    /* Bauschritt 25: Desktop-Auto-Vergrößern des Dashboards bei viel
       Leerraum unter dem Grid (siehe kachelGridZoomEinrichten() in
       assets/js/dashboard.js) - Standard 1 (keine Vergrößerung). Wirkt
       AUSSCHLIESSLICH auf Werte, die die Spaltenbreite/-anzahl nicht
       beeinflussen können (siehe .kachel, padding-top/-bottom) - niemals auf
       column-gap oder grid-template-columns von .kachel-grid. */
    --kachel-grid-zoom: 1;
}

* {
    box-sizing: border-box;
}

/* Bauschritt 18: globale Schriftgröße "Text" (Seiteneinstellungen ->
   Schrift) - ein Faktor auf die WURZEL-Schriftgröße, nicht auf body direkt:
   "rem" ist überall in dieser Datei relativ zur Schriftgröße von <html>
   (nicht von <body>!), so skaliert diese eine Regel automatisch praktisch
   jede Text-/Überschriftgröße der ganzen Anwendung gemeinsam mit - ganz
   ohne jede einzelne font-size-Angabe von Hand anzufassen. Die Variable
   selbst kommt (falls eingestellt) als Inline-Style auf <html> selbst an
   (siehe includes/kopf.php, seiteSchriftVariablenStil()) - ohne Einstellung
   bleibt es bei calc(16px * 1) = 16px, dem bisherigen, unveränderten
   Standard. Der separate Überschriften-Regler (--schriftgroesse-anzeige-
   faktor) wirkt NICHT hier, sondern zusätzlich NUR auf einzelne
   Überschriften-Elemente weiter unten (z. B. .kachel__titel) - so lässt
   sich mit "Text" die ganze Anwendung gemeinsam und mit "Überschriften"
   zusätzlich NUR die Überschriften nochmal eigens skalieren. */
html {
    font-size: calc(16px * var(--schriftgroesse-text-faktor, 1));
}

body {
    margin: 0;
    background: var(--farbe-hintergrund);
    color: var(--farbe-text);
    font-family: var(--schrift-text);
    font-size: 16px;
    line-height: 1.5;
}

/* Globale Seiten-Hintergrundbild-Ebene (Bauschritt 15, siehe
   includes/kopf.php und includes/seiteneinstellungen.php,
   seiteHintergrundBildStil()) - dasselbe Prinzip wie die
   Hintergrundbild-Ebene einer einzelnen Kachel (.kachel__hintergrund-bild-
   ebene weiter unten), nur für die ganze Seite: eine eigene Ebene, damit
   sich ihre Deckkraft unabhängig vom restlichen Seiteninhalt einstellen
   lässt. "position: fixed" + negativer z-index reichen hier aus, ohne dass
   .kopfleiste/.app dafür extra positioniert werden müssten - ein negativer
   z-index-Wert malt immer hinter allen normal fließenden (nicht selbst
   positionierten) Geschwister-Elementen, unabhängig von der Reihenfolge im
   Quelltext. */
.seite-hintergrund-bild-ebene {
    position: fixed;
    inset: 0;
    z-index: -1;
    background-size: cover;
    background-position: center;
    pointer-events: none;
}

a {
    color: var(--farbe-akzent);
}

.app__eyebrow {
    font-family: var(--schrift-anzeige);
    letter-spacing: 0.03em;
    text-transform: uppercase;
    font-size: 0.85rem;
    color: var(--farbe-text-gedaempft);
}

.app__title {
    font-family: var(--schrift-anzeige);
    font-size: 2rem;
    margin: 8px 0 0;
}

/* --- Anmeldeseite / Fehlerseiten -------------------------------------- */

.login-body {
    display: flex;
    min-height: 100vh;
}

.login-buehne {
    margin: auto;
    width: 100%;
    max-width: 420px;
    padding: 24px;
}

.login-konsole {
    background: var(--farbe-flaeche);
    border: 1px solid var(--farbe-rand);
    border-radius: var(--radius);
    box-shadow: var(--schatten);
    padding: 32px;
    text-align: center;
}

.login-fehler {
    background: var(--farbe-fehler-flaeche);
    color: var(--farbe-fehler);
    border-radius: 8px;
    padding: 12px 16px;
    font-size: 0.95rem;
}

.button {
    display: inline-block;
    padding: 12px 24px;
    border-radius: 8px;
    text-decoration: none;
    font-weight: 600;
    cursor: pointer;
    border: none;
}

.button--iserv {
    background: var(--farbe-akzent);
    color: #fff;
}

.button--iserv:hover {
    background: var(--farbe-akzent-dunkel);
}

/* Bauschritt 17: bisher hatte kein <button class="button ..."> je ein
   "disabled" gebraucht (z. B. "Aus IServ laden" vor dem Verbinden, siehe
   klassendienste-verwalten.php) - ohne diese Regel sah ein deaktivierter
   Knopf optisch identisch zu einem aktiven aus. */
.button:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

.button--iserv:disabled:hover {
    background: var(--farbe-akzent);
}

/* --- Kopfleiste (angemeldeter Bereich) --------------------------------- */

.kopfleiste {
    background: var(--farbe-flaeche);
    border-bottom: 1px solid var(--farbe-rand);
}

/* Bauschritt 21: "Menüleiste bleibt beim Scrollen fest" (Seiteneinstellungen
   -> Menüleiste), Standard AN - siehe seiteLeisteFest() in includes/
   seiteneinstellungen.php. z-index hebt die Leiste über den restlichen
   Seiteninhalt (Kacheln erreichen höchstens z-index:2, aber nur innerhalb
   ihrer eigenen, lokalen Stapelkontext-Box - siehe .kachel__link-
   ueberlagerung weiter unten); der bestehende Hintergrund/die Trennlinie
   von .kopfleiste sorgen schon dafür, dass darunter wegscrollender Inhalt
   nicht durchscheint. Bauschritt 26: die frühere zusätzliche Kopfzeile
   UNTER der Menüleiste bei einem geöffneten Screen (.screen-kopfzeile) ist
   entfallen - Zurück-Pfeil/Screen-Titel stehen jetzt direkt IN dieser
   Menüleiste selbst, siehe includes/kopf.php ($aktuellerScreenTitel). */
.kopfleiste--fest {
    position: sticky;
    top: 0;
    z-index: 30;
}

/* Innerer Wrapper der Kopfleiste (Bauschritt 17) - übernimmt die eigentliche
   Ausrichtung von Logo/Titel (.kopfleiste__marke) und den rechten Knöpfen
   (.kopfleiste__rechts). WICHTIG (Bauschritt-18-Korrektur): das horizontale
   Padding sitzt bewusst HIER statt auf .kopfleiste selbst - .kopfleiste hat
   gar kein eigenes Padding mehr. Vorher hatte .kopfleiste "padding: 0 24px"
   UND dieser innere Wrapper zusätzlich "max-width:1200px; margin:0 auto;"
   OHNE eigenes Padding - zwei verschachtelte Boxen mit unterschiedlicher
   Breitenrechnung, die je nach Fensterbreite einen anderen linken Abstand
   ergaben als .app (max-width:1200px; margin:0 auto; padding:32px 24px;
   EINE Box). Ergebnis: Logo/Titel standen nicht exakt auf Höhe des übrigen
   Seiteninhalts (von Hand nachgerechnet: bis zu 24px Versatz je nach
   Fensterbreite). Jetzt rechnen beide Boxen identisch (max-width + margin:0
   auto + dasselbe Padding), Logo/Titel stehen bei "inhaltsbreite" exakt auf
   Höhe des Seiteninhalts, unabhängig von der Fensterbreite.
   Zwei Layout-Varianten, einstellbar über Seiteneinstellungen -> Menüleiste
   -> Layout (siehe includes/seiteneinstellungen.php,
   seiteLeisteLayoutKlasse()):
    - "inhaltsbreite" (Standard, Fortführung des bisherigen Verhaltens):
      ganz normales Flex-Leiste, aber auf dieselbe maximale Breite wie
      .app begrenzt und zentriert, damit Logo/Titel auf Höhe des
      Seiteninhalts stehen statt ganz links am Fensterrand.
    - "zentriert": Logo/Titel stehen mittig in der Leiste, die rechten
      Knöpfe bleiben rechtsbündig (CSS-Grid mit drei Spalten, die mittlere
      für die Marke). */
.kopfleiste__inhalt {
    max-width: 1200px;
    margin: 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    row-gap: 8px;
    padding: 16px 24px;
}

.kopfleiste__inhalt--zentriert {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    column-gap: 16px;
}

.kopfleiste__inhalt--zentriert .kopfleiste__marke {
    grid-column: 2;
    justify-content: center;
}

.kopfleiste__inhalt--zentriert .kopfleiste__rechts {
    grid-column: 3;
    justify-self: end;
}

/* Auf schmalen Bildschirmen bringt die 3-Spalten-Zentrierung eher Nachteile
   (Marke und Knöpfe konkurrieren um wenig Platz) - dort wie bei
   "inhaltsbreite" ganz normal umbrechen lassen. */
@media (max-width: 640px) {
    .kopfleiste__inhalt--zentriert {
        display: flex;
        flex-wrap: wrap;
        justify-content: space-between;
    }

    .kopfleiste__inhalt--zentriert .kopfleiste__marke,
    .kopfleiste__inhalt--zentriert .kopfleiste__rechts {
        grid-column: auto;
        justify-self: auto;
    }
}

/* Umschließt Logo und/oder Anwendungsname links in der Kopfleiste - welche
   Kombination angezeigt wird, entscheidet logo_anzeige in den globalen
   Seiteneinstellungen (siehe includes/kopf.php). */
.kopfleiste__marke {
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 0;
    /* Bauschritt 22: jetzt ein <a> (Link zur Hauptseite) statt eines reinen
       div - Standard-Link-Optik (Unterstrich, Linkfarbe) zurücksetzen, die
       Kopfleiste soll optisch unverändert aussehen, nur eben klickbar sein. */
    color: inherit;
    text-decoration: none;
}

.kopfleiste__marke:hover {
    opacity: 0.85;
}

.kopfleiste__logo {
    display: block;
    height: 32px;
    width: auto;
    max-width: 200px;
    object-fit: contain;
}

/* Titel/Anwendungsname in der Kopfleiste des angemeldeten Bereichs - eigene
   Klasse (statt der .app__eyebrow der Anmelde-/Fehlerseiten), damit sich
   hier über Seiteneinstellungen -> Menüleiste eine eigene Schriftgröße/-art
   einstellen lässt (leiste_schriftgroesse/-schriftart, siehe
   includes/kopf.php), ohne die Anmelde-/Fehlerseiten mit zu beeinflussen.
   Optik unverändert zur bisherigen .app__eyebrow als Standard. */
.kopfleiste__titel {
    font-family: var(--schrift-anzeige);
    letter-spacing: 0.03em;
    text-transform: uppercase;
    font-size: 0.85rem;
    color: var(--farbe-text-gedaempft);
}

/* Bauschritt 26: Zurück-Pfeil unmittelbar links vom Titel-Text, wenn gerade
   ein zusätzlicher Screen (nicht der Haupt-Screen) angezeigt wird - siehe
   includes/kopf.php ($aktuellerScreenTitel). Liegt innerhalb desselben
   .kopfleiste__marke-Links wie Logo/Titel, ein Klick auf den Pfeil (oder
   irgendwo sonst auf Logo/Titel) führt deshalb ganz automatisch zurück zu
   index.php, ohne eigenen Klick-Handler. */
.kopfleiste__zurueck-pfeil {
    margin-right: 0.35em;
}

.kopfleiste__rechts {
    display: flex;
    align-items: center;
    gap: 16px;
    font-size: 0.9rem;
}

/* --- Profilmenü (Bauschritt 18) -------------------------------------------
   Ersetzt die bisherigen einzelnen Elemente in .kopfleiste__rechts
   (Bearbeiten-Modus-Knopf, Seiteneinstellungen-Verweis, Benutzername,
   Abmelden) durch ein einziges dezentes Symbol mit aufklappbarem Menü -
   siehe includes/kopf.php für die Markup-Struktur und
   assets/js/dashboard.js (profilmenueEinrichten()) für Öffnen/Schließen. */
.profilmenue {
    position: relative;
}

.profilmenue__knopf {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    padding: 0;
    border: none;
    border-radius: 50%;
    background: transparent;
    cursor: pointer;
}

.profilmenue__knopf:hover,
.profilmenue__knopf[aria-expanded="true"] {
    background: rgba(20, 24, 33, 0.08);
}

.profilmenue__icon {
    width: 22px;
    height: 22px;
    fill: #1f2430;
}

.profilmenue__panel {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    z-index: 20;
    min-width: 200px;
    display: flex;
    flex-direction: column;
    background: var(--farbe-flaeche);
    border: 1px solid var(--farbe-rand);
    border-radius: 10px;
    box-shadow: var(--schatten);
    padding: 6px;
}

/* WICHTIG: "display: flex;" oben überstimmt sonst die Browser-Vorgabe für
   das HTML-Attribut "hidden" (beide haben dieselbe Spezifität 0-1-0, bei
   Gleichstand gewinnt die zuletzt geladene Regel - und Autoren-CSS lädt
   immer nach dem User-Agent-Stylesheet) - das Menü bliebe dadurch trotz
   gesetztem "hidden"-Attribut sichtbar. Diese Regel stellt das Verstecken
   wieder ausdrücklich sicher. */
.profilmenue__panel[hidden] {
    display: none;
}

.profilmenue__name {
    padding: 8px 10px 6px;
    font-weight: 600;
    color: var(--farbe-text);
    font-size: 0.9rem;
    border-bottom: 1px solid var(--farbe-rand);
    margin-bottom: 4px;
}

.profilmenue__eintrag {
    display: block;
    width: 100%;
    text-align: left;
    border: none;
    background: transparent;
    color: var(--farbe-text);
    font-family: var(--schrift-text);
    font-size: 0.9rem;
    padding: 8px 10px;
    border-radius: 6px;
    cursor: pointer;
    text-decoration: none;
}

.profilmenue__eintrag:hover,
.profilmenue__eintrag:focus {
    background: var(--farbe-hintergrund);
    outline: none;
}

.profilmenue__eintrag--abmelden {
    color: var(--farbe-fehler);
}

/* --- Dashboard ----------------------------------------------------------- */

/* Bauschritt 21: der frühere einheitliche Wert "32px 24px" ließ oben (zur
   Kopfleiste) mehr Platz als den Abstand zwischen den Kacheln selbst (20px,
   siehe .kachel-grid gap weiter unten) - dadurch wirkte die erste
   Kachel-Reihe "abgerückt". Jetzt oben exakt derselbe Wert wie der
   Grid-Abstand, unten bewusst etwas mehr (Seitenende statt Kachel-zu-
   Kachel-Abstand, dort darf es ruhig etwas mehr Luft sein). Seitlich
   unverändert. */
.app {
    max-width: 1200px;
    margin: 0 auto;
    padding: 20px 24px 32px;
}

.dashboard-platzhalter {
    background: var(--farbe-flaeche);
    border: 1px dashed var(--farbe-rand);
    border-radius: var(--radius);
    padding: 48px 24px;
    text-align: center;
    color: var(--farbe-text-gedaempft);
}

.dashboard-platzhalter__hinweis {
    font-size: 0.9rem;
    max-width: 480px;
    margin: 8px auto 0;
}

/* --- Kachel-Grid -----------------------------------------------------------
   Seit Bauschritt 16 ein feineres Spalten-Raster (170px statt vorher direkt
   260px), damit eine einzelne Kachel darüber in drei Breiten-Stufen
   (schmal/normal/breit, siehe .kachel--schmal/.kachel--breit weiter unten
   und KACHEL_BREITEN in includes/kacheln.php) über "grid-column: span N"
   ausgedrückt werden kann - "normal" (Standard, ohne eigene Einstellung)
   entspricht mit 2 Spalten optisch ungefähr der bisherigen einheitlichen
   Kachel-Breite.

   "grid-auto-flow: dense" lässt nachfolgende Kacheln in bereits entstandene
   Lücken vorrücken, statt platzsparend brav der Reihe nach auf die nächste
   passende Stelle zu warten - dafür kann die sichtbare Anordnung dann leicht
   von der eingestellten Reihenfolge abweichen (bewusst in Kauf genommen,
   siehe HINWEISE-SCHRITT-16.md).

   "grid-auto-rows: 4px" definiert eine feine Hilfs-Zeilenraster-Einheit;
   jede Kachel bekommt ihre tatsächliche Höhe darüber als "grid-row: span N"
   zugewiesen (siehe assets/js/dashboard.js, kachelMasonryEinrichten()) -
   erst dieses Zusammenspiel aus feinem Zeilenraster + dense-Packung sorgt
   dafür, dass eine kurze Kachel neben einer hohen keine große Lücke mehr
   hinterlässt.

   Bauschritt 21 (Korrektur - ungleiche Abstände zwischen den Kachel-Reihen):
   vorher setzte "gap: 20px" den Abstand SOWOHL zwischen Spalten ALS AUCH
   zwischen jeder der vielen feinen Hilfs-Zeilen, die eine "grid-row: span N"
   -Kachel überspannt. Bei N Zeilen entstehen dadurch (N-1) Zwischenräume
   INNERHALB der eigenen Kachel-Fläche, die kachelMasonryEinrichten() in die
   Berechnung mit einbeziehen musste - und weil die tatsächliche
   Kachel-Höhe praktisch nie exakt durch (Zeilen-Einheit + Abstand) teilbar
   ist, musste JS auf die nächste ganze Zeilenzahl AUFRUNDEN. Genau dieses
   Aufrunden war der eigentliche Fehler: je nach Kachel-Höhe blieb
   unterschiedlich viel "Rest" übrig (bis zu fast einer ganzen
   Zeilen-Einheit + einem Abstand, hier vorher bis zu 27px), der als
   zusätzliche Lücke UNTER der jeweiligen Kachel sichtbar wurde - deshalb
   wirkten die Abstände zwischen den Reihen uneinheitlich, obwohl der Wert
   überall derselbe (20px) war.

   Die Lösung: row-gap auf 0 gesetzt (column-gap bleibt 20px, betrifft nur
   den - vom Nutzer als stimmig bestätigten - Abstand NEBEN den Kacheln) und
   die gewünschten 20px stattdessen direkt in die Höhen-Berechnung jeder
   Kachel eingerechnet (siehe kachelMasonryEinrichten()) - die Zeilen-Einheit
   selbst ist jetzt außerdem feiner (4px statt 8px), damit auch der
   verbleibende Rundungsfehler (jetzt höchstens etwas unter 4px statt bis zu
   27px) kaum noch wahrnehmbar ist. */
.kachel-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
    grid-auto-flow: dense;
    /* "minmax(4px, auto)" statt eines festen "4px": passt JS die Höhe einer
       Kachel korrekt in ein "grid-row: span N" um (Regelfall), reicht "auto"
       ohnehin nie - N*4px deckt die tatsächliche Höhe immer ab, weil
       kachelMasonryEinrichten() in assets/js/dashboard.js dafür aufrundet.
       Ohne funktionierendes JavaScript (z. B. sehr alter Browser ohne
       ResizeObserver) würde eine feste "4px"-Zeile dagegen jede Kachel ohne
       eigene Spanne beschneiden/überlappen lassen - "auto" wächst in diesem
       Ausnahmefall stattdessen einfach mit dem Inhalt und fällt so
       gefahrlos auf ein Layout ähnlich dem vor Bauschritt 16 zurück. */
    grid-auto-rows: minmax(4px, auto);
    column-gap: 20px;
    row-gap: 0;
    align-items: start;
}

.kachel {
    position: relative;
    overflow: hidden;
    grid-column: span 2;
    background: var(--farbe-flaeche);
    background-size: cover;
    background-position: center;
    border: 1px solid var(--farbe-rand);
    border-radius: var(--radius);
    box-shadow: var(--schatten);
    /* Bauschritt 22: der Innenabstand oben (zwischen Kachelrand und
       Überschrift) ist bewusst kleiner als an den übrigen drei Seiten
       (15px statt 20px, ca. 25% weniger) - Rückmeldung, dass hier zu viel
       Luft war. Die anderen drei Seiten bleiben unverändert bei 20px.
       Bauschritt 25: oben/unten zusätzlich mit "--kachel-grid-zoom"
       multipliziert (Desktop-Auto-Vergrößern bei viel Leerraum unter dem
       Grid, siehe kachelGridZoomEinrichten() in assets/js/dashboard.js) -
       links/rechts bewusst UNVERÄNDERT fest bei 20px, damit dieses
       Vergrößern niemals die Spaltenbreite/-anzahl beeinflusst (siehe
       .kachel-grid, grid-template-columns bleibt ebenfalls unangetastet). */
    padding-top: calc(15px * var(--kachel-grid-zoom, 1));
    padding-right: 20px;
    padding-bottom: calc(20px * var(--kachel-grid-zoom, 1));
    padding-left: 20px;
    min-height: 140px;
}

.kachel--schmal {
    grid-column: span 1;
}

.kachel--breit {
    grid-column: span 3;
}

/* Auf mittelbreiten Bildschirmen ist eine dreispaltig breite Kachel relativ
   zu den übrigen (2 Spalten) oft schon fast die ganze Zeile - dort auf
   "normal"-Breite zurückstufen, statt fast leere Restspalten zu riskieren.
   Ab Smartphone-Breite (siehe @media (max-width: 640px) weiter unten) dann
   ohnehin einheitlich einspaltig. */
@media (max-width: 900px) {
    .kachel--breit {
        grid-column: span 2;
    }
}

/* Bauschritt 23: "Halbiert anzeigen" bei der Link-Kachel - zwei UNMITTELBAR
   aufeinanderfolgende Link-Kacheln mit dieser Einstellung landen in einem
   gemeinsamen Grid-Feld (siehe kachelnRendern() in includes/kacheln.php)
   statt je einer eigenen Grid-Spalte - ".kachel-paar" selbst ist dabei das
   eigentliche Grid-Element, mit genau derselben Spannweite wie eine
   einzelne "normal" breite Kachel (span 2, siehe ".kachel" oben). Innerhalb
   des Paares liegen die beiden echten ".kachel"-Elemente unverändert
   nebeneinander in einem einfachen Flex-Container - jede bleibt eine
   eigenständige, vollwertige Kachel mit eigener data-kachel-id (Drag & Drop,
   Positions-/Breite-Knöpfe, Löschen-Knopf funktionieren dadurch
   unverändert je Kachel für sich, siehe kachelRendern()). "align-items:
   stretch" (Grid-/Flex-Standard) sorgt dafür, dass beide Hälften optisch
   gleich hoch wirken (an der jeweils höheren ausgerichtet), "min-width: 0"
   auf den Kindern verhindert, dass eine lange Überschrift die Aufteilung
   sprengt. */
.kachel-paar {
    grid-column: span 2;
    display: flex;
    gap: 20px; /* derselbe Abstand wie column-gap im .kachel-grid */
}

.kachel-paar > .kachel {
    flex: 1 1 0;
    min-width: 0;
}

/* Bauschritt 19: "Rahmenlos" (nur Bild-Kachel, siehe kachel-aussehen.php,
   Abschnitt "Inhalt" bei diesem Typ) - entfernt Rahmen, Hintergrundfarbe,
   Schatten UND Innenabstand der ganzen Kachel, damit das Bild randlos die
   komplette Fläche ausfüllen kann. ".kachel" behält dabei weiterhin
   "overflow: hidden" plus "border-radius" (siehe oben) - dadurch wird das
   Bild automatisch an den abgerundeten Ecken der Kachel beschnitten, ganz
   ohne eigene border-radius-Regel auf dem Bild selbst. */
.kachel--rahmenlos {
    border: none;
    background: none;
    box-shadow: none;
    padding: 0;
}

/* "Ohne Rahmen" (nur PDF-Kachel) ist bewusst schwächer als "rahmenlos" oben:
   nur Rahmen und Schatten verschwinden, die Hintergrundfarbe bleibt - die
   soll bei der PDF-Kachel laut Rückmeldung ausdrücklich weiterhin "wie bei
   anderen Kacheln" einstellbar bleiben (siehe kachel-aussehen.php). */
.kachel--ohne-rahmen {
    border: none;
    box-shadow: none;
}

.bild-kachel__bild {
    display: block;
    width: 100%;
    height: auto;
    border-radius: var(--radius);
}

/* Bauschritt 22: Titel-Modus "auf dem Bild liegend" bei der Bild-Kachel
   (siehe kachelBildTitelModus(), kachel-aussehen.php) - der Kachel-Kopf
   (mit der Überschrift) legt sich als Leiste mit dunklem Verlauf über den
   oberen Rand des Bildes, statt normal darüber zu stehen. :has() wählt den
   Kopf anhand der Titel-Klasse aus (moderne Browser vorausgesetzt - genau
   wie schon color-mix() an anderer Stelle in dieser Datei), eine eigene
   Kopf-Klasse extra dafür wäre unnötige Zusatz-Komplexität in
   kachelRendern(). Die Schriftfarbe wird hier bewusst fest auf Weiß
   gesetzt statt die eingestellte Schriftfarbe zu übernehmen - die muss
   über wechselnden Bildinhalten nicht zwangsläufig lesbar sein. */
.kachel__kopf:has(.kachel__titel--auf-bild) {
    position: absolute;
    inset: 0 0 auto 0;
    z-index: 2;
    margin-bottom: 0;
    padding: 10px 14px;
    background: linear-gradient(to bottom, color-mix(in srgb, black 55%, transparent), transparent);
    border-radius: var(--radius) var(--radius) 0 0;
}

.kachel__titel--auf-bild {
    color: #fff;
}

/* Bauschritt 19: die Überschrift einer PDF-Kachel lässt sich unabhängig
   ausblenden (kachel-aussehen.php, Abschnitt "Inhalt") - dasselbe Prinzip
   wie schon bei der leeren Kalender-Notiz weiter unten (body:not(
   .bearbeiten-modus-aktiv)): im Bearbeiten-Modus bleibt sie trotzdem
   sichtbar, damit sich der Titel weiterhin bearbeiten lässt. Bauschritt 22:
   dieselbe Klasse (umbenannt von "--pdf-versteckt", da jetzt nicht mehr
   PDF-exklusiv) übernimmt jetzt auch das Ausblenden bei der Link-Kachel
   (kachelLinkTitelAnzeigen()) und beim "ausgeblendet"-Modus der Bild-Kachel
   (kachelBildTitelModus()). */
body:not(.bearbeiten-modus-aktiv) .kachel__titel--versteckt {
    display: none;
}

/* --- PDF-Kachel ---------------------------------------------------------- */

.pdf-kachel__vorschau-knopf {
    display: block;
    width: 100%;
    border: none;
    background: none;
    padding: 0;
    cursor: zoom-in;
    /* Bauschritt 26: Zoom-Faktor/unterer Beschnitt der kleinen Vorschau
       (siehe pdfKachelnEinrichten() in assets/js/dashboard.js) - der Knopf
       ist der Beschnitt-Rahmen: eine über 100% hinaus vergrößerte Vorschau
       ragt links/rechts über ihn hinaus (durch overflow:hidden
       abgeschnitten), ein per JS gesetzter fester Höhenwert schneidet
       entsprechend unten ab. Ohne Zoom/Beschnitt (Standard) bleibt das
       Verhalten unverändert - JS setzt dann keine Inline-Maße. */
    overflow: hidden;
    position: relative;
}

.pdf-kachel__vorschau {
    display: block;
    width: 100%;
    height: auto;
    margin: 0 auto;
    border-radius: 6px;
    box-shadow: var(--schatten);
}

.pdf-kachel-overlay {
    position: fixed;
    inset: 0;
    z-index: 1000;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(20, 24, 33, 0.75);
    padding: 24px;
}

.pdf-kachel-overlay[hidden] {
    display: none;
}

.pdf-kachel-overlay__rahmen {
    position: relative;
    max-width: 90vw;
    max-height: 90vh;
}

.pdf-kachel-overlay__canvas {
    display: block;
    max-width: 90vw;
    max-height: 90vh;
    width: auto;
    height: auto;
    border-radius: 6px;
    box-shadow: var(--schatten);
}

.pdf-kachel-overlay__schliessen {
    position: absolute;
    top: -18px;
    right: -18px;
    width: 36px;
    height: 36px;
    border: none;
    border-radius: 50%;
    background: #fff;
    color: var(--farbe-text);
    font-size: 1.2rem;
    line-height: 1;
    cursor: pointer;
    box-shadow: var(--schatten);
}

/* Eigene, absolut positionierte Ebene für ein Hintergrundbild (siehe
   includes/kacheln.php, kachelHintergrundBildStil()) - ihre Deckkraft
   (opacity, inline über style gesetzt) lässt sich dadurch unabhängig vom
   Textinhalt einstellen (bild_transparenz in kacheln.konfiguration_json,
   siehe kachel-aussehen.php). Liegt hinter .kachel__kopf/.kachel__inhalt
   (z-index 0 vs. 1 dort), .kachel selbst braucht dafür position:relative
   und overflow:hidden (schneidet das Bild am border-radius ab). */
.kachel__hintergrund-bild-ebene {
    position: absolute;
    inset: 0;
    z-index: 0;
    background-size: cover;
    background-position: center;
    pointer-events: none;
}

.kachel--wird-gezogen {
    opacity: 0.4;
}

.kachel__kopf {
    position: relative;
    z-index: 1;
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 12px;
}

.kachel__griff {
    display: none; /* siehe Bearbeiten-Modus-Regeln weiter unten */
    flex: none;
    color: var(--farbe-text-gedaempft);
    font-size: 0.95rem;
    cursor: grab;
    user-select: none;
}

.kachel__titel {
    flex: 1;
    font-family: var(--schrift-anzeige);
    /* Bauschritt 26: die Kachel-EIGENE Textgröße ("--kachel-titel-faktor")
       ist entfallen - die Überschriftsgröße richtet sich seither
       ausschließlich nach der globalen Einstellung
       "--schriftgroesse-anzeige-faktor" (Seiteneinstellungen), siehe
       kachelUeberschriftStil() in includes/kacheln.php. */
    font-size: calc(1.15rem * var(--schriftgroesse-anzeige-faktor, 1));
    margin: 0;
}

/* Bauschritt 20: Überschrift wahlweise zentriert statt linksbündig (siehe
   kachel-aussehen.php, Abschnitt "Schrift"). Die anderen Kopf-Elemente
   (Griff, Positions-/Breite-Knöpfe, Zahnrad-/Löschen-Knopf) bleiben davon
   unberührt - .kachel__kopf ist weiterhin ein flex-Container, nur die
   Überschrift selbst zentriert ihren eigenen Text. */
.kachel__titel--zentriert {
    text-align: center;
}

/* Textinhalt der Kachel liegt (wie .kachel__kopf) über der
   Hintergrundbild-Ebene (siehe .kachel__hintergrund-bild-ebene weiter
   oben). */
.kachel__inhalt {
    position: relative;
    z-index: 1;
}

/* Link-Kachel (Bauschritt 20, siehe includes/kacheln.php, kachelRendern()):
   eine unsichtbare Ebene über der GANZEN Kachel macht sie im Lesemodus
   komplett klickbar, nicht nur einen einzelnen Text/Knopf darin. z-index 2
   liegt über .kachel__kopf/.kachel__inhalt (beide 1) und der
   Hintergrundbild-Ebene (0). pointer-events:none ist der Normalfall - nur
   außerhalb jedes der drei Modi, die Griff/Positions-Knöpfe im Kachel-Kopf
   zeigen (Bearbeiten-Modus, "Mobile Reihenfolge bearbeiten", Anordnen-Modus
   - siehe die jeweiligen "body.*-aktiv .kachel__*"-Regeln weiter unten)
   wird die Ebene tatsächlich klickbar; in jedem dieser drei Modi liegen
   ohnehin schon Griff/Zahnrad-Knöpfe/Löschen-Knopf/▲▼-Knöpfe usw. an
   derselben Stelle und müssen weiter normal bedienbar bleiben - diese
   Kachel-Kopf-Knöpfe sind außerhalb aller drei Modi ohnehin per
   display:none unsichtbar, die Link-Ebene kann ihnen dort also nie in die
   Quere kommen.

   Bauschritt 29 (Fehlerbehebung): bis einschließlich Bauschritt 28 stand
   hier nur "body:not(.bearbeiten-modus-aktiv)" - das "Mobile Reihenfolge
   bearbeiten" gab es zwar schon länger, aber erst der neue Anordnen-Modus
   (Bauschritt 26) machte den Fehler sichtbar/gemeldet: in BEIDEN Modi blieb
   diese Ebene fälschlich klickbar und lag (z-index 2) über den ▲▼-Knöpfen
   (z-index 1 im Kachel-Kopf) - ein Tippen/Klicken auf einen ▲▼-Knopf einer
   LINK-Kachel in einem dieser beiden Modi traf dadurch in Wirklichkeit
   diese unsichtbare Ebene statt den Knopf und bewegte die Kachel deshalb
   gar nicht (reproduziert und verifiziert mit Playwright, siehe
   HINWEISE-SCHRITT-29.md - betraf nachweisbar nicht nur Touch/iOS, sondern
   genauso einen normalen Maus-Klick auf jedem Gerät, nur bei JEDER anderen
   Kachel-Art als "Link" ist gar keine solche Ebene vorhanden, weshalb es
   dort nie auffiel). */
.kachel__link-ueberlagerung {
    position: absolute;
    inset: 0;
    z-index: 2;
    pointer-events: none;
}

body:not(.bearbeiten-modus-aktiv):not(.mobil-reihenfolge-aktiv):not(.anordnen-modus-aktiv) .kachel__link-ueberlagerung {
    pointer-events: auto;
}

/* Bauschritt 21: der Inhaltsbereich der Link-Kachel ist jetzt komplett
   leer (kein Pfeil mehr, siehe kachelInhaltRendern()) - der 12px-Abstand
   unter der Überschrift (.kachel__kopf) wäre dann reine Leerfläche ohne
   Zweck, deshalb hier auf 0 reduziert. Die Kachel besteht dadurch
   tatsächlich "quasi nur aus dem Titel". Bauschritt 22: die allgemeine
   Mindesthöhe von 140px (.kachel, für Kacheln mit echtem Inhalt gedacht)
   sorgte bei der inhaltslosen Link-Kachel für sichtbar mehr Leerraum UNTER
   der Überschrift als darüber (der obere Innenabstand der Kachel, oben
   ohnehin schon symmetrisch zum unteren) - deshalb hier aufgehoben, die
   Kachel ist jetzt nur so hoch wie Innenabstand + Überschrift zusammen
   ergeben, oben genauso groß wie unten. */
.kachel[data-kachel-typ="link"] .kachel__kopf {
    margin-bottom: 0;
}

.kachel[data-kachel-typ="link"] {
    min-height: 0;
    /* .kachel selbst hat oben (15px) bewusst weniger Innenabstand als an
       den übrigen drei Seiten (20px, siehe .kachel weiter oben) - bei der
       Link-Kachel soll der Abstand um die Überschrift aber ausdrücklich
       gleich groß sein, deshalb hier für beide Seiten auf denselben
       (kleineren) Wert gesetzt statt den allgemeinen Bottom-Wert zu erben.
       Bauschritt 25: auch hier mit --kachel-grid-zoom skaliert, siehe
       .kachel weiter oben. */
    padding-bottom: calc(15px * var(--kachel-grid-zoom, 1));
}

/* Bauschritt 24: EIN einzelner Zahnrad-Verweis im Kachel-Kopf statt der
   bisherigen zwei getrennten (Zahnrad zu kachel-eintraege.php + Palette zu
   kachel-aussehen.php, siehe HINWEISE-SCHRITT-24.md) - führt jetzt zu
   kachel-eintraege.php (dort sind Einträge/Inhalt/Hintergrund/Schrift zu
   EINER Seite zusammengeführt), bei Klassendienste-Kacheln weiterhin zu
   klassendienste-verwalten.php. Bewusst fest SCHWARZ (nicht die
   Akzent-/Linkfarbe, die "a"-Elemente sonst über die globale "a"-Regel
   erben, und auch nicht die je Kachel einstellbare Schriftfarbe) - damit
   der Knopf auf jeder noch so bunten Kachel gleich gut erkennbar bleibt.
   Steht jetzt als ERSTES Element im Kachel-Kopf (siehe kachelRendern() in
   includes/kacheln.php) statt hinter Griff/Positions-/Breite-Knöpfen -
   bleibt dadurch auch auf einer schmalen Kachel sichtbar, wo die übrigen
   Kopf-Knöpfe eher zum Umbruch/Abschneiden neigen. */
.kachel__einstellungen-knopf {
    display: none; /* siehe Bearbeiten-Modus-Regeln weiter unten */
    flex: none;
    text-decoration: none;
    border: none;
    background: transparent;
    color: #000;
    font-size: 1rem;
    line-height: 1;
    padding: 2px 4px;
    border-radius: 6px;
    cursor: pointer;
    opacity: 0;
    /* Bauschritt 29: siehe ausführlicher Kommentar bei .kachel__auf-knopf/
       .kachel__ab-knopf weiter unten. */
    touch-action: manipulation;
}

.kachel:hover .kachel__einstellungen-knopf,
.kachel__einstellungen-knopf:focus {
    opacity: 1;
}

.kachel__einstellungen-knopf:hover {
    background: rgba(0, 0, 0, 0.08);
}

.kachel__positions-knoepfe {
    display: none; /* siehe Bearbeiten-Modus-Regeln weiter unten */
    flex-direction: column;
    flex: none;
}

.kachel__auf-knopf,
.kachel__ab-knopf {
    flex: none;
    border: none;
    background: transparent;
    color: var(--farbe-text-gedaempft);
    font-size: 0.55rem;
    line-height: 1;
    padding: 1px 3px;
    border-radius: 4px;
    cursor: pointer;
    opacity: 0;
    /* Bauschritt 29: verhindert, dass Safari auf iOS einen Tipp auf diesen
       (kleinen, eng beieinanderliegenden) Knopf erst mit der Doppeltipp-
       Zoom-Geste abgleicht, bevor das click-Ereignis ausgelöst wird - macht
       den Knopf spürbar reaktionsschneller/zuverlässiger antippbar.
       Behebt NICHT den eigentlichen, in dieser Runde gefundenen Fehler bei
       Link-Kacheln (siehe .kachel__link-ueberlagerung weiter oben und
       HINWEISE-SCHRITT-29.md) - eine zusätzliche, unabhängig sinnvolle
       Verbesserung für alle Touch-Geräte. */
    touch-action: manipulation;
}

.kachel:hover .kachel__auf-knopf,
.kachel:hover .kachel__ab-knopf,
.kachel__auf-knopf:focus,
.kachel__ab-knopf:focus {
    opacity: 1;
}

.kachel__auf-knopf:hover,
.kachel__ab-knopf:hover {
    background: rgba(0, 0, 0, 0.08);
}

/* ◀/▶-Knöpfe zum Ändern der Breiten-Stufe (Bauschritt 16, siehe
   kachelBreiteEinrichten() in assets/js/dashboard.js) - optisch dasselbe
   Muster wie .kachel__auf-knopf/.kachel__ab-knopf oben, nur nebeneinander
   statt übereinander (Breite statt Position). */
.kachel__breite-knoepfe {
    display: none; /* siehe Bearbeiten-Modus-Regeln weiter unten */
    flex-direction: row;
    gap: 2px;
    flex: none;
}

.kachel__schmaler-knopf,
.kachel__breiter-knopf {
    flex: none;
    border: none;
    background: transparent;
    color: var(--farbe-text-gedaempft);
    font-size: 0.55rem;
    line-height: 1;
    padding: 1px 3px;
    border-radius: 4px;
    cursor: pointer;
    opacity: 0;
    /* Bauschritt 29: siehe ausführlicher Kommentar bei .kachel__auf-knopf/
       .kachel__ab-knopf weiter oben. */
    touch-action: manipulation;
}

.kachel:hover .kachel__schmaler-knopf,
.kachel:hover .kachel__breiter-knopf,
.kachel__schmaler-knopf:focus,
.kachel__breiter-knopf:focus {
    opacity: 1;
}

.kachel__schmaler-knopf:hover,
.kachel__breiter-knopf:hover {
    background: rgba(0, 0, 0, 0.08);
}

.kachel__loeschen-knopf {
    display: none; /* siehe Bearbeiten-Modus-Regeln weiter unten */
    flex: none;
    border: none;
    background: transparent;
    color: var(--farbe-text-gedaempft);
    font-size: 1.2rem;
    line-height: 1;
    padding: 2px 6px;
    border-radius: 6px;
    cursor: pointer;
    opacity: 0;
    /* Bauschritt 29: siehe ausführlicher Kommentar bei .kachel__auf-knopf/
       .kachel__ab-knopf weiter oben. */
    touch-action: manipulation;
}

.kachel:hover .kachel__loeschen-knopf,
.kachel__loeschen-knopf:focus {
    opacity: 1;
}

.kachel__loeschen-knopf:hover {
    background: rgba(179, 38, 30, 0.1);
    color: var(--farbe-fehler);
}

.kachel__platzhaltertext {
    color: var(--farbe-text-gedaempft);
    font-size: 0.9rem;
    font-style: italic;
    margin: 0;
}

.kachel__rich-text h1 {
    font-family: var(--schrift-anzeige);
    /* Bauschritt 25: "--kachel-text-faktor" siehe kachelTextStil() in
       includes/kacheln.php - dieselbe Begründung wie bei .kachel__titel
       oben (eigene rem-Angabe erbt nicht von .kachel__inhalt). */
    font-size: calc(1.3rem * var(--schriftgroesse-anzeige-faktor, 1) * var(--kachel-text-faktor, 1));
    margin: 0 0 8px;
}

.kachel__rich-text h2 {
    font-family: var(--schrift-anzeige);
    font-size: calc(1.1rem * var(--schriftgroesse-anzeige-faktor, 1) * var(--kachel-text-faktor, 1));
    margin: 0 0 8px;
}

.kachel__rich-text p {
    margin: 0 0 10px;
}

.kachel__rich-text ul,
.kachel__rich-text ol {
    margin: 0 0 10px;
    padding-left: 22px;
}

/* execCommand('indent') erzeugt <blockquote> ohne Attribute (der Sanitizer
   entfernt style-Attribute grundsätzlich) - die optische Einrückung kommt
   daher von hier statt von einem inline style. */
.kachel__rich-text blockquote {
    margin: 0 0 10px 4px;
    padding-left: 14px;
    border-left: 3px solid var(--farbe-rand);
}

/* --- To-Do-Liste ------------------------------------------------------- */

.todo-liste {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.todo-eintrag {
    display: flex;
    align-items: center;
    gap: 8px;
    /* Bauschritt 25: "--kachel-text-faktor" siehe kachelTextStil() in
       includes/kacheln.php - .todo-eintrag__text setzt selbst keine eigene
       font-size und erbt deshalb normal von hier. */
    font-size: calc(0.95rem * var(--kachel-text-faktor, 1));
}

.todo-eintrag--wird-gezogen {
    opacity: 0.4;
}

.todo-eintrag__griff {
    display: none; /* siehe Bearbeiten-Modus-Regeln weiter unten */
    flex: none;
    color: var(--farbe-text-gedaempft);
    font-size: 0.9rem;
    cursor: grab;
    user-select: none;
}

.todo-eintrag__checkbox {
    flex: none;
    width: 16px;
    height: 16px;
    accent-color: var(--farbe-akzent);
    cursor: pointer;
}

.todo-eintrag__text {
    flex: 1;
    border-radius: 4px;
    padding: 1px 4px;
    margin: -1px -4px;
    cursor: text;
}

.todo-eintrag__text:hover,
.todo-eintrag__text:focus {
    background: rgba(47, 95, 221, 0.06);
    outline: none;
}

.todo-eintrag--erledigt .todo-eintrag__text {
    color: var(--farbe-text-gedaempft);
    text-decoration: line-through;
}

/* Bauschritt 25: keinen eigenen Löschen-Knopf mehr auf der Kachel-Fläche -
   ein To-Do-Eintrag lässt sich nur noch über die Einträge-Verwaltung
   (kachel-eintraege.php) ganz entfernen, siehe kachelRenderTodo() in
   includes/kacheln.php. Die frühere ".todo-eintrag__loeschen"-Regel (samt
   Bearbeiten-Modus-Sichtbarkeit) wurde deshalb entfernt. */

.todo-eintrag__positions-knoepfe {
    display: none; /* siehe Bearbeiten-Modus-Regeln weiter unten */
    flex-direction: column;
    flex: none;
}

.todo-eintrag__auf-knopf,
.todo-eintrag__ab-knopf {
    flex: none;
    border: none;
    background: transparent;
    color: var(--farbe-text-gedaempft);
    font-size: 0.5rem;
    line-height: 1;
    padding: 1px 3px;
    border-radius: 4px;
    cursor: pointer;
    opacity: 0;
}

.todo-eintrag:hover .todo-eintrag__auf-knopf,
.todo-eintrag:hover .todo-eintrag__ab-knopf,
.todo-eintrag__auf-knopf:focus,
.todo-eintrag__ab-knopf:focus {
    opacity: 1;
}

.todo-eintrag__auf-knopf:hover,
.todo-eintrag__ab-knopf:hover {
    background: rgba(0, 0, 0, 0.08);
}

/* Neue To-Do-Einträge werden seit Bauschritt 14 über kachel-eintraege.php
   angelegt statt über ein Formular hier in der Kachel - siehe
   includes/kacheln.php, kachelRenderTodo(). */

/* --- Stundenplan-Widget ------------------------------------------------ */

.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
}

/* Bauschritt 23: "Heute · <Datum>"-Zeile direkt unter der Kachel-
   Überschrift, im selben dezenten Stil wie der Heute/Morgen-Hinweis der
   iCal-Kachel (siehe .ical-tage-kopf weiter unten) - bewusst nur diese
   eine schlichte Textzeile, KEINE Spalten-Hervorhebung im Stundenplan-
   Raster selbst (laut Rückfrage-Antwort ausdrücklich nicht gewünscht).
   Der minimale Abstand nach oben kommt von der Kachel-typ-spezifischen
   Reduktion von .kachel__kopf weiter unten (dieselbe Reduktion wie bei der
   Klassendienste-Kachel, für eine einheitliche Optik). */
.stundenplan-heute-zeile {
    margin: 0 0 8px 0;
    font-size: 0.82rem;
    color: var(--farbe-text-gedaempft);
}

.kachel[data-kachel-typ="stundenplan"] .kachel__kopf {
    margin-bottom: 4px;
}

.stundenplan-wrapper {
    overflow-x: auto;
    margin: 0 -4px;
}

.stundenplan {
    width: 100%;
    border-collapse: collapse;
    /* Bauschritt 25: "--kachel-text-faktor" siehe kachelTextStil() in
       includes/kacheln.php - Fach/Raum (.stundenplan-eintrag__fach/__raum)
       setzen selbst keine eigene font-size und erben deshalb normal von
       dieser Tabelle. */
    font-size: calc(0.8rem * var(--kachel-text-faktor, 1));
    table-layout: fixed;
}

.stundenplan__eck {
    width: 28px;
}

.stundenplan__wochentag {
    font-family: var(--schrift-anzeige);
    font-size: calc(0.75rem * var(--schriftgroesse-anzeige-faktor, 1));
    letter-spacing: 0.02em;
    color: var(--farbe-text-gedaempft);
    padding: 4px 2px;
    text-align: center;
}

.stundenplan__stunde {
    color: var(--farbe-text-gedaempft);
    font-weight: 600;
    text-align: right;
    padding: 3px 4px 3px 0;
    white-space: nowrap;
}

.stundenplan__zelle {
    border: 1px solid var(--farbe-rand);
    border-radius: 4px;
    padding: 0;
    height: 34px;
    vertical-align: middle;
    background: rgba(255, 255, 255, 0.5);
}

/* Neue Stundenplan-Zellen werden seit Bauschritt 14 über
   kachel-eintraege.php angelegt statt über einen "+"-Knopf hier in der
   Kachel - siehe includes/kacheln.php, kachelRenderStundenplan(). */

.stundenplan-eintrag {
    position: relative;
    padding: 3px 4px;
    text-align: center;
    line-height: 1.2;
}

.stundenplan-eintrag__fach {
    display: block;
    font-weight: 600;
    border-radius: 4px;
    cursor: text;
}

.stundenplan-eintrag__raum {
    display: block;
    font-size: 0.7rem;
    color: var(--farbe-text-gedaempft);
    border-radius: 4px;
    cursor: text;
    min-height: 1.1em;
}

.stundenplan-eintrag__fach:hover,
.stundenplan-eintrag__fach:focus,
.stundenplan-eintrag__raum:hover,
.stundenplan-eintrag__raum:focus {
    background: rgba(47, 95, 221, 0.1);
    outline: none;
}

.stundenplan-eintrag__raum:empty::before {
    content: 'Raum …';
    color: var(--farbe-text-gedaempft);
    font-style: italic;
    opacity: 0.7;
}

.stundenplan-eintrag__loeschen {
    display: none; /* siehe Bearbeiten-Modus-Regeln weiter unten */
    position: absolute;
    top: -2px;
    right: -2px;
    border: none;
    background: var(--farbe-flaeche);
    color: var(--farbe-text-gedaempft);
    border-radius: 50%;
    width: 15px;
    height: 15px;
    font-size: 0.75rem;
    line-height: 1;
    padding: 0;
    cursor: pointer;
    opacity: 0;
    box-shadow: var(--schatten);
}

.stundenplan-eintrag:hover .stundenplan-eintrag__loeschen,
.stundenplan-eintrag__loeschen:focus {
    opacity: 1;
}

.stundenplan-eintrag__loeschen:hover {
    color: var(--farbe-fehler);
}

/* --- Geburtstags-Kachel ------------------------------------------------- */

/* "Anzahl anzeigen"/"Tage im Voraus" und das Hinzufügen neuer Geburtstage
   laufen seit Bauschritt 14 über kachel-eintraege.php statt über ein
   Inline-Panel/-Formular hier in der Kachel - siehe includes/kacheln.php,
   kachelRenderGeburtstage(). */

.geburtstage-liste {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

/* Bauschritt 18: Ausrichtung der Geburtstags-Einträge, einstellbar pro
   Kachel (siehe kachel-eintraege.php, "Anzeige-Einstellungen" ->
   "Ausrichtung"). Standard bleibt linksbündig (keine eigene Regel nötig) -
   für "zentriert" die Reihe aus Name/Datum/Hinweis als Gruppe mittig
   stellen, dafür auch das sonst nach rechts drückende margin-left:auto des
   Hinweises wieder aufheben. */
.geburtstage-liste--zentriert .geburtstag-eintrag {
    justify-content: center;
    text-align: center;
}

.geburtstage-liste--zentriert .geburtstag-eintrag__hinweis {
    margin-left: 0;
}

.geburtstag-eintrag {
    position: relative;
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 4px 8px;
    /* Bauschritt 25: "--kachel-text-faktor" siehe kachelTextStil() in
       includes/kacheln.php - .geburtstag-eintrag__name setzt selbst keine
       eigene font-size und erbt deshalb normal von hier. */
    font-size: calc(0.9rem * var(--kachel-text-faktor, 1));
    padding: 3px 22px 3px 2px;
    border-radius: 6px;
}

.geburtstag-eintrag--heute {
    background: rgba(47, 95, 221, 0.08);
}

.geburtstag-eintrag__name {
    font-weight: 600;
    border-radius: 4px;
    padding: 1px 3px;
    margin: -1px -3px;
    cursor: text;
}

.geburtstag-eintrag__datum {
    color: var(--farbe-text-gedaempft);
    font-size: 0.85rem;
    border-radius: 4px;
    padding: 1px 3px;
    margin: -1px -3px;
    cursor: text;
    white-space: nowrap;
}

.geburtstag-eintrag__name:hover,
.geburtstag-eintrag__name:focus,
.geburtstag-eintrag__datum:hover,
.geburtstag-eintrag__datum:focus {
    background: rgba(47, 95, 221, 0.1);
    outline: none;
}

.geburtstag-eintrag__hinweis {
    flex: none;
    margin-left: auto;
    font-size: 0.78rem;
    color: var(--farbe-text-gedaempft);
}

.geburtstag-eintrag--heute .geburtstag-eintrag__hinweis {
    color: var(--farbe-akzent-dunkel);
    font-weight: 600;
}

.geburtstag-eintrag__loeschen {
    display: none; /* siehe Bearbeiten-Modus-Regeln weiter unten */
    position: absolute;
    top: 2px;
    right: 0;
    border: none;
    background: transparent;
    color: var(--farbe-text-gedaempft);
    font-size: 1.05rem;
    line-height: 1;
    padding: 2px 4px;
    cursor: pointer;
    opacity: 0;
}

.geburtstag-eintrag:hover .geburtstag-eintrag__loeschen,
.geburtstag-eintrag__loeschen:focus {
    opacity: 1;
}

.geburtstag-eintrag__loeschen:hover {
    color: var(--farbe-fehler);
}

/* --- Kalender-Kachel ----------------------------------------------------- */

/* "Anzahl anzeigen"/"Tage im Voraus" und das Hinzufügen neuer Termine laufen
   seit Bauschritt 14 über kachel-eintraege.php - siehe
   includes/kacheln.php, kachelRenderKalender(), und den Kommentar bei der
   Geburtstags-Kachel weiter oben (dasselbe Muster). */

.kalender-liste {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

/* Bauschritt 21: Ausrichtung der Termine, einstellbar pro Kachel (siehe
   kachel-eintraege.php, "Anzeige-Einstellungen" -> "Ausrichtung der
   Liste") - bislang nur bei Geburtstagen möglich (.geburtstage-liste--
   zentriert weiter oben), jetzt dasselbe Muster auch hier. */
.kalender-liste--zentriert .kalender-eintrag {
    justify-content: center;
    text-align: center;
}

.kalender-liste--zentriert .kalender-eintrag__hinweis {
    margin-left: 0;
}

.kalender-liste--zentriert .kalender-eintrag__notiz {
    margin-left: -3px;
}

.kalender-eintrag {
    position: relative;
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    /* Bauschritt 22: Zeilenabstand (erste Zahl) von 4px auf 2px verkleinert
       - das ist der Abstand, der auch zwischen der Titel/Wann-Zeile und der
       darunter umgebrochenen Notiz-Zeile wirkt (siehe .kalender-eintrag__
       notiz, flex-basis 100%, weiter unten). */
    gap: 2px 8px;
    /* Bauschritt 25: "--kachel-text-faktor" siehe kachelTextStil() in
       includes/kacheln.php - .kalender-eintrag__titel setzt selbst keine
       eigene font-size und erbt deshalb normal von hier. */
    font-size: calc(0.9rem * var(--kachel-text-faktor, 1));
    padding: 3px 22px 3px 2px;
    border-radius: 6px;
}

.kalender-eintrag--heute {
    background: rgba(47, 95, 221, 0.08);
}

.kalender-eintrag__titel {
    font-weight: 600;
    border-radius: 4px;
    padding: 1px 3px;
    margin: -1px -3px;
    cursor: text;
}

.kalender-eintrag__wann {
    color: var(--farbe-text-gedaempft);
    font-size: 0.85rem;
    border-radius: 4px;
    padding: 1px 3px;
    margin: -1px -3px;
    cursor: text;
    white-space: nowrap;
}

.kalender-eintrag__notiz {
    flex: 1 1 100%;
    font-size: 0.82rem;
    color: var(--farbe-text-gedaempft);
    border-radius: 4px;
    padding: 1px 3px;
    margin: -1px -3px;
    /* Bauschritt 22: bei linksbündiger Ausrichtung (Standard) leicht
       eingerückt, damit die Notiz optisch erkennbar "zum Termin darüber
       gehört" statt wie eine gleichrangige neue Zeile zu wirken - bei
       zentrierter Ausrichtung (.kalender-liste--zentriert weiter oben)
       ergibt eine Einrückung dagegen keinen Sinn und wird dort wieder
       aufgehoben. margin-left steht bewusst NACH dem "margin:"-Kurzform-
       Wert oben, damit nur die linke Seite den größeren Wert bekommt, die
       übrigen drei Seiten bleiben beim kompensierenden -1px/-3px (siehe
       .kalender-eintrag__titel/__wann für dasselbe Hover-Highlight-Muster). */
    margin-left: 14px;
    cursor: text;
    min-height: 1.1em;
}

.kalender-eintrag__notiz:empty::before {
    content: 'Notiz …';
    color: var(--farbe-text-gedaempft);
    font-style: italic;
    opacity: 0.7;
}

/* Bauschritt 18: eine leere Notiz nimmt außerhalb des Bearbeiten-Modus gar
   keinen Platz mehr ein (statt des kursiven Platzhaltertextes für alle
   Betrachtenden) - im Bearbeiten-Modus bleibt der Platzhalter wie bisher
   sichtbar/anklickbar, damit sich dort weiterhin eine Notiz eintragen lässt.
   Nebenwirkung, die genau der zweiten Rückmeldung dieser Runde entspricht:
   ".kalender-eintrag__notiz { flex: 1 1 100%; }" erzwingt sonst auch im
   LEEREN Zustand eine eigene volle Zeile, wodurch der "in … Tagen"-Hinweis
   (der danach im Quelltext kommt) immer in eine neue Zeile mit sichtbar
   großem Abstand rutschte - fällt mit dem Ausblenden von selbst weg. */
body:not(.bearbeiten-modus-aktiv) .kalender-eintrag__notiz:empty {
    display: none;
}

.kalender-eintrag__titel:hover,
.kalender-eintrag__titel:focus,
.kalender-eintrag__wann:hover,
.kalender-eintrag__wann:focus,
.kalender-eintrag__notiz:hover,
.kalender-eintrag__notiz:focus {
    background: rgba(47, 95, 221, 0.1);
    outline: none;
}

.kalender-eintrag__hinweis {
    flex: none;
    font-size: 0.78rem;
    color: var(--farbe-text-gedaempft);
    margin-left: auto;
}

.kalender-eintrag--heute .kalender-eintrag__hinweis {
    color: var(--farbe-akzent-dunkel);
    font-weight: 600;
}

.kalender-eintrag__loeschen {
    display: none; /* siehe Bearbeiten-Modus-Regeln weiter unten */
    position: absolute;
    top: 2px;
    right: 0;
    border: none;
    background: transparent;
    color: var(--farbe-text-gedaempft);
    font-size: 1.05rem;
    line-height: 1;
    padding: 2px 4px;
    cursor: pointer;
    opacity: 0;
}

.kalender-eintrag:hover .kalender-eintrag__loeschen,
.kalender-eintrag__loeschen:focus {
    opacity: 1;
}

.kalender-eintrag__loeschen:hover {
    color: var(--farbe-fehler);
}

/* --- Klassendienste-Kachel (Bauschritt 17) --------------------------------
   Reine Anzeige, wer diese Kalenderwoche dran ist - keine Inline-Bearbeitung
   in der Kachel selbst (Klassenliste/Zuteilung laufen über
   klassendienste-verwalten.php, siehe includes/kacheln.php,
   kachelRendern()), deshalb deutlich schlichter als die Listen der
   Geburtstags-/Kalender-Kachel oben. */

/* Bauschritt 22: Datumsbereich der angezeigten Woche + Vor-/Zurück-Pfeil
   für die reine Wochen-Vorschau (siehe kachelRenderKlassendienste()). Drei
   Grid-Spalten (Pfeil zurück | Text | Pfeil vor) - der Zurück-Pfeil ist
   nicht per HTML "hidden" ausgeblendet, sondern nur über Deckkraft/
   pointer-events (siehe die "--zeigt-naechste"-Regeln weiter unten,
   dasselbe Muster wie bei den beiden Wochentexten/-listen) - so bleibt die
   mittlere Spalte immer exakt mittig, unabhängig davon, welcher der beiden
   Pfeile gerade "aktiv" ist, und der Pfeil kann sanft ein-/ausblenden statt
   abrupt zu erscheinen. */
/* Bauschritt 23: minimaler Abstand zwischen der Kachel-Überschrift und
   dieser Zeile (statt des sonst üblichen größeren Abstands vor dem
   restlichen Inhalt) - dieselbe Reduktion wie bei der neuen "Heute ·
   <Datum>"-Zeile der Stundenplan-Kachel (.stundenplan-heute-zeile weiter
   unten), für eine einheitliche Optik zwischen beiden. */
.kachel[data-kachel-typ="klassendienste"] .kachel__kopf {
    margin-bottom: 4px;
}

/* Bauschritt 23: "minmax(0, 1fr)" statt eines nackten "1fr" - ein nacktes
   "1fr" darf laut Grid-Spezifikation nicht kleiner werden als der
   Mindestinhalt seiner Kinder (hier: der nicht umbrechende Wochentext,
   white-space:nowrap weiter unten). Bei einer schmalen Kachel und einem
   langen Wochentext hätte das die ganze Zeile (und mit ihr die beiden
   Pfeile) über den verfügbaren Platz hinaus wachsen lassen - mit
   "minmax(0, …)" darf die mittlere Spalte dagegen bis auf 0 schrumpfen, der
   Text wird dann stattdessen abgeschnitten (siehe overflow/text-overflow
   bei .klassendienste-woche-text), die beiden 22px-Pfeil-Spalten bleiben
   davon unberührt immer in derselben Zeile - kein Umbruch mehr möglich. */
.klassendienste-woche-kopf {
    display: grid;
    grid-template-columns: 22px minmax(0, 1fr) 22px;
    align-items: center;
    gap: 8px;
    margin-bottom: 10px;
    font-size: 0.82rem;
    color: var(--farbe-text-gedaempft);
}

.klassendienste-woche-kopf--zentriert {
    justify-items: center;
}

.klassendienste-wochen-text-schieber {
    display: grid;
    justify-self: center;
    min-width: 0;
    max-width: 100%;
}

/* Bauschritt 24: die vorherige Regel
   ".klassendienste-woche-kopf--zentriert .klassendienste-wochen-text-schieber
   { grid-column: 1 / -1; }" wurde entfernt - sie ließ den Wochentext auf
   eine EIGENE Zeile rutschen (Spalte 1 war durch den Zurück-Pfeil bereits
   belegt, ein Grid-Element kann keine belegte Spalte "überspringen"), so
   dass bei aktiviertem "Titel zentrieren" (kachelTitelZentriert(), siehe
   includes/kacheln.php) aus der einen Zeile "Pfeil · Text · Pfeil" drei
   gestapelte Zeilen wurden - user-sichtbar bestätigt per Playwright-
   Screenshot. Die Regel war unnötig: ".klassendienste-wochen-text-schieber"
   steht dank "justify-self: center" (oben) bereits mittig in der 1fr-
   Mittelspalte, flankiert von zwei gleich breiten 22px-Pfeil-Spalten - exakt
   dasselbe optische Ergebnis, aber ohne die drei Zeilen. Die verbleibende
   ".klassendienste-woche-kopf--zentriert"-Klasse bleibt (wirkungslos für
   diese Zeile, aber weiterhin für andere etwaige zentrierte Inhalte
   vorhanden) und wird von kacheln.php weiterhin gesetzt. */

.klassendienste-woche-text {
    grid-area: 1 / 1;
    transition: opacity 0.25s ease;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
}

/* Bauschritt 23: aus den bis dahin zwei Zuständen ("aktuell"/"naechste")
   sind jetzt vier geworden (siehe KLASSENDIENSTE_WOCHEN_SCHLUESSEL in
   includes/klassendienste.php) - "aktuell" bleibt weiterhin der
   unmarkierte Normalfall (keine Modifikator-Klasse auf .klassendienste-
   wochen nötig), die drei übrigen sind standardmäßig ausgeblendet und
   werden erst über die jeweilige ".klassendienste-wochen--zeigt-…"-Klasse
   eingeblendet. */
.klassendienste-woche-text[data-woche="vorherige"],
.klassendienste-woche-text[data-woche="naechste"],
.klassendienste-woche-text[data-woche="uebernaechste"] {
    opacity: 0;
    pointer-events: none;
}

.klassendienste-wochen--zeigt-vorherige .klassendienste-woche-text[data-woche="aktuell"],
.klassendienste-wochen--zeigt-naechste .klassendienste-woche-text[data-woche="aktuell"],
.klassendienste-wochen--zeigt-uebernaechste .klassendienste-woche-text[data-woche="aktuell"] {
    opacity: 0;
    pointer-events: none;
}

.klassendienste-wochen--zeigt-vorherige .klassendienste-woche-text[data-woche="vorherige"] {
    opacity: 1;
    pointer-events: auto;
}

.klassendienste-wochen--zeigt-naechste .klassendienste-woche-text[data-woche="naechste"] {
    opacity: 1;
    pointer-events: auto;
}

.klassendienste-wochen--zeigt-uebernaechste .klassendienste-woche-text[data-woche="uebernaechste"] {
    opacity: 1;
    pointer-events: auto;
}

/* Dezenter, runder Pfeil-Knopf - bewusst zurückhaltend gestaltet (kein
   eigener Rahmen/Schatten wie die übrigen Kopf-Knöpfe einer Kachel), da er
   Teil des ruhigen Anzeige-Charakters dieser Kachel bleiben soll. */
/* Bauschritt 22: derselbe dezente Pfeil-Knopf-Stil wird auch von der neuen
   iCal-Kachel wiederverwendet (.ical-pfeil, siehe weiter unten) - eine
   gemeinsame Regel statt einer wörtlichen Kopie. */
.klassendienste-pfeil,
.ical-pfeil {
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    border: none;
    border-radius: 50%;
    background: none;
    color: var(--farbe-text-gedaempft);
    font-size: 0.95rem;
    line-height: 1;
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease, opacity 0.25s ease;
}

.klassendienste-pfeil:not(:disabled):hover,
.ical-pfeil:hover {
    background: rgba(47, 95, 221, 0.1);
    color: var(--farbe-akzent-dunkel);
}

/* Bauschritt 23: aus dem bis dahin binären Umschalter (ein Pfeil jeweils
   komplett unsichtbar/nicht klickbar) ist ein echter 4-Stufen-Blätterer
   geworden - beide Pfeile bleiben jetzt IMMER sichtbar, werden an den
   beiden Enden (-1 Woche/+2 Wochen) aber über das echte "disabled"-
   Attribut deaktiviert (siehe assets/js/dashboard.js,
   klassendiensteWochenEinrichten()) - dieselbe Optik wie bei jedem anderen
   deaktivierten Knopf dieser Anwendung (vgl. .screens-liste__pfeil:disabled
   weiter unten). */
.klassendienste-pfeil:disabled {
    opacity: 0.3;
    cursor: default;
}

/* Die eigentlichen Wochen-Listen (vorherige/aktuell/nächste/übernächste)
   liegen ebenfalls übereinander in derselben Grid-Zelle - anders als beim
   Wochentext oben zusätzlich mit einer leichten seitlichen Verschiebung
   beim Ein-/Ausblenden ("elegante Animation" laut Rückmeldung), die an ein
   Weiterblättern erinnert. Alle vier Listen sind immer im DOM vorhanden
   (siehe kachelRenderKlassendienste()) - so bleibt die Kachel-Höhe beim
   Umschalten stabil (alle vier haben immer dieselbe Anzahl Zeilen, drei
   Dienste), ganz ohne Nachmessen durch die Masonry-Logik
   (kachelMasonryEinrichten() in assets/js/dashboard.js). Da beim Blättern
   immer nur EIN Schritt (-1/+1) auf einmal möglich ist (siehe
   klassendiensteWochenEinrichten()), reicht hier - wie schon bei den
   Wochentexten oben - je eine eigene Regel pro Zustand. */
.klassendienste-wochen-schieber {
    display: grid;
}

.klassendienste-wochen-schieber > .klassendienste-liste {
    grid-area: 1 / 1;
    transition: opacity 0.25s ease, transform 0.25s ease;
}

.klassendienste-liste[data-woche="vorherige"] {
    opacity: 0;
    transform: translateX(-14px);
    pointer-events: none;
}

.klassendienste-liste[data-woche="naechste"],
.klassendienste-liste[data-woche="uebernaechste"] {
    opacity: 0;
    transform: translateX(14px);
    pointer-events: none;
}

.klassendienste-wochen--zeigt-vorherige .klassendienste-liste[data-woche="aktuell"],
.klassendienste-wochen--zeigt-naechste .klassendienste-liste[data-woche="aktuell"],
.klassendienste-wochen--zeigt-uebernaechste .klassendienste-liste[data-woche="aktuell"] {
    opacity: 0;
    transform: translateX(-14px);
    pointer-events: none;
}

.klassendienste-wochen--zeigt-vorherige .klassendienste-liste[data-woche="vorherige"] {
    opacity: 1;
    transform: translateX(0);
    pointer-events: auto;
}

.klassendienste-wochen--zeigt-naechste .klassendienste-liste[data-woche="naechste"] {
    opacity: 1;
    transform: translateX(0);
    pointer-events: auto;
}

.klassendienste-wochen--zeigt-uebernaechste .klassendienste-liste[data-woche="uebernaechste"] {
    opacity: 1;
    transform: translateX(0);
    pointer-events: auto;
}

/* Eine Person, die über assets/js/computer.js "prefers-reduced-motion"
   eingestellt hat, bekommt die Animation nicht - reines Umschalten ohne
   Verschiebung/Verblassen (Barrierefreiheit, dasselbe Prinzip wie an
   anderer Stelle üblich). */
@media (prefers-reduced-motion: reduce) {
    .klassendienste-woche-text,
    .klassendienste-wochen-schieber > .klassendienste-liste,
    .ical-tage-text,
    .ical-tage-schieber,
    .ical-tage-schieber > .ical-liste {
        transition: none;
    }
}

.klassendienste-liste {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.klassendienste-eintrag {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 8px 16px;
    flex-wrap: wrap;
    padding: 4px 0;
    border-bottom: 1px solid var(--farbe-rand);
}

.klassendienste-eintrag:last-child {
    border-bottom: none;
}

/* Bauschritt 20: keine eigene (kleinere) Schriftgröße mehr - die
   Dienst-Bezeichnung ist genauso wichtiger Bestandteil der Zeile wie der
   Name daneben (anders als z. B. ein kurzer Hinweis-Zusatz bei Termin-/
   Geburtstags-Einträgen), sollte also nicht kleiner wirken. Die
   Unterscheidung zur Namens-Spalte kommt jetzt allein über die gedämpfte
   Farbe. */
/* Bauschritt 24: Rückmeldung, der Text dieser Kachel wirke "deutlich
   kleiner" als bei anderen Kacheln. Geprüft: .klassendienste-eintrag hatte
   schon vorher KEINE eigene (kleinere) font-size - ohne eigene Angabe erbte
   die Zeile die normale Kachel-Inhaltsgröße (1rem), tatsächlich sogar etwas
   GRÖSSER als z. B. .todo-eintrag (0.95rem) oder .geburtstag-eintrag
   (0.9rem). Trotzdem hier jetzt explizit auf 1rem gesetzt (statt weiter nur
   implizit geerbt) - macht die Absicht robust gegenüber künftigen Änderungen
   an einer der umschließenden Regeln (.kachel__inhalt/.kachel), und stellt
   sicher, dass Dienst UND Name sichtbar gleich groß wie der Haupttext
   anderer Kacheln bleiben. */
.klassendienste-eintrag__dienst {
    /* Bauschritt 25: "--kachel-text-faktor" siehe kachelTextStil() in
       includes/kacheln.php. */
    font-size: calc(1rem * var(--kachel-text-faktor, 1));
    color: var(--farbe-text-gedaempft);
}

.klassendienste-eintrag__namen {
    font-size: calc(1rem * var(--kachel-text-faktor, 1));
    font-weight: 600;
    text-align: right;
}

.klassendienste-eintrag__namen--leer {
    font-weight: 400;
    font-style: italic;
    color: var(--farbe-text-gedaempft);
}

/* --- iCal-Kachel (Bauschritt 22) -------------------------------------------
   Zeigt die heutigen/morgigen Termine eines abonnierten Kalenders, mit
   demselben Umschalt-Aufbau (Grid-Stapelung + Deckkraft-Übergang) wie die
   Wochen-Vorschau der Klassendienste-Kachel weiter oben - siehe
   kachelRenderIcal() in includes/kacheln.php und icalTageEinrichten() in
   assets/js/dashboard.js. Bewusst nur zwei feste Zustände ("Heute"/
   "Morgen", kein weiteres Blättern), siehe Rückfrage-Antwort dazu. */
.ical-tage-kopf {
    display: grid;
    grid-template-columns: 22px 1fr 22px;
    align-items: center;
    justify-items: center;
    gap: 8px;
    margin-bottom: 10px;
    font-size: 0.82rem;
    color: var(--farbe-text-gedaempft);
}

.ical-tage-text-schieber {
    display: grid;
    justify-self: center;
}

.ical-tage-text {
    grid-area: 1 / 1;
    transition: opacity 0.25s ease;
    white-space: nowrap;
}

.ical-tage-text[data-tag="morgen"] {
    opacity: 0;
    pointer-events: none;
}

.ical-tage--zeigt-morgen .ical-tage-text[data-tag="heute"] {
    opacity: 0;
    pointer-events: none;
}

.ical-tage--zeigt-morgen .ical-tage-text[data-tag="morgen"] {
    opacity: 1;
    pointer-events: auto;
}

.ical-pfeil--zurueck {
    opacity: 0;
    pointer-events: none;
}

.ical-tage--zeigt-morgen .ical-pfeil--zurueck {
    opacity: 1;
    pointer-events: auto;
}

.ical-tage--zeigt-morgen .ical-pfeil--vor {
    opacity: 0;
    pointer-events: none;
}

/* Beide Listen (heute/morgen) liegen übereinander in derselben Grid-Zelle
   und sind immer im DOM vorhanden (siehe kachelRenderIcal()) - dieselbe
   seitliche Verschiebung beim Ein-/Ausblenden wie bei den Klassendiensten
   oben ("elegante Animation" laut Rückmeldung). */
/* Bauschritt 23: die Kachel soll sich beim Umschalten Heute<->Morgen auf
   die Höhe der GERADE SICHTBAREN Liste zusammenziehen/ausdehnen, statt (wie
   bis dahin) immer auf die Höhe der HÖHEREN der beiden Listen fixiert zu
   bleiben. "align-items: start" verhindert, dass die beiden übereinander
   liegenden Listen (grid-area 1/1, siehe unten) sich gegenseitig auf
   gleiche Höhe strecken - das allein ändert aber noch nichts an der
   GRÖSSE der (einzigen, von beiden Listen gemeinsam belegten) Grid-Zeile
   selbst, die weiterhin nach dem höheren Inhalt bemessen wird. Deshalb
   setzt assets/js/dashboard.js (icalSchieberHoeheAnpassen()) zusätzlich
   eine explizite Höhe direkt als Inline-Style auf dieses Element - das
   überschreibt die automatische Bemessung, "overflow: hidden" schneidet
   die (jetzt unsichtbare) höhere Liste dabei einfach ab, "transition:
   height" lässt die Höhenänderung sanft mitlaufen, statt abrupt zu
   springen. */
.ical-tage-schieber {
    display: grid;
    align-items: start;
    overflow: hidden;
    transition: height 0.25s ease;
}

.ical-tage-schieber > .ical-liste {
    grid-area: 1 / 1;
    transition: opacity 0.25s ease, transform 0.25s ease;
}

.ical-liste[data-tag="morgen"] {
    opacity: 0;
    transform: translateX(14px);
    pointer-events: none;
}

.ical-tage--zeigt-morgen .ical-liste[data-tag="heute"] {
    opacity: 0;
    transform: translateX(-14px);
    pointer-events: none;
}

.ical-tage--zeigt-morgen .ical-liste[data-tag="morgen"] {
    opacity: 1;
    transform: translateX(0);
    pointer-events: auto;
}

.ical-liste {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.ical-eintrag {
    display: flex;
    align-items: baseline;
    gap: 8px;
    padding: 4px 0;
    border-bottom: 1px solid var(--farbe-rand);
}

.ical-eintrag:last-child {
    border-bottom: none;
}

.ical-eintrag__zeit {
    flex: none;
    font-variant-numeric: tabular-nums;
    color: var(--farbe-text-gedaempft);
}

.ical-eintrag--leer {
    color: var(--farbe-text-gedaempft);
    font-style: italic;
    border-bottom: none;
}

/* --- Klassenstunde-Kachel (Bauschritt 23, überarbeitet in Bauschritt 24) --
   Reihenfolge auf der Kachel selbst: Überschrift "Themen", Checkliste der
   freigegebenen Themen, ggf. die schlichte Hinweiszeile "weitere Vorschläge
   vorhanden", das Einreich-Formular, ggf. die eigenen ausstehenden Themen
   mit "zurückziehen". Siehe kachelRenderKlassenstunde() in includes/
   kacheln.php und HINWEISE-SCHRITT-24.md. Die vollständige, nach Rolle
   gefilterte Verwaltung der ausstehenden Themen (mit Namen, freigeben/
   ablehnen/umbenennen) liegt seit Bauschritt 24 ausschließlich auf
   kachel-eintraege.php - eigene CSS-Klassen dafür weiter unten (Abschnitt
   "kachel-eintraege.php - Themen verwalten"). */

/* Bauschritt 24: umbenannt aus "THEMA FÜR DIE NÄCHSTE KLASSENSTUNDE" (groß,
   gedämpft) zu schlicht "Themen", jetzt in derselben Schriftart wie die
   Kachel-Überschrift (var(--schrift-anzeige), dieselbe Variable wie
   .kachel__titel) - etwas kleiner als diese (0.95rem gegenüber 1.15rem *
   Schriftgrößen-Faktor). */
.klassenstunde-thema-titel {
    margin: 0 0 8px 0;
    font-family: var(--schrift-anzeige);
    font-size: calc(0.95rem * var(--schriftgroesse-anzeige-faktor, 1) * var(--kachel-text-faktor, 1));
    font-weight: 400;
}

/* Bauschritt 25: der Platzhaltertext bei noch keinen freigegebenen Themen
   ("Noch keine Themen.") ist NUR hier zentriert - die gemeinsame Klasse
   .kachel__platzhaltertext selbst bleibt für alle anderen Kachel-Typen
   (iCal/Bild/PDF, siehe includes/kacheln.php) unverändert linksbündig,
   deshalb ein eigener, auf die Klassenstunde-Kachel beschränkter Selektor
   statt einer Änderung an .kachel__platzhaltertext selbst. */
.klassenstunde .kachel__platzhaltertext {
    text-align: center;
}

/* Bauschritt 24: dieselbe optische Checklisten-Zeile wie die To-Do-Kachel
   (.todo-eintrag, siehe weiter oben) - Ankreuzen löst "abhaken" aus (siehe
   assets/js/dashboard.js), keine dauerhaft speicherbare Häkchen-Stellung.
   Für Nicht-Lehrkräfte ist die Checkbox über das HTML-Attribut "disabled"
   fest gesperrt (siehe kachelRenderKlassenstunde()), für Lehrkräfte nur
   innerhalb von body.bearbeiten-modus-aktiv klickbar (siehe
   "pointer-events" unten) - dieselbe Zwei-Stufen-Absicherung wie jeder
   andere mutierende Knopf dieser Anwendung. */
.klassenstunde-checkliste {
    list-style: none;
    margin: 0 0 4px;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.klassenstunde-checkliste__eintrag {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 0.95rem;
}

.klassenstunde-checkliste__checkbox {
    flex: none;
    pointer-events: none;
}

body.bearbeiten-modus-aktiv .klassenstunde-checkliste__checkbox:not(:disabled) {
    pointer-events: auto;
    cursor: pointer;
}

.klassenstunde-checkliste__text {
    flex: 1 1 auto;
}

.klassenstunde-checkliste__von {
    flex: none;
    font-size: 0.78rem;
    color: var(--farbe-text-gedaempft);
    font-style: italic;
}

/* Bauschritt 24: reine Hinweiszeile - keine Namen, keine Liste, keine
   Knöpfe (siehe Aufgabenstellung/HINWEISE-SCHRITT-24.md). */
.klassenstunde-hinweis-weitere {
    margin: 0 0 12px;
    text-align: center;
    font-size: 0.8rem;
    font-style: italic;
    color: var(--farbe-text-gedaempft);
}

.klassenstunde-formular {
    display: flex;
    gap: 8px;
    /* Bauschritt 26: deutlich mehr Abstand ÜBER dem Formular (vorher 0,
       direkt unter der Checkliste/dem Hinweistext) - in etwa so viel wie
       der untere Innenabstand der Kachel selbst (.kachel, 20px), damit das
       Formular optisch "genauso viel Luft" nach oben wie die ganze Kachel
       nach unten hat. */
    margin-top: 20px;
    margin-bottom: 4px;
}

.klassenstunde-formular__feld {
    flex: 1;
    display: block;
}

.klassenstunde-formular__feld input {
    width: 100%;
    padding: 8px 10px;
    border: 1px solid var(--farbe-rand);
    border-radius: 8px;
    background: var(--farbe-flaeche);
    color: inherit;
    font-family: inherit;
    font-size: 0.9rem;
}

.klassenstunde-formular__feld input:focus {
    outline: 2px solid var(--farbe-akzent);
    outline-offset: 1px;
}

/* Bauschritt 24: SVG-"Senden"-Symbol (Flugzeug) statt des bisherigen
   Text-Knopfes - "currentColor" im SVG-<path> übernimmt automatisch die
   "color", die die Kachel für ihren Text konfiguriert hat (siehe
   kachelTextStil() in includes/kacheln.php, inline auf .kachel__inhalt
   gesetzt - dieser Knopf liegt als Nachfahre darunter und erbt sie ganz
   ohne eigenes Zutun). Rund, dezent, dieselbe Grundform wie die
   Pfeil-Knöpfe der Klassendienste-/iCal-Kachel (.klassendienste-pfeil). */
.klassenstunde-formular__absenden {
    flex: none;
    width: 36px;
    height: 36px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: none;
    border-radius: 50%;
    background: var(--farbe-akzent);
    color: #fff;
    cursor: pointer;
}

.klassenstunde-formular__absenden:hover {
    background: var(--farbe-akzent-dunkel);
}

.klassenstunde-formular__absenden:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}

/* Bauschritt 24: die eigenen noch ausstehenden Themen der angemeldeten
   Person, mit "zurückziehen" - siehe HINWEISE-SCHRITT-24.md, Punkt 2f, für
   die Begründung dieser eigenen Einschätzung. Bewusst schlicht/knapp
   gehalten (kleinere Schrift, gedämpfte Farbe), damit sie nicht mit der
   "offiziellen" Checkliste freigegebener Themen verwechselt werden. */
.klassenstunde-eigene-ausstehend {
    list-style: none;
    margin: 10px 0 0;
    padding: 8px 0 0;
    border-top: 1px dashed var(--farbe-rand);
    display: flex;
    flex-direction: column;
    gap: 4px;
    font-size: 0.78rem;
    color: var(--farbe-text-gedaempft);
}

.klassenstunde-eigene-ausstehend__zeile {
    display: flex;
    align-items: center;
    gap: 6px;
}

.klassenstunde-eigene-ausstehend__text {
    flex: 1 1 auto;
    font-style: italic;
}

.klassenstunde-eigene-ausstehend__status {
    flex: none;
}

.klassenstunde-eigene-ausstehend__zurueckziehen {
    flex: none;
    border: none;
    background: transparent;
    color: var(--farbe-akzent);
    font-size: 0.78rem;
    text-decoration: underline;
    cursor: pointer;
    padding: 0;
}

.klassenstunde-eigene-ausstehend__zurueckziehen:hover {
    color: var(--farbe-akzent-dunkel);
}

/* --- kachel-eintraege.php - "Themen verwalten" (Klassenstunde, Bauschritt
   24) - teacher-only Verwaltung ALLER Themen dieser Kachel (ausstehend UND
   freigegeben), siehe kachel-eintraege.php. Baut auf den bereits
   vorhandenen .eintraege-liste(__zeile)-Grundregeln weiter oben auf, nur
   die zusätzlichen Elemente (Text-Eingabefeld statt reinem Text, mehrere
   Aktions-Knöpfe) bekommen hier ihre eigene Feinabstimmung. */
.klassenstunde-verwalten__untertitel {
    margin: 16px 0 8px;
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--farbe-text-gedaempft);
}

.klassenstunde-verwalten__untertitel:first-of-type {
    margin-top: 0;
}

.klassenstunde-verwalten__zeile {
    flex-wrap: wrap;
}

.klassenstunde-verwalten__text {
    flex: 1 1 220px;
    min-width: 0;
    padding: 5px 8px;
    border: 1px solid var(--farbe-rand);
    border-radius: 6px;
    font: inherit;
    font-size: 0.88rem;
}

.klassenstunde-verwalten__freigeben,
.klassenstunde-verwalten__ablehnen,
.klassenstunde-verwalten__abhaken {
    flex: none;
    border: none;
    border-radius: 50%;
    background: none;
    color: var(--farbe-text-gedaempft);
    font-size: 0.95rem;
    line-height: 1;
    width: 26px;
    height: 26px;
    cursor: pointer;
}

.klassenstunde-verwalten__abhaken {
    width: auto;
    border-radius: 6px;
    padding: 4px 8px;
    font-size: 0.8rem;
}

.klassenstunde-verwalten__freigeben:hover,
.klassenstunde-verwalten__abhaken:hover {
    background: rgba(47, 95, 221, 0.12);
    color: var(--farbe-akzent-dunkel);
}

.klassenstunde-verwalten__ablehnen:hover {
    background: var(--farbe-fehler-flaeche);
    color: var(--farbe-fehler);
}

/* --- klassendienste-verwalten.php ----------------------------------------- */

.klassendienste-wochen-navigation {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 16px;
}

.klassendienste-wochen-navigation__aktuell {
    font-weight: 600;
    text-align: center;
}

.klassendienste-tabelle {
    width: 100%;
    border-collapse: collapse;
    /* Bauschritt 25: "--kachel-text-faktor" siehe kachelTextStil() in
       includes/kacheln.php. */
    font-size: calc(0.9rem * var(--kachel-text-faktor, 1));
}

.klassendienste-tabelle th,
.klassendienste-tabelle td {
    padding: 8px 10px;
    border-bottom: 1px solid var(--farbe-rand);
    text-align: center;
}

.klassendienste-tabelle__name-spalte {
    text-align: left;
    white-space: nowrap;
}

.klassendienste-tabelle thead th {
    color: var(--farbe-text-gedaempft);
    font-weight: 600;
    font-size: 0.82rem;
}

.klassendienste-tabelle__haekchen {
    width: 20px;
    height: 20px;
    cursor: pointer;
}

/* --- Inline-Editing ------------------------------------------------------ */

.kachel__titel[contenteditable="true"],
.kachel__rich-text[contenteditable="true"] {
    border-radius: 6px;
    padding: 2px 4px;
    margin: -2px -4px;
    cursor: text;
}

.kachel__titel[contenteditable="true"]:hover,
.kachel__rich-text[contenteditable="true"]:hover {
    background: rgba(47, 95, 221, 0.06);
}

.kachel__titel[contenteditable="true"]:focus,
.kachel__rich-text[contenteditable="true"]:focus {
    outline: 2px solid var(--farbe-akzent);
    outline-offset: 2px;
    background: var(--farbe-flaeche);
}

.kachel__rich-text:empty::before {
    content: 'Klicken, um Text hinzuzufügen …';
    color: var(--farbe-text-gedaempft);
    font-style: italic;
}

.kachel__meldung {
    margin: 10px 0 0;
    font-size: 0.8rem;
    padding: 6px 10px;
    border-radius: 6px;
    background: var(--farbe-fehler-flaeche);
    color: var(--farbe-fehler);
}

/* --- Formatierungsleiste --------------------------------------------- */

.kachel__editor {
    position: relative;
}

.formatierungsleiste {
    display: none;
    align-items: center;
    gap: 2px;
    flex-wrap: wrap;
    background: var(--farbe-text);
    border-radius: 8px;
    padding: 4px;
    margin-bottom: 8px;
    box-shadow: var(--schatten);
}

/* Nur sichtbar, solange das Textfeld darunter (oder ein Knopf der Leiste)
   den Fokus hat - kein JS zum Ein-/Ausblenden nötig. */
.kachel__editor:focus-within .formatierungsleiste {
    display: flex;
}

.formatierungsleiste__knopf {
    min-width: 26px;
    height: 26px;
    padding: 0 6px;
    border: none;
    border-radius: 5px;
    background: transparent;
    color: #fff;
    font-family: var(--schrift-text);
    font-size: 0.8rem;
    font-weight: 600;
    line-height: 1;
    cursor: pointer;
}

.formatierungsleiste__knopf:hover {
    background: rgba(255, 255, 255, 0.15);
}

.formatierungsleiste__knopf--aktiv {
    background: var(--farbe-akzent);
}

.formatierungsleiste__knopf--kursiv {
    font-style: italic;
}

.formatierungsleiste__knopf--unterstrichen {
    text-decoration: underline;
}

.formatierungsleiste__trenner {
    width: 1px;
    align-self: stretch;
    background: rgba(255, 255, 255, 0.25);
    margin: 3px 2px;
}

/* Bauschritt 19: Schriftart-Auswahl und Textfarbe in der Formatierungsleiste
   der Info-Kachel - dieselbe dunkle Leiste wie die übrigen Knöpfe, deshalb
   bewusst NICHT die Quicksand-Festlegung von .aussehen-formular select
   (siehe weiter oben) - diese Auswahl gehört zur Kachel selbst, nicht zu
   den beiden Einstellungsseiten. */
.formatierungsleiste__schriftart {
    height: 26px;
    max-width: 130px;
    border: none;
    border-radius: 5px;
    padding: 0 4px;
    background: rgba(255, 255, 255, 0.12);
    color: #fff;
    font-family: var(--schrift-text);
    font-size: 0.75rem;
    cursor: pointer;
}

.formatierungsleiste__schriftart:hover {
    background: rgba(255, 255, 255, 0.2);
}

.formatierungsleiste__farbe {
    width: 26px;
    height: 26px;
    padding: 2px;
    border: none;
    border-radius: 5px;
    background: transparent;
    cursor: pointer;
}

/* --- "Neue Kachel hinzufügen" ------------------------------------------ */

.kachel-hinzufuegen-knopf {
    display: none; /* siehe Bearbeiten-Modus-Regeln weiter unten */
    /* Bauschritt 21: fest ans Ende der Reihenfolge (unabhängig von
       "grid-auto-flow: dense", das ihn sonst je nach gerade vorhandenen
       Lücken auch mitten im Grid platzieren könnte) - vorher gab es
       denselben Wert nur innerhalb von @media(max-width:640px) und
       body.mobil-reihenfolge-aktiv, jetzt einheitlich immer. */
    order: 9999;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;
    min-height: 140px;
    border: 1.5px dashed var(--farbe-rand);
    border-radius: var(--radius);
    background: transparent;
    color: var(--farbe-text-gedaempft);
    font-family: var(--schrift-text);
    font-size: 0.9rem;
    cursor: pointer;
}

.kachel-hinzufuegen-knopf:hover {
    border-color: var(--farbe-akzent);
    color: var(--farbe-akzent);
}

.kachel-hinzufuegen-knopf__plus {
    font-size: 1.8rem;
    line-height: 1;
}

.neue-kachel-dialog {
    border: none;
    border-radius: var(--radius);
    box-shadow: var(--schatten);
    padding: 24px;
    width: 100%;
    max-width: 420px;
}

.neue-kachel-dialog::backdrop {
    background: rgba(20, 24, 33, 0.45);
}

.neue-kachel-dialog__titel {
    font-family: var(--schrift-anzeige);
    font-size: calc(1.3rem * var(--schriftgroesse-anzeige-faktor, 1));
    margin: 0 0 12px;
}

.neue-kachel-dialog__hinweis {
    margin: 0 0 12px;
    color: var(--farbe-text-gedaempft);
}

.neue-kachel-dialog__hinweis--klein {
    font-size: 0.8rem;
    margin-top: 16px;
}

.neue-kachel-dialog__typen {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
    gap: 10px;
}

.neue-kachel-dialog__typ {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    padding: 16px 8px;
    border: 1px solid var(--farbe-rand);
    border-radius: 10px;
    background: var(--farbe-hintergrund);
    font-family: var(--schrift-text);
    font-size: 0.85rem;
    cursor: pointer;
}

.neue-kachel-dialog__typ:hover:not(:disabled) {
    border-color: var(--farbe-akzent);
    background: rgba(47, 95, 221, 0.08);
}

.neue-kachel-dialog__typ:disabled {
    opacity: 0.6;
    cursor: default;
}

.neue-kachel-dialog__icon {
    font-size: 1.5rem;
}

.neue-kachel-dialog__fehler {
    background: var(--farbe-fehler-flaeche);
    color: var(--farbe-fehler);
    border-radius: 8px;
    padding: 8px 12px;
    font-size: 0.85rem;
    margin: 12px 0 0;
}

.neue-kachel-dialog__aktionen {
    display: flex;
    justify-content: flex-end;
    margin: 20px 0 0;
    padding: 0;
}

/* Bauschritt 21: zweiter Dialog-Schritt für die Link-Kachel (URL-Eingabe
   direkt beim Anlegen) - siehe neueKachelDialogEinrichten() in
   assets/js/dashboard.js. Bauschritt 22: derselbe Schritt wird jetzt auch
   für "iCal" wiederverwendet (Beschriftung/Platzhalter je nach Typ per JS
   umgeschrieben), daher der allgemeinere Klassenname "...-url" statt
   "...-link". */
.neue-kachel-dialog__schritt-url {
    margin-top: 8px;
}

.neue-kachel-dialog__link-aktionen {
    display: flex;
    justify-content: space-between;
    gap: 8px;
    margin-top: 16px;
}

.button--sekundaer {
    background: transparent;
    color: var(--farbe-text-gedaempft);
    border: 1px solid var(--farbe-rand);
}

.button--sekundaer:hover {
    background: var(--farbe-hintergrund);
}

/* --- Bearbeiten-Modus -----------------------------------------------------
   Alle Bearbeiten-/Verschieben-/Löschen-/Einstellungs-Knöpfe sowie "+ Neue
   Kachel" sind oben bei ihrer jeweiligen Klasse bewusst auf
   "display: none;" gesetzt - nicht nur unsichtbar (opacity), sondern
   wirklich aus dem Layout entfernt und damit auch nicht per Tab
   erreichbar. Sichtbar (und bedienbar) werden sie erst, wenn <body> die
   Klasse "bearbeiten-modus-aktiv" trägt - gesetzt von assets/js/dashboard.js
   über den Zahnrad-Schalter in der Kopfleiste (siehe .bearbeiten-modus-
   schalter unten), der nur für die Rolle "Lehrer" überhaupt gerendert wird
   (siehe includes/kopf.php, istLehrer()). Diese Regel ist rein kosmetisch -
   die eigentliche Absicherung (dass nur Lehrkräfte tatsächlich etwas
   verändern können) läuft serverseitig über erfordereLehrerJson() in jedem
   api/*.php, unabhängig davon, ob diese Knöpfe im Browser sichtbar wären. */
body.bearbeiten-modus-aktiv .kachel__griff,
body.bearbeiten-modus-aktiv .kachel__einstellungen-knopf,
body.bearbeiten-modus-aktiv .kachel__loeschen-knopf,
body.bearbeiten-modus-aktiv .todo-eintrag__griff,
body.bearbeiten-modus-aktiv .stundenplan-eintrag__loeschen,
body.bearbeiten-modus-aktiv .geburtstag-eintrag__loeschen,
body.bearbeiten-modus-aktiv .kalender-eintrag__loeschen {
    display: inline-block;
}

/* Bauschritt 24: die Klassenstunde-Checkbox auf der Kachel selbst (Lehrkraft-
   Aktion "abhaken") ist für Nicht-Lehrkräfte per "disabled"-Attribut
   gesperrt (siehe kachelRenderKlassenstunde()) und für Lehrkräfte nur
   innerhalb dieses Bearbeiten-Modus klickbar - siehe die "pointer-events"-
   Regel direkt bei .klassenstunde-checkliste__checkbox weiter oben (bleibt
   dort, weil sie zusätzlich das :not(:disabled) braucht und deshalb nicht
   in dieses gemeinsame, einfache "display"-Muster passt). Die "Themen
   verwalten"-Knöpfe auf kachel-eintraege.php sind bewusst NICHT hier
   gelistet - diese ganze Seite ist ohnehin nur für Lehrkräfte erreichbar,
   dieselbe zusätzliche Bearbeiten-Modus-Stufe wie auf dem Dashboard selbst
   wäre dort nur ein weiterer, unnötiger Klick. */

body.bearbeiten-modus-aktiv .kachel__positions-knoepfe,
body.bearbeiten-modus-aktiv .todo-eintrag__positions-knoepfe,
body.bearbeiten-modus-aktiv .kachel__breite-knoepfe {
    display: flex;
}

body.bearbeiten-modus-aktiv .kachel-hinzufuegen-knopf {
    display: flex;
}

/* --- Bauschritt 20: eigener "Mobile Reihenfolge bearbeiten"-Modus --------
   Getrennt vom normalen Bearbeiten-Modus (siehe assets/js/dashboard.js,
   mobilReihenfolgeEinrichten()) - zeigt nur Griff und ▲/▼-Knöpfe zum
   Umsortieren, NICHT die übrigen Bearbeiten-Knöpfe (Aussehen/Einträge/
   Löschen) und auch keine contenteditable-Felder, damit in diesem Modus
   wirklich nur die (mobile) Reihenfolge verändert werden kann. Das Grid
   wird dabei unabhängig von der tatsächlichen Fenstergröße auf eine
   schmale Einzelspalte gezwungen (wie auf einem Smartphone), damit sich
   die mobile Reihenfolge auch bequem am Desktop-Bildschirm einstellen
   lässt, ohne das Browser-Fenster dafür schmaler ziehen zu müssen. */
body.mobil-reihenfolge-aktiv .kachel-grid {
    grid-template-columns: 1fr;
    max-width: 480px;
    margin: 0 auto;
}

body.mobil-reihenfolge-aktiv .kachel,
body.mobil-reihenfolge-aktiv .kachel--schmal,
body.mobil-reihenfolge-aktiv .kachel--breit {
    grid-column: span 1;
}

/* order:9999 für .kachel-hinzufuegen-knopf gilt inzwischen allgemein (siehe
   die Grundregel weiter oben), hier deshalb keine eigene Regel mehr nötig. */

body.mobil-reihenfolge-aktiv .kachel__griff {
    display: inline-block;
}

body.mobil-reihenfolge-aktiv .kachel__positions-knoepfe {
    display: flex;
}

/* --- Bauschritt 26: "Anordnen-Modus" (persönliche Kachel-Reihenfolge) ----
   Eigener, dritter Modus - technisch UNABHÄNGIG vom Bearbeitungsmodus und
   von "Mobile Reihenfolge bearbeiten" oben (eigene body-Klasse, eigene
   JS-Zustandsvariable, siehe anordnenModusAnwenden() in assets/js/
   dashboard.js) und für JEDE angemeldete Person erreichbar, nicht nur
   Lehrkräfte. Zeigt bewusst NUR Griff + Positions-Knöpfe (dieselben beiden
   Klassen wie beim Bearbeitungsmodus oben - die Sichtbarkeits-Regel kennt
   keinen Unterschied zwischen den Gründen, warum eine Kachel gerade
   verschiebbar sein soll) - KEINE der übrigen Bearbeiten-Knöpfe
   (Einstellungen-Zahnrad, Löschen, Breite, "+ Neue Kachel") und kein
   contenteditable werden dadurch sichtbar/aktiv, damit in diesem Modus
   wirklich nur die Reihenfolge verändert werden kann, wie im Auftrag
   verlangt. */
body.anordnen-modus-aktiv .kachel__griff {
    display: inline-block;
}

body.anordnen-modus-aktiv .kachel__positions-knoepfe {
    display: flex;
}

/* Reine Anzeige-Elemente (kein contenteditable mehr, siehe
   editierbaresFeldEinrichten() in assets/js/dashboard.js), solange der
   Bearbeiten-Modus aus ist - der Mauszeiger soll dann nicht wie ein
   Textcursor aussehen, das würde Bearbeitbarkeit suggerieren, die es gerade
   nicht gibt. */
.kachel__titel:not([contenteditable="true"]),
.kachel__rich-text:not([contenteditable="true"]),
.todo-eintrag__text:not([contenteditable="true"]),
.stundenplan-eintrag__fach:not([contenteditable="true"]),
.stundenplan-eintrag__raum:not([contenteditable="true"]),
.geburtstag-eintrag__name:not([contenteditable="true"]),
.geburtstag-eintrag__datum:not([contenteditable="true"]),
.kalender-eintrag__titel:not([contenteditable="true"]),
.kalender-eintrag__wann:not([contenteditable="true"]),
.kalender-eintrag__notiz:not([contenteditable="true"]) {
    cursor: default;
}

.todo-eintrag__checkbox:disabled {
    cursor: default;
    opacity: 0.6;
}

/* --- Profilmenü: Bearbeitungsmodus-Menüpunkt -----------------------------
   Bauschritt 18: der frühere eigenständige Knopf in der Kopfleiste
   (.bearbeiten-modus-schalter) ist jetzt ein Menüpunkt im Profilmenü (siehe
   .profilmenue__eintrag oben) - dieselbe ID/Umschalt-Logik in
   assets/js/dashboard.js, nur optisch als Menüzeile statt als eigener
   Knopf. Im aktiven Zustand (Bearbeiten-Modus an, Beschriftung zeigt dann
   "Lesemodus") bewusst leicht hervorgehoben, damit der aktuelle Modus auch
   ohne erneutes Öffnen der Beschriftung erkennbar bliebe. */
#bearbeiten-modus-schalter[aria-pressed="true"],
#mobil-reihenfolge-schalter[aria-pressed="true"] {
    background: var(--farbe-akzent);
    color: #fff;
}

#bearbeiten-modus-schalter[aria-pressed="true"]:hover,
#bearbeiten-modus-schalter[aria-pressed="true"]:focus,
#mobil-reihenfolge-schalter[aria-pressed="true"]:hover,
#mobil-reihenfolge-schalter[aria-pressed="true"]:focus {
    background: var(--farbe-akzent-dunkel);
}

/* --- Touch-Geräte (Tablet/Smartphone) ------------------------------------
   Innerhalb des Bearbeiten-Modus sind viele der obigen Knöpfe zusätzlich
   bewusst standardmäßig unsichtbar (opacity: 0) und blenden sich erst per
   :hover oder :focus ein - eine schlanke Optik auf dem Desktop, wo die Maus
   über eine Kachel/einen Eintrag fährt, bevor etwas angeklickt wird. Auf
   einem Touchscreen gibt es aber gar kein ":hover" (der Finger "schwebt"
   nicht erst kurz drüber) - ohne diese Regel blieben Löschen-,
   Einstellungen- und Verschieben-Knöpfe auf Tablet/Handy deshalb (selbst
   MIT eingeschaltetem Bearbeiten-Modus) dauerhaft unsichtbar und damit
   praktisch unbedienbar, obwohl sie technisch längst da und anklickbar
   wären. "(hover: none)" erkennt genau diesen Fall (kein Zeigegerät mit
   echtem Hover) und macht alle diese Knöpfe dort dauerhaft sichtbar statt
   erst bei Hover/Focus. -------------- */
@media (hover: none) {
    .kachel__einstellungen-knopf,
    .kachel__loeschen-knopf,
    .kachel__auf-knopf,
    .kachel__ab-knopf,
    .kachel__schmaler-knopf,
    .kachel__breiter-knopf,
    .todo-eintrag__loeschen,
    .todo-eintrag__auf-knopf,
    .todo-eintrag__ab-knopf,
    .stundenplan-eintrag__loeschen,
    .geburtstag-eintrag__loeschen,
    .kalender-eintrag__loeschen {
        opacity: 1;
    }
}

/* --- Einstellungs-Seiten (kachel-aussehen.php, kachel-eintraege.php) -----
   Beide seit Bauschritt 14 eigene Unterseiten statt Inline-Panels in der
   Kachel - gemeinsamer, schlichter Formular-Baukasten statt für jede der
   beiden Seiten eigene Klassen zu erfinden. */

.einstellungs-seite {
    max-width: 900px;
    margin: 0 auto;
}

.einstellungs-seite__zurueck {
    display: inline-block;
    margin-bottom: 16px;
    font-size: 0.9rem;
    text-decoration: none;
}

.einstellungs-seite__titel {
    font-family: var(--schrift-anzeige);
    font-size: calc(1.6rem * var(--schriftgroesse-anzeige-faktor, 1));
    margin: 0 0 4px;
}

.einstellungs-seite__untertitel {
    color: var(--farbe-text-gedaempft);
    margin: 0 0 20px;
}

.einstellungs-seite__erfolg {
    background: rgba(47, 95, 221, 0.1);
    color: var(--farbe-akzent-dunkel);
    border-radius: 8px;
    padding: 10px 14px;
    font-size: 0.9rem;
    margin: 0 0 20px;
}

.einstellungs-seite__fehler {
    background: var(--farbe-fehler-flaeche);
    color: var(--farbe-fehler);
    border-radius: 8px;
    padding: 10px 14px;
    font-size: 0.9rem;
    margin: 0 0 20px;
}

.einstellungs-seite__abschnitt {
    background: var(--farbe-flaeche);
    border: 1px solid var(--farbe-rand);
    border-radius: var(--radius);
    box-shadow: var(--schatten);
    padding: 20px 24px;
    margin-bottom: 20px;
}

.einstellungs-seite__abschnitt-titel {
    font-family: var(--schrift-anzeige);
    font-size: calc(1.05rem * var(--schriftgroesse-anzeige-faktor, 1));
    margin: 0 0 14px;
}

.einstellungs-seite__hinweis {
    color: var(--farbe-text-gedaempft);
    font-size: 0.85rem;
    margin: -6px 0 14px;
}

/* Formular/Vorschau nebeneinander auf breiten Bildschirmen, siehe
   @media (max-width: 900px) weiter unten für schmale. */
.aussehen-layout {
    display: grid;
    grid-template-columns: 1fr 260px;
    gap: 20px;
    align-items: start;
}

/* ":not([hidden])" nötig, sonst überstimmt diese Autor-Regel die
   eingebaute Browser-Regel "[hidden] { display: none }" bei gleicher
   Spezifität, wie schon an anderer Stelle in diesem Projekt (siehe die
   ausführliche Erklärung bei der inzwischen entfallenen
   .kachel__hintergrund-einstellungen-Regel aus Bauschritt 9) - relevant
   hier, weil assets/js/kachel-aussehen.js das hidden-Attribut auf
   #aussehen-farbe-feld/#aussehen-bild-feld setzt. */
.formular-feld:not([hidden]) {
    display: block;
    margin-bottom: 14px;
    font-size: 0.9rem;
}

.formular-feld__beschriftung {
    display: block;
    font-weight: 600;
    margin-bottom: 4px;
}

.formular-feld input[type="text"],
.formular-feld input[type="number"],
.formular-feld input[type="file"],
.formular-feld select {
    width: 100%;
    border: 1px solid var(--farbe-rand);
    border-radius: 6px;
    padding: 8px 10px;
    font-family: var(--schrift-text);
    font-size: 0.9rem;
    background: var(--farbe-flaeche);
    color: var(--farbe-text);
}

.formular-feld input[type="color"] {
    width: 56px;
    height: 34px;
    border: 1px solid var(--farbe-rand);
    border-radius: 6px;
    padding: 2px;
    cursor: pointer;
    background: none;
}

.formular-feld input[type="range"] {
    width: 100%;
}

.formular-feld input:focus,
.formular-feld select:focus {
    outline: 2px solid var(--farbe-akzent);
    outline-offset: 1px;
}

/* Bauschritt 19: die Dropdown-Menüs auf den beiden Einstellungsseiten
   (kachel-aussehen.php/seiteneinstellungen.php, beide mit der Klasse
   .aussehen-formular) sollen unabhängig von der jeweils gewählten
   Schriftart immer in derselben, gut lesbaren Schrift (Quicksand)
   erscheinen - fest, nicht einstellbar. Ohne diese Regel würde ein
   Dropdown sonst .formular-feld select { font-family: var(--schrift-text); }
   erben, also z. B. in einer verspielten, schwer lesbaren Schrift
   dargestellt, falls die/der Benutzer:in genau diese als globale
   Standardschrift eingestellt hat. Betrifft ausdrücklich nur die
   Dropdown-Menüs selbst, nicht die Vorschaukacheln auf denselben Seiten -
   die zeigen weiterhin wahrheitsgemäß die tatsächlich gewählte Schrift
   (siehe assets/js/kachel-aussehen.js/seiteneinstellungen.js,
   vorschauAktualisieren()/schriftVorschauAktualisieren()). Höhere
   Spezifität (zwei Klassen) gewinnt hier unabhängig von der Reihenfolge
   gegen die allgemeinere Regel oben. */
.aussehen-formular select {
    font-family: 'Quicksand', sans-serif;
}

.formular-zeile {
    display: flex;
    flex-wrap: wrap;
    gap: 20px;
}

.formular-zeile > .formular-feld {
    flex: 1 1 160px;
}

.formular-feld--radio {
    display: flex;
    align-items: center;
    gap: 6px;
    font-weight: 400;
    margin-bottom: 8px;
    cursor: pointer;
}

.formular-feld--radio input {
    accent-color: var(--farbe-akzent);
}

.formular-aktionen {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-top: 8px;
}

.formular-status {
    color: var(--farbe-text-gedaempft);
    font-style: italic;
    font-size: 0.85rem;
}

/* Kleine Live-Vorschau auf kachel-aussehen.php (assets/js/kachel-aussehen.js
   spiegelt Farbe/Bild/Transparenz/Schriftart/-farbe direkt in dieses
   Element, ohne dafür schon zu speichern). */
.aussehen-vorschau {
    position: sticky;
    top: 20px;
}

.aussehen-vorschau__kachel {
    width: 100%;
    min-height: 160px;
}

.aussehen-vorschau__hinweis {
    color: var(--farbe-text-gedaempft);
    font-size: 0.8rem;
    margin: 8px 0 0;
    text-align: center;
}

.aussehen-bild-aktuell {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 10px;
}

.aussehen-bild-aktuell img {
    width: 72px;
    height: 48px;
    object-fit: cover;
    border-radius: 6px;
    border: 1px solid var(--farbe-rand);
}

.aussehen-bild-aktuell__entfernen {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 0.85rem;
    color: var(--farbe-text-gedaempft);
}

/* --- seiteneinstellungen.php: Vorschau von Kopfleiste + Seite ------------
   Zwei übereinanderliegende Kästen statt eines einzelnen wie bei
   .aussehen-vorschau__kachel, weil hier gleich drei verschiedene Bereiche
   (Kopfleiste, Seiten-Hintergrund, Standard-Schrift einer Kachel ohne
   eigene Einstellung) auf einmal vorzuschauen sind - assets/js/
   seiteneinstellungen.js spiegelt jede Änderung sofort hinein. */
.seiteneinstellungen-vorschau__leiste {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 14px;
    background: var(--farbe-flaeche);
    border: 1px solid var(--farbe-rand);
    border-radius: var(--radius) var(--radius) 0 0;
}

.seiteneinstellungen-vorschau__marke {
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
    font-family: var(--schrift-anzeige);
    font-size: 0.8rem;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: var(--farbe-text-gedaempft);
}

.seiteneinstellungen-vorschau__logo {
    display: block;
    height: 22px;
    width: auto;
    max-width: 90px;
    object-fit: contain;
}

/* Bauschritt 17: Vorschau des Layouts "zentriert" (siehe
   seiteneinstellungen.php und .kopfleiste__inhalt--zentriert oben, deren
   volle Grid-Logik hier bewusst nicht 1:1 übernommen wird - die kleine
   Vorschau-Leiste hat keine zweite Ecke mit Rechts-Knöpfen, "zentriert"
   heißt hier einfach: Marke mittig statt linksbündig). */
.seiteneinstellungen-vorschau__leiste--zentriert {
    justify-content: center;
}

.seiteneinstellungen-vorschau__seite {
    position: relative;
    overflow: hidden;
    background: var(--farbe-hintergrund);
    border: 1px solid var(--farbe-rand);
    border-top: none;
    border-radius: 0 0 var(--radius) var(--radius);
    padding: 16px;
}

.seiteneinstellungen-vorschau__seite-bild {
    position: absolute;
    inset: 0;
    background-size: cover;
    background-position: center;
    pointer-events: none;
}

.seiteneinstellungen-vorschau__kachel {
    position: relative;
    min-height: 90px;
}

/* --- kachel-eintraege.php: bestehende Einträge, Hinzufügen, CSV-Import --- */

.eintraege-liste {
    list-style: none;
    margin: 0 0 16px;
    padding: 0;
    max-height: 320px;
    overflow-y: auto;
    border: 1px solid var(--farbe-rand);
    border-radius: 8px;
}

.eintraege-liste__leer {
    padding: 14px;
    color: var(--farbe-text-gedaempft);
    font-size: 0.85rem;
    font-style: italic;
    margin: 0;
}

.eintraege-liste__zeile {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 12px;
    font-size: 0.88rem;
    border-bottom: 1px solid var(--farbe-rand);
}

.eintraege-liste__zeile:last-child {
    border-bottom: none;
}

.eintraege-liste__text {
    flex: 1;
    min-width: 0;
}

.eintraege-liste__nebentext {
    color: var(--farbe-text-gedaempft);
    font-size: 0.82rem;
}

.eintraege-liste__loeschen {
    flex: none;
    border: none;
    background: transparent;
    color: var(--farbe-text-gedaempft);
    font-size: 1.05rem;
    line-height: 1;
    padding: 2px 6px;
    border-radius: 6px;
    cursor: pointer;
}

.eintraege-liste__loeschen:hover {
    background: rgba(179, 38, 30, 0.1);
    color: var(--farbe-fehler);
}

/* Bauschritt 20: screens-verwalten.php - Liste der zusätzlichen Screens.
   Jede Zeile ist ihr eigenes <form> (siehe screens-verwalten.php, Kommentar
   zu den benannten Absende-Knöpfen) - deshalb hier flex statt der
   list-item/button-Aufteilung der Eintraege-Liste oben. */
.screens-liste {
    list-style: none;
    margin: 0 0 16px;
    padding: 0;
    border: 1px solid var(--farbe-rand);
    border-radius: 8px;
}

.screens-liste__zeile {
    border-bottom: 1px solid var(--farbe-rand);
}

.screens-liste__zeile:last-child {
    border-bottom: none;
}

.screens-liste__formular {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 12px;
    flex-wrap: wrap;
}

.screens-liste__titel-feld {
    flex: 1 1 160px;
    min-width: 120px;
    padding: 6px 8px;
    border: 1px solid var(--farbe-rand);
    border-radius: 6px;
    font-size: 0.88rem;
    font-family: inherit;
}

.screens-liste__link {
    flex: none;
    font-size: 0.82rem;
    white-space: nowrap;
}

.screens-liste__pfeil {
    flex: none;
    border: 1px solid var(--farbe-rand);
    background: transparent;
    color: var(--farbe-text);
    font-size: 0.95rem;
    line-height: 1;
    padding: 4px 8px;
    border-radius: 6px;
    cursor: pointer;
}

.screens-liste__pfeil:hover:not(:disabled) {
    background: var(--farbe-hintergrund);
}

.screens-liste__pfeil:disabled {
    opacity: 0.35;
    cursor: default;
}

.screens-liste__loeschen {
    flex: none;
    border: none;
    background: transparent;
    color: var(--farbe-text-gedaempft);
    font-size: 1.15rem;
    line-height: 1;
    padding: 2px 8px;
    border-radius: 6px;
    cursor: pointer;
}

.screens-liste__loeschen:hover {
    background: rgba(179, 38, 30, 0.1);
    color: var(--farbe-fehler);
}

.screens-liste__neu-formular {
    max-width: 360px;
}

.csv-import__format {
    background: var(--farbe-hintergrund);
    border-radius: 8px;
    padding: 10px 12px;
    font-size: 0.82rem;
    color: var(--farbe-text-gedaempft);
    margin: 0 0 14px;
}

.csv-import__format code {
    font-family: var(--schrift-mono);
    background: rgba(0, 0, 0, 0.06);
    padding: 1px 5px;
    border-radius: 4px;
}

.csv-import__ergebnis {
    margin-top: 12px;
    font-size: 0.85rem;
}

.csv-import__fehlerliste {
    margin: 8px 0 0;
    padding-left: 20px;
    color: var(--farbe-fehler);
}

@media (max-width: 900px) {
    .aussehen-layout {
        grid-template-columns: 1fr;
    }

    .aussehen-vorschau {
        position: static;
    }
}

/* --- Schmale Bildschirme (Smartphone-Hochformat) -------------------------
   Ab hier zusätzlich etwas mehr "Luft" für Finger statt Mauszeiger: größere
   Tippflächen bei den kleinen ▲/▼-Knöpfen und etwas mehr Abstand in den
   Listen-Zeilen.
   Bauschritt-18-Korrektur: .kachel-grid braucht hier DOCH eine eigene Regel
   - ".kachel-grid { grid-template-columns: repeat(auto-fill,
   minmax(170px, 1fr)); }" wurde in Bauschritt 16 von "minmax(260px, 1fr)"
   auf "minmax(170px, 1fr)" verkleinert (damit auf einem normalen Monitor
   mehr Spalten gleichzeitig passen), der Kommentar hier blieb dabei stehen -
   mit 170px passen auf vielen Smartphones (alles ab ca. 400px Breite)
   inzwischen tatsächlich ZWEI schmale Spalten nebeneinander statt der
   gewünschten einen. Deshalb unten "grid-template-columns: 1fr;" explizit
   erzwungen, statt sich weiter auf "auto-fill" allein zu verlassen. -------- */
@media (max-width: 640px) {
    .app {
        padding: 20px 14px;
    }

    .kachel-grid {
        grid-template-columns: 1fr;
    }

    /* Bauschritt 20: eigene Kachel-Reihenfolge NUR für schmale Bildschirme
       (siehe includes/kacheln.php, kachelPositionMobil(), und die
       Verwaltung dieser Reihenfolge im Bearbeiten-Modus, assets/js/
       dashboard.js) - unabhängig von der normalen Desktop-Reihenfolge, die
       weiterhin über die DOM-Position selbst läuft (siehe die Regeln ohne
       @media weiter oben). --order-mobil steht als Inline-Style an jeder
       .kachel (siehe kachelRendern()); mit nur einer Spalte hier bestimmt
       "order" die Position ganz einfach von oben nach unten. Der
       "+ Neue Kachel"-Knopf bleibt dabei ganz am Ende (order:9999, siehe
       die allgemeine Regel bei .kachel-hinzufuegen-knopf weiter oben). */
    .kachel {
        order: var(--order-mobil, 0);
    }

    /* Bauschritt 23: ".kachel-paar" (Link-Kachel "Halbiert anzeigen", siehe
       weiter oben) bekommt hier dieselbe mobile Reihenfolge wie eine
       normale Kachel (übernimmt dafür die Position der ERSTEN der beiden
       Kacheln, siehe kachelnRendern() in includes/kacheln.php) - und
       nimmt, wie jede einzelne Kachel auf Smartphone-Breite, nur noch eine
       Spalte ein. Nebeneinander ergäbe bei einer Spalte kaum noch Platz je
       Hälfte - deshalb stapelt sich das Paar hier stattdessen senkrecht
       (flex-direction:column), jede Hälfte bleibt aber weiterhin eine
       eigenständige, vollständige Kachel. */
    .kachel-paar {
        grid-column: span 1;
        order: var(--order-mobil, 0);
        flex-direction: column;
    }

    /* ".kachel-paar > .kachel { flex: 1 1 0; }" (siehe weiter oben) ist
       genau richtig für die nebeneinander liegende DESKTOP-Aufteilung -
       "flex-basis: 0" auf der dortigen waagerechten Hauptachse verteilt die
       feste Breite des Paares gleichmäßig auf beide Hälften. In der
       gestapelten MOBILEN Spalten-Richtung liegt die Hauptachse aber
       senkrecht, und "flex-basis: 0" hätte dort (ohne selbst eine
       Höhen-Vorgabe für ".kachel-paar" zu haben, aus der sich "zu
       verteilender Platz" ergäbe) jede Hälfte auf ihre automatische
       Mindesthöhe zusammenschrumpfen lassen - bei "overflow: hidden" auf
       ".kachel" (siehe dort) ist diese Mindesthöhe 0, der Titel wäre also
       abgeschnitten. "flex: initial" (= "0 1 auto") lässt jede Hälfte
       stattdessen wieder ihre normale, am eigenen Inhalt bemessene Höhe
       behalten - genau wie eine gewöhnliche, nicht gepaarte Kachel. */
    .kachel-paar > .kachel {
        flex: initial;
    }

    /* Seit der Bauschritt-18-Korrektur sitzt das horizontale Padding der
       Kopfleiste auf .kopfleiste__inhalt (siehe dort) statt auf
       .kopfleiste selbst - diese Regel muss deshalb mitziehen, sonst bliebe
       sie wirkungslos (stale seit der Umstellung). */
    .kopfleiste__inhalt {
        padding: 14px 16px;
    }

    /* Auf Smartphone-Breite passt ohnehin nur eine Spalte - Breiten-Stufen
       (schmal/normal/breit) würden hier nur unterschiedlich große Ränder
       neben einer einzigen Kachel bedeuten, kein sinnvoller Unterschied. */
    .kachel,
    .kachel--schmal,
    .kachel--breit {
        grid-column: span 1;
    }

    .kachel__auf-knopf,
    .kachel__ab-knopf,
    .kachel__schmaler-knopf,
    .kachel__breiter-knopf,
    .todo-eintrag__auf-knopf,
    .todo-eintrag__ab-knopf {
        font-size: 0.75rem;
        padding: 4px 8px;
    }

    .todo-eintrag,
    .geburtstag-eintrag,
    .kalender-eintrag {
        gap: 8px;
    }

    .todo-eintrag__checkbox {
        width: 20px;
        height: 20px;
    }

    .einstellungs-seite__abschnitt {
        padding: 16px;
    }
}
