:root{
  --bg:#f4f6f8; --flaeche:#fff; --rand:#dde2e8; --rand-stark:#c6ced8;
  --text:#2a3138; --text-schwach:#5b6472; --text-sehr-schwach:#67717f;
  /* Markenfarben RS Ostfriesland Charter GmbH.
     Blau- und Goldtöne für SCHRIFT sind bewusst dunkler als die reinen
     Markenfarben: #3d7cad erreichte mit weißer bzw. auf weißer Fläche
     nur 4,48:1 und verfehlte damit knapp die Kontrastnorm (WCAG AA 4,5:1),
     Gold als Schriftfarbe lag bei 2,1-2,9:1. Flächen und Ränder dürfen
     weiterhin die helleren Originaltöne tragen. */
  --marke-blau:#2f6389; --marke-blau-dunkel:#25506f; --marke-blau-hell:#eaf2f8;
  --marke-gold:#dfa84c; --marke-gold-dunkel:#8a6626; --marke-gold-hell:#fdf4e5;
  --marke-anthrazit:#2a3138;
  --akzent:#2f6389; --akzent-hell:#eaf2f8; --akzent-dunkel:#25506f;
  --rot:#b3261e; --rot-bg:#fdecea; --rot-rand:#f0b8b3;
  --orange:#9a6410; --orange-bg:#fdf4e5; --orange-rand:#eec98c;
  --gelb:#6d5600; --gelb-bg:#fdf8d8; --gelb-rand:#e8dc95;
  --gruen:#14653a; --gruen-bg:#e3f5ea; --gruen-rand:#a9dcbd;
  --grau:#3c4551; --grau-bg:#eceef1; --grau-rand:#cdd3db;
  --schatten:0 1px 2px rgba(16,24,40,.05), 0 1px 3px rgba(16,24,40,.06);
  --schatten-gross:0 4px 16px rgba(16,24,40,.10);
  --radius:10px;
  /* Abgeleitete Flaechen- und Texttoene (Dunkelmodus überschreibt sie) */
  --kopf-bg:#fff; --flaeche-2:#f6f8fa; --eingabe-bg:#fff;
  --th-bg:#f0f3f6; --th-hover:#e4e9ef; --rand-fein:#eef1f4;
  --zeile-hover:#f8fafc; --zeile-zebra:#f8fafb;
  --zeile-rot:#fff7f6; --zeile-rot-hover:#fff0ee;
  --rot-text:#7e1c15; --orange-text:#7a4a00; --gruen-text:#0f4f2d;
  --info-text:#1c4470; --info-rand:#b9d0ea; --orange-mittel:#d98a0b;
  --fstd-bg:#f7f4fb;
  /* Formularelemente folgen der Palette; der Dunkelmodus setzt
     color-scheme:dark, damit Datums-/Auswahlfelder mitgehen. */
  color-scheme:light;
}
*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%; text-size-adjust:100%}
html,body{margin:0;padding:0}
body{
  background:var(--bg); color:var(--text); min-height:100vh;
  display:flex; flex-direction:column;
  font:15px/1.55 "Segoe UI Variable Text","Segoe UI",system-ui,
       -apple-system,BlinkMacSystemFont,"Helvetica Neue",Roboto,Arial,sans-serif;
  -webkit-font-smoothing:antialiased; -moz-osx-font-smoothing:grayscale;
}
/* Auf Mobilgeraeten wandert die Adressleiste - dvh vermeidet den Sprung. */
@supports (min-height:100dvh){body{min-height:100dvh}}
img,svg{max-width:100%}
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{transition-duration:.01ms !important;
    animation-duration:.01ms !important; scroll-behavior:auto !important}
}
a{color:var(--akzent); text-decoration:none}
a:hover{text-decoration:underline}
h1{font-size:26px; margin:0 0 4px; letter-spacing:-.02em; font-weight:600}
h2{font-size:18px; margin:30px 0 12px; font-weight:600; letter-spacing:-.01em}
h2:first-child{margin-top:0}
h3{font-size:14.5px; margin:20px 0 8px; font-weight:600; color:var(--grau)}
p{margin:0 0 10px}
.klein{font-size:13.5px; color:var(--text-schwach)}
.sehr-klein{font-size:12.5px; color:var(--text-sehr-schwach)}
.mono{font-family:"Cascadia Mono",Consolas,monospace; font-size:12.5px}
.num{text-align:right; font-variant-numeric:tabular-nums; white-space:nowrap}
.mitte{text-align:center}

/* ---------- Kopf ----------
   ACHTUNG: dieser Kopf klebt (position:sticky). Was der Browser von oben ins
   Bild rollt, landet sonst DAHINTER. Dagegen steht html{scroll-padding-top}
   weiter unten bei --kopf-platz; ändert sich hier die Höhe des Kopfes,
   gehören die Bänder dort nachgemessen. Zwei weitere Regeln nehmen den Kopf
   aus dem Kleben: bis 820 px Breite (Z342) und bis 480 px Höhe (am Ende). */
.kopf{background:var(--kopf-bg); border-bottom:1px solid var(--rand); position:sticky; top:0; z-index:50}
.kopf-innen{max-width:1320px; margin:0 auto; padding:0 24px; display:flex;
  align-items:center; gap:0 18px; min-height:56px; flex-wrap:wrap}
.marke{display:flex; align-items:center; gap:9px; font-weight:700; font-size:16px;
  color:var(--text); letter-spacing:-.01em}
.marke:hover{text-decoration:none}
.marke-zeichen{display:grid; place-items:center; width:30px; height:30px; border-radius:8px;
  background:var(--marke-blau); color:#fff; font-size:16px}
.marke-logo{height:40px; width:auto; max-width:230px; display:block}
.marke-text{display:flex; flex-direction:column; line-height:1.15}
.marke-text .firma{font-size:14.5px; font-weight:700; color:var(--marke-anthrazit)}
.marke-text .produkt{font-size:11px; font-weight:600; letter-spacing:.06em;
  text-transform:uppercase; color:var(--marke-gold-dunkel)}
.kopf{border-bottom:2px solid var(--marke-gold)}

.umschalter{position:relative}
.umschalter-knopf{display:flex; align-items:center; gap:8px; background:var(--flaeche);
  border:1px solid var(--rand-stark); border-radius:8px; padding:7px 12px;
  font:inherit; font-size:13.5px; color:var(--text); cursor:pointer; min-width:0; max-width:250px}
.umschalter-knopf:hover{border-color:var(--akzent); background:var(--akzent-hell)}
.umschalter-muster{color:var(--text-schwach); font-size:12.5px}
.pfeil{margin-left:auto; color:var(--text-sehr-schwach); font-size:11px}
.umschalter-liste{position:absolute; top:calc(100% + 6px); left:0; min-width:290px;
  background:var(--flaeche); border:1px solid var(--rand); border-radius:var(--radius);
  box-shadow:var(--schatten-gross); padding:5px; z-index:60;
  /* Bei vielen Einträgen scrollt die Liste, statt unter den
     Seitenrand zu wachsen. */
  max-height:min(78vh, 640px); overflow-y:auto}
.umschalter-liste a{display:block; padding:8px 11px; border-radius:7px; color:var(--text)}
.umschalter-liste a:hover{background:var(--akzent-hell); text-decoration:none}
.umschalter-liste a.aktiv{background:var(--akzent-hell); box-shadow:inset 2px 0 0 var(--akzent)}
.umschalter-liste a strong{display:block; font-size:13.5px}
.umschalter-liste a span{font-size:12px; color:var(--text-schwach)}
.umschalter-liste a.neu{margin-top:5px; border-top:1px solid var(--rand);
  border-radius:0 0 7px 7px; color:var(--akzent); font-weight:600; font-size:13px}

/* Die Reiter stehen immer in einer eigenen Zeile unter der Kopfleiste -
   dadurch bleibt die Kopfhoehe auf allen Seiten gleich und der Inhalt
   springt beim Wechseln nicht. */
.hauptnav{display:flex; gap:2px; flex-wrap:wrap; order:3;
  width:calc(100% + 48px); margin:0 -24px; padding:4px 24px 5px;
  border-top:1px solid var(--rand); background:var(--flaeche-2)}
.hauptnav:empty{display:none}
.hauptnav a{padding:6px 13px; border-radius:7px; color:var(--text-schwach);
  font-size:14px; font-weight:500}
.hauptnav a:hover{background:var(--grau-bg); color:var(--text); text-decoration:none}
.hauptnav a.aktiv{background:var(--marke-blau); color:#fff}

/* ---------- Inhalt ---------- */
.inhalt{max-width:1320px; width:100%; margin:0 auto; padding:26px 24px 50px; flex:1}
.seitenkopf{display:flex; align-items:flex-start; justify-content:space-between;
  gap:20px; margin-bottom:22px; flex-wrap:wrap}
.seitenkopf .unter{color:var(--text-schwach); font-size:13.5px; margin:0}

.karte{background:var(--flaeche); border:1px solid var(--rand); border-radius:var(--radius);
  box-shadow:var(--schatten); padding:18px 20px; margin-bottom:18px}
.karte-kopf{display:flex; align-items:center; justify-content:space-between;
  gap:14px; margin:-2px 0 14px; flex-wrap:wrap}
.karte-kopf h2,.karte-kopf h3{margin:0}

.raster{display:grid; gap:16px}
/* Karten enden dort, wo ihr Inhalt endet - sonst zieht die laengste Karte
   alle Nachbarn auf ihre Hoehe und es entstehen grosse leere Flaechen. */
.r2,.r3{align-items:start}
.r2{grid-template-columns:repeat(auto-fit,minmax(330px,1fr))}
.r3{grid-template-columns:repeat(auto-fit,minmax(250px,1fr))}
.r4{grid-template-columns:repeat(auto-fit,minmax(190px,1fr))}

/* ---------- Kennzahlen ---------- */
.kennzahl{background:var(--flaeche); border:1px solid var(--rand); border-radius:var(--radius);
  padding:14px 16px; box-shadow:var(--schatten)}
.kennzahl .wert{font-size:27px; font-weight:600; letter-spacing:-.02em; line-height:1.15}
.kennzahl .bez{font-size:11.5px; text-transform:uppercase; letter-spacing:.05em;
  color:var(--text-schwach); margin-top:3px; font-weight:600}
.kennzahl.rot .wert{color:var(--rot)} .kennzahl.rot{background:var(--rot-bg); border-color:var(--rot-rand)}
.kennzahl.orange .wert{color:var(--orange)} .kennzahl.orange{background:var(--orange-bg); border-color:var(--orange-rand)}
.kennzahl.gelb .wert{color:var(--gelb)} .kennzahl.gelb{background:var(--gelb-bg); border-color:var(--gelb-rand)}
.kennzahl.gruen .wert{color:var(--gruen)} .kennzahl.gruen{background:var(--gruen-bg); border-color:var(--gruen-rand)}
.kennzahl.grau .wert{color:var(--grau)} .kennzahl.grau{background:var(--grau-bg); border-color:var(--grau-rand)}

/* ---------- Tabellen ---------- */
.scroll{overflow-x:auto; border-radius:var(--radius); border:1px solid var(--rand);
  background:var(--flaeche); box-shadow:var(--schatten)}
/* Lange Tabellen scrollen im Rahmen — die Spaltenkoepfe (th sticky)
   bleiben dadurch beim Scrollen sichtbar. Klasse setzt base.html ab
   >25 Zeilen. */
.scroll.hoch{max-height:75vh; overflow-y:auto}
table{border-collapse:collapse; width:100%; font-size:13.5px}
th{background:var(--th-bg); text-align:left; padding:9px 12px; font-weight:600; font-size:12.5px;
  color:var(--grau); border-bottom:1px solid var(--rand); white-space:nowrap; position:sticky; top:0}
td{padding:9px 12px; border-bottom:1px solid var(--rand-fein); vertical-align:top}
th.sortierbar{cursor:pointer; user-select:none}
th.sortierbar:hover{background:var(--th-hover); color:var(--text)}
.sortier-pfeil{font-size:10px; color:var(--marke-blau)}
/* Drei Stufen je Modul (2.1.0, Betreiber 06.09.2026: „vorne mit einem haken
   und dahinter mit einem umschalter zwischen lesend und bearbeitend“):
   EINE Zeile je Modul — Haken „an“, dahinter zwei Radios. Reines HTML, kein
   Skript (CSP); form label ist sonst block und fett, hier inline. */
.modul-stufe{display:flex; align-items:center; gap:14px; flex-wrap:wrap; padding:3px 0}
.modul-stufe label{display:inline-flex; align-items:center; gap:6px; margin:0;
  font-weight:400; color:var(--text); cursor:pointer}
.modul-stufe .modul-name{min-width:170px}
.modul-stufe .stufen{display:inline-flex; gap:12px; font-size:12.5px; color:var(--text-schwach)}
.modul-stufe .stufen label{font-size:12.5px; color:var(--text-schwach)}
/* Checkbox-Liste: eine PDF mit mehreren Fristen zugleich verknüpfen */
.haken-liste{max-height:220px; overflow-y:auto; border:1px solid var(--rand);
  border-radius:6px; padding:6px 10px; margin-top:8px; background:var(--flaeche)}
.haken-liste label{display:block; font-size:12.5px; padding:3px 0; cursor:pointer}
.haken-liste label:hover{color:var(--marke-blau)}
.haken-liste input{margin-right:6px}
/* Blätter-Pfeile im Positions-/AD-Editor: ohne Ziel ausgegraut */
.knopf.inaktiv{opacity:.4; pointer-events:none}
tbody tr:last-child td{border-bottom:none}
/* Zebrastreifen fuer die Zeilenverfolgung in breiten Tabellen -
   Status-Einfaerbungen (z-ÜBERFÄLLIG usw.) liegen darueber. */
.scroll tbody tr:nth-child(even):not([class*="z-"]) td{background:var(--zeile-zebra)}
tbody tr:hover{background:var(--zeile-hover)}
.scroll tbody tr:hover:not([class*="z-"]) td{background:var(--zeile-hover)}
tr.z-ÜBERFÄLLIG td{background:var(--zeile-rot)}
tr.z-ÜBERFÄLLIG:hover td{background:var(--zeile-rot-hover)}
tr.z-UNBEKANNT td{background:var(--flaeche-2)}

/* ---------- Marken ---------- */
.marke-status{display:inline-block; padding:2px 9px; border-radius:20px; font-size:11.5px;
  font-weight:700; white-space:nowrap; border:1px solid}
.s-ÜBERFÄLLIG{background:var(--rot-bg); color:var(--rot); border-color:var(--rot-rand)}
.s-FÄLLIG{background:var(--orange-bg); color:var(--orange); border-color:var(--orange-rand)}
.s-BEOBACHTEN{background:var(--gelb-bg); color:var(--gelb); border-color:var(--gelb-rand)}
.s-OK{background:var(--gruen-bg); color:var(--gruen); border-color:var(--gruen-rand)}
.s-UNBEKANNT{background:var(--grau-bg); color:var(--grau); border-color:var(--grau-rand)}
.schild{display:inline-block; padding:1px 7px; border-radius:5px; font-size:11px;
  font-weight:600; border:1px solid var(--rand-stark); background:var(--grau-bg);
  color:var(--grau); margin-right:4px; white-space:nowrap}
.schild.warn{background:var(--orange-bg); border-color:var(--orange-rand); color:var(--orange)}
.schild.rot{background:var(--rot-bg); border-color:var(--rot-rand); color:var(--rot)}
/* Rotes „I“-Abzeichen: Pilot mit INDIVIDUELLEM Vergütungssatz (Abrechnung) */
.schild-i{display:inline-block; min-width:16px; padding:0 4px; border-radius:50%;
  font-size:10.5px; font-weight:800; line-height:15px; text-align:center;
  background:var(--rot-bg); color:var(--rot); border:1px solid var(--rot-rand);
  vertical-align:middle; cursor:help; white-space:nowrap}
.pruefen{color:var(--rot); font-weight:600; font-size:12px}

/* ---------- Hinweise ---------- */
.hinweis{border:1px solid; border-left-width:4px; border-radius:8px;
  padding:12px 15px; margin:0 0 14px}
.hinweis h3{margin:0 0 6px; font-size:13.5px}
.hinweis ul{margin:5px 0 0; padding-left:19px}
.hinweis li{margin:3px 0; font-size:13px}
.h-crit{background:var(--rot-bg); border-color:var(--rot-rand); border-left-color:var(--rot); color:var(--rot-text)}
.h-warn{background:var(--orange-bg); border-color:var(--orange-rand); border-left-color:var(--orange-mittel); color:var(--orange-text)}
.h-info{background:var(--akzent-hell); border-color:var(--info-rand); border-left-color:var(--akzent); color:var(--info-text)}
.h-ok{background:var(--gruen-bg); border-color:var(--gruen-rand); border-left-color:var(--gruen); color:var(--gruen-text)}
details.hinweis summary{cursor:pointer; font-weight:600; font-size:13.5px}
details.hinweis summary::-webkit-details-marker{color:currentColor}
/* Aufklappbares Formular ohne JS (Abrechnung: Individuellen Satz anlegen) */
details.aufklapp{margin-top:14px}
details.aufklapp > summary{cursor:pointer; font-weight:600; font-size:13.5px; color:var(--marke-blau)}
details.aufklapp[open] > summary{margin-bottom:10px}

.meldungen{margin-bottom:18px}
.meldung{padding:11px 15px; border-radius:8px; margin-bottom:8px; font-size:14px;
  border:1px solid; border-left-width:4px}
.m-ok{background:var(--gruen-bg); border-color:var(--gruen-rand); border-left-color:var(--gruen); color:var(--gruen-text)}
.m-warn{background:var(--orange-bg); border-color:var(--orange-rand); border-left-color:var(--orange-mittel); color:var(--orange-text)}
.m-error{background:var(--rot-bg); border-color:var(--rot-rand); border-left-color:var(--rot); color:var(--rot-text)}
.m-message{background:var(--akzent-hell); border-color:var(--info-rand); border-left-color:var(--akzent); color:var(--info-text)}

/* ---------- Formulare ---------- */
.feld{margin-bottom:14px}
.feld label{display:block; font-size:13.5px; font-weight:600; color:var(--grau); margin-bottom:4px}
.feld .hilfe{font-size:12.5px; color:var(--text-sehr-schwach); margin-top:3px}
input[type=text],input[type=number],input[type=date],input[type=file],
input[type=time],input[type=email],input[type=password],input[type=search],
input[type=tel],input[type=url],input[type=month],input[type=datetime-local],
input:not([type]),select,textarea{
  width:100%; padding:8px 11px; border:1px solid var(--rand-stark); border-radius:7px;
  font:inherit; font-size:14px; line-height:1.35; background:var(--eingabe-bg); color:var(--text);
  min-height:38px; -webkit-appearance:none; appearance:none}
/* Safari/iOS zeichnen Datum und Uhrzeit sonst mittig und zu klein */
input[type=date],input[type=time],input[type=month],input[type=datetime-local]{
  text-align:left; min-width:0}
input[type=date]::-webkit-date-and-time-value,
input[type=time]::-webkit-date-and-time-value{text-align:left}
input[type=file]{padding:6px 9px; -webkit-appearance:auto; appearance:auto}
input[type=search]::-webkit-search-decoration,
input[type=search]::-webkit-search-cancel-button{-webkit-appearance:none}
/* Auswahlfelder: eigener Pfeil, damit sie in allen Browsern gleich aussehen */
select{padding-right:32px; cursor:pointer;
  background-image:url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath fill='%235b6472' d='M2 4.2h8L6 9z'/%3E%3C/svg%3E");
  background-repeat:no-repeat; background-position:right 10px center;
  background-size:11px 11px}
select[multiple],select[size]:not([size="1"]){background-image:none;
  padding-right:11px; min-height:auto}
::placeholder{color:var(--text-sehr-schwach); opacity:1}
input:focus,select:focus,textarea:focus{outline:none; border-color:var(--akzent);
  box-shadow:0 0 0 3px rgba(27,95,168,.14)}
/* Sichtbarer Fokus fuer Tastaturbedienung in jedem Browser */
a:focus-visible,button:focus-visible,summary:focus-visible,
.knopf:focus-visible,label.lfz-chip:focus-within{
  outline:2px solid var(--akzent); outline-offset:2px; border-radius:6px}
textarea{resize:vertical; min-height:70px}
input[type=checkbox],input[type=radio]{width:16px; height:16px; accent-color:var(--akzent);
  vertical-align:middle; cursor:pointer}
/* Haken und Auswahlknoepfe brauchen einen eigenen sichtbaren Fokusring -
   der box-shadow-Fokus der Textfelder greift bei ihnen nicht. */
input[type=checkbox]:focus-visible,input[type=radio]:focus-visible{
  outline:2px solid var(--akzent); outline-offset:2px}
fieldset{border:1px solid var(--rand); border-radius:9px; padding:14px 16px; margin:0 0 16px; min-width:0}
legend{font-size:12.5px; font-weight:600; color:var(--grau); padding:0 6px}

.knopf{display:inline-flex; align-items:center; gap:7px; padding:9px 17px; border-radius:8px;
  border:1px solid var(--rand-stark); background:var(--flaeche); color:var(--text);
  font:inherit; font-size:13.5px; font-weight:600; cursor:pointer; white-space:nowrap}
.knopf:hover{background:var(--grau-bg); text-decoration:none}
.knopf.haupt{background:var(--marke-blau); border-color:var(--marke-blau); color:#fff}
.knopf.haupt:hover{background:var(--marke-blau-dunkel)}
.knopf.gefahr{background:var(--rot); border-color:var(--rot); color:#fff}
.knopf.gefahr:hover{background:#8f1e17}
.knopf.klein{padding:5px 11px; font-size:12.5px}
.knopf-reihe{display:flex; gap:9px; flex-wrap:wrap; align-items:center; min-width:0}
.knopf-reihe form{display:flex; gap:8px; flex-wrap:wrap; align-items:center; min-width:0}
.knopf-reihe form input[type=text]{flex:1 1 190px; min-width:0; width:auto}

.filter{display:flex; gap:6px; flex-wrap:wrap}
.filter a{padding:5px 12px; border-radius:20px; border:1px solid var(--rand-stark);
  font-size:12.5px; color:var(--text-schwach); background:var(--flaeche)}
.filter a:hover{background:var(--grau-bg); text-decoration:none}
.filter a.aktiv{background:var(--marke-blau); border-color:var(--marke-blau); color:#fff}

/* ---------- Datenliste ---------- */
/* Nur Nicht-Tabellen: <table class="daten"> (updates.php) zerfiel als Grid — Gegenprobe 15.09.2026: thead 2997 px; Nachmessung
   1280 px (?p=updates, Kopie): vorher display:grid, thead 4703 px; mit der Regel display:table, thead 38 px.
   :not(:where(table)) hält die Spezifität von .daten, damit die Handy-Regel (max-width:640px) weiter greift. */
.daten:not(:where(table)){display:grid; grid-template-columns:repeat(auto-fit,minmax(215px,1fr)); gap:13px 22px}
.daten:not(:where(table)) div{font-size:14px}
.daten:not(:where(table)) span{display:block; font-size:11px; text-transform:uppercase; letter-spacing:.05em;
  color:var(--text-schwach); font-weight:600; margin-bottom:1px}
.leer{color:var(--text-sehr-schwach)}

/* ---------- Checkliste ---------- */
.pruefpunkt{display:flex; gap:11px; padding:9px 0; border-bottom:1px solid var(--rand-fein)}
.pruefpunkt:last-child{border-bottom:none}
.pruefpunkt input{margin-top:3px; flex:none}
.pruefpunkt .text{flex:1}
.pruefpunkt.erledigt .text{color:var(--text-sehr-schwach); text-decoration:line-through}
.teile{margin:6px 0 2px; padding:7px 10px; background:var(--flaeche-2);
  border:1px solid var(--rand); border-left:3px solid var(--marke-blau);
  border-radius:0 6px 6px 0}
.teile-titel{font-size:12.5px; font-weight:620; color:var(--text-schwach, #4a5260)}
.teile-liste{list-style:none; margin:5px 0 0; padding:0}
.teile-liste li{padding:3px 0; display:flex; flex-wrap:wrap; align-items:baseline;
  gap:5px 9px; border-top:1px dotted var(--rand)}
.teile-liste li:first-child{border-top:none}
.t-bez{font-weight:560}
.t-pn{background:var(--grau-bg); border:1px solid var(--rand); border-radius:4px;
  padding:0 5px; font-size:12px}
.t-menge{color:var(--text-schwach, #4a5260); font-size:12.5px}
.t-hinweis{flex-basis:100%}

/* ---------- Fuss ---------- */
.fuss{border-top:3px solid var(--marke-gold); background:var(--kopf-bg); margin-top:auto}
.fuss-innen{max-width:1320px; margin:0 auto; padding:18px 24px 26px}
.vorbehalt{font-size:12.5px; color:var(--rot-text); background:var(--rot-bg);
  border:1px solid var(--rot-rand); border-left:4px solid var(--rot);
  border-radius:8px; padding:11px 15px; margin:0 0 9px}

@media (max-width:1200px){
  .suchfeld input{width:140px}
  .umschalter-knopf{min-width:170px}
}
@media (max-width:980px){
  .suchfeld{order:2}
}
@media (max-width:820px){
  /* Der Kopf staple sich hier auf mehrere Zeilen (gemessen 287-407 px
     hoch) - sticky wuerde bis zur Haelfte des Handybildschirms dauerhaft
     belegen. Deshalb scrollt der Kopf auf schmalen Bildschirmen mit. */
  .kopf{position:static}
  .kopf-innen{padding:8px 16px 0; gap:8px 12px}
  .hauptnav{width:calc(100% + 32px); margin:0 -16px; padding:4px 16px 5px;
    /* Reiter in EINER seitlich schiebbaren Zeile statt 3-4 Umbruchzeilen */
    flex-wrap:nowrap; overflow-x:auto; -webkit-overflow-scrolling:touch;
    scrollbar-width:thin}
  .hauptnav a{white-space:nowrap; flex:none}
  .marke-text{display:none}
  .marke-logo{height:32px}
  .suchfeld input{width:100%}
  .suchfeld{flex:1; min-width:0}
  .inhalt{padding:18px 16px 40px}
  .karte{padding:14px 14px}
  h1{font-size:22px}
  .seitenkopf{margin-bottom:16px}
  /* Unter 16px zoomt iOS beim Antippen in das Feld hinein */
  input,select,textarea{font-size:16px !important}
  .daten{grid-template-columns:repeat(auto-fit,minmax(150px,1fr))}
}
/* Fingerbedienung: groessere Schaltflaechen */
@media (pointer:coarse){
  .knopf{min-height:42px; padding-top:10px; padding-bottom:10px}
  .knopf.klein{min-height:36px}
  .hauptnav a,.filter a,.umschalter-liste a{min-height:38px;
    display:flex; align-items:center}
  .umschalter-liste a{display:block; padding:10px 12px}
  input[type=checkbox],input[type=radio]{width:18px; height:18px}
  /* Auch die Kopf-Bedienelemente (Gruppen-/Bereichs-/LFZ-Wahl, Suche,
     Zahnrad) brauchen Fingerzielgroesse - sie sind der Hauptbedienweg. */
  .umschalter-knopf{min-height:42px}
  .suchfeld input,.suchfeld button{min-height:42px}
  /* Buchungsmatrix: 14-px-Zellen sind kein Fingerziel - fuer Touch
     verdoppeln, damit der Tipp den richtigen 30-Minuten-Slot trifft. */
  td.mzelle,.seg{height:28px; line-height:28px}
}
@media print{
  .kopf,.fuss .klein,.knopf,.filter,.hauptnav,.knopf-reihe{display:none}
  body{background:#fff}
  .karte,.scroll{box-shadow:none; break-inside:avoid; border-color:#999}
  th{position:static}
  .scroll{overflow:visible}
  a{color:inherit; text-decoration:none}
  table{font-size:10.5pt}
}

/* ---------- Exportbereich ---------- */
.export-block{border:1px solid var(--rand); border-radius:9px; padding:14px 16px;
  background:var(--flaeche-2)}
.export-block h3{margin:0 0 6px; color:var(--text)}
.export-block p{margin:0 0 12px}

/* ---------- Suche ---------- */
.suchfeld{display:flex; align-items:center; gap:0}
.suchfeld input{width:190px; padding:7px 11px; border:1px solid var(--rand-stark);
  border-right:none; border-radius:8px 0 0 8px; font:inherit; font-size:13.5px;
  background:var(--eingabe-bg); color:var(--text)}
.suchfeld input:focus{outline:none; border-color:var(--marke-blau);
  box-shadow:0 0 0 3px rgba(61,124,173,.14)}
.suchfeld button{padding:7px 13px; border:1px solid var(--rand-stark);
  border-radius:0 8px 8px 0; background:var(--grau-bg); cursor:pointer;
  font-size:16px; line-height:1; color:var(--grau)}
.suchfeld button:hover{background:var(--marke-blau); border-color:var(--marke-blau);
  color:#fff}
.hauptnav{margin-left:0}

.schnellfilter{display:flex; align-items:center; gap:9px; flex-wrap:wrap}
.schnellfilter input{width:230px; padding:6px 11px; border:1px solid var(--rand-stark);
  border-radius:8px; font:inherit; font-size:13px; background:var(--eingabe-bg); color:var(--text)}
.schnellfilter input:focus{outline:none; border-color:var(--marke-blau);
  box-shadow:0 0 0 3px rgba(61,124,173,.14)}
.schnellfilter .zaehler{font-size:12.5px; color:var(--text-schwach)}
tr.verborgen{display:none}

/* ---------- Benutzermenue ---------- */
.konto{display:flex; align-items:center; gap:9px}
.konto > a{display:flex; flex-direction:column; line-height:1.2; padding:4px 9px;
  border-radius:7px; color:var(--text)}
.konto > a:hover{background:var(--grau-bg); text-decoration:none}
.konto > a strong{font-size:13px}
.konto > a span{font-size:11px; color:var(--text-schwach)}

/* ---------- Hilfe ---------- */
.hilfe-aufbau{display:grid; grid-template-columns:250px 1fr; gap:18px; align-items:start}
@media (max-width:900px){.hilfe-aufbau{grid-template-columns:1fr}}
.hilfe-inhalt{position:sticky; top:76px; padding:12px 8px}
.hilfe-gruppe{font-size:11px; text-transform:uppercase; letter-spacing:.05em;
  color:var(--text-schwach); font-weight:600; padding:10px 10px 4px}
.hilfe-inhalt a{display:block; padding:6px 10px; border-radius:7px;
  font-size:13.5px; color:var(--text)}
.hilfe-inhalt a:hover{background:var(--grau-bg); text-decoration:none}
.hilfe-inhalt a.aktiv{background:var(--marke-blau); color:#fff}
.hilfe-karte{display:block; color:var(--text)}
.hilfe-karte:hover{border-color:var(--marke-blau); text-decoration:none}
.hilfe-karte strong{display:block; margin-bottom:4px}
.hilfe-artikel p{margin:0 0 12px; line-height:1.65}
.hilfe-artikel ul,.hilfe-artikel ol{margin:0 0 12px; padding-left:22px}
.hilfe-artikel li{margin:5px 0; line-height:1.55}
.hilfe-artikel h3{margin-top:24px; padding-bottom:4px;
  border-bottom:1px solid var(--rand)}

/* Hilfe als aeusserster Reiter ganz rechts in der Kopfzeile */
.hilfe-reiter{ padding:7px 13px; border-radius:7px;
  font-size:13.5px; font-weight:600;
  color:var(--marke-gold-dunkel); border:1px solid var(--marke-gold);
  background:var(--marke-gold-hell); white-space:nowrap}
/* Auf Gold traegt nur dunkle Schrift genug Kontrast (weiss: 2,1:1) */
.hilfe-reiter:hover{background:var(--marke-gold); color:var(--marke-anthrazit);
  text-decoration:none}
.hilfe-reiter.aktiv{background:var(--marke-gold); color:var(--marke-anthrazit)}

/* ---- Drag-and-drop-Zonen fuer PDF-Uploads ------------------------------ */
form[data-dropzone]{position:relative; border:1.5px dashed var(--rand-stark);
  border-radius:10px; padding:14px; transition:border-color .12s, background .12s}
form[data-dropzone].dz-aktiv{border-color:var(--akzent);
  background:var(--akzent-hell)}
form[data-dropzone].dz-aktiv *{pointer-events:none}
.dz-hinweis{font-size:12.5px; color:var(--text-schwach); margin:6px 0 0}
.dz-hinweis strong{color:var(--akzent)}

/* ---- Buchungsmatrix ---------------------------------------------------- */
table.matrix{border-collapse:collapse}
table.matrix td, table.matrix th{border:1px solid var(--rand); padding:1px 4px}
table.matrix .zeit{font-size:10.5px; color:var(--text-schwach); padding:0 6px}
table.matrix .zelle{min-width:58px; height:15px; font-size:10px;
  text-align:center; overflow:hidden; white-space:nowrap}
.zelle-frei{background:var(--flaeche); cursor:pointer}
.zelle-frei:hover{background:var(--akzent-hell)}
.zelle-vorbei{background:var(--grau-bg)}
.zelle-belegt{background:var(--grau-rand); color:var(--grau)}
.zelle-eigen{background:var(--marke-blau); color:#fff}
.zelle-sperre{background:var(--orange-bg); color:var(--orange);
  border-color:var(--orange-rand)}
.zelle-lehrer{background:var(--gruen-bg); color:var(--gruen);
  border-color:var(--gruen-rand); cursor:pointer}
.zelle-lehrer:hover{background:var(--gruen-rand)}

/* ---- Kombinierte Buchungsmatrix --------------------------------------- */
.lfz-chip{display:inline-flex; align-items:center; gap:6px; padding:4px 10px;
  border:2px solid var(--chip); border-radius:16px; cursor:pointer;
  font-weight:600; font-size:13.5px; -webkit-user-select:none; user-select:none}
.lfz-chip.an{background:var(--chip); color:#fff}
.lfz-chip:has(input:checked){background:var(--chip); color:#fff}
/* Helle LFZ-Farben (Gold, Tuerkis) tragen dunkle Schrift */
.lfz-chip.hell.an{color:#1d232a}
.lfz-chip.hell:has(input:checked){color:#1d232a}
/* Rueckfall ohne :has(): das Haekchen bleibt sichtbar und markiert die Wahl */
.lfz-chip input{margin:0; flex:none}
.lfz-punkt{display:inline-block; width:10px; height:10px; border-radius:50%;
  margin-right:4px}
table.matrix2{border-collapse:collapse; -webkit-user-select:none; user-select:none; width:100%;
  touch-action:pan-x pan-y}
table.matrix2 th{border:1px solid var(--rand); padding:2px 4px; font-size:11px}
table.matrix2 td.zeit{border:none; padding:0 6px 0 0; font-size:10.5px;
  color:var(--text-schwach); text-align:right; width:48px; vertical-align:top}
table.matrix2 td.zeit.volle{font-weight:600; color:var(--text)}
td.mzelle{border:1px solid var(--rand); padding:0; height:18px;
  font-size:0; min-width:96px; white-space:nowrap}
.seg{display:inline-block; height:18px; font-size:10.5px; line-height:18px;
  text-align:center; overflow:hidden; color:#fff; vertical-align:top;
  box-sizing:border-box}
/* Auf hellen Luftfahrzeug-Farben (Gold, Tuerkis) traegt weisse Schrift
   keinen Kontrast - der Server vergibt dann .seg-dunkel. */
.seg-dunkel{color:#1d232a}
.seg-frei{color:transparent; cursor:crosshair}
.seg-vorbei{background:var(--grau-bg)}
.seg-sperre{background:var(--orange-bg); color:var(--orange);
  border-left:2px solid var(--orange-rand)}
.seg-fenster{background:var(--gruen-bg); color:var(--gruen);
  border-left:3px solid; cursor:crosshair; font-weight:700}
.seg-eigen{outline:2px solid var(--marke-anthrazit); outline-offset:-2px}
.seg-auswahl{outline:2px solid var(--marke-anthrazit); outline-offset:-2px;
  filter:brightness(0.85)}

/* ---- Navigations-Gruppen: Flugbetrieb / Instandhaltung ----------------- */
.nav-etikett{align-self:center; font-size:10px; font-weight:700;
  text-transform:uppercase; letter-spacing:.08em; color:var(--text-sehr-schwach);
  border-left:2px solid var(--rand-stark); padding-left:10px; margin-left:6px;
  white-space:nowrap; -webkit-user-select:none; user-select:none}
.nav-etikett.nav-flug{color:var(--marke-blau); border-left-color:var(--marke-blau)}
.nav-etikett.nav-wartung{color:var(--orange); border-left-color:var(--orange-rand)}

/* ---- Hilfe: Bereiche und Bilder --------------------------------------- */
.hilfe-bereich{margin:14px 0 4px; font-size:12px; font-weight:700;
  letter-spacing:.05em; text-transform:uppercase; padding-bottom:4px;
  border-bottom:2px solid var(--rand-stark)}
.hilfe-bereich.b-1, .hilfe-bereich-kopf.b-1{color:var(--marke-blau);
  border-color:var(--marke-blau)}
.hilfe-bereich.b-2, .hilfe-bereich-kopf.b-2{color:var(--orange);
  border-color:var(--orange-rand)}
.hilfe-bereich.b-3, .hilfe-bereich-kopf.b-3{color:var(--text-schwach)}
.hilfe-bereich-kopf{margin:26px 0 8px; padding-bottom:6px;
  border-bottom:2px solid var(--rand-stark)}
figure.hilfe-bild{margin:14px 0 20px; padding:0}
figure.hilfe-bild img{max-width:100%; width:auto; height:auto; display:block;
  border:1px solid var(--rand-stark); border-radius:8px;
  box-shadow:0 2px 8px rgba(0,0,0,.08)}
figure.hilfe-bild figcaption{margin-top:6px; font-size:12.5px;
  color:var(--text-schwach)}
/* 2.5.0 — Bilder mit Nummern-Legende (Betreiber 13.09.2026: „ich moechte im
   hilfebereich screenshots, woran an den screenshots erklaert wird“).
   Handy-Aufnahmen sind 780 px breit (390 CSS-px mal 2): width:100% blies sie
   auf Kartenbreite auf — auf 390 px begrenzt und mittig. Kreis wie die Marke
   im Bild (#c62828, weisse fette Ziffer); die Bilder sind immer hell, darum
   im Dunkelmodus unveraendert. Die Ziffer kommt aus data-nr, weil
   counter() das value-Attribut des li nicht kennt. */
figure.hilfe-bild:has(+ ol.hilfe-legende){margin-bottom:8px}
figure.hilfe-bild.mobil img{max-width:min(390px,100%); margin:0 auto}
figure.hilfe-bild.mobil figcaption{text-align:center}
ol.hilfe-legende{list-style:none; margin:0 0 20px; padding:0}
ol.hilfe-legende li{position:relative; margin:6px 0; padding-left:36px;
  min-height:24px; line-height:1.55}
/* Der weiße Ring um den Kreis ist box-shadow (2px), KEIN border — die
   Gegenprobe 14.09.2026 las getComputedStyle border 0px, nannte der Bericht
   aber „weißen Rand“. Ohne border bleibt der Kreis exakt 24px. */
ol.hilfe-legende li::before{content:attr(data-nr); position:absolute; left:0; top:0;
  width:24px; height:24px; border-radius:50%; background:#c62828; color:#fff;
  font-weight:700; font-size:13px; line-height:24px; text-align:center;
  box-shadow:0 0 0 2px #fff}
@media print{
  figure.hilfe-bild{break-inside:avoid}
  ol.hilfe-legende,ol.hilfe-legende li{break-inside:avoid; page-break-inside:avoid}
  ol.hilfe-legende li::before{-webkit-print-color-adjust:exact; print-color-adjust:exact}
}

/* ---- Kopf: Bereichswahl und Einstellungs-Menü -------------------------- */
.bereichswahl .bereich-knopf{background:var(--marke-blau); color:#fff;
  border-color:var(--marke-blau-dunkel); font-size:14px}
.bereichswahl .bereich-knopf:hover{background:var(--marke-blau-dunkel)}
.umschalter-liste.breit{min-width:290px}
.umschalter-liste.breit a strong{display:block; font-size:14px}
.umschalter-liste.breit a span{display:block; font-size:12px;
  color:var(--text-schwach)}
.umschalter.rechts{margin-left:0}
.umschalter-liste.rechts-liste{right:0; left:auto}
/* Nie breiter als der Bildschirm - sonst ragen Eintraege ins Unsichtbare */
.umschalter-liste{max-width:calc(100vw - 16px)}
/* Auf schmalen Bildschirmen umbricht der Kopf und der Zahnrad-Knopf
   rutscht an den LINKEN Rand - die rechts verankerte Liste wuerde dann
   290 px ins Leere zeigen (im Test lag sie bei x = -222). Deshalb dort
   links verankern. */
@media (max-width:980px){
  .umschalter-liste.rechts-liste{left:0; right:auto}
}
.einstell-knopf{font-size:16px; padding:7px 10px;
  min-width:auto !important; width:auto}
.abmelden-form{padding:8px 12px; border-top:1px solid var(--rand)}
/* Gruppen-Etiketten im Zahnrad-Menue */
.menue-etikett{margin:6px 0 2px; padding:8px 11px 2px; font-size:10.5px;
  font-weight:700; letter-spacing:.06em; text-transform:uppercase;
  color:var(--text-schwach); border-top:1px solid var(--rand)}
.menue-etikett:first-child{border-top:none; margin-top:0; padding-top:4px}

/* ---- Persönliches Flugbuch (EASA-Aufbau) ------------------------------ */
table.flugbuch{border-collapse:collapse; font-size:12.5px}
table.flugbuch th, table.flugbuch td{border:1px solid var(--rand);
  padding:2px 5px; white-space:nowrap}
table.flugbuch thead th{background:var(--grau-bg); text-align:center;
  font-size:11.5px}
table.flugbuch tfoot td{font-weight:600; background:var(--grau-bg)}
table.flugbuch tfoot tr.gesamt td{background:var(--akzent-hell);
  font-size:12.5px}

/* Rechte Kopfgruppe: Suche, Einstellungen, Hilfe bleiben zusammen */
.kopf-rechts{display:flex; align-items:center; gap:10px; margin-left:auto;
  order:2; padding:8px 0}
.kopf-innen > .marke,.kopf-innen > .umschalter{order:1}
@media (max-width:980px){
  .kopf-rechts{width:100%; order:2; margin-left:0; padding:0 0 8px}
  .kopf-rechts .suchfeld{flex:1; min-width:0}
  .kopf-rechts .suchfeld input{width:100%}
}

/* ---- Statusleiste je Luftfahrzeug im Belegungsplan -------------------- */
.lfz-leiste{display:flex; flex-wrap:wrap; align-items:center; gap:6px 8px;
  background:var(--flaeche); border:1px solid var(--rand);
  border-radius:8px; padding:7px 11px; margin:0 0 8px; font-size:12.5px}
.ll-name{display:inline-flex; align-items:center; gap:6px; font-size:14px;
  padding-right:8px; border-right:1px solid var(--rand)}
.ll-wert{display:inline-flex; align-items:baseline; gap:5px;
  background:var(--grau-bg); border-radius:6px; padding:3px 9px;
  color:var(--grau); white-space:nowrap}
.ll-wert b{font-size:10.5px; text-transform:uppercase; letter-spacing:.04em;
  font-weight:700; color:var(--text-schwach)}
.ll-wert.rot{background:var(--rot-bg); color:var(--rot)}
.ll-wert.rot b{color:var(--rot)}
.ll-wert.gruen{background:var(--gruen-bg); color:var(--gruen)}
.ll-wert.gruen b{color:var(--gruen)}
.ll-links{display:inline-flex; align-items:center; gap:12px; margin-left:auto;
  white-space:nowrap}
.ll-links a.rot{color:var(--rot); font-weight:600}
.lfz-betrieb{display:flex; flex-wrap:wrap; align-items:baseline; gap:4px 16px;
  margin:-4px 0 10px; padding:5px 11px; font-size:12.5px;
  background:var(--flaeche-2); border:1px solid var(--rand);
  border-top:none; border-radius:0 0 8px 8px}
.lfz-betrieb .lb-oel strong, .lfz-betrieb .lb-sprit strong{color:var(--text-schwach)}
.lfz-betrieb .lb-hinweis{flex-basis:100%; color:var(--text-schwach)}
.ampel-punkt{display:inline-block; width:11px; height:11px; border-radius:50%;
  border:1px solid rgba(0,0,0,.18); flex:none}
.ampel-punkt.a-gruen{background:#2eab63}
.ampel-punkt.a-gelb{background:#e8b23a}
.ampel-punkt.a-rot{background:#d4453b}
/* Ampel mit Wort daneben - Farbe verstaerkt nur noch, traegt nicht allein */
.ampel-wort{display:inline-flex; align-items:center; gap:5px;
  font-size:11.5px; font-weight:700; white-space:nowrap}
.ampel-wort.aw-gruen{color:var(--gruen)}
.ampel-wort.aw-gelb{color:var(--gelb)}
.ampel-wort.aw-rot{color:var(--rot)}

/* ---- 90-Tage-Erfahrung je Muster (FCL.060) --------------------------- */
.muster-reihe{display:grid; gap:12px;
  grid-template-columns:repeat(auto-fit,minmax(210px,1fr))}
.muster-kachel{border:1px solid var(--rand); border-left-width:4px;
  border-radius:9px; padding:10px 13px; background:var(--flaeche-2)}
.muster-kachel.gut{border-left-color:var(--gruen); background:var(--gruen-bg)}
.muster-kachel.knapp{border-left-color:var(--rot); background:var(--rot-bg)}
.muster-kachel .m-kopf{font-size:13px; font-weight:600; line-height:1.3;
  overflow-wrap:anywhere}
.muster-kachel .m-zahl{font-size:26px; font-weight:700; line-height:1.15;
  font-variant-numeric:tabular-nums}
.muster-kachel .m-von{font-size:14px; font-weight:600;
  color:var(--text-schwach)}
.muster-kachel.gut .m-zahl{color:var(--gruen)}
.muster-kachel.knapp .m-zahl{color:var(--rot)}
.muster-kachel .m-unter{font-size:12px; font-weight:600}
.muster-kachel .m-fuss{font-size:11px; color:var(--text-schwach); margin-top:2px}

/* ---- Lange Inhalte brechen statt die Tabelle zu sprengen ------------- */
td .mono,.daten div{overflow-wrap:anywhere}
.scroll{overscroll-behavior-x:contain}
@media (max-width:820px){
  .ll-links{margin-left:0; width:100%; border-top:1px solid var(--rand);
    padding-top:6px}
  .ll-name{border-right:none; width:100%}
}

/* Datum und Uhrzeit als Paar - auch in schmalen Karten nebeneinander */
.zeitpaar{display:grid; grid-template-columns:minmax(0,1fr) 128px;
  gap:0 10px}
@media (max-width:420px){.zeitpaar{grid-template-columns:1fr}}

/* Benutzerverwaltung: Rollenerklaerung und Nachweisspalte */
.rollen-hilfe{list-style:none; margin:6px 0 0; padding:0}
.rollen-hilfe li{font-size:11.5px; line-height:1.45; color:var(--text-schwach);
  padding:4px 0 4px 9px; border-left:2px solid var(--rand)}
.rollen-hilfe li b{color:var(--text); display:block; font-size:12px}
.nachweis-spalte span{display:inline-block; margin-right:5px;
  font-weight:700; white-space:nowrap}
.nw-ok{color:var(--gruen)} .nw-fehlt{color:var(--rot)}
.nw-aus{color:var(--text-sehr-schwach)}

/* ---- Breite Tabellen auf kleinen Bildschirmen ------------------------
   Statt die Spalten bis zur Unlesbarkeit zusammenzuquetschen, behalten
   Tabellen mit vielen Spalten ihre Mindestbreite und der Rahmen wird
   seitlich scrollbar. Die Klasse setzt das Skript in base.html. */
@media (max-width:820px){
  .scroll > table.breit{min-width:680px}
  .scroll > table.sehr-breit{min-width:900px}
}
.scroll-hinweis{display:none}
@media (max-width:820px){
  .scroll-hinweis{display:block; font-size:11.5px;
    color:var(--text-sehr-schwach); margin:4px 2px 0}
}

/* Live-Vorschau der Zeiten im Flugbuchformular */
.zeitvorschau{margin:0; padding:8px 11px; background:var(--akzent-hell);
  border:1px solid var(--info-rand); border-radius:7px; font-size:13.5px;
  font-weight:600; color:var(--info-text); min-height:38px}
.zeitvorschau.warnung{background:var(--rot-bg); border-color:var(--rot-rand);
  color:var(--rot)}
/* FSTD-Zeilen in der Flugbuchtabelle */
tr.fstd-zeile td{background:var(--fstd-bg)}
.gerechnet{color:var(--text-sehr-schwach); font-weight:700; margin-left:1px}

/* Bordbuch: Querprüfung des abgelesenen Gesamtzählers */
.zp-ok{color:var(--gruen); font-weight:700}
.zp-warn{color:var(--rot); font-weight:700; white-space:nowrap}

/* Klickbare Kennzahl-Kacheln (Übersicht -> gefilterte Liste) */
a.kennzahl.klickbar{display:block; color:inherit; text-decoration:none;
  transition:box-shadow .12s, transform .12s, border-color .12s}
a.kennzahl.klickbar:hover{text-decoration:none; box-shadow:var(--schatten-gross);
  transform:translateY(-1px); border-color:var(--rand-stark)}
a.kennzahl.klickbar:focus-visible{outline:2px solid var(--akzent);
  outline-offset:2px}
a.kennzahl.klickbar .bez{color:var(--akzent)}

/* ICAO-/Kennzeichen-Felder: schon beim Tippen groß anzeigen. Der Marker
   autocapitalize="characters" sitzt genau an diesen Feldern. Verbindlich
   normalisiert der Server beim Speichern — das hier ist nur die Optik. */
input[autocapitalize="characters"]{text-transform:uppercase}

/* Kontextuelle Hilfe: kleines ?-Symbol neben Seitenueberschriften,
   verweist auf den passenden Hilfe-Artikel. */
.hilfe-punkt{display:inline-flex; align-items:center; justify-content:center;
  width:21px; height:21px; border-radius:50%; margin-left:8px;
  vertical-align:3px; font-size:13px; font-weight:700;
  color:var(--marke-gold-dunkel); border:1.5px solid var(--marke-gold);
  background:var(--marke-gold-hell)}
.hilfe-punkt:hover{background:var(--marke-gold); color:var(--marke-anthrazit);
  text-decoration:none}

/* ---------- Dunkelmodus -------------------------------------------------
   Folgt der Systemeinstellung (prefers-color-scheme). Alle Farben laufen
   über die Token oben — hier wird nur die Palette getauscht. Die
   Druckansichten (eigene Vorlagen) bleiben bewusst hell. */
@media (prefers-color-scheme: dark){
  :root{
    --bg:#14191f; --flaeche:#1c232b; --rand:#2e3843; --rand-stark:#41505f;
    --text:#dbe2e9; --text-schwach:#9aa7b4; --text-sehr-schwach:#8e9cab;
    --marke-blau:#2f6389; --marke-blau-dunkel:#3a7ba8; --marke-blau-hell:#22303c;
    --marke-gold:#dfa84c; --marke-gold-dunkel:#d3a355; --marke-gold-hell:#33291a;
    --marke-anthrazit:#dbe2e9;
    --akzent:#8ab8dd; --akzent-hell:#22303c; --akzent-dunkel:#a5c9e6;
    --rot:#f0958d; --rot-bg:#382220; --rot-rand:#5c332e;
    --orange:#e3b269; --orange-bg:#362e1c; --orange-rand:#5a4a26;
    --gelb:#ded27b; --gelb-bg:#33301a; --gelb-rand:#555025;
    --gruen:#8fd4a8; --gruen-bg:#1e3227; --gruen-rand:#31543f;
    --grau:#c3cbd4; --grau-bg:#242d36; --grau-rand:#3a4550;
    --schatten:0 1px 2px rgba(0,0,0,.35), 0 1px 3px rgba(0,0,0,.4);
    --schatten-gross:0 4px 16px rgba(0,0,0,.5);
    --kopf-bg:#181f26; --flaeche-2:#212933; --eingabe-bg:#141a21;
    --th-bg:#232c36; --th-hover:#2b3642; --rand-fein:#28313c;
    --zeile-hover:#222b34; --zeile-zebra:#20272f;
    --zeile-rot:#31211e; --zeile-rot-hover:#3a2722;
    --rot-text:#f0a49d; --orange-text:#e8c088; --gruen-text:#a4dbb9;
    --info-text:#a8c8e8; --info-rand:#33506c; --orange-mittel:#c98a2c;
    --fstd-bg:#241f2d;
    color-scheme:dark;
  }
  /* Auswahlfeld-Pfeil in hell nachzeichnen */
  select{background-image:url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath fill='%239aa7b4' d='M2 4.2h8L6 9z'/%3E%3C/svg%3E")}
  /* Weisse Knopf-/Aktiv-Schrift bleibt auf den Markenflaechen lesbar —
     die Flaechen selbst sind unveraendert dunkel genug. */
  .marke-logo{filter:brightness(1.15)}
  .hilfe-reiter{color:var(--marke-gold-dunkel)}
  .hilfe-reiter:hover,.hilfe-reiter.aktiv{color:#1d232a}
  .hilfe-punkt:hover{color:#1d232a}
  .ampel-punkt{border-color:rgba(255,255,255,.25)}
  .lfz-chip.an,.lfz-chip:has(input:checked){color:#fff}
  .lfz-chip.hell.an,.lfz-chip.hell:has(input:checked){color:#1d232a}
}

/* =========================================================================
   SQL-Ausgabe: Kompatibilitätsklassen.
   Das Stylesheet oben ist die unveränderte Kopie der Python-Oberfläche.
   Die PHP-Module nutzen einige eigene Klassennamen — hier werden sie auf
   die Original-Optik abgebildet (nur Token von oben, keine neuen Farben).
   ========================================================================= */

/* Tabellenrahmen wie .scroll */
.tabelle-rolle{overflow-x:auto; border-radius:var(--radius); border:1px solid var(--rand);
  background:var(--flaeche); box-shadow:var(--schatten)}
.tabelle-rolle tbody tr:nth-child(even):not([class*="z-"]) td{background:var(--zeile-zebra)}

.rechts{text-align:right; font-variant-numeric:tabular-nums; white-space:nowrap}
.leise{color:var(--text-schwach)}
.oben{margin-top:0}

/* Meldungen (Flash) der PHP-Module */
.hinweis.warnung{background:var(--orange-bg); border-color:var(--orange-rand);
  border-left-color:var(--orange-mittel); color:var(--orange-text)}
.hinweis.fehler{background:var(--rot-bg); border-color:var(--rot-rand);
  border-left-color:var(--rot); color:var(--rot-text)}
.hinweis:not(.warnung):not(.fehler):not(.h-crit):not(.h-warn):not(.h-info):not(.h-ok){
  background:var(--gruen-bg); border-color:var(--gruen-rand);
  border-left-color:var(--gruen); color:var(--gruen-text)}

/* Ampelpunkte der Fristen-/Statusspalten */
.punkt{display:inline-block; width:11px; height:11px; border-radius:50%;
  margin-right:5px; vertical-align:baseline}
.punkt.ok{background:var(--gruen)}
.punkt.bald{background:var(--orange-mittel)}
.punkt.faellig{background:var(--rot)}
.punkt.unbestimmt{background:var(--text-sehr-schwach)}

/* Formulare der PHP-Module (nackte label/button) */
form.formular{max-width:560px}
form label{display:block; font-size:13.5px; font-weight:600; color:var(--grau);
  margin:13px 0 4px}
form label:first-of-type{margin-top:0}
.zeile2{display:grid; grid-template-columns:1fr 1fr; gap:0 16px}
@media (max-width:700px){ .zeile2{grid-template-columns:1fr} }
button{display:inline-flex; align-items:center; gap:7px; padding:9px 17px;
  border-radius:8px; border:1px solid var(--marke-blau); background:var(--marke-blau);
  color:#fff; font:inherit; font-size:13.5px; font-weight:600; cursor:pointer;
  white-space:nowrap; margin-top:12px}
button:hover{background:var(--marke-blau-dunkel); border-color:var(--marke-blau-dunkel)}
button.neben{background:var(--flaeche); border-color:var(--rand-stark); color:var(--text)}
button.neben:hover{background:var(--grau-bg)}
button.gefahr{background:var(--rot); border-color:var(--rot); color:#fff}
button.gefahr:hover{background:#8f1e17}

/* LFZ-Reiterleisten der Module (nav.nav) wie .filter */
nav.nav, .lfz-leiste{display:flex; gap:6px; flex-wrap:wrap; margin-bottom:16px}
nav.nav a, .lfz-leiste a{padding:5px 12px; border-radius:20px;
  border:1px solid var(--rand-stark); font-size:12.5px;
  color:var(--text-schwach); background:var(--flaeche)}
nav.nav a:hover, .lfz-leiste a:hover{background:var(--grau-bg); text-decoration:none}
nav.nav a.aktiv, .lfz-leiste a.aktiv{background:var(--marke-blau);
  border-color:var(--marke-blau); color:#fff}

/* Kopfzeile: Abmelden rechts */
.kopf-rechts{margin-left:auto; display:flex; align-items:center; gap:10px}
.kopf-rechts form{margin:0}
.kopf-rechts button{margin-top:0; padding:6px 13px; font-size:12.5px;
  background:var(--flaeche); border-color:var(--rand-stark); color:var(--text)}
.kopf-rechts button:hover{background:var(--grau-bg)}

/* Schiebeschalter (CSS-only, kein JS — CSP): Checkbox + gestylte Bahn.
   Verwendung: Rechnungsmodus je Gruppe (extern <-> intern). Die aktive
   Seite wird farbig hervorgehoben; Zustand kommt allein von :checked. */
.schalter{display:flex; align-items:center; gap:10px; cursor:pointer;
  margin:12px 0; font-weight:400}
.schalter input{position:absolute; opacity:0; width:0; height:0}
.schalter-bahn{flex:0 0 auto; width:46px; height:24px; border-radius:12px;
  background:var(--grau-bg); border:1px solid var(--rand-stark);
  position:relative; transition:background .15s, border-color .15s}
.schalter-bahn::after{content:""; position:absolute; top:2px; left:2px;
  width:18px; height:18px; border-radius:50%; background:var(--flaeche);
  border:1px solid var(--rand-stark); transition:left .15s}
.schalter input:checked ~ .schalter-bahn{background:var(--gruen-bg);
  border-color:var(--gruen-rand)}
.schalter input:checked ~ .schalter-bahn::after{left:24px;
  border-color:var(--gruen)}
.schalter input:focus-visible ~ .schalter-bahn{outline:2px solid var(--akzent);
  outline-offset:2px}
/* Schmale Bildschirme: Gegenprobe 15.09.2026 (Meine Gruppe, Rechnungsmodus-Schalter) — „Internes Rechnungsmodul“ ragte bei
   279/300/340 px um 65/44/4 px über den Kartenrand („Rechnungsprogramm“ 132 px und „Rechnungsmodul“ 100 px am Stück). Darum
   unter 375 px Umbruch der Schalterzeile (Beschriftungen ohne Wortbruch, 279/300/340 px: raus ≤ −21 px); overflow-wrap:anywhere
   nur als Notbremse für noch schmalere Karten. Allein brach anywhere „Aktiv“ (Gruppenverwaltung, 279 px) und bei 360 px
   „Rechnungsprogramm“ (3 Zeilen) mitten im Wort; flex-wrap ohne Media-Query brach schon bei 375 px um — verworfen.
   Ab 375 px alle Schalter-Maße gleich wie vorher (gemessen 375 hell/dunkel, 1280). */
.schalter-seite{font-size:13px; color:var(--text-schwach); overflow-wrap:anywhere}
@media (max-width:374.98px){
  .schalter{flex-wrap:wrap}
}
.schalter input:not(:checked) ~ .s-aus{font-weight:700; color:var(--text)}
.schalter input:checked ~ .s-an{font-weight:700; color:var(--gruen)}

/* Logo-Vorschau in der Gruppen-Pflege (Rechnungs-Briefkopf) */
.logo-vorschau{max-height:80px; max-width:280px; border:1px solid var(--rand);
  border-radius:6px; background:#fff; padding:4px}

/* Abrechnung: kompakte Zeilen-Formulare (Landegebühr + Status) — die beiden
   Formulare je Flugzeile kollidierten ohne Layout (Knopf ragte unter das
   Rechnungsnummern-Feld). Betreiber-Meldung 28.08.2026. */
.geb-form{display:flex;gap:4px;justify-content:flex-end;align-items:center;margin-top:4px}
.geb-form input{width:5.5em;min-width:0;text-align:right}
.geb-form button{margin:0;white-space:nowrap}
.status-zelle{min-width:13em}
.status-form{display:flex;flex-direction:column;gap:4px;max-width:14em}
.status-form label{white-space:nowrap;margin:0}
.status-form input[type="text"]{width:100%;min-width:0;box-sizing:border-box;margin:0}
.status-form button{align-self:flex-start;margin:0}

/* =========================================================================
   Mobil und offline (30.08.2026) — Erfassung passiert am Flugzeug.
   Nur Ergaenzungen; die Klassen und Farbtoken oben bleiben unveraendert.
   ========================================================================= */

/* ---- Offline-Warteschlange (public/offline.js) ------------------------
   Die Karte wird von offline.js oben in den Inhalt gehaengt, sobald ein
   Formular ohne Netz zwischengespeichert wurde. Sie soll auffallen: die
   Eintraege stehen noch NICHT im Buch. */
.wsl-karte{border-left:4px solid var(--orange-mittel)}
.wsl-karte h2{margin-top:0}
.wsl-karte table{font-size:13px}
.wsl-karte td{vertical-align:middle}
.wsl-karte .knopf{margin:0}
.wsl-reihe{margin-top:12px}
.wsl-fehler{color:var(--rot-text); font-weight:600; overflow-wrap:anywhere}
.wsl-meldung{margin-bottom:14px}
/* Auf schmalen Bildschirmen scrollt die Liste seitlich statt zu quetschen */
@media (max-width:700px){
  .wsl-karte table{min-width:520px}
}

/* ---- Fingerbedienung in den Erfassungsformularen ----------------------
   Empfehlung fuer Tippziele: mindestens 44 px. Die nackten Formulare der
   PHP-Module (form.formular) benutzen <button> statt .knopf - der Block
   oben deckt nur .knopf ab. */
@media (pointer:coarse){
  button,.knopf{min-height:44px}
  .knopf.klein{min-height:38px}
  form.formular input[type=text],form.formular input[type=date],
  form.formular input[type=number],form.formular input[type=time],
  form.formular select,form.formular textarea{min-height:44px}
  form.formular label{padding:2px 0}
  /* Haken und Auswahlknoepfe im Formular grosszuegiger antippbar */
  form.formular input[type=checkbox],form.formular input[type=radio]{
    width:22px; height:22px; margin-right:8px}
  .wsl-karte .knopf.klein{min-height:38px}
}

/* Auf dem Handy stehen die Formularfelder untereinander: .zeile2 loest
   sich bereits bei 700 px auf; das Datum-/Zeit-Paar folgt jetzt derselben
   Grenze (frueher erst 420 px - auf 390 px breiten Geraeten wurde das
   Zeitfeld sonst schmaler als seine eigene Beschriftung). */
@media (max-width:700px){
  .zeitpaar{grid-template-columns:1fr}
  form.formular{max-width:none}
  /* Absendeknopf ueber die volle Breite: er ist das Ziel am Flugzeug. */
  form.formular > button[type=submit]{width:100%; justify-content:center}
}

/* Bordbuch- und Flugbuchlisten: breite Tabellen scrollen im Rahmen, statt
   die Seite seitlich zu sprengen. .scroll und .tabelle-rolle bringen das
   overflow-x schon mit - hier wird nur sichergestellt, dass auch der
   Karteninhalt selbst nichts nach aussen drueckt. */
.karte{min-width:0}
.karte > .scroll,.karte > .tabelle-rolle{max-width:100%}
@media (max-width:820px){
  .tabelle-rolle > table.breit{min-width:680px}
  .tabelle-rolle > table.sehr-breit{min-width:900px}
}

/* --- Rechnungsnummernkreis (Karte "Rechnungsnummern", ?p=gruppe) ---------
   Die klassischen Muster stehen als Kacheln nebeneinander: Knopf (Link,
   belegt das Musterfeld vor), darunter das Muster als Code und ein
   Beispiel. Reine Layoutklassen - keine Inline-Styles (CSP). */
.nk-vorlagen{display:grid; gap:10px; margin:10px 0 14px;
  grid-template-columns:repeat(auto-fill,minmax(230px,1fr))}
.nk-vorlage{display:flex; flex-direction:column; align-items:flex-start; gap:4px;
  padding:9px 11px; border:1px solid var(--rand); border-radius:8px; min-width:0}
.nk-vorlage .knopf{width:100%; justify-content:center; text-align:center}
.nk-vorlage code{word-break:break-all}
.nk-vorschau{margin:10px 0 14px; padding:10px 12px; border-radius:8px;
  border:1px solid var(--rand); background:var(--grau-bg)}
.nk-vorschau code{font-size:14px}
@media (max-width:520px){
  .nk-vorlagen{grid-template-columns:1fr}
}

/* --- Sicherungspaket (Karte "Komplettsicherung", ?p=sicherung) -----------
   Die drei Umfaenge stehen als Bloecke untereinander: Radioknopf, Titel und
   Groesse in einer Zeile, darunter Erklaerung und die ehrliche Ansage, was
   im Ernstfall fehlt. Reine Layoutklassen - keine Inline-Styles (CSP). */
.paket-wahl{display:grid; gap:10px; margin:4px 0 16px}
.paket-wahl > label{display:block; padding:11px 13px; border:1px solid var(--rand);
  border-radius:8px; cursor:pointer}
.paket-wahl > label:hover{border-color:var(--akzent); background:var(--akzent-hell)}
.paket-wahl > label > span{display:block; margin-top:4px}
.paket-wahl .wahl-kopf{display:flex; align-items:center; gap:9px;
  flex-wrap:wrap; margin-top:0}
.paket-wahl .wahl-kopf input{flex:none; margin:0}
.paket-wahl .wahl-kopf .schild{margin-left:auto}

/* --- Popup "+ Neuer Flug eintragen" (Bordbuch und Flugbuch, 2.2.0) -----
   Betreiber 06.09.2026: das Erfassungsformular oeffnet sich rechts oben aus
   dem Kartenkopf in einem Popup; Speichern laedt die Seite neu (Dialog zu).
   Markup: <button class="knopf neuer-flug" data-dialog="#flug-neu"> im
   .karte-kopf und <dialog id="flug-neu" class="flug-dialog"> mit dem
   serverseitig gerenderten Formular (public/popup.js, Vertrag V3).
   Farben laufen ueber die Token oben - der Dunkelmodus kommt von selbst.
   Reine Layoutklassen, keine Inline-Styles (CSP). */
.karte-kopf .knopf.neuer-flug{margin:0 0 0 auto}
/* 🔴 29.09.2026 — HIER LAG DER FEHLER, DEN DER BETREIBER GEMELDET HAT:
   „wichtig ist auch noch, dass ich bei einem neuen eintrag unten nicht auf
    den bestaetigungsbutton klicken kann. Wenn ich das Iphone oder Ipad quer
    nehme dann kann ich auf den button klicken“
   Zwei Ursachen, beide hier gemessen (Flugbuch, 29.09.2026):
   (1) 100vh IST AUF iOS NICHT DIE SICHTBARE HÖHE. vh rechnet mit dem
       Fenster OHNE die Bedienleisten des Browsers; hochkant blendet Safari
       unten eine Leiste ein (rund 85–115 px samt Griffleiste), die von
       diesen 100vh abgeht. Der Dialog stand unten bündig auf 100vh
       (gemessen 390x844: Dialog-Unterkante 844 = 100vh, margin 0), der
       Knopf endete 18 px darüber — er lag also VOLLSTÄNDIG in dem Streifen,
       den die Bedienleiste verdeckt. Kein Element der Seite fängt den Klick
       ab (document.elementFromPoint auf der Knopfmitte meldet BUTTON), der
       Knopf ist schlicht nicht auf dem Schirm. QUER greift die Weiche
       max-width:700px nicht: dort steht der Dialog mittig mit 16 px Rand,
       und Safari zeigt quer keine Bodenleiste — deshalb ging es quer.
       Abhilfe: dvh statt vh. 100dvh ist die GERADE sichtbare Höhe. Die
       vh-Zeile bleibt als Rückfall für Browser ohne dvh (vor Safari 15.4)
       und wird von der dvh-Zeile überall sonst überschrieben.
   (2) DER KNOPF LAG 2500–3800 px WEIT UNTEN im Dialog. Gemessen: Inhalt
       4611 px in einem 844 px hohen Kasten; ohne zu rollen lag der Knopf bei
       y 4549, elementFromPoint dort: nichts. Man mußte den Dialog erst ganz
       herunterrollen, um ihn überhaupt zu sehen. Deshalb klebt die
       Bestätigungszeile jetzt am unteren Rand des Dialogs (Regel weiter
       unten) — der Knopf steht ab dem ersten Augenblick im Bild.
   Die Ursache, die der Auftrag vermutete (die Listenkarte werde durch
   width:fit-content breiter als der Schirm), ist NACHGEMESSEN NICHT die
   Ursache: unterhalb 1281 px war diese Regel schon vorher zurückgenommen,
   und document.documentElement.scrollWidth entsprach bei 390x844 exakt der
   Fensterbreite (390/390, window.scrollX 0). Sie wird hier trotzdem
   abgeräumt — aber wegen (B), der mitlaufenden Kopfzeile. */
dialog.flug-dialog{width:min(760px,calc(100vw - 32px)); max-width:100%;
  max-height:calc(100vh - 32px);
  max-height:calc(100dvh - 32px);
  /* padding-bottom 0: die klebende Bestätigungszeile unten bringt ihr
     eigenes Polster mit. Stünde hier ein Wert, säße die Zeile im geklebten
     Zustand bündig am Rahmen, im ungeklebten aber um dieses Polster höher —
     ein sichtbarer Sprung am Ende des Rollwegs. */
  overflow:auto; margin:auto; padding:18px 20px 0;
  /* 🔴 29.09.2026, Gegenprobe: OHNE DIESE ZEILE ROLLT DER BROWSER JEDES
     FOKUSSIERTE FELD UNTER DIE BESTÄTIGUNGSLEISTE.
     Der Browser holt ein Feld, das den Fokus bekommt (Tab, der „Weiter“-
     Pfeil der iOS-Tastatur, ein Bildschirmleser), an die UNTERKANTE des
     Rollbereichs — und genau dort klebt seit heute die deckende Leiste mit
     》Eintragen《 und 》Abbrechen《. Der Nutzer tippt dann in ein Feld, das er
     nicht sieht. NACHGEMESSEN (eigener Chrome über CDP, Reihenfolge wie beim
     Durchtabben, verdeckte Felder Bordbuch/Flugbuch):
         390x844   2 von 29 / 8 von 40      844x390  9/29 / 12/40
         360x780   3/29 / 5/40              768x1024 4/29 / 6/40
         1024x768  5/29 / 9/40              1280x800 2/29 / 6/40
         1440x900  4/29 / 6/40              900x240 14/29 / 18/40
         390x420  11/29 / (Tastatur)
     document.elementFromPoint mitten auf dem fokussierten Feld meldete dort
     A.knopf.neben bzw. DIV.knopf-reihe statt des Feldes.
     scroll-padding-bottom hält am unteren Rand des Rollbereichs einen
     Streifen frei, in den der Browser NICHT hineinrollt.
     Betrifft nur dieses Popup; der Wert wirkt ausschließlich auf das Rollen,
     nicht auf die Darstellung.

     🔴 WARUM 120 px UND NICHT DIE LEISTENHÖHE — 29.09.2026 nachgemessen,
     hier stand vorher 96 px (Leiste 82 px plus Luft), UND DAS REICHTE NICHT.
     Der Browser rollt ein Feld, das schon halb im Bild steht, nur SO WEIT
     WIE NÖTIG — und er unterschreitet dabei das Polster um einen festen
     Betrag. Gemessen am selben Feld (Bordbuch 》Bemerkung《, 844x390,
     echtes Tab vom Feld davor):
         Polster  96 px → Feldunterkante 306, Leiste bei 291 → 15 px DRUNTER
         Polster 110 px → Feldunterkante 292, Leiste bei 291 →  1 px drunter
         Polster 120 px → Feldunterkante 174                  → 117 px frei
     Die Luft ist also durchweg 30 px kleiner als das Polster, solange der
     Browser nur nachjustiert; ab 120 px liegt das Feld ganz außerhalb des
     Streifens, und er rollt es weit frei. 120 px = Leiste 82 + diese 30 +
     8 px Reserve. Der ganze Durchlauf danach (beide Bücher, alle neun Maße,
     31–43 Felder je Buch, echte Tab-Anschläge): KEIN verdecktes Feld,
     kleinste gemessene Luft 14 px (Flugbuch 》Bemerkung《 — dort steht der
     Rollweg am Ende, die 14 px sind der Abstand der Leiste selbst).
     scroll-margin-bottom AN DEN FELDERN ist ausprobiert und wirkt NICHT:
     mit Polster 0 und Rand 96/140 px blieb das Feld unverändert unter der
     Leiste (dreimal nachgemessen, 844x390 / 900x240 / 390x420).
     OBERGRENZE: das Polster darf den Rollbereich nicht auffressen. Das
     kleinste Fenster (900x240) läßt dem Dialog 206 px; 120 px Polster
     lassen 86 px, das höchste Feld dort ist 70 px hoch — es paßt, gemessen
     32 px Luft.

     🔴 IST DIE LEISTENHÖHE ZUVERLÄSSIG BEKANNT? — 30.09.2026 durchgemessen,
     weil die ganze Zahl 120 auf ihr aufsitzt. Die Leiste ist von 250 px bis
     1280 px Fensterbreite IMMER 82 px hoch (gemessen bei 250/255/258/260/
     262/265/270/280/300/360/390/700/701/760/900/1280 px) und ändert sich auch
     dann nicht, wenn die Wurzelschriftgröße auf 24 oder 28 px gesetzt wird
     (Knopfmaße stehen in px, nicht in rem — gemessen 82 px bei 280x640/28px
     und 390x844/24px). Die Zahl steht also fest; nur der UMBRUCH kippt sie,
     siehe die Nachbesserung unter 250 px weiter unten. */
  scroll-padding-bottom:120px;
  border:1px solid var(--rand); border-radius:var(--radius);
  background:var(--flaeche); color:var(--text); box-shadow:var(--schatten-gross)}
dialog.flug-dialog::backdrop{background:rgba(16,24,40,.45)}
/* Das Formular fuellt den Dialog; die 560-px-Grenze gilt nur in Karten. */
dialog.flug-dialog form.formular{max-width:none}
.flug-dialog-kopf{display:flex; align-items:center; justify-content:space-between;
  gap:14px; margin:0 0 12px}
.flug-dialog-kopf h2{margin:0}
.flug-dialog-kopf .knopf,.flug-dialog-kopf button{margin-top:0}
/* Ohne JavaScript (noscript-Link ?neu=1) oder in Browsern ohne showModal
   steht <dialog open> als normaler Abschnitt im Seitenfluss, nicht ueber
   der Liste. Aeltere Browser ohne :modal verwerfen nur diese eine Regel. */
dialog.flug-dialog[open]:not(:modal){position:static; width:auto; margin:0 0 18px}
/* ---- DIE BESTÄTIGUNGSZEILE KLEBT AM BODEN DES DIALOGS -------------------
   Das ist die eigentliche Absicherung gegen den Befund oben: der Knopf ist
   sichtbar, sobald der Dialog offen ist — ganz gleich, wie lang das Formular
   ist, wie hoch das Gerät und ob zwischendurch die Bildschirmtastatur
   aufging. Ohne sie lag er bis zu 3767 px unterhalb des Rollbeginns.
   GETROFFEN WIRD NUR DIE LETZTE KNOPFREIHE: das Formular trägt noch eine
   zweite (》Neu berechnen《 über den Zeitanteilen), und die soll da bleiben,
   wo sie hingehört. > .knopf-reihe:last-child ist dafür genau: die
   Bestätigungszeile ist in beiden Büchern das letzte Kind des Formulars
   (flugbuch.php fb_formular, bordbuch.php) — geprüft, kein HTML geändert.
   Die negativen Seitenränder ziehen den Streifen über das Polster des
   Dialogs, damit er wie eine Fußleiste über die ganze Breite läuft.
   env(safe-area-inset-bottom) hält ihn auf iPhones über der Griffleiste;
   max(…) sorgt dafür, daß auf Geräten ohne diesen Wert das gewöhnliche
   Polster stehen bleibt. */
dialog.flug-dialog form.formular > .knopf-reihe:last-child{
  position:sticky; bottom:0; z-index:2;
  margin:14px -20px 0;
  /* Zwei Zeilen mit Absicht: env() steckt NICHT im Kurzschreibweise-Wert.
     Kennt ein Browser env() nicht, verwürfe er sonst die ganze padding-Zeile
     und der Streifen stünde ohne jedes Polster da. So bleibt es dort bei den
     14 px. (Ohne viewport-fit=cover im Viewport-Meta liefert iOS ohnehin 0 —
     max() hält dann die 14 px; sollte das Meta je erweitert werden, wächst
     das Polster von selbst über die Griffleiste hinaus.) */
  padding:11px 20px 14px;
  padding-bottom:max(14px, env(safe-area-inset-bottom));
  background:var(--flaeche);
  border-top:1px solid var(--rand);
}
@media (max-width:700px){
  dialog.flug-dialog:modal{width:100vw; max-width:100vw; max-height:100vh;
    height:100vh;
    /* dvh: die WIRKLICH sichtbare Höhe — Begründung oben bei (1). */
    max-height:100dvh; height:100dvh;
    margin:0; border:0; border-radius:0}
}
/* 🔴 30.09.2026 — HIER LAG EIN RESTBEFUND, DER BIS HEUTE OFFEN WAR.
   Unter 250 px Fensterbreite passen 》Eintragen《 und 》Abbrechen《 nicht mehr
   nebeneinander; .knopf-reihe bricht um (flex-wrap:wrap) und die Leiste ist
   dann ZWEI Zeilen hoch. Gemessen mit echten Tab-Anschlägen, Bordbuch und
   Flugbuch:
       240 px breit → Leiste 135 px → Polster 120 px REICHT NICHT
                      Bordbuch 2 von 31, Flugbuch 4 von 40 Feldern lagen
                      teilweise unter der Leiste (bis 15 px; von drei
                      Meßpunkten trafen nur zwei das Feld, der dritte
                      DIV.knopf-reihe)
       200 px breit → Leiste 135 px → Bordbuch 2/31, Flugbuch 6/40 verdeckt
       200x320      → Bordbuch 13/31, Flugbuch 18/40 verdeckt
       250 px breit → Leiste  82 px → nichts verdeckt (Umbruch kippt zwischen
                      240 und 250 px)
   176 px = Leiste 135 + die 30 px, die der Browser das Polster unterschreitet,
   + 11 px Reserve. DANACH GEMESSEN: 200x640, 240x640, 240x420, 240x844,
   200x320, 260x240, 260x640, 280x640, 300x640, 320x568 — KEIN verdecktes Feld
   mehr, in beiden Büchern.
   WARUM DIE WEICHE BEI 279 UND NICHT BEI 249 px: die gutmütige Richtung. Ein
   etwas zu großes Polster kostet zwischen 250 und 279 px nichts (dort
   nachgemessen: unverändert kein verdecktes Feld), ein zu kleines kostet ein
   unsichtbares Feld. Und die Umbruchkante hängt am Text der Knöpfe — sie kann
   mit einer Übersetzung oder einem längeren Wort wandern.
   min(…,55dvh) ist der Deckel gegen das Auffressen des Rollbereichs (dieselbe
   Überlegung wie oben bei 120 px). Bei allen geprüften Maßen ändert er nichts;
   bei einem Fenster, das schmal UND niedriger als 320 px ist (240x240, kein
   Gerät der Liste), bleibt ein Rest von 3 px: das Feld ist dort an allen drei
   Meßpunkten getroffen, also lesbar und beschreibbar, ragt aber 3 px unter die
   Leiste. Weiter kommt CSS dort nicht — der Dialog ist 208 px hoch, die Leiste
   135 px davon. Das steht hier, statt daß es beschwiegen wird.
   Nur dieses Popup, nur unter 280 px; die neun Gerätemaße sind unberührt. */
@media (max-width:279px){
  dialog.flug-dialog{scroll-padding-bottom:min(176px, 55dvh)}
}
@media print{dialog.flug-dialog{display:none}}

/* --- "Neu berechnen" ueber den Zeitanteilen (public/zeiten.js, Vertrag V4)
   Betreiber 06.09.2026: nach dem Aendern der Zeiten oben werden die Felder
   unten auf Knopfdruck neu berechnet - und bleiben von Hand aenderbar.
   .rechnen-anzeige ist die Zeile "Blockzeit 1:09 . Flugzeit 0:59" (+Warn-
   text in .pruefen); input.zu-gross markiert Nacht/IFR/Kopilot/Lehrer, die
   die neue Blockzeit uebersteigen (der Server weist sie beim Speichern ab). */
.rechnen-zeile{display:flex; gap:10px; flex-wrap:wrap; align-items:center;
  margin:14px 0 4px}
.rechnen-zeile .knopf,.rechnen-zeile button{margin-top:0}
.knopf.neu-berechnen{margin-top:12px}
.rechnen-zeile .knopf.neu-berechnen{margin-top:0}
.rechnen-anzeige{display:inline-block; font-size:12.5px; color:var(--text-schwach);
  margin:6px 0 0 4px; line-height:1.4}
.rechnen-anzeige .pruefen{font-size:12.5px}
input.zu-gross{border-color:var(--rot); box-shadow:0 0 0 3px var(--rot-bg)}

/* Runde 12 (2.3.1, E5): Karte „Bestätigung erforderlich“ vor jeder Löschung — Vorschau in Worten, roter Rand. */
.bestaetigung-karte{border-color:var(--rot-rand); border-left-width:4px}
.bestaetigung-karte h3,.vorschau-liste+h3{margin:10px 0 4px; font-size:13.5px}
.vorschau-liste{margin:4px 0 8px; padding-left:20px}
.vorschau-liste li{margin:3px 0; font-size:13px}
/* Runde 13 (2.3.1, E9): Loeschvorschau der Benutzer-Loesch-Karte - Ueberschriften wie in der Bestaetigungs-Karte, Tabelle der Flugbuch-Eintraege kompakt. */
.loeschvorschau h3{margin:10px 0 4px; font-size:13.5px}
.loeschvorschau-tabelle{margin:4px 0 8px}
.loeschvorschau-tabelle table{font-size:12.5px}
/* Runde 18 (2.4.2): Umschalter Neueste/Aelteste zuerst ueber den Listen von Bordbuch und Mein Flugbuch (Chip-Stil .filter, aktive Richtung .aktiv + aria-current). */
.buecher-sortwahl{margin:6px 0 10px}
/* Pilotenauswertung (2.5.0): Formularfelder Mandant, Pilot, Von, Bis nebeneinander, auf dem Handy untereinander.
   2.9.5: dazu Reihenfolge; .aw-felder ist dasselbe Raster fuer den Zeitraumfilter der Auswertung des Bordbuchs. */
.pa-felder,.aw-felder{display:grid; grid-template-columns:repeat(auto-fit,minmax(190px,1fr)); gap:0 16px}
/* Die ZWEI Summenleisten unter den Listen beider Auswertungen (2.9.5, Betreiber 10.10.2026:
   „unten dann eine leiste mit den gesamtstunden ... und darueber eine leiste nur mit den stunden
   aus diesem zeitraum“). Beide stehen im <tfoot>: oben .aw-zeitraum, unten .aw-gesamt — die
   untere traegt den Akzentton, weil sie die Bezugsgroesse ist. Kein Skript, nur Farbe und Fettung. */
tfoot tr.aw-zeitraum th{background:var(--grau-bg); color:var(--text); border-top:2px solid var(--rand-stark)}
tfoot tr.aw-gesamt th{background:var(--akzent-hell); color:var(--text); font-weight:700;
  border-top:1px solid var(--rand-stark)}
tfoot tr.aw-zeitraum th,tfoot tr.aw-gesamt th{position:static; white-space:nowrap}
/* Regelname UNTER der l/h-Zahl einer Leiste (Nachbesserung 10.10.2026, beide Gegenproben):
   Deckte der Zeitraum das ganze Buch ab, standen fuer DIESELBEN Fluege zwei verschiedene
   l/h-Zahlen untereinander (oben Tank zu Tank, unten Gesamtschnitt) — die Regel stand nur im
   title. Jetzt steht sie sichtbar darunter, wie in der Kennzahl-Kachel. Eigene Zeile trotz
   white-space:nowrap der Leistenzelle, und nicht fett wie die Gesamtleiste. */
tfoot tr.aw-zeitraum th .leiste-regel,tfoot tr.aw-gesamt th .leiste-regel{
  display:block; font-weight:400; line-height:1.25}
/* Grund eines „—“ in der l/h-Spalte einer MONATSZEILE (2.9.7, Betreiber 10.10.2026 „bitte alles
   machen“): Seit die Monatszeile Tank zu Tank rechnet, steht dort haeufiger „—“ (unter zwei
   Betankungen im Monat). Der Grund gehoert sichtbar daneben, nicht nur in den Mauszeiger-Text —
   dieselbe Entscheidung wie fuer die Leisten (.leiste-regel oben).
   NEBEN der Zahl und nicht darunter, und nicht umbrechend: gemessen am Pruefstand AW9021 bei
   375 px (Monatsliste mit acht Monaten, fuenf davon ohne Zahl) — als eigene Zeile wuchsen die
   betroffenen Zeilen von 40 auf 72 px (umgebrochen) bzw. 56 px (nowrap), nebeneinander bleiben
   es 40 px. Breiter wird dabei nur die Tabelle (840 → 890 px), und die rollt in ihrem Rahmen
   ohnehin schon; die SEITE bekommt keinen Ueberlauf (gemessen 0). Bei zwei Dutzend Monatszeilen
   ist das der Unterschied zwischen einer Liste und einer Rolltreppe. Die beiden Leisten behalten
   ihre eigene Zeile (dort sind es zwei Zeilen, nicht vierundzwanzig). */
tbody td .aw-grund{white-space:nowrap; margin-left:.35em}
/* Dieselben zwei Leisten in der Karte „Auswertung“ des persoenlichen Flugbuchs (2.9.6,
   app/module/flugbuch.php, fb_aw_leisten). Die Farben oben gelten unveraendert mit; neu ist
   allein, dass die BESCHRIFTUNGSSPALTE auf schmalen Geraeten umbrechen darf. Grund (gemessen
   bei 375 px): das white-space:nowrap der Zeile gilt fuer JEDE Zelle, also auch fuer
   „GESAMT — ganzes Buch (unabhaengig vom Filter)“ — diese eine lange Zelle schob die Zahlen
   aus dem Bild, und auf dem Telefon stand von der Zeitraumleiste nur noch ihr Name da. Die
   ZAHLENspalten bleiben nowrap (170:00 darf nie brechen). Nur hier, damit die Monatslisten
   von auswertung.php/pilotenauswertung.php unberuehrt bleiben. */
@media (max-width:820px){
  .aw-leisten tfoot tr.aw-zeitraum th:first-child,
  .aw-leisten tfoot tr.aw-gesamt th:first-child{white-space:normal}
}
/* Inspektionsaufträge (app/module/inspektion.php, Betreiber 13.09.2026:
   „Inspektionslisten bearbeiten und auch zum Abhaken haben um ein Workreport
   zu drucken“) — additiv, keine bestehende Regel geändert. Zeile: Haken+Nr |
   Text | Kürzel | Bemerkung/Messwert | Knöpfe; unter 640 px einspaltig. */
.insp-zeile{display:grid; grid-template-columns:auto minmax(0,1fr) 6.5em minmax(8em,15em) auto;
  gap:6px 11px; align-items:start; padding:9px 0; border-bottom:1px solid var(--rand-fein)}
.insp-zeile:last-child{border-bottom:none}
.insp-zeile.erledigt .insp-text{color:var(--text-schwach)}
.insp-zeile.geaendert{box-shadow:inset 3px 0 0 var(--marke-blau); padding-left:9px}
.insp-zeile.konflikt{background:var(--rot-bg); box-shadow:inset 3px 0 0 var(--rot); padding-left:9px}
.insp-zeile.offen-markiert .insp-nr{font-weight:700}
.insp-haken{display:flex; gap:6px; align-items:center; white-space:nowrap; margin:0}
.insp-nr{min-width:1.8em; text-align:right; color:var(--text-schwach)}
.insp-kuerzel{max-width:6em}
.insp-zeile input[type=text],.insp-zeile textarea{width:100%; min-width:0; box-sizing:border-box}
.insp-knopf{display:flex; gap:6px; flex-wrap:wrap}
.insp-zeile-meldung{grid-column:1 / -1; margin:0}
.insp-kopf{display:grid; grid-template-columns:max-content minmax(0,1fr); gap:4px 14px; margin:10px 0 0}
.insp-kopf dt{color:var(--text-schwach); font-size:13.5px}
.insp-kopf dd{margin:0}
.insp-sammel{position:sticky; bottom:0; z-index:5; background:var(--flaeche); padding:9px 0;
  border-top:1px solid var(--rand); margin-bottom:14px}
.insp-sammel.oben{position:static; border-top:none; background:transparent}
.insp-schild-zusatz{margin-top:4px}
.insp-vorlage-raster{display:grid; grid-template-columns:repeat(auto-fit,minmax(170px,1fr)); gap:0 14px}
@media (max-width:640px){
  .insp-zeile{grid-template-columns:auto minmax(0,1fr)}
  .insp-zeile .insp-kuerzel,.insp-zeile .insp-befund,.insp-zeile .insp-knopf{grid-column:2}
}
@media print{.insp-sammel,.insp-knopf{display:none}}

/* Abrechnung Startplatz (2.5.0) — RUNDE 20: Auswahl „Startplatz“ neben „Pilot suchen“ (app/module/abrechnung.php,
   abrechnung_startplatz_auswahl()); Abstand wie die Knöpfe .neben, kein style-Attribut (CSP). */
.fl-sp-wahl{margin-left:10px}
select[data-fl-sp]{max-width:16em}

/* Anhang nachreichen (Teil A, 14.09.2026) — Betreiber-Antwort 17: „‚Anhang hinzufuegen‘ unter jedem Eintrag
   (Waegung, Aenderungsregister, Komponentenakte)“; app/anlagen.php anlage_nachreichen_formular(). Das <details>
   steht in einer Tabellenzelle: engerer Abstand als details.aufklapp (14px), kleine Schrift. Gegenprobe 14.09.2026
   (Browser 264 px): Zelle 125 px, Datei-Feld 101 px, „Datei au…“ und „Hochlade…“ angeschnitten — darum untereinander
   in voller Zellenbreite, knapper Innenabstand, der Knopf darf umbrechen. Nachmessung: bei 79 px Zelleninhalt blieb
   „Datei auswä…“ angeschnitten (der native Knopf braucht rund 95 px) — das offene Formular hält darum 9.5rem; die
   Spalte wird breiter, es scrollt die Tabelle (.tabelle-rolle), nicht die Seite. */
details.aufklapp.anhang-nachreichen{margin-top:4px}
details.aufklapp.anhang-nachreichen > summary{font-size:12.5px; font-weight:600}
details.aufklapp.anhang-nachreichen[open] > summary{margin-bottom:6px}
details.anhang-nachreichen form{display:flex; flex-direction:column; align-items:stretch; gap:6px; min-width:9.5rem; max-width:100%}
details.anhang-nachreichen label{margin:0; font-size:12.5px}
details.anhang-nachreichen input[type=file]{width:100%; max-width:100%; min-width:0; min-height:0; padding:3px; font-size:12px}
details.anhang-nachreichen input[type=file]::file-selector-button{padding:3px 6px; margin-right:4px; font-size:12px}
details.anhang-nachreichen button{margin-top:0; padding:6px 8px; justify-content:center; white-space:normal; font-size:12.5px}

/* Sicherung (2.5.0) — Oberfläche des Sicherungstools v2, Paket P8 U1–U5 (app/module/sicherung.php, public/sicherung.js).
   Betreiber 13.09.2026: „ein besseres Sicherungstool, welches man auch wieder als ZIP einspielen kann …“. Additiv, keine
   bestehende Regel geändert; nur Variablen des Themas (hell und dunkel), kein style-Attribut (CSP). Unter 375 px brechen
   lange Paketnamen und Befehle um, Tabellen scrollen in .tabelle-rolle — die Seite selbst scrollt nie waagerecht. */
[data-sicherung] [hidden]{display:none !important}
.sich-block{display:block; margin-top:3px}
.marke-status.sich-gruen{background:var(--gruen-bg); border-color:var(--gruen-rand); color:var(--gruen)}
.marke-status.sich-rot{background:var(--rot-bg); border-color:var(--rot-rand); color:var(--rot)}
.marke-status.sich-gelb{background:var(--orange-bg); border-color:var(--orange-rand); color:var(--orange)}
.marke-status.sich-grau{background:var(--grau-bg); border-color:var(--rand); color:var(--text-schwach)}
.sich-form{display:inline-flex; flex-wrap:wrap; gap:6px; align-items:center; margin:0; min-width:0; max-width:100%}
.sich-aktionen{gap:6px}
.sich-loeschen > summary{list-style:none; cursor:pointer}
.sich-loeschen > summary::-webkit-details-marker{display:none}
.sich-loeschen[open]{flex-basis:100%}
.sich-loeschen form input[type=text]{width:9em; min-width:0}
.sich-tabelle .mono,.sich-assistent .mono,.sich-tabelle td{overflow-wrap:anywhere}
.sich-befehl{white-space:pre-wrap; overflow-wrap:anywhere; font-family:"Cascadia Mono",Consolas,monospace; font-size:12.5px;
  background:var(--grau-bg); color:var(--text); border:1px solid var(--rand); border-radius:8px; padding:8px 10px; margin:6px 0; max-width:100%}
.sich-meldung{margin:8px 0; font-size:13.5px}
.sich-meldung-fehler{color:var(--rot-text); font-weight:600}
.sich-schritte{margin:8px 0 10px; padding-left:22px}
.sich-schritte li{margin:5px 0}
.sich-schritte li[data-zustand=offen] .sich-schritt-titel{color:var(--text-schwach)}
.sich-schritte li[data-zustand=laeuft] .sich-schritt-titel{font-weight:700}
.sich-schritte li[data-zustand=fertig] .sich-schritt-titel,.sich-schritte li[data-zustand=uebersprungen] .sich-schritt-titel{color:var(--gruen-text)}
.sich-schritte li[data-zustand=fehler] .sich-schritt-titel,.sich-schritte li[data-zustand=abgewiesen] .sich-schritt-titel,
.sich-schritte li[data-zustand=angehalten] .sich-schritt-titel{color:var(--rot-text); font-weight:700}
.sich-abschnitt{margin:12px 0; border-top:1px solid var(--rand-fein); padding-top:8px}
.sich-abschnitt > summary{cursor:pointer; padding:4px 0}
.sich-vorschau,.sich-ablauf,.sich-abschluss{margin-top:14px; border-top:1px solid var(--rand); padding-top:10px}
.sich-felder{display:grid; grid-template-columns:repeat(auto-fit,minmax(200px,1fr)); gap:0 16px}
.sich-felder input{width:100%; box-sizing:border-box}
.sich-haken{display:flex; gap:8px; align-items:flex-start; font-weight:400}
.sich-haken input{flex:none; margin-top:3px}
.sich-upload progress:not([hidden]){display:block; width:100%; max-width:420px; margin:6px 0}
.sich-upload input[type=file]{max-width:100%; min-width:0}
.sich-art select{max-width:100%}
.sich-ereignisse{margin:4px 0 10px; padding-left:18px; font-size:12.5px; color:var(--text-schwach)}
.sich-wartung{border-color:var(--orange-rand)}
/* „Tabellen im Einzelnen“: Tabellenname am Stück, Regel mit Mindestbreite — die Tabelle scrollt in .tabelle-rolle (375 px brach „zusatzpositionen“ Buchstabe für Buchstabe). */
.sich-assistent td.sich-tab-name{overflow-wrap:normal; white-space:nowrap}
.sich-assistent td.sich-tab-regel{min-width:16em}
/* Antwort 27 (Betreiber 15.09.2026 „Mit Knopf zur Sicherung“): von ?p=versionen vorgewähltes Paket — Zeile markiert, Kasten darüber. */
.sich-tabelle tr.sich-markiert > td{background:var(--orange-bg)}
.sich-tabelle tr.sich-markiert > td:first-child{box-shadow:inset 4px 0 0 var(--orange-rand)}
.sich-vorwahl{scroll-margin-top:12px}
/* Gegenprobe nach SI9 (15.09.2026): Rote Pakete statt Knopf mit Satz; Versionen-Liste mit Knopf zur Vorab-Sicherung unter dem Zeitpunkt
   (375 px: rechter Rand des Knopfs vorher 548 px in der Aktionsspalte). */
.sich-nicht-einspielbar{color:var(--rot-text); flex-basis:100%}
.versionen-vorab{display:flex; flex-wrap:wrap; gap:4px 6px; align-items:center; margin-top:4px}
.versionen-vorab .knopf{white-space:normal}
@media (max-width:640px){
  .sich-form{width:100%}
  .sich-tabelle td{min-width:7em}
}

/* Abrechnung kompakt (2.5.0) — Flugliste #fl-tabelle: Gesamtansicht „Alle Luftfahrzeuge“ und Einzelansicht je Luftfahrzeug,
   Reiter offen und abgerechnet (app/module/abrechnung.php). Betreiber 14.09.2026: „Tabelle kompakter — Status und Bemerkung
   werden schmaler, Rechnungsnummer und Notiz stehen untereinander. Bei 1280 Pixeln ist die ganze Zeile samt Haken sichtbar, die
   Zeilen werden etwas hoeher. Die Einzelansicht wird angeglichen“. WARUM: gemessen vorher im Browser bei 1280 px (Tabellenrahmen
   clientWidth 1173 px): Gesamtansicht scrollWidth 1498 px (325 px, Spalte Status mit Haken rechts ausserhalb), Einzelansicht 1331 px
   (157 px), Gesamtansicht mit Suche und Startplatz im Summentitel 1706 px. Ursachen: th und td.rechts mit white-space:nowrap (das
   Ersatzwert-Schild „Blockzeit — Altbestand ohne Flugzeit“ machte die Zeitspalte 361 px breit, der Summentitel die ersten Spalten),
   Landegebuehr-Feld und Knopf nebeneinander (186 px), .status-zelle min-width:13em (176 px), Bemerkung ohne Obergrenze.
   Rechnungsnummer und Notiz stehen schon untereinander (.status-form, flex-direction:column) und bleiben so. Nur Darstellung: kein
   Feldname, kein Formular, keine Zahl; nur @media screen (Druck unveraendert); nur #fl-tabelle (Selbstauskunft, Zusatzposten und alle
   anderen Tabellen unberuehrt). Die bestehenden Regeln .status-zelle, .geb-form, .rechts und th bleiben stehen und werden allein
   innerhalb #fl-tabelle ueberschrieben. Mobil scrollt die Tabelle weiter in .tabelle-rolle. */
@media screen{
  #fl-tabelle th,#fl-tabelle td{padding-left:8px; padding-right:8px}
  #fl-tabelle th{white-space:normal}
  #fl-tabelle td.rechts .schild{display:block; width:max-content; max-width:7em; margin:3px 0 0 auto;
    white-space:normal; text-align:left}
  #fl-tabelle .geb-form{flex-wrap:wrap}
  #fl-tabelle .geb-form button{padding:6px 10px}
  /* Gegenprobe 14.09.2026: ein unteilbares Wort in der Bemerkung („Donaudampfschifffahrts…flugueberpruefung“, 69 Zeichen, 438 px)
     machte die Gesamtansicht abgerechnet bei 1280 px wieder 1174/1356 breit (Bemerkung 454 px, 21 von 21 Haken ausserhalb, bis
     -67 px). overflow-wrap:anywhere bricht so ein Wort innerhalb der Bemerkungszelle; Woerter mit Leerzeichen brechen wie bisher. */
  /* Gegenprobe 15.09.2026 (Zeilenhoehe): eine Bemerkung mit der erlaubten Hoechstlaenge 300 Zeichen machte die Zeile bei 1280 px
     437 px hoch (Bemerkung auf 176 px begrenzt, HEAD 165/197 px). Die Bemerkung darf jetzt bis 24em breit werden; den Platz gibt die
     Zeitspalte frei: das Ersatzwert-Schild hoechstens 7em statt 10em (oben) und Zeit/Summe duerfen zwischen „33 min“, „(0:33)“ und
     „Blockzeit“ umbrechen (Zahl mit Einheit bleibt am Stueck). Gemessen 1280 px Gesamt abgerechnet: Zeitspalte 150 -> 102 px,
     Bemerkung 176 -> 230 px, hoechste Zeile 437 -> 291 px, Tabelle 1174/1174. Mobil (375 px, Tabelle scrollt in .tabelle-rolle) fiel
     die Bemerkung mit overflow-wrap:anywhere auf 81 px (Zeile 981 px hoch); min-width:14em haelt sie bei 189 px (Zeile 312 px), bei
     1280 px ohne Wirkung (Bemerkung 230 px). */
  #fl-tabelle tbody td.klein{width:24em; min-width:14em; overflow-wrap:anywhere}
  #fl-tabelle td.rechts{white-space:normal}
  #fl-tabelle td.rechts .klein,#fl-tabelle td.rechts strong{white-space:nowrap}
  /* Gegenprobe 15.09.2026 (Rechnungsnummer): ab 20 Zeichen war die Nummer im Feld abgeschnitten („12345678901234567890“ braucht
     168 px, Feld 153 px; HEAD ebenso bei 152 px). Die Status-Zelle mindestens 16em, die Formular-Obergrenze 14em faellt in der
     Flugliste weg und die Felder haben 6 px statt 11 px Innenabstand links/rechts. Gemessen 1280 px: Feld 154 -> 200 px, Nummern bis
     25 Zeichen vollstaendig sichtbar (vorher bis 11), Haken 189 px vor dem rechten Rand, Tabelle 1174/1174. */
  #fl-tabelle .status-zelle{min-width:16em}
  #fl-tabelle .status-form{max-width:none}
  #fl-tabelle .status-form input[type="text"]{padding-left:6px; padding-right:6px}
  /* Flugkennung f-NNNNNN am Stueck: im ersten Nachbau brach sie am Bindestrich („f-“ / „000004“, Bildschirmfoto 1280 px);
     umbrechen darf nur zwischen Datum und Kennung. */
  #fl-tabelle tbody td:first-child .klein{white-space:nowrap}
  /* Gegenprobe 15.09.2026 (Pilot): ein Pilotname ohne Leerzeichen (80 Zeichen, Feld erlaubt 120; schon ab 19 Zeichen wie
     „m.mustermann@web.de“) machte die Flugliste bei 1280 px bis 1174/1763 breit (Pilot 731 px, 33 von 33 Haken ausserhalb; HEAD
     1174/4654). Die Pilot-Spalte bricht jetzt wie die Bemerkung (overflow-wrap:anywhere); min-width haelt normale Namen am Stueck.
     Pilot ist td 3 in der Gesamtansicht (Zeilen mit data-lfz) und td 2 in der Einzelansicht. Gemessen Gesamt offen mit 60- und
     80-Zeichen-Namen, 1280 px / 1024 px, Teilwoerter (zwischen Leerzeichen/Bindestrich) mitten im Wort gebrochen: ohne min-width
     1174/1174 aber 93 gebrochen (Pilot 42 px); 7em 6 („Luedenscheidt“); 8em 0 und 1174/1174 (Pilot 108 px); 9em 0, aber 1174/1175. */
  #fl-tabelle tbody tr[data-lfz] > td:nth-child(3),
  #fl-tabelle tbody tr[data-flug]:not([data-lfz]) > td:nth-child(2){min-width:8em; overflow-wrap:anywhere}
  /* Volle Rechnungsnummer unter dem Feld (data-fl-rn-voll, nur wenn sie nicht hineinpasst): bricht in der Zelle um. */
  #fl-tabelle [data-fl-rn-voll]{overflow-wrap:anywhere; line-height:1.25}
}
/* Druck unveraendert: die Zeile mit der vollen Rechnungsnummer gibt es nur am Bildschirm. */
@media print{
  #fl-tabelle [data-fl-rn-voll]{display:none}
}
/* =========================================================================
   MITLAUFENDE KOPFZEILE der Bücherlisten — Bordbuch und Flugbuch
   (Betreiber 23.09.2026: „wenn ich nach unten scrolle soll die
   beschreibungszeile mit nach unten rutschen, dass ich sie immer lesen
   kann“). Greift an den Haken, die bordbuch.php und flugbuch.php setzen:
   <div class="tabelle-rolle kopf-mitlaufend"> · <table class="kopf-mitlaufend">
   · <thead class="kopf-mitlaufend">.

   🔴 NEUFASSUNG 29.09.2026 — DIE WEICHE BEI 1281 px IST WEG.
   Der Betreiber hat die Einschränkung vom 23.09. („Am Rechner mitlaufend,
   am Handy nicht“) aufgehoben, wörtlich:
       „In der Darstellung funktioniert leider noch nicht, dass die im
        Bordbuch und Logbuch die Zeile oben mit nach unten geht wenn ich in
        der Übersicht scrolle. wenn ich in der mitte der Tabelle bin, muss
        ich auch sehen können was was für eine zeit ist“
   Auf die Rückfrage nach seiner Fensterbreite: „Weiß ich nicht“. Die
   Kopfzeile läuft deshalb bei JEDER Breite mit — es gibt hier keine
   Breitenweiche mehr, nur noch EINE Bauweise für alle Geräte.

   WIE: die Liste bekommt einen EIGENEN Rollrahmen MIT HÖHE, und die
   Kopfzeile klebt an diesem Rahmen (top:0) statt am Fenster.

   WARUM DIE FENSTERLÖSUNG WEICHT (sie stand hier bis zum 29.09.2026):
   Damit die Kopfzeile am FENSTER kleben konnte, durfte die Liste keinen
   eigenen Rollbereich haben — overflow rechnet der Browser neben einem
   auto auf der anderen Achse selbst auf auto um (nachgemessen 23.09.2026
   bei 1280x900: overflowX „auto“, overflowY „auto“), und eine klebende
   Kopfzeile hängt dann am Rahmen statt am Fenster. Der Rahmen mußte deshalb
   auf Tabellenbreite mitwachsen (width:fit-content, max-width:none), und im
   Bordbuch die Karte darum ebenso. Das hatte zwei Folgen:
     · die LISTE war breiter als der Schirm und das seitliche Schieben
       besorgte die SEITE statt des Rahmens;
     · unterhalb 1281 px klebte die Kopfzeile ohnehin nicht (thead th
       position:static) — genau der Zustand, den der Betreiber beanstandet.
   Der Rollrahmen mit Höhe räumt beides auf einmal ab: die Kopfzeile läuft
   überall mit, und seitlich schiebt nur noch die TABELLE in ihrem Rahmen
   (window.scrollX bleibt 0).

   WAS DAFÜR IN KAUF GENOMMEN IST — ehrlich benannt: neben dem Rahmen rollt
   auch die SEITE. Rollt man die Seite weit genug, wandert der Rahmen samt
   Kopfzeile nach oben aus dem Bild, während Datenzeilen stehenbleiben.
   Das ist der alte, richtig gemessene Einwand vom 23.09.2026. Er ist seit
   01.10.2026 ABGERÄUMT — vom Halter unten (Variante (C)), der im HTML beider
   Module steht; der Satz „mit CSS allein nicht abzuräumen“ stand hier bis
   dahin und war zu pessimistisch. Wie weit er ohne Halter trug und was ihn
   wirklich schließt, steht unten — gemessen, nicht geschätzt.

   🔴 KEINE BESCHÖNIGUNG — hier stand bis zur Gegenprobe vom 29.09.2026, der
   Einwand sei „gedämpft, die Seite hat über der Liste nur wenig Weg“. DAS
   IST FALSCH, und zwar meßbar: UNTER der Liste stehen Auswertung, Übertrag
   und Fuß, gemessen 1075–2217 px (Prüfbestand 80 Zeilen je Buch,
   30.09.2026). Die Seite kann also weit über die ausgerichtete Stellung
   hinaus rollen.

   🔴 WIE WEIT DER EINWAND TRÄGT — 30.09.2026 neu gemessen, eigener Chrome
   über CDP, Seite in 10-px-Schritten über den GANZEN Rollweg UND ZURÜCK, je
   Stelle mit document.elementFromPoint geprüft, ob die Beschriftungszeile
   wirklich im Bild steht (unterhalb des Seitenkopfs, Mitte getroffen) und
   wieviele Datenzeilen wirklich sichtbar sind. Rollweg, auf dem Datenzeilen
   OHNE Beschriftungszeile stehen (》das Fenster《), und die schlimmste
   Zeilenzahl. ALLE Zahlen dieses Blocks stammen aus demselben Prüfbestand
   (80 erzeugte Zeilen je Buch in einer Arbeitskopie); mit einem längeren Buch
   wird das Fenster eher größer, nicht kleiner — bei 93 bzw. 98 Zeilen maß
   dieselbe Probe 660 px / 9 Zeilen statt 640 / 7. Die Zahl 0 unter (C) blieb
   in BEIDEN Beständen 0:
       390x844   Bordbuch 640 px / 7 Zeilen   Flugbuch 650 px / 5 Zeilen
       844x390   Bordbuch 230 px / 2          Flugbuch  20 px / 1
       390x420   Bordbuch 230 px / 2          Flugbuch  20 px / 1
       360x780   Bordbuch 550 px / 6          Flugbuch 530 px / 4
       768x1024  Bordbuch 790 px / 9          Flugbuch 650 px / 5
       1024x768  Bordbuch 470 px / 5          Flugbuch 430 px / 3
       1280x800  Bordbuch 530 px / 6          Flugbuch 530 px / 4
       1440x900  Bordbuch 700 px / 8          Flugbuch 650 px / 5
       900x240   Bordbuch  20 px / 1          Flugbuch   0 px / 0
   Das Fenster ist also rund so lang wie der Rahmen hoch ist: sobald seine
   Oberkante über den Schirm hinaus ist, sind die Beschriftungen weg, und
   es dauert eine Rahmenhöhe, bis auch die letzte Datenzeile weg ist.
   (Bei 900x240 ist es fast null, weil dort die Mindesthöhe den Rahmen auf
   232 px drückt und der Seitenkopf mitrollt.)

   🔴 DREI WEGE AUSPROBIERT UND GEMESSEN (30.09.2026, beide Bücher, eigener
   Chrome, dieselbe Meßart wie oben). Die Zahl in Klammern ist das Fenster
   nach der Änderung, gegen den Bestand darüber:

   (A) NUR position:sticky AM RAHMEN, top:var(--kopf-platz).
       Flugbuch  390x844 650→70 px · 844x390 20→20 · 1440x900 650→150
       Bordbuch  390x844 640→630   · 844x390 230→230 · 1440x900 700→700
       PREIS: der klebende Rahmen ist deckend und liegt ÜBER allem, was
       folgt. Von der Karte 》Auswertung — ganzes Buch《 (679 px) waren dann
       höchstens 122 px lesbar, 844x390 66 px, 1440x900 18 px, 900x240
       10 px. Die Auswertung war auf dem Telefon nicht mehr lesbar.
       Im BORDBUCH bringt A ohnehin fast nichts: dort hängt die Liste in
       einer Karte (main.inhalt > div.karte > div.tabelle-rolle), und ein
       klebender Kasten darf nur innerhalb seines ELTERNKASTENS wandern —
       der Klebeweg ist genau, was unter der Liste NOCH IN DER KARTE steht
       (gemessen 113–360 px). Im Flugbuch hängt sie direkt in main.inhalt,
       dort sind es 1031–2217 px.

   (B) A UND ZUSÄTZLICH: WAS FOLGT, MALT ÜBER DEM RAHMEN
       (.tabelle-rolle.kopf-mitlaufend ~ *{position:relative; z-index:1}).
       Dann schiebt sich die Auswertung beim Weiterrollen von unten über den
       Rahmen — die Auswertung bleibt GANZ lesbar (679/507/784 px, wie ohne
       sticky).
       Flugbuch  390x844 650→250 px · 844x390 20→40 · 1440x900 650→50
       Bordbuch  390x844 640→300   · 844x390 230→20 · 1440x900 700→620
       PREIS, UND DESHALB NICHT EINGEBAUT: zwischen den Karten stehen 18 px
       Luft, und die ist durchsichtig. Durch diese Spalten schaut der
       klebende Rahmen hindurch — genau das ist der Rest, den die Messung
       oben noch als Fenster zählt (Datenzeile im 18-px-Spalt sichtbar,
       Beschriftungszeile längst verdeckt). Im Bordbuch bleibt zusätzlich
       der kurze Klebeweg: 640→300 px ist eine Verbesserung, aber KEINE
       Lösung.

   (C) DER WEG, DER ES WIRKLICH SCHLIESST — ein HALTER um den Rollrahmen.
       Der Halter bringt den Klebeweg als eigenen INHALT mit (::after,
       100dvh hoch), zieht das Folgende mit margin-bottom:-100dvh wieder an
       seinen Platz und BESCHNEIDET sich selbst auf die ursprüngliche Höhe
       (clip-path). Damit klebt der Rahmen oben fest und SCHRUMPFT beim
       Weiterrollen von unten — Oberkante bleibt, Unterkante weicht dem
       Nachfolgenden. Nichts wird verdeckt, weil der Rahmen dort gar nicht
       mehr gemalt wird.
       GEMESSEN an ALLEN NEUN MASSEN, in BEIDEN Büchern, hin und zurück:
           Fenster 0 px / 0 Zeilen — überall.
           Auswertung, Übertrag und Fuß genau so lesbar wie im Bestand
           (identische Werte, z. B. 390x844 Flugbuch 679/507/784 px).
           Seitenlänge unverändert — identisch in allen 18 Läufen
           (z. B. 3039/3714/2226/2616/3095/3770 px).
       🔴 SEIT 01.10.2026 GREIFT ER — DER KASTEN STEHT IM HTML. Hier stand
       bis dahin, (C) liege still, weil der Halter ein Kasten UM den
       Rollrahmen ist und das HTML der beiden Module ihn nicht setzte.
       bordbuch.php und flugbuch.php geben jetzt
       <div class="listen-halter"> unmittelbar um
       <div class="tabelle-rolle kopf-mitlaufend"> aus — ein Kasten, sonst
       nichts; an Abfragen, Spalten und Formularen ist dabei nichts angefaßt.
       NACHGEMESSEN im Endstand (01.10.2026, alle NEUN Maße, BEIDE Bücher,
       10-px-Schritte hin UND zurück, dazu Bild-ab/Bild-auf):
           Fenster 0 px / 0 Zeilen an jedem Maß, in beide Richtungen;
           Auswertung/Übertrag genau wie im Bestand (390x844 Flugbuch
           679/679 px, Bordbuch Übertrag 368/368);
           sichtbare Datenzeilen unverändert (z. B. 390x844 Bordbuch 8,
           900x240 Bordbuch 2, 390x420 Flugbuch 1 — mit Halter wie ohne);
           Seitenlänge unverändert, wo --kopf-platz gleich blieb
           (390x844 3919/4456 px, 844x390 2663/2912, 390x420 3551/4088);
           waagerecht schiebt nur die Tabelle (Seite 390/390 … 1440/1440);
           Druck: Textauszug echter PDFs aus Page.printToPDF ist mit und
           ohne Halter ZEICHENGLEICH, bei gleicher Seitenzahl (Bordbuch
           hoch 8 / quer 10, Flugbuch hoch 16 / quer 13).
       DER PREIS, DER BLEIBT: ab 1281 px war --kopf-platz zu klein (Band 112,
       Kopf 149) — dazu der 🔴-Block bei den Bändern weiter unten.

   🔴 WARUM position:sticky AM RAHMEN OHNE DEN HALTER HIER NICHT STEHT —
   außer (A) und (B) oben noch ein dritter Grund, gemessen: am 1024-px-Band
   ist --kopf-platz 152 px, der Seitenkopf maß dort 162 px; die geklebte
   Beschriftungszeile läge also 9 px hinter ihm. Die Kopfhöhe hängt am
   Inhalt (Kontoname, Reiter, Schriftgröße) und ist nicht sicher
   vorherzusagen. Mit dem Halter fällt das nicht auf, weil die Zeile dort
   nur dann oben klebt, wenn der Rahmen noch Zeilen zeigt; ohne ihn wäre es
   ein Dauerzustand.

   🔴 WAS CSS HIER HEUTE TUT, ist das Erreichbare: der Rahmen paßt an jedem
   geprüften Maß ganz ins Fenster (außer 900x240, wo die Mindesthöhe
   vorgeht), beim Rollen IM Rahmen läuft die Beschriftungszeile immer mit —
   und das ist der Fall, den der Betreiber beschrieben hat —, und unter ihm
   bleibt genug Seite frei, um am Rahmen VORBEI zu rollen; siehe
   --listen-luft weiter unten. 🔴 DER REST DES EINWANDS IST SEIT 01.10.2026
   ERLEDIGT, nicht mehr offen: der Halter unten steht im HTML beider Module
   und drückt das Fenster an allen neun Maßen auf 0 px / 0 Zeilen. Was dafür
   noch nötig war — die wirkliche Kopfhöhe statt der geratenen Bänder und
   kein Tastaturfokus auf dem abgeschnittenen Teil — steht bei den Bändern
   und in public/listenkopf.js.

   🔴 DIE MINDESTHÖHE IST DER KERN, an dem der erste Anlauf gescheitert war.
   Damals stand nur max-height:calc(100vh - Seitenkopf). Bei niedrigen
   Fenstern rechnet das gegen null: bei 900x240 ist der Seitenkopf allein
   189 px hoch (sticky, nachgemessen 29.09.2026 in 2.8.0), 240 − 189 − 16 =
   35 px — der Rahmen war praktisch zu, keine einzige Datenzeile stand im
   Bild. Deshalb steht die Höhe hier als
       max( --listen-mindesthoehe , Fensterrechnung )
   und kann nie unter die Mindesthöhe fallen.
   WARUM NICHT min-height: die bläht auch eine Liste mit zwei Zeilen auf
   volle Mindesthöhe auf (leerer Kasten unter der letzten Zeile). Als
   Untergrenze IM max-height wirkt der Wert nur dort, wo die Fensterrechnung
   zu klein wird; kurze Listen bleiben kurz, weil die Höhe eines Kastens
   ohnehin dem Inhalt folgt, solange max-height nicht greift.

   WIE GROSS DIE MINDESTHÖHE IST — gemessen, nicht geschätzt (29.09.2026):
       Kopfzeile (thead)          38 px   in BEIDEN Büchern, 390 und 1440 px
       Datenzeile Flugbuch        82 px (1440) / 90 px (390)
       Datenzeile Bordbuch        82 px, mit langer Bemerkung 124 px
   320 px tragen also die Kopfzeile plus drei gewöhnliche Datenzeilen
   (38 + 3×90 = 308) bzw. plus zwei der höchsten Bordbuchzeilen
   (38 + 2×124 = 286, die dritte angeschnitten). Das ist „Kopfzeile plus
   mehrere Datenzeilen“ und paßt zugleich noch in ein 390 px breites
   Telefon, ohne die Seite zu sprengen.

   dvh STATT vh — Absicht. 100vh ist auf iOS die Höhe OHNE die Bedienleisten
   des Browsers; 100dvh ist die gerade wirklich sichtbare. Die vh-Zeile
   steht zuerst als Rückfall für Browser ohne dvh (vor Safari 15.4), die
   dvh-Zeile überschreibt sie überall sonst. Dieselbe Umstellung steht beim
   Popup „+ Neuer Flug eintragen“ (Z999 ff.) — dort war 100vh die Ursache
   dafür, daß der Bestätigungsknopf auf dem iPhone hochkant nicht anklickbar
   war (Befund des Betreibers vom 29.09.2026).

   HÖHE DES SEITENKOPFS — GEMESSEN, NICHT GESCHÄTZT (29.09.2026 in 2.8.0,
   Flugbuch, Konto agent71 mit allen Reitern; .kopf klebt bei top:0, Z65):
       1440/1280 px           → .kopf  99 px  sticky
       1024/981 px            → .kopf 148 px  sticky
       900/821 px             → .kopf 189 px  sticky
       768 px                 → .kopf 167 px  STATIC
       390/360 px             → .kopf 302 px  STATIC (Reiterzeile bricht um)
   Ab 820 px abwärts rollt der Seitenkopf mit (Z342), dort muß oben nichts
   frei bleiben.
   --kopf-platz steht jeweils ein paar Pixel ÜBER dem gemessenen Höchstwert
   des Bandes. Diese Richtung ist die gutmütige: ist der Wert zu groß, bleibt
   der Rahmen ein wenig niedriger als nötig — sichtbar bleibt alles. Wäre er
   zu klein, ragte der Rahmen unter das Fenster.
   WARUM DIE BÄNDER NICHT GENAUER SITZEN (nachgemessen 23.09.2026, am
   29.09.2026 unverändert): der Sprung von 148 auf 99 px liegt zwischen 1240
   und 1270 px Fensterbreite und wird von KEINER Medienabfrage ausgelöst —
   der Kopf bricht dort inhaltsabhängig um (Kontoname, Gruppen- und
   Luftfahrzeugwahl, Suchfeld, Zahl der Reiter). Die Kante wandert also mit
   Konto und Schriftgröße; deshalb bleibt es bei 1281 px.
   ========================================================================= */

/* --kopf-platz steht am DOKUMENT, nicht an der Liste — zwei Regeln brauchen
   denselben Wert, und zwei Zahlen, die auseinanderlaufen können, sind eine
   Fehlerquelle:
     · die Rahmenhöhe der Liste (100dvh minus diesem Platz),
     · scroll-padding-top des Dokuments, direkt hier darunter.
   🔴 WOFÜR scroll-padding-top AM DOKUMENT (Gegenprobe 29.09.2026, ein
   Altbefund, kein neuer): holt der Browser ein Element von oben ins Bild —
   beim Durchtabben eines Formulars, über einen Anker, über einen
   Bildschirmleser —, dann setzt er es an die OBERKANTE des Fensters. Genau
   dort klebt der Seitenkopf. Gemessen ohne diese Zeile:
       1440x900 LFZ neu   Feld 》Mandant《 bei y 11 → elementFromPoint
                          IMG.marke-logo (Seitenkopf), nicht das Feld
       1024x768 LFZ neu   Kennzeichen/Serial y 58 → DIV.kopf-innen
       1440x900 Bordbuch  Filterfelder 》Von《/》Bis《 y 0 → IMG.marke-logo
                          bzw. BUTTON.umschalter-knopf
   scroll-padding-top hält diesen Streifen beim Rollen frei. Es rührt NICHTS
   an der Darstellung — kein Kasten wird größer, nichts verschiebt sich; es
   wirkt ausschließlich, wenn der Browser von sich aus rollt. Deshalb ist es
   an dieser Stelle die gutmütigste Abhilfe, die es gibt.
   Die Liste braucht daneben KEIN eigenes scroll-margin-top mehr: beides
   addierte sich sonst, und die Liste stünde eine Kopfhöhe zu tief. */
html{
  --kopf-platz:200px;                       /* Band 821–980 px: gemessen 190 */
  scroll-padding-top:var(--kopf-platz);
}
/* 🔴 30.09.2026, ZWEITE GEGENPROBE: DIE BÄNDER HATTEN ZU WENIG LUFT.
   Die Gegenprobe hat den Seitenkopf bei 1024 px mit 162 px gemessen — bei
   --kopf-platz 152 läge die Liste dann 10 px hinter ihm. Hier nachgemessen
   (Konto agent99, beide Bücher, Breiten 821/860/900/960/980/981/1000/1024/
   1100/1180/1240/1270/1280/1281/1320/1440 px):
       821–900 px   Kopf 190 px      981–1180 px  Kopf 149 px
       960–980 px   Kopf 141 px     1240–1440 px  Kopf 100 px
   Mit DIESEM Konto trägt 152 also (149+3). Die 162 der Gegenprobe konnte ich
   nicht nachstellen — geblieben ist aber ihr Kern: die Kante hängt am INHALT
   des Kopfes (Kontoname, Zahl der Reiter, Schriftgröße) und wandert mit ihm.
   Deshalb hat jedes Band jetzt zweistellige Luft statt 2–4 px:
       Band 821–980   192 → 200 px  (gemessen 190)
       Band 981–1280  152 → 168 px  (gemessen 149, Gegenprobe 162)
       Band ab 1281   104 → 112 px  (gemessen 100)
   PREIS, gemessen: der Rollrahmen wird um denselben Betrag niedriger —
   bei 1024x768 von 732 auf 716 px, also weniger als ein Fünftel einer
   Datenzeile (82–90 px). Die Richtung ist die gutmütige: ein etwas zu
   niedriger Rahmen zeigt eine Zeile weniger, ein zu hoher schöbe seine
   letzten Zeilen unter den Fensterrand.
   WAS DAMIT NICHT BEHOBEN IST — und das steht hier statt einer Beschwichtigung:
   zwischen 1240 und 1280 px ist der Kopf schon 100 px hoch, --kopf-platz aber
   168; dort bleiben 68 px ungenutzt. Die Kante des Kopfumbruchs liegt
   inhaltsabhängig zwischen 1180 und 1240 px und wird von KEINER Medienabfrage
   ausgelöst; würde die Weiche dorthin gezogen, wäre sie für ein Konto mit mehr
   Reitern falsch. CSS kann die Höhe eines Kastens nicht lesen. */
.tabelle-rolle.kopf-mitlaufend{
  --listen-luft:16px;                       /* Luft unter der Liste          */
  --listen-mindesthoehe:320px;              /* Begründung oben               */

  /* RASTER STATT BLOCK — einziger Zweck: der Schattenkante unten eine volle
     Höhe und einen Halt über die GANZE Rollbreite geben. Ein ::after im
     Block-Rahmen bekäme beides nicht (height:100% findet keine feste Höhe,
     und ein Kasten im Block-Fluß hört dort auf, wo die Tabelle endet). Als
     Rasterfeld erbt es die Zeilenhöhe (align-self:stretch) und die volle
     Spaltenbreite.
     minmax(min-content,1fr) ist die Spalte, die den BESTAND nachbaut:
      · min-content = die Breite, die die Tabelle wirklich braucht;
      · 1fr zieht die Spalte auf Rahmenbreite auf, wenn die Tabelle SCHMALER
        ist — das ist der Dienst, den die Tabellenregel min-width:100% tut.
     max-content wäre hier FALSCH und ist ausprobiert: es hieße „nichts
     umbrechen“ und blies die Bordbuchtabelle von 1351 auf 2108 px auf. */
  display:grid;
  grid-template-columns:minmax(min-content,1fr);

  /* Der Rahmen ist ein Rollbereich in BEIDEN Richtungen: waagerecht schiebt
     die Tabelle in ihm (die Seite bleibt heil), senkrecht rollt die Liste,
     und genau daran klebt die Kopfzeile unten. */
  overflow:auto;
  /* Der Rahmen wächst NICHT auf Tabellenbreite mit — das war die Ursache
     dafür, daß die Liste breiter als der Schirm wurde. */
  width:auto; min-width:0; max-width:100%;

  /* 🔴 HIER STEHT ABSICHTLICH KEIN position:sticky AM RAHMEN — ausprobiert,
     gemessen und wieder ausgebaut (29.09.2026, am 30.09.2026 neu vermessen).
     Warum, steht mit allen Meßwerten im Block darüber unter (A) und (B): ohne
     Halter klebt der Rahmen im Bordbuch nur 113–360 px weit (Karte als
     Elternkasten) und verdeckt im Flugbuch die Auswertung (679 px hoch,
     höchstens 122 px davon je frei). Geklebt wird er nur MIT dem Halter,
     weiter unten unter .listen-halter — der steht seit 01.10.2026 im HTML
     beider Module. Ohne diesen Elternkasten bleibt der Rahmen ein
     gewöhnlicher Kasten im Seitenfluß, und genau das ist hier Absicht. */

  /* Rückfall für Browser ohne dvh; die Zeile darunter gewinnt sonst.
     🔴 DIE MINDESTHÖHE IST AUF DAS FENSTER GEDECKELT (min(…)): sonst wäre
     der Rahmen HÖHER als das Fenster — bei 900x240 stünden 320 px Rahmen in
     240 px Fenster, und man müßte die Seite weiterrollen, um seine letzten
     80 px und damit die untersten Zeilen zu sehen. Mit dem Deckel bleibt die
     Mindesthöhe dort 8 px unter der Fensterhöhe, der ganze Rahmen steht auf
     einmal im Bild. Bei allen anderen geprüften Maßen ändert der Deckel
     NICHTS (die Fensterrechnung ist dort ohnehin größer): gemessen
     29.09.2026 unverändert 326 px bei 844x390, 356 px bei 390x420,
     724 px bei 390x844. */
  max-height:max(min(var(--listen-mindesthoehe), calc(100vh - 8px)),
                 calc(100vh - var(--kopf-platz) - var(--listen-luft)));
  max-height:max(min(var(--listen-mindesthoehe), calc(100dvh - 8px)),
                 calc(100dvh - var(--kopf-platz) - var(--listen-luft)));
  /* Springt die Seite an einen Anker, landet die Liste UNTER dem klebenden
     Seitenkopf — das besorgt jetzt html{scroll-padding-top} oben; ein
     eigenes scroll-margin-top stünde daneben und addierte sich dazu. */
  /* 🔴 29.09.2026, Gegenprobe: DIE EIGENE KOPFZEILE VERDECKT SONST, WAS DER
     RAHMEN VON OBEN INS BILD ROLLT. Wer mit Umschalt+Tab nach OBEN aus dem
     Bild heraus wandert, bekommt den Fokus auf einen Knopf, den der Rahmen
     exakt unter die klebende Beschriftungszeile rollt — gemessen bei 390x844
     mit echtem Umschalt+Tab: aktives Element A 》Bearbeiten《 bei y 1–39,
     document.elementFromPoint dort TH. 40 px = Kopfzeile 38 px plus Luft.
     Rechts dieselbe Überlegung für die Schattenkante (26 px): ein Knopf, den
     das Querrollen an den rechten Rand holt, läge sonst unter dem Verlauf.
     Beides wirkt NUR auf das Rollen, nicht auf die Darstellung. */
  scroll-padding-top:40px;
  scroll-padding-right:28px;
  /* Hell: dunkler Schleier; dunkel: derselbe Gedanke, nur kräftiger — auf
     #1c232b trüge ein 24-Prozent-Schleier nicht. Gehört zur Kante unten. */
  --rollkante:rgba(16,24,40,.24);
}
/* Die Grundregel table{width:100%} (Z152) trägt hier nichts zur
   inhaltsabhängigen Breite bei. Mit width:auto rechnet die Tabelle ihre
   eigene Mindestbreite aus, min-width:100% hält sie mindestens auf
   Rahmenbreite (sonst stünde eine schmale Liste linksbündig im Rahmen). */
.tabelle-rolle.kopf-mitlaufend table.kopf-mitlaufend{width:auto; min-width:100%}
/* Die Tabelle bleibt das erste und einzige Rasterfeld; die Schattenkante
   legt sich als zweites Kind in DASSELBE Feld, also über sie. */
.tabelle-rolle.kopf-mitlaufend > table.kopf-mitlaufend{grid-area:1/1}

/* ---- DER HALTER: DER SCHRUMPFENDE RAHMEN ------------------------------------
   🔴 DAS IST DIE LÖSUNG DES ZWEITEN BEFUNDS (Variante (C) im Block oben),
   und sie IST SEIT 01.10.2026 IN BETRIEB. Den Kasten geben
   app/module/bordbuch.php und app/module/flugbuch.php aus:
       <div class="listen-halter">
         <div class="tabelle-rolle kopf-mitlaufend"> … </div>
       </div>
   unmittelbar um die Liste — ein Kasten, sonst nichts. Hier stand bis dahin,
   die Regeln lägen still, weil das HTML ihn nicht setzt; das gilt nicht mehr.
   WER DEN KASTEN WIEDER HERAUSNIMMT, nimmt damit die mitlaufende
   Beschriftungszeile zurück: ohne ihn trifft keine Regel dieses Abschnitts
   ein Element, und das Fenster aus dem Block oben ist wieder da (gemessen
   630–890 px je Maß). Die Regeln selbst sind dann wirkungslos, nicht falsch.

   WIE ES WIRKT, in drei Schritten:
   (1) --halter-weg als eigener INHALT. ::after ist ein Kastenkind und macht
       den Halter 100dvh höher. NUR so wächst der Klebeweg des Rahmens:
       padding-bottom am Halter tut es NICHT — nachgemessen 30.09.2026, mit
       844 px Polster blieb der Rahmen ungeklebt (Chrome nimmt für die
       Klebeschranke den INHALTSkasten des Elternkastens, nicht den
       Polsterkasten). 100dvh reicht immer, weil der Rahmen selbst nie höher
       als 100dvh minus Seitenkopf minus --listen-luft wird.
   (2) margin-bottom holt die 100dvh wieder heraus, damit unter der Liste
       nichts verrutscht. Der Rahmen hat margin-bottom 0 (gemessen in beiden
       Büchern, Abstand zum nächsten Kasten 0) — deshalb steht hier der
       nackte Gegenwert und kein Zuschlag. GEMESSEN: die Seitenlänge ist in
       allen 18 Läufen IDENTISCH mit dem Bestand (390x844 Bordbuch 3039 px,
       Flugbuch 3714 px, 844x390 2226/2616, 390x420 3095/3770 …). Stünde hier
       ein Zuschlag von 18 px, wäre jede Seite 18 px länger — genau so ist es
       beim ersten Versuch aufgefallen.
   (3) clip-path beschneidet den Halter auf seine ursprüngliche Höhe. Damit
       wird der geklebte Rahmen dort, wo er über das Folgende ragen würde,
       GAR NICHT GEMALT: er schrumpft von unten, während seine Oberkante mit
       der Beschriftungszeile stehenbleibt. Das ist der Rahmen, von dem der
       Block oben sagte, CSS könne ihn nicht — mit dem Halter kann es.
       Die seitlichen -24 px lassen der Schattenkante und dem Rahmenrand
       Luft; beschnitten wird nur unten.

   GEMESSEN (30.09.2026, eigener Chrome, alle NEUN Maße, BEIDE Bücher, Seite
   in 10-px-Schritten hin UND zurück, Sichtbarkeit mit elementFromPoint):
       Fenster ohne Beschriftungszeile   0 px / 0 Zeilen — an jedem Maß
       Auswertung/Übertrag/Fuß           genau wie im Bestand lesbar
       Seitenlänge                        unverändert
       waagerecht                         390/390 px, die Seite schiebt nicht

   🔴 WAS DER BESCHNITT KOSTET — offen benannt, nicht beschwichtigt
   (01.10.2026, eigene Messung nb/balken.mjs, alle NEUN Maße, beide Bücher):
   Die Tabelle ist in JEDEM geprüften Maß breiter als der Rahmen (Überlauf
   Bordbuch 95–1042 px, Flugbuch 121–1080 px; am Laptop groß also nur 95 bzw.
   121 px, am Telefon über 1000 px). Dafür hat der Rahmen unten einen
   waagerechten Rollbalken, 17 px hoch. Steht der Rahmen UNGEKLEBT, ist der
   Balken gemalt und mit der Maus erreichbar (elementFromPoint 8 px über der
   Rahmenunterkante trifft den Rahmen: 18 von 18 Fällen). KLEBT der Rahmen und
   ist er von unten beschnitten, liegt seine Unterkante im weggeschnittenen
   Teil — dann ist der Balken nicht gemalt und nicht anklickbar (18 von 18,
   getroffen wird dort, was unter der Liste steht: TD.rechts, P.leise,
   DIV.karte …). Im Bestand war es die umgekehrte Wahl: Balken sichtbar,
   Beschriftungszeile weg.
   WAS WEITER GEHT, mit echten Radereignissen nachgemessen: Umschalt+Mausrad
   über der Liste rollt den Rahmen auch im geklebten Zustand waagerecht — in
   12 von 18 Fällen mit sechs Rastungen bis an den Anschlag, in den übrigen
   (Telefon, Überlauf über 720 px) 720 px weit, also frei weiter. Touch und
   Trackpad gehen denselben Weg; die Pfeiltasten im Rahmen und das Tabben in
   die rechten Spalten rollen ihn ohnehin. Die SEITE schiebt dabei nirgends
   waagerecht (scrollX blieb 0 in 18 von 18). Wer den Balken selbst anfassen
   will, rollt die Seite ein Stück zurück, bis die Rahmenunterkante frei ist.
   Abstellen ließe sich das nur, indem die Tabelle in den Rahmen paßt — am
   Laptop fehlen dafür 95 bzw. 121 px, also eine umbrechende Bemerkungsspalte.
   Das wäre eine Änderung am Spaltenbild und gehört nicht in diesen Umbau.

   WARUM NICHT overflow:clip STATT clip-path: overflow am Halter würde den
   geklebten Rahmen an der HALTERhöhe abschneiden (9724 px) und damit gar
   nichts bewirken; clip-path schneidet an der Stelle, die wir kennen.
   WARUM NICHT 9000px STATT 100dvh: ausprobiert und verworfen — der 9000 px
   hohe Kasten zählt zum Rollbereich der SEITE (clip-path nimmt ihn dort
   nicht heraus), die Seite wuchs von 3714 auf 11334 px. Mit 100dvh liegt die
   Unterkante des Halters innerhalb dessen, was unter der Liste ohnehin steht
   (gemessen 1031–2217 px gegen 240–1024 px Fensterhöhe) — die Seitenlänge
   bleibt deshalb unverändert.
   ------------------------------------------------------------------------- */
/* 🔴 KEINE EIGENE VARIABLE FÜR DIESE LÄNGE — Absicht, und es war hier schon
   einmal falsch. Stünde --halter-weg:100dvh und darunter
   margin-bottom:calc(0px - var(--halter-weg)), dann wäre in einem Browser
   OHNE dvh (vor Safari 15.4) die Zeile nicht etwa ungültig und der vh-Rückfall
   davor gültig — eine Eigenschaft mit var() wird erst BEIM RECHNEN ungültig
   und fällt dann auf ihren ANFANGSWERT zurück, nicht auf die Zeile davor. Der
   Rand wäre 0, der Beschnitt keiner, und unter der Liste stünde ein
   fensterhohes Loch. Mit dvh als LITERAL verwirft ein solcher Browser die
   Zeile schon beim Lesen und behält die vh-Zeile — dieselbe Bauweise wie bei
   max-height oben. */
.listen-halter{
  margin-bottom:calc(0px - 100vh);            /* Rückfall ohne dvh */
  margin-bottom:calc(0px - 100dvh);
  clip-path:inset(-24px -24px 100vh -24px);   /* Rückfall ohne dvh */
  clip-path:inset(-24px -24px 100dvh -24px);
}
.listen-halter::after{content:""; display:block; height:100vh; height:100dvh}
.listen-halter > .tabelle-rolle.kopf-mitlaufend{position:sticky; top:var(--kopf-platz)}
/* 🔴 30.09.2026, ZWEITE GEGENPROBE — OHNE DIESE ZEILE DARF DER HALTER NICHT
   INS HTML. Der Beschnitt (clip-path) ist für den Browser UNSICHTBAR: er
   rechnet weiter mit dem ganzen geklebten Rahmen. Gibt man einem Knopf IN
   der Liste den Fokus (Tab, Umschalt+Tab, Bildschirmleser), hält der Browser
   ihn deshalb für sichtbar und rollt NICHT nach — der Knopf liegt aber im
   abgeschnittenen Teil. Der Nutzer bedient dann Bearbeiten, 》Löschen…《 oder
   》im Flugbuch ✓《, ohne sie zu sehen. Das ist derselbe Fehler wie beim Popup
   weiter oben, nur in der Liste.
   GEMESSEN am 30.09.2026 (eigener Chrome, alle NEUN Maße, BEIDE Bücher, Seite
   so gerollt, daß vom Rahmen noch 150 px zu sehen sind, echte Tab-Anschläge
   vom Element VOR der Liste und Umschalt+Tab vom Element DANACH; je
   Haltestelle fünf Meßpunkte — Mitte und vier Ecken — mit elementFromPoint):
       ohne Halter (Bestand)      0 von 720 vorwärts, 0 von 216 rückwärts
       Halter OHNE diese Zeile  556 von 720 vorwärts, 127 von 216 rückwärts
       Halter MIT dieser Zeile    0 von 720 vorwärts, 0 von 216 rückwärts
   (Zum Vergleich mitgemessen: nur den BESCHNITT zurückzunehmen
   — .listen-halter:focus-within{clip-path:none} — ließ 6 von 720 und 1 von
   216 stehen. Deshalb die Klebung selbst.)
   🔴 DIESE ZAHLEN SIND DER STAND VOM 30.09.2026 UND EINE UNTERE SCHRANKE. Die
   Rollstellung wurde damals von oben abgetastet und der ERSTE Treffer mit rund
   150 px Rest genommen; der liegt an mehreren Maßen beim HEREINROLLEN, wo der
   Rahmen noch nicht klebt und es die Falle gar nicht gibt. Maßgeblich sind die
   Zahlen im Block darunter (01.10.2026, 3006 Haltestellen, Rollstellung
   ausdrücklich benannt).
   WAS ES KOSTET, offen gesagt: solange der Fokus in der Liste steht, klebt
   der Rahmen nicht, und die Beschriftungszeile kann dabei aus dem Bild
   rollen — genau wie im heutigen Zustand. Die Wahl ist: sichtbar ohne
   Beschriftung, oder unsichtbar. Das erste ist die gutmütige Richtung.
   Sobald der Fokus die Liste verläßt, klebt der Rahmen wieder. */
/* 🔴 01.10.2026 — DIESE ZEILE IST JETZT DER RÜCKFALL, NICHT DER HAUPTWEG.
   public/listenkopf.js setzt html.js-listenfokus und holt ein nicht ganz
   gemaltes Element in der Liste selbst ins Bild (erst rollt der RAHMEN nach,
   notfalls springt die Seite auf die Halteroberkante). Dann darf die Klebung
   BLEIBEN — und nur so bleibt die Beschriftungszeile auch bei
   Tastaturbedienung im Bild.

   GEMESSEN am 01.10.2026, zweite Runde, mit ECHTEN Tastenanschlägen; Datei
   nb/fokus.mjs, Ergebnisse nb/fokusN-*.json. 18 Läufe (alle NEUN Gerätemaße ×
   BEIDE Bücher) × sieben Rollstellungen = 3006 Haltestellen IN der Liste.
   Die Rollstellungen sind ausdrücklich benannt, weil es darauf ankommt — in
   einer ungeklebten Stellung gibt es die Falle gar nicht:
       S1 Seite ganz oben, 40 Tab vom Element VOR der Liste
       S2 Seite so gerollt, daß vom Rahmen rund 150 px WIRKLICH GEMALT sind
          (abgetastet, nicht gerechnet: clip-path steckt in keinem Rechteck),
          40 Tab
       S3 wie S2, aber halbe Rahmenhöhe gemalt, 40 Tab
       S4 Rahmen ganz weggeschnitten, 15 Umschalt+Tab aus dem Element NACH
          der Liste
       S5 Seitenende, Umschalt+Tab bis in die Liste und 12 weiter
       S6/S7 aus dem Seitenkopf herein, gerollt und ungerollt
   Je Haltestelle fünf Umrißpunkte UND ein 3×3-Raster je Zeilenkasten mit
   elementFromPoint; »beschnitten« heißt: gemalt, aber nicht ganz.
       A ohne jede Abhilfe          1050 von 3006 Haltestellen GANZ
                                    unsichtbar, 130 beschnitten;
                                    Beschriftungszeile 2562 von 3006
       B nur diese Zeile (Rückfall)    0 unsichtbar, 1 beschnitten;
                                    Beschriftungszeile aber nur 1890 von
                                    3006 — sie rollt weg, solange der Fokus
                                    in der Liste steht
       C listenkopf.js, erstes Maß     0 unsichtbar, 41 beschnitten;
                                    Beschriftungszeile 3006 von 3006
       D listenkopf.js, Maß von heute  0 unsichtbar, 1 beschnitten;
                                    Beschriftungszeile 3006 von 3006
   Die EINE verbliebene Haltestelle (D und B gleich) ist nicht der Beschnitt:
   es ist der Verweis »aus Bordbuch …« im Flugbuch bei 1440x900, dessen erste
   Zeile 3 px unter dem EIGENEN senkrechten Rollbalken des Rahmens liegt,
   während die Tabelle schon am Anschlag steht. In B klebt der Rahmen dabei
   gar nicht (position static) — derselbe Befund ohne jeden Beschnitt.
   Ohne JavaScript greift weiter diese Zeile: sichtbar ohne Beschriftung ist
   die gutmütige Richtung, unsichtbar wäre die schlechte. Sobald der Fokus die
   Liste verläßt, klebt der Rahmen wieder (gemessen: an allen 18 Läufen
   position wieder sticky und Beschriftungszeile wieder im Bild). */
html:not(.js-listenfokus) .listen-halter:focus-within > .tabelle-rolle.kopf-mitlaufend{position:static}
/* 🔴 AUF PAPIER MUSS DER HALTER VERSCHWINDEN, sonst wäre der Bestand nach
   einem Blatt zu Ende: der Beschnitt würde die Liste unterhalb der ersten
   Rahmenhöhe abschneiden und der negative Rand das Folgende darüberziehen.
   Dieselbe Vorsorge wie beim Rahmen selbst weiter unten (position:static). */
@media print{
  .listen-halter{margin-bottom:0; clip-path:none}
  .listen-halter::after{display:none}
  .listen-halter > .tabelle-rolle.kopf-mitlaufend{position:static}
}

@media (min-width:981px){
  html{--kopf-platz:168px}          /* dort 149 px gemessen, Gegenprobe 162 */
}
/* 🔴 01.10.2026 — DAS BAND AB 1281 px IST WEG, WEIL ES GEMESSEN FALSCH WAR.
   Hier stand html{--kopf-platz:112px} („dort 100 px gemessen“). Mit dem Halter
   klebt die Beschriftungszeile genau auf dieser Höhe — und bei einem Konto mit
   ALLEN Reitern ist der Seitenkopf dort nicht 100, sondern 149 px hoch. Die
   Zeile lag dann vollständig HINTER ihm. GEMESSEN (01.10.2026, eigener Chrome,
   Konto agent42 mit allen Reitern, Seite 900 px gerollt, Mitte der ersten
   th-Zelle mit document.elementFromPoint):
       Breite 981–1280 px   Kopf 149 px, --kopf-platz 168  → th 169..207, TH getroffen
       Breite 1281–1600 px  Kopf 149 px, --kopf-platz 112  → th 113..151, A.aktiv
                                                             getroffen (= der Reiter
                                                             im Seitenkopf) — VERDECKT
   Folge in der Rollmessung: an 1440x900 standen 8 Bordbuch- bzw. 3
   Flugbuchzeilen OHNE Beschriftungszeile im Bild (Fenster 650 bzw. 530 px),
   während alle anderen acht Maße 0 zeigten. Die Kopfhöhe hängt am INHALT
   (Kontoname, Zahl der Reiter, Schriftgröße) und springt NICHT an einer
   Medienabfrage — die 100 px galten für ein Konto mit wenigen Reitern.
   Ab 981 px gilt deshalb EIN Wert: 168 px (gemessen 149, Gegenprobe 162).
   PREIS, gemessen: bei 1440x900 wird der Rollrahmen von 772 auf 716 px
   niedriger — weniger als eine Datenzeile (82–90 px).
   Genau sitzt es erst mit public/listenkopf.js, das die wirkliche Kopfhöhe
   liest und --kopf-platz überschreibt; diese Bänder sind der Rückfall, wenn
   kein JavaScript läuft, und müssen deshalb für sich allein tragen. */
@media (max-width:820px){
  /* Hier rollt der Seitenkopf mit (Z342) — es muß oben nichts frei bleiben.
     🔴 DAFÜR MUSS UNTEN MEHR FREI BLEIBEN — Gegenprobe 29.09.2026:
     Mit --kopf-platz 0 und 16 px Luft wurde der Rahmen fast fensterhoch
     (gemessen 390x844: 826 von 844 px; 360x780: 762 von 780; 768x1024:
     1006 von 1024). Übrig blieb ein 16–18 px schmaler Streifen Seite. Wer
     dort mit dem Finger über der Liste wischt, rollt IMMER nur die Liste;
     an alles, was UNTER der Liste steht (Auswertung des ganzen Buchs,
     Übertrag, Fuß — gemessen 1217–2378 px Inhalt), kommt man dann erst nach
     dem Durchrollen des ganzen Bestandes (390x844 Bordbuch: 8603 px). Das
     ist kein Gewinn, sondern ein Preis, den niemand zahlen muß.
     120 px Luft geben einen Streifen, der sich mit dem Daumen sicher treffen
     läßt (rund zwei Fingerbreiten), und kosten EINE Zeile: nachgemessen
     390x844 Bordbuch 8 → 7 ganze Zeilen, Flugbuch 8 → 7. Mit 160 px wären
     es zwei Zeilen weniger gewesen (6/7) — deshalb 120.
     WER MEHR ZEILEN WILL, dreht hier — es ist genau EINE Zahl. */
  html{--kopf-platz:0px}
  .tabelle-rolle.kopf-mitlaufend{--listen-luft:120px}
}
@media (max-height:480px){
  /* Niedriges Fenster: der Seitenkopf klebt hier nicht mehr (Regel unten bei
     .kopf), also ist auch nichts abzuziehen.
     Luft kleiner als im Band oben: bei 390 px Fensterhöhe (iPhone quer)
     wären 160 px mehr als ein Drittel des Schirms. 64 px lassen dort einen
     greifbaren Streifen und die Mindesthöhe trägt die Liste (gemessen
     844x390: Rahmen 326 px, 3 ganze Bordbuchzeilen). Bei 900x240 rechnet
     die Formel ohnehin unter die Mindesthöhe — dort gilt weiter 320 px. */
  html{--kopf-platz:0px}
  .tabelle-rolle.kopf-mitlaufend{--listen-luft:64px}
}

/* Die Kopfzeile klebt am RAHMEN, ganz oben. Hintergrund kommt aus der
   Grundregel th (Z153) und ist deckend, sonst schienen die Zeilen durch.
   z-index 2 — über den Datenzellen, aber WEIT unter dem Seitenkopf (.kopf
   hat 50, Z65): rollt die Seite den Rahmen unter den Seitenkopf, verschwindet
   die Kopfzeile dort hinter ihm statt ihn zu überdecken. Das ist die vom
   Betreiber geforderte Richtung. */
.tabelle-rolle.kopf-mitlaufend thead.kopf-mitlaufend th{
  position:sticky; top:0; z-index:2;
  /* border-collapse zeichnet die Trennlinie an der TABELLE, nicht an der
     Zelle — beim Rollen bliebe sie stehen. Der Innenschatten nimmt sie mit. */
  box-shadow:inset 0 -1px 0 var(--rand);
}

/* ---- SCHATTENKANTE AN DER SCHNITTKANTE --------------------------------
   Hinweis darauf, daß rechts noch Spalten folgen. 26 px breiter Verlauf,
   rechts am sichtbaren Rand des Rahmens, KLEBEND — er wandert beim
   Querrollen mit und markiert immer die Stelle, an der die Tabelle
   abgeschnitten ist. Er hängt am Rasterfeld, nicht an der Tabelle: right:0
   hält ihn am Fenster des Rahmens, solange die Spalte (= die volle
   Rollbreite) darunter weiterläuft. Genau dafür muß die Spalte oben
   min-content breit sein — säße das Feld nur auf Rahmenbreite, bliebe die
   Kante beim Rollen zurück (ausprobiert: mit fit-content(100%) stand sie bei
   scrollLeft 100 um 100 px zu weit links).

   pointer-events:none ist Pflicht, nicht Vorsicht: darunter liegen die
   Knöpfe Bearbeiten/Löschen und Abzeichnen. Nachgeprüft am 29.09.2026 mit
   document.elementFromPoint mitten auf der Kante — dort liegt TD bzw.
   A.knopf, nicht das Pseudoelement; der Verlauf fängt keinen einzigen Klick
   ab. Zusätzlich abgesichert: die Kante ist ein ::after und kann deshalb
   auch nie den Tastaturfokus bekommen.

   z-index 3 — eine Stufe ÜBER der klebenden Kopfzeile (2). Sonst läge der
   Hinweis auf jeder Datenzeile, aber ausgerechnet auf der Beschriftungszeile
   nicht. Gegen Klicks schützt weiter pointer-events:none, nicht der Stapel.

   WARUM NICHT DER NAHELIEGENDE WEG — mehrere Hintergründe am Rollrahmen mit
   background-attachment:local/scroll? Weil dieser Rahmen keine durchsichtige
   Tabelle trägt. Ein Hintergrund am RAHMEN liegt hinter allem, was die
   Zellen selbst malen, und die malen deckend: gemessen 23.09.2026 am
   Flugbuch thead th rgb(240,243,246) (Z153) und jede ZWEITE Datenzeile
   rgb(248,250,251) (Zebrastreifen Z795) — nur die ungeraden Zeilen sind
   durchsichtig. Der Hinweis käme also gestreift durch. Ein überlagernder
   Kasten ist hier nicht der Umweg, sondern der einzige Weg, der auf jeder
   Zeile gleich aussieht.

   KEINE KANTE LINKS — Absicht, nicht vergessen. Links verbirgt sich nur,
   was der Leser selbst weggeschoben hat. Eine zweite Kante links verdeckte
   vom ersten Rollpixel an dauerhaft 26 px der ERSTEN Spalte (Datum). */
.tabelle-rolle.kopf-mitlaufend::after{
  content:"";
  grid-area:1/1;
  justify-self:end;
  align-self:stretch;
  position:sticky;
  right:0;
  width:26px;
  z-index:3;
  /* OHNE die Rollzeitleiste unten (alte Browser) bleibt es bei diesem
     Grundzustand: Kante immer sichtbar. Das ist die gutmütige Richtung —
     lieber ein Hinweis zuviel als die Liste wieder ohne jeden. */
  opacity:1;
  background:linear-gradient(to left, var(--rollkante), transparent);
  pointer-events:none;
}
/* Die App folgt für „dunkel“ der Systemeinstellung (Z748), es gibt keinen
   eigenen Umschalter — deshalb hier dieselbe Abfrage. BEIDE Bilder am
   Bildpunkt nachgemessen (23.09.2026, Bordbuch 1280x900, quer über den
   26-px-Streifen bis an den Rahmenrand):
      hell    #FFFFFF → #CACBCF
      dunkel  #1C232B → #0D1013
   In beiden ein sichtbarer Schleier, in keinem eine Wand. */
@media (prefers-color-scheme:dark){
  .tabelle-rolle.kopf-mitlaufend{--rollkante:rgba(0,0,0,.55)}
}
/* Die Kante soll NUR dort stehen, wo wirklich etwas verdeckt ist. Das kann
   CSS allein über die Rollzeitleiste: der Verlauf blendet über die letzten
   32 Rollpixel aus, und wo gar nichts zu rollen ist, kommt er nie zum
   Vorschein (Grundwert hier 0, die Zeitleiste steht dann still am Ende ihres
   Bereichs).
   Gemessen 23.09.2026, Bordbuch 1280x900, 177 px Überlauf:
      scrollLeft   0/60/145 → Kante 1 (voll sichtbar)
      scrollLeft 161/169/177 → Kante 0,5 / 0,25 / 0 (aus)
   und mit einer Tabelle ohne Überlauf: Kante 0 — kein falscher Hinweis.
   @supports ist kein Schmuck: ohne die Abfrage stünde in einem Browser ohne
   Rollzeitleisten eine Animation ohne Dauer mit fill:both, und die spränge
   sofort auf ihren Endwert — die Kante wäre ÜBERALL unsichtbar. Mit der
   Abfrage greift dort nur der Grundzustand oben.
   BEWEGUNGSARME EINSTELLUNG — geprüft: Z47 setzt bei prefers-reduced-motion
   animation-duration:.01ms !important auf ALLES, also auch hierauf. Die
   Kante bleibt davon heil; es entfällt nur das weiche Überblenden. */
@supports (animation-timeline:scroll()){
  @keyframes tll-rollkante{from{opacity:1} to{opacity:0}}
  .tabelle-rolle.kopf-mitlaufend::after{
    opacity:0;
    animation:tll-rollkante linear both;
    animation-timeline:scroll(nearest inline);
    animation-range:calc(100% - 32px) 100%;
  }
}

/* Beim Drucken klebt nichts und wird nichts abgeschnitten: die Kopfzeile
   wiederholt der Browser ohnehin je Seite (thead). Die Grundregel
   th{position:static} (Z381) reicht hier nicht, weil die Regeln oben genauer
   sind.
   🔴 max-height:none UND overflow:visible sind hier lebenswichtig: mit einem
   Rollbereich druckte der Browser nur dessen sichtbaren Ausschnitt — der
   Bestand wäre nach ein paar Zeilen zu Ende. Ebenso muß das Raster zurück
   auf Block, sonst nimmt der Browser den Rasterkasten als eine Einheit und
   kann ihn nicht über Blätter verteilen; und die Schattenkante hat auf
   Papier nichts zu suchen.
   Papier ist schmal (A4 hochkant ≈ 794 px): width:auto und max-width:100%
   halten den Rahmen im Blatt. */
@media print{
  /* 🔴 position:static ist hier ein WÄCHTER, kein Muß: am Bildschirm klebt
     der Rahmen nicht (der Versuch ist ausgebaut, siehe oben). Sollte ihn je
     wieder jemand kleben lassen, hielte der Browser ihn auf Papier als
     Ganzes an einer Stelle, statt ihn über die Blätter zu verteilen — der
     Bestand wäre nach einem Blatt zu Ende. Die Zeile kostet nichts und
     verhindert genau das. */
  .tabelle-rolle.kopf-mitlaufend{display:block; overflow:visible;
    position:static;
    width:auto; min-width:0; max-width:100%; max-height:none; min-height:0}
  .tabelle-rolle.kopf-mitlaufend::after{display:none}
  .tabelle-rolle.kopf-mitlaufend table.kopf-mitlaufend{width:100%; min-width:0}
  .tabelle-rolle.kopf-mitlaufend thead.kopf-mitlaufend th{position:static;
    z-index:auto; box-shadow:none}

  /* 🔴 29.09.2026, Gegenprobe: DIE SPALTEN FIELEN RECHTS VOM BLATT.
     width:100% oben hält nur den RAHMEN im Blatt — die Tabelle darin rechnet
     ihre Breite weiter aus dem Inhalt, und th{white-space:nowrap} (Z153)
     verbietet jeden Umbruch in der Beschriftungszeile. NACHGEMESSEN mit
     Druckmedien-Nachbildung auf 794 px (A4 hochkant):
         Bordbuch  Tabelle 1188 px → ohne Kraftstoff, Öl, Pilot, Bemerkung
         Flugbuch  Tabelle 1348 px → ohne IFR, PIC, Kopilot, Dual, FI, CRI,
                                     FSTD, Bemerkungen
     Alle ZEILEN standen auf dem Papier, aber halbe Zeilen: die eiserne
     Vorgabe 》nichts abgeschnitten《 war damit nicht erfüllt. Das ist ein
     Altbefund, nicht neu — hier fällt er an, hier wird er erledigt.
     DREI SCHRAUBEN, mehr braucht es nicht: Umbruch in der Beschriftungs-
     zeile erlauben, lange Wörter (Bemerkung, Pilotenname) brechen lassen,
     Schrift und Polster auf Papiermaß. Alles nur im Druck und nur an den
     beiden Bücherlisten — andere Listen drucken unverändert.
     DANACH GEMESSEN, gleiches Blatt: Bordbuch 730 px, Flugbuch 760 px von
     794 px, NULL Zellen außerhalb (825 bzw. 1440 Zellen geprüft), alle 74
     bzw. 70 Zeilen auf dem Papier, alle 70 Bemerkungen und alle 14 langen
     Bemerkungen im Text. Die Breite kommt danach aus width:100% oben — die
     Schriftgröße ändert sie NICHT mehr (bei 7,5/8/8,5/9 pt jeweils dieselben
     730 bzw. 760 px), sie bestimmt nur noch die Zeilenhöhe und damit die
     Blattzahl. 8 pt ist der Ausgleich: lesbar, und der Bestand braucht
     dadurch ein Blatt mehr statt drei (Bordbuch Gesamthöhe 4665 px gegen
     5830 px bei 8,5 pt). Daß es überhaupt mehr Blätter sind als vorher, ist
     der Preis dafür, daß die abgeschnittenen Spalten jetzt WIRKLICH mit
     gedruckt werden — vorher war der Rest schlicht nicht auf dem Papier.

     ======================================================================
     🔴 30.09.2026, ZWEITE GEGENPROBE: overflow-wrap:anywhere HAT DAS PAPIER
     UNLESBAR GEMACHT. Hier stand bis heute 》anywhere《, und das ist der
     Unterschied, auf den es ankommt: 》anywhere《 setzt die MINDESTBREITE
     jeder Zelle auf EIN ZEICHEN herab (》break-word《 nicht — dort bleibt das
     längste Wort die Mindestbreite). Die Tabelle mit automatischer Breite
     verteilt den Platz danach nach der LÄNGSTEN Zelle, und das ist die
     Bemerkung. Ergebnis, nachgemessen im Druckmedium auf dem Satzspiegel
     von A4 hochkant (717 px, siehe unten); gezählt sind Zellen mit einem
     EINTEILIGEN Inhalt (keine Leerzeichen, höchstens 14 Zeichen), die der
     Browser auf mehrere Zeilenkästen verteilt hat:
         Bordbuch   5 von 8 Spaltenköpfen, 80 von 381 Datenzellen
                    — 》1304:00《 in DREI Stücken, 》Landung《 in dreien
         Flugbuch  15 von 16 Spaltenköpfen, 634 von 634 Datenzellen
                    — 》Kopilot《 in FÜNF Stücken, Datum 》30.09.《/》2026《,
                    Pilot 》Prue/fkon/to/age/nt99《
     (Auf 794 px gemessen dasselbe Bild: Bemerkungsspalte 274 von 730 px,
     Zählerspalte 23 px.)
     Im ECHTEN PDF (Page.printToPDF, A4) ist deshalb kein Spaltenkopf mehr
     als Wort auffindbar: die Textsuche nach 》Kraftstoff《, 》Kopilot《,
     》FSTD《, 》Nacht《 und selbst nach dem Datum der ersten Zeile schlug fehl;
     das Wort 》Pruefkonto《 steht im alten Bordbuch-PDF NULL mal, im neuen
     99 mal. Ein so gedrucktes Buch ist als Nachweis nicht brauchbar — und
     auch nicht durchsuchbar.

     🔴 UND DER SATZSPIEGEL IST NICHT 794 px. Die Messung darüber stand auf
     der PAPIERbreite. Der Satz steht innerhalb der Ränder: A4 hochkant bei
     0,4 Zoll Rand = (8,27−0,8)×96 = 717 px, quer = (11,69−0,8)×96 = 1045 px.
     Nachgerechnet am PDF selbst: Blatt 595,9 pt, Textkasten von 27,75 bis
     567,1 pt = 539 pt = 719 px — die 717 px stimmen, die 794 px nicht.

     🔴 WAS PASSIERT, WENN DIE TABELLE BREITER IST ALS DER SATZ — gemessen,
     weil die ganze Abwägung daran hängt: Der Browser SCHNEIDET NICHT AB, er
     VERKLEINERT DAS GANZE BLATT. Nachgewiesen an echten PDFs (Wortkästen in
     Punkten, pymupdf — pypdf/visitor_text gibt hier falsche x-Werte, die
     Textmatrix ist dort nicht zusammengesetzt; darauf ist zuerst auch diese
     Datei hereingefallen):
         Flugbuch hochkant, Tabelle braucht 902 px bei 717 px Satz
             → 8-pt-Text steht mit 6,27 pt im PDF (Faktor 0,78), KEIN Wort
               außerhalb des Blattkastens
         alle anderen Stände                → 7,99 pt, also unverkleinert
     Der Preis für eine zu breite Tabelle ist demnach nicht der fehlende
     Rest, sondern kleinere Schrift auf der GANZEN Seite — und das auch nur,
     solange der Druckdialog seine übliche Einstellung 》an Seitenbreite
     anpassen《 behält. Darauf baut hier nichts: quer liegendes Papier
     braucht die Anpassung gar nicht erst.

     WAS JETZT HIER STEHT — vier Schrauben, jede gemessen:
      (1) overflow-wrap:break-word statt anywhere. Damit ist die
          Mindestbreite jeder Spalte wieder ihr längstes Wort.
      (2) Die Schilder (.schild, Z200 mit white-space:nowrap) dürfen auf
          Papier umbrechen. Ohne das zwingt ein Schild wie 》aus Bordbuch
          D-EOOC f-000123《 die Bemerkungsspalte auf seine volle Breite
          (gemessen Flugbuch 166 px Mindestbreite statt 115).
      (3) Die Bedienteile der letzten Spalte (Bearbeiten, Löschen…,
          Abzeichnen, 》im Flugbuch ✓《) verschwinden. Sie sind Knöpfe, nicht
          Bestand — .knopf ist schon durch Z378 draußen, 》Bearbeiten《 im
          Flugbuch (a.klein) und das Schild im Bordbuch waren es nicht.
          Getroffen wird NUR das, was in der letzten Zelle als eigenes Kind
          steht; Zellen mit Bemerkungstext bleiben unberührt (nachgemessen:
          die Verweise 》aus Bordbuch …《 in der Bemerkungsspalte stehen
          weiter auf dem Papier). Gewinn: Bordbuch 101 px, Flugbuch 64 px.
      (4) EINE Schriftgröße für Tabelle, Spaltenköpfe UND Schilder. th trägt
          font-size:12,5 px (Z153) und .schild 11 px — ABSOLUTE Größen, die
          der 8 pt der Tabelle nicht folgten. Genau sie bestimmten die
          Mindestbreite der schmalen Spalten; deshalb reagierte die Breite
          früher kaum auf die Schriftgröße (8→6 pt nur 811→729 px).

     DANACH GEMESSEN (Satzspiegel 717 px, beide Bücher, zusätzlich mit einem
     30 Zeichen langen Pilotennamen als Belastungsprobe):
         Bordbuch hochkant 8 pt   Tabelle 653 px, 32 px Luft, 0 von 389
                                  einteiligen Zellen zerhackt, Gesamthöhe
                                  5026 px statt 9820 px (weniger Blätter);
                                  mit Belastungswort unverändert 653 px.
         Flugbuch hochkant 8 pt   780 px — davon ragen 80 px über den Satz
                                  (274 Zellen); das Blatt würde also auf
                                  6,3 pt verkleinert. Auch 7 pt (711) und
                                  6,5 pt (683) tragen die Belastungsprobe
                                  nicht (774 bzw. 735).
         Flugbuch QUER    8 pt    995 px von 1045, 25 px Luft AUCH mit
                                  Belastungswort, 0 zerhackt, Gesamthöhe
                                  6792 px statt 14332 px.
     Am echten PDF nachgeprüft (pymupdf, Wortkästen in Punkten): Bordbuch
     10 Blätter hochkant, Flugbuch 12 quer + 7 hochkant, in BEIDEN null
     Wörter außerhalb des Blattkastens und null über dem Satzspiegel,
     Schrift 7,99 pt (unverkleinert), alle Spaltenköpfe als GANZE Wörter
     wiederfindbar (》Kraftstoff《, 》Kopilot《, 》FSTD《, 》Nacht《 — im Bestand
     war keines davon auffindbar), erste und letzte Zeile im Text.
     Das Flugbuch hat 20 Spalten; hochkant sind sie bei lesbarer Schrift
     nicht unterzubringen. Deshalb bekommt NUR das Flugbuch quer liegendes
     Papier — über eine BENANNTE Seite, damit der Rest der Seite
     (Auswertung, Monatsarchiv, Festschreiben) hochkant bleibt. Siehe unten.
     ====================================================================== */
  .tabelle-rolle.kopf-mitlaufend table.kopf-mitlaufend,
  .tabelle-rolle.kopf-mitlaufend table.kopf-mitlaufend th,
  .tabelle-rolle.kopf-mitlaufend table.kopf-mitlaufend td,
  .tabelle-rolle.kopf-mitlaufend table.kopf-mitlaufend .schild{font-size:8pt}
  .tabelle-rolle.kopf-mitlaufend table.kopf-mitlaufend th,
  .tabelle-rolle.kopf-mitlaufend table.kopf-mitlaufend td{
    white-space:normal; overflow-wrap:break-word; padding:2px 3px}
  .tabelle-rolle.kopf-mitlaufend table.kopf-mitlaufend .schild{white-space:normal}
  /* Nur eigene Kinder der LETZTEN Zelle — siehe (3) oben. */
  .tabelle-rolle.kopf-mitlaufend table.kopf-mitlaufend tbody td:last-child > a,
  .tabelle-rolle.kopf-mitlaufend table.kopf-mitlaufend tbody td:last-child > form,
  .tabelle-rolle.kopf-mitlaufend table.kopf-mitlaufend tbody td:last-child > button{
    display:none}
}

/* ---- DRUCK DER BÜCHERLISTEN: DAS FLUGBUCH LIEGT QUER --------------------
   20 Spalten eines Pilotenflugbuchs passen auf A4 hochkant nur zerhackt
   (Meßwerte im Block darüber). Papierflugbücher liegen quer; hier tut es
   das Flugbuch auch — aber NUR die Blätter, auf denen die Liste steht.
   WIE: eine BENANNTE Seite (@page buchliste) und page:buchliste am
   Rollrahmen. Gemessen am echten PDF (134 Einträge): Flugbuch 20 Blätter,
   davon 13 quer (842×596) und 7 hochkant (596×842) — Auswertung,
   Monatsarchiv und Festschreiben bleiben also hochkant; vorher 24 Blätter,
   alle hochkant und alle zerhackt. Bordbuch bleibt ganz hochkant: es paßt
   dort (653 von 717 px) und braucht so 10 Blätter statt 14.
   WARUM NICHT @page{size:A4 landscape} OHNE NAMEN: das gilt für das ganze
   Dokument und damit für JEDE Seite der Anwendung (Fristen, Abrechnung,
   Belege) — @page läßt sich nicht über einen Selektor eingrenzen. Und ein
   eigenes <style> im Kopf verbietet die CSP (style-src 'self',
   app/sicherheit.php Z57). Deshalb die Seitenkennung am <body>
   (app/layout.php, 2.9.1) und die benannte Seite hier.
   🔴 RÜCKFALL FÜR BROWSER OHNE BENANNTE SEITEN: dort bleibt das Flugbuch
   hochkant — und hochkant paßt es bei 8 pt nicht. Darum steht für diesen
   Fall der bisherige Zustand (overflow-wrap:anywhere) weiter da: lieber
   zerhackt als abgeschnitten, das ist die Richtung der eisernen Vorgabe.
   Die Regel darunter im @supports-Block nimmt ihn zurück, sobald das Papier
   quer liegen kann. Geprüft: CSS.supports('page','buchliste') ist in
   diesem Chrome true und die Blätter liegen wirklich quer (Maße oben);
   in iOS-Safari ist es NICHT geprüft — kein Gerät hier. Fällt der Rückfall
   dort an, druckt das Flugbuch wie bisher, das Bordbuch aber besser.
   ------------------------------------------------------------------------- */
@media print{
  body.seite-flugbuch .tabelle-rolle.kopf-mitlaufend table.kopf-mitlaufend th,
  body.seite-flugbuch .tabelle-rolle.kopf-mitlaufend table.kopf-mitlaufend td{
    overflow-wrap:anywhere}
}
@supports (page:buchliste){
  @media print{
    @page buchliste{size:A4 landscape}
    body.seite-flugbuch .tabelle-rolle.kopf-mitlaufend{page:buchliste}
    body.seite-flugbuch .tabelle-rolle.kopf-mitlaufend table.kopf-mitlaufend th,
    body.seite-flugbuch .tabelle-rolle.kopf-mitlaufend table.kopf-mitlaufend td{
      overflow-wrap:break-word}
  }
}

/* -------------------------------------------------------------------------
   NIEDRIGES FENSTER: DER SEITENKOPF KLEBT NICHT.
   Dieselbe Abwägung, die bei 820 px Breite schon steht (Z338: „sticky würde
   bis zur Hälfte des Handybildschirms dauerhaft belegen“), nur über die
   HÖHE. Gemessen 29.09.2026 in 2.8.0:
       900x240 → .kopf 189 px von 240 px = 79 % des Fensters
       844x390 → .kopf 189 px von 390 px = 48 %  (iPhone quer!)
   Solange er dort klebt, kann UNTER ihm nichts mehr stehen: bei 900x240
   blieben 51 px, das trägt die Beschriftungszeile (38 px) und keine einzige
   ganze Datenzeile. Unterhalb von 480 px Fensterhöhe rollt der Seitenkopf
   deshalb mit, wie auf schmalen Geräten auch. 480 px ist die Schwelle, ab
   der die drei gemessenen Kopfhöhen wieder unter 40 % des Fensters bleiben
   (189/480 = 39 %).
   ------------------------------------------------------------------------- */
@media screen and (max-height:480px){
  .kopf{position:static}
}

/* -------------------------------------------------------------------------
   Auswahlfeld „Einträge pro Seite“ über den Bücherlisten
   (buecher_pro_seite_wahl() in bordbuch.php, beide Bücher).
   OHNE eigene Regel macht form label{display:block} (Z820) zusammen mit
   button{margin-top:12px} (Z828) daraus DREI gestapelte Zeilen — gemessen
   115 px hoch über der Liste. Hier dieselbe eine Zeile wie bei
   .knopf-reihe form (Z285); Schriftgröße und Farbe des Labels bleiben, wie
   sie der Bestand für Formulare setzt.
   ------------------------------------------------------------------------- */
form.pro-seite-wahl{display:flex; gap:8px; flex-wrap:wrap; align-items:center;
  min-width:0; margin:0 0 10px}
form.pro-seite-wahl label{display:inline-flex; align-items:center; margin:0}
/* Ohne das zieht die Grundregel input,select,textarea{width:100%} (Z240) das
   Auswahlfeld auf die volle Breite und jedes Stück bekommt eine eigene Zeile —
   dieselbe Stelle, an der .knopf-reihe form input[type=text] (Z286) gegenhält. */
form.pro-seite-wahl select{width:auto; min-width:0}
form.pro-seite-wahl button{margin-top:0}
/* Auf dem Papier hat ein Bedienelement nichts zu suchen. Die Druckregel Z378
   blendet .kopf, .filter, .knopf und .knopf-reihe aus — die Blätterleiste
   (.knopf-reihe) und der Sortier-Umschalter (.filter) fallen darunter, dieses
   Formular nicht: es trägt keine dieser Klassen, und sein Knopf heißt
   class="neben". Deshalb hier ausdrücklich. */
@media print{
  form.pro-seite-wahl{display:none}
}
/* -------------------------------------------------------------------------
   SAMMELRECHNUNG (2.10.0) — Auswahlspalte „Sammel“ in der Flugliste
   (#fl-tabelle) und in den Zusatzkosten (#zs-tabelle) sowie das Formular
   hinter der Tabelle (form.sr-wahl, aktion sr_merken).
   WARUM EIGENE KLASSE sr-zelle statt „klein“: in der Flugliste gilt seit
   2.5.0 #fl-tabelle tbody td.klein{width:24em; min-width:14em} für die
   Bemerkungsspalte — mit class="klein" wäre die Auswahlspalte 24em breit
   geworden und hätte die Tabelle bei 1280 px wieder über den Rand geschoben.
   Hier: so schmal wie ihr Inhalt, Haken und Schild in EINER Zeile.
   Nur Darstellung — kein Feldname, kein Formular, keine Zahl.
   ------------------------------------------------------------------------- */
td.sr-zelle{font-size:12px; white-space:nowrap; width:1%; vertical-align:top}
/* display:inline-flex hält Haken, Wort und Schild „vorgemerkt“ zusammen;
   die Grundregel form label{display:block} greift hier ohnehin nicht (das
   Feld gehört per form-Attribut zu einem Formular AUSSERHALB der Tabelle). */
td.sr-zelle label{display:inline-flex; align-items:center; gap:4px; margin:0}
td.sr-zelle input[type=checkbox]{width:auto; margin:0}
form.sr-wahl{margin:10px 0 0}
form.sr-wahl p{margin:4px 0}
/* Auf dem Papier hat ein Bedienelement nichts zu suchen (wie form.pro-seite-wahl). */
@media print{
  form.sr-wahl{display:none}
  /* Spalte GANZ weg — Kopf UND Zellen, sonst verrutscht die gedruckte Tabelle. */
  td.sr-zelle,th.sr-kopf{display:none}
}
