/* =====================================================================
   css/heft.css — das Heft (Stufe 2, Paket 07-2, docs/HEFT-2026-09-24.md)

   Zwei Welten in einem Kasten, wie im Zeichen-Editor (css/zeichnung.css):
   - Kopf, Leiste und Liste sind Portal und folgen dem Theme — nur
     --pp-Tokens, Schriftgrößen aus der Leiter, Abstände ab 16 px im
     4-px-Raster (verify-skala.js führt diese Datei in PORTAL).
   - Das BLATT ist Papier und bleibt in beiden Themes weiß. Die Tinten
     von js/zeichnung.js sind für weißes Papier gewählt; ein dunkles
     Blatt machte die schwarze Tinte unsichtbar.

   touch-action: none steht an der BÜHNE — sie IST die Zeichenfläche des
   Hefts (Muster .sb-canvas der Arbeitsfläche): Schieben, Aufziehen und
   Schreiben laufen dort alle über Zeiger. Die Leisten behalten ihr
   Wischen (eine Reihe auf Touch), die Liste ihren Bildlauf.
   ===================================================================== */

.hf-ico { display: block; width: 18px; height: 18px; flex: none; }
.pp-btn .hf-ico { display: inline-block; width: 16px; height: 16px; margin-right: 6px; vertical-align: -3px; }

/* ---------------- Die Liste ---------------- */
.hf-lokal {
  margin: 0 0 var(--pp-sp-4); font-size: var(--pp-fs-klein); line-height: var(--pp-lh-text);
  color: var(--pp-text-2);
}
.hf-warn {
  margin: 0 0 var(--pp-sp-4); padding: var(--pp-sp-3) var(--pp-sp-4);
  font-size: var(--pp-fs-klein); line-height: var(--pp-lh-text); color: var(--pp-text);
  background: var(--pp-warn-tint); border: 1px solid var(--pp-line); border-left: 3px solid var(--pp-warn);
  border-radius: 6px;
}
.hf-anker { display: flex; align-items: center; gap: var(--pp-sp-4); margin-bottom: var(--pp-sp-4); flex-wrap: wrap; }
.hf-anker .grow { flex: 1; min-width: 0; }
.hf-anker-sym { color: var(--pp-text-2); }
.hf-anker-sym .hf-ico { width: 22px; height: 22px; }
.hf-anker-titel { font-weight: 600; font-size: var(--pp-fs-text); line-height: var(--pp-lh-knapp); overflow-wrap: anywhere; }
.hf-neu { margin-bottom: var(--pp-sp-4); }
.hf-neu-titel { font-weight: 600; font-size: var(--pp-fs-text); margin-bottom: var(--pp-sp-3); }
.hf-neu-reihe { display: flex; flex-wrap: wrap; gap: var(--pp-sp-2); }
.hf-meldung { font-size: var(--pp-fs-klein); line-height: var(--pp-lh-text); color: var(--pp-text-2); }
.hf-meldung:empty { display: none; }
.hf-neu .hf-meldung { margin-top: var(--pp-sp-3); }
.hf-meldung.fehler { color: var(--pp-err); }
.hf-zeile { cursor: pointer; }
.hf-zeile-sym { color: var(--pp-text-2); }
.hf-zeile-titel { font-weight: 600; font-size: var(--pp-fs-text); line-height: var(--pp-lh-knapp); overflow-wrap: anywhere; }
.hf-zeile-meta { margin-top: 2px; font-size: var(--pp-fs-klein); line-height: var(--pp-lh-knapp); color: var(--pp-text-2); }
.hf-leer { font-size: var(--pp-fs-text); line-height: var(--pp-lh-text); color: var(--pp-text-2); }
.hf-leer-weg { margin-top: var(--pp-sp-3); }
/* Heft im Papierkorb (Politur 03.10.2026): ein Satz, zwei Wege — dürfen
   auf dem Telefon untereinander stehen (wrap), nie über den Rand. */
.hf-korb-satz { margin: 0; }
.hf-korb-wege { display: flex; flex-wrap: wrap; gap: var(--pp-sp-2); }
.hf-laedt { padding: var(--pp-sp-3) 0; }

/* ---------------- Die Ansicht: randlos, so hoch wie das Fenster ----------------
   Die Oberkante misst js/heft.js (obenMessen, Muster --sb-oben der
   Arbeitsfläche): Die Kopfzeile ist mal höher, mal niedriger.
   dvh nach vh: Auf dem iPad ist 100vh die Höhe OHNE Safaris Leiste — die
   Fußzeile stünde darunter. Wer dvh nicht kennt, nimmt die erste Zeile. */
.pp-page.hf-page.hf-ansicht {
  max-width: none; margin: 0; padding: 0;
  height: calc(100vh - var(--hf-oben, 54px));
  height: calc(100dvh - var(--hf-oben, 54px));
  display: flex; flex-direction: column; min-height: 0;
  /* DER BALLEN AUSSERHALB DER BÜHNE (r2-10, 26.09.2026, Befund 22 —
     docs/TINTE-IPAD-2-2026-09-26.md): Kopf, Leisten und Zeichenleiste
     liegen neben der Bühne, und dort gilt weder touch-action: none noch
     user-select: none — ein Handballen, der über die Symbole rutscht,
     MARKIERTE sie (WebKit wählt SVG und Knopftext aus). Die ganze Ansicht
     ist jetzt unauswählbar; Textfelder nehmen sich ihre Auswahl darunter
     zurück. touch-action: pan-x pan-y lässt die Leisten wischen und die
     Listen rollen, verbietet aber den Pinch- und Doppeltipp-Zoom der
     SEITE — ein Handgelenk über einer Leiste zoomte sonst Safari, nicht
     das Blatt. Die Bühne bleibt bei none (die Schnittmenge entscheidet). */
  user-select: none; -webkit-user-select: none; -webkit-touch-callout: none;
  touch-action: pan-x pan-y;
}
.hf-ansicht input, .hf-ansicht textarea, .hf-ansicht [contenteditable="true"], .hf-ansicht .zg-textbox {
  user-select: text; -webkit-user-select: text;
}
/* Paket H (17.10.2026, js/heft.js seitenZoomAus): WebKit beginnt die
   Schnittmenge des touch-action an JEDEM Bildlauf-Kasten neu (overflow
   auto/scroll) — dort galt wieder „auto", und ein Handgelenk mit zwei
   Kontakten auf Reitern, Zeichenleiste, ⋯-Liste, Randspalte oder
   Seitenleiste zoomte Safaris Seite. Diese Kästen rollen weiter, zoomen
   aber nicht. */
.hf-ansicht .hf-leiste, .hf-ansicht .hf-doks, .hf-ansicht .zg-leiste, .hf-ansicht .hf-rand,
.hf-ansicht .hf-sync-liste, .hf-ansicht .psl-liste {
  touch-action: pan-x pan-y;
}
/* Solange die Ansicht einen Stift gesehen hat (Marke am body,
   js/heft.js stiftKlasse): auch Kopfzeile und Seitenleiste der App sind
   unauswählbar, und die Seite selbst kennt keinen Pinch-Zoom mehr — der
   Ballen landet auch dort. Weg mit dem Schließen der Ansicht. */
body.hf-stift .pp-top, body.hf-stift .pp-mtop, body.hf-stift .pp-side {
  user-select: none; -webkit-user-select: none; -webkit-touch-callout: none;
}
body.hf-stift { touch-action: pan-x pan-y; }
/* Solange der Stift AKTIV ist (aufliegend oder vor weniger als zwei
   Sekunden gehoben — Marke hf-stift-aktiv, js/heft.js stiftAktiv; P5,
   12.10.2026, Ursache 4): die ganze App unauswählbar und ohne Aufklappmenü.
   Im eingebetteten Heft liegt der Aufgabentext direkt neben dem Papier —
   ein Stift, der das Blatt um Millimeter verfehlt, begann dort eine
   iOS-Textauswahl, und das Auswahlmenü stand über dem Heft. Textfelder
   nehmen sich die Auswahl zurück. */
body.hf-stift-aktiv #app, body.hf-stift-aktiv .pp-top, body.hf-stift-aktiv .pp-mtop, body.hf-stift-aktiv .pp-side {
  user-select: none; -webkit-user-select: none; -webkit-touch-callout: none;
}
body.hf-stift-aktiv input, body.hf-stift-aktiv textarea, body.hf-stift-aktiv [contenteditable="true"] {
  user-select: text; -webkit-user-select: text;
}
/* st1020: Solange der Stift schreibt (hf-stift-aktiv, bis STIFT_AKTIV_MS nach
   dem Heben), beginnt KEINE Rollgeste der Seite — ein Handballen auf Kopf,
   Leiste oder Seitenleiste ließe WebKit sonst alle Web-Touches zurücknehmen
   (pointercancel an den Stift, Kontakte bis zum Ende der Geste verloren —
   „schreibt ein paar Sekunden nicht"). Preis: währenddessen rollt kein
   Finger die Seitenleiste. */
body.hf-stift-aktiv, body.hf-stift-aktiv .pp-page.hf-page.hf-ansicht { touch-action: none; }
/* W2 (21.10.2026, docs/W2-STIFT.md): dasselbe in JEDEM Bildlauf-Kasten.
   WebKit beginnt die Schnittmenge des touch-action an jedem Bildlauf-Kasten
   neu (Paket H) — ein Ballen auf der Seitenübersicht, der Zeichenleiste, dem
   KI-Fenster oder der anderen Spalte der Arbeitsumgebung durfte dort rollen,
   obwohl body und Ansicht „none" trugen. Beginnt die Rollgeste, nimmt WebKit
   alle Kontakte zurück und liefert keinen neuen, bis jede Berührung gehoben
   ist: „schreibt nicht weiter, solange der Ballen liegt". Js/heft.js hält
   die Marke, solange die Hand nach dem Stift noch aufliegt. Textfelder
   behalten ihr Verhalten. */
body.hf-stift-aktiv *:not(input):not(textarea):not([contenteditable="true"]) { touch-action: none !important; }
/* Das Messgerät (P5, js/heft.js diag): eine kleine Leiste unten links,
   der Text erst auf Klick — und auswählbar, damit er sich kopieren lässt. */
.hf-diag {
  position: fixed; left: 8px; bottom: 8px; z-index: 2000; max-width: min(96vw, 720px);
  font: 12px/1.4 var(--pp-mono, ui-monospace, monospace); color: var(--pp-text, #222);
  background: var(--pp-surface, #fff); border: 1px solid var(--pp-line, #ccc); border-radius: 8px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, .18); padding: 6px 8px;
  user-select: text; -webkit-user-select: text; touch-action: auto;
}
.hf-diag-kopf { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.hf-diag-kopf button { font: inherit; padding: 2px 8px; border: 1px solid var(--pp-line, #ccc); border-radius: 6px; background: var(--pp-bg-2, #f4f4f4); color: inherit; min-height: 28px; }
.hf-diag textarea { display: block; width: min(92vw, 700px); margin-top: 6px; font: inherit; white-space: pre; overflow: auto;
  user-select: text; -webkit-user-select: text; }
.hf-diag textarea[hidden] { display: none; }
.hf-kopf {
  flex: none; display: flex; align-items: center; flex-wrap: wrap; gap: var(--pp-sp-2);
  padding: 6px 14px; background: var(--pp-surface); border-bottom: 1px solid var(--pp-line);
}
.hf-titel {
  min-width: 0; max-width: 40ch; margin: 0; padding: 2px 4px;
  font: inherit; font-weight: 600; font-size: var(--pp-fs-text); line-height: var(--pp-lh-knapp);
  color: var(--pp-text); background: none; border: 1px solid transparent; border-radius: 6px;
  cursor: pointer; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: left;
}
.hf-titel:hover { border-color: var(--pp-line); }
/* R2: kein Stand-Text mehr — nur der eine Satz, wenn der Browser keinen
   dauerhaften Speicher hergibt (js/heft.js fluechtigHtml). */
.hf-fluechtig { font-size: var(--pp-fs-klein); line-height: var(--pp-lh-knapp); color: var(--pp-err); white-space: nowrap; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
/* Die Kurswahl im Kopf (Plan 10 F): darf schrumpfen, nie den Kopf sprengen. */
.hf-kurs-wirt { flex: 0 1 auto; min-width: 0; display: inline-flex; }
/* Die Klasse pp-select hatte bis K3-P6 keine eigene Regel — ohne diese stand im
   dunklen Theme ein weißes Browser-Auswahlfeld im Kopf (WebKit gemessen). Seit
   K3-P6 gibt es die allgemeine Regel in css/prepp.css; diese hier bleibt die
   genauere für den Heftkopf (später geladen, gleiche Spezifität). */
.hf-kurs { max-width: 200px; min-width: 0;
  border: 1px solid var(--pp-line-feld); background: var(--pp-surface); color: var(--pp-text);
  border-radius: 6px; padding: 6px 28px 6px 8px; font-size: var(--pp-fs-klein); font-family: inherit; min-height: 32px;
  /* WebKit malt ein natives Auswahlfeld in fester Höhe (21 px) und ohne
     Theme; ohne appearance greifen Höhe und Farben. Der Pfeil sind zwei
     Verläufe in der Textfarbe. */
  -webkit-appearance: none; appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, var(--pp-text-2) 50%), linear-gradient(135deg, var(--pp-text-2) 50%, transparent 50%);
  background-position: calc(100% - 14px) 50%, calc(100% - 9px) 50%; background-size: 5px 5px; background-repeat: no-repeat; }
.hf-kurs:focus-visible { border-color: var(--pp-accent); }
@media (hover: none) { .hf-kurs { min-height: 44px; } }
.hf-fluechtig .hf-kurz { display: none; }
.hf-kopf-luft { flex: 1; }
.hf-link { display: inline-flex; align-items: center; gap: 2px; min-width: 0; }
.hf-link-auf, .hf-link-weg {
  display: inline-flex; align-items: center; gap: 6px; margin: 0; padding: 4px 8px; min-height: 32px;
  font: inherit; font-size: var(--pp-fs-klein); line-height: var(--pp-lh-knapp); color: var(--pp-accent-2);
  background: var(--pp-accent-tint); border: 1px solid var(--pp-accent-line); border-radius: 6px; cursor: pointer;
}
.hf-link-auf { max-width: 28ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hf-link-weg { padding: 4px; color: var(--pp-text-2); background: none; border-color: transparent; }
.hf-link-tot { font-size: var(--pp-fs-klein); color: var(--pp-text-2); }

/* ---------------- Insel und ⋯ über der Seite (UI1015-U3, 15.10.2026) ----------------
   docs/UI1015-U3-2026-10-15.md. Jonas: „Um Platz zu sparen, mache diese
   Leiste zu einer Insel, die über der Seite in der Mitte schwebt." Die
   Schwebe liegt in .hf-mitte über der Bühne (Geschwister, nicht Kind — die
   Bühne fängt jeden Zeiger ein) und lässt selbst jeden Zeiger durch: Nur
   Insel und ⋯ nehmen Klicks an, daneben schreibt der Stift wie vorher.
   Links rückt sie neben die angedockte Seitenleiste (216 px), rechts vor
   die Randspalte (260 px) — mittig über der SEITE, nicht über dem Fenster.
   Unter der Seitenleiste als Blatt (z-index 6) liegt sie (z-index 5). */
.hf-schwebe {
  position: absolute; top: 0; bottom: 0; left: 0; right: 0; z-index: 5;
  display: flex; justify-content: flex-start; align-items: flex-start;
  padding: 8px 60px 0; box-sizing: border-box; pointer-events: none;
}
.hf-sl-an .hf-schwebe { left: 216px; }
.hf-rand:not([hidden]) ~ .hf-schwebe { right: 260px; }
.hf-insel {
  pointer-events: auto; flex: 0 1 auto; min-width: 0; max-width: 100%; margin: 0 auto;
  display: flex; align-items: center; gap: 2px; padding: 4px 6px; box-sizing: border-box;
  background: var(--pp-surface); color: var(--pp-text);
  border: 1px solid var(--pp-line); border-radius: 14px;
  box-shadow: 0 2px 6px rgba(0, 0, 0, .08), 0 10px 28px rgba(0, 0, 0, .14);
}
.hf-insel > .hf-sl-knopf { flex: none; }
/* Die Zeichenleiste der offenen Seite (js/zeichnung.js) in der Insel: ohne
   eigenen Rahmen, und OHNE contain — die Insel schmiegt sich an ihren
   Inhalt, mit `contain: inline-size` fiele sie auf null zusammen.
   Rückgängig/Wiederholen stehen vorn (die kompakte Leiste tut das schon). */
.hf-insel .zg-leiste {
  flex: 0 1 auto; min-width: 0; contain: none; padding: 0 0 0 6px; margin-left: 4px;
  background: transparent; border: 0; border-left: 1px solid var(--pp-line); border-radius: 0;
}
.hf-insel .zg-leiste > [data-gruppe="verlauf"] { order: -2; }
/* Mit der Maus (feiner Zeiger) etwas dichter: So passt die Insel bei
   1440 px auch neben der angedockten Seitenleiste in EINE Reihe (gemessen
   890 → 840 px, Bühne 988 px). Auf dem Finger bleiben es 44 px. */
@media (pointer: fine) {
  .hf-insel .zg-leiste { gap: 2px 4px; }
  .hf-insel .zg-gruppe { padding-right: 4px; }
  .hf-insel .zg-knopf { width: 30px; }
}
/* Auf einer PDF-Seite gibt es kein Raster: Die Stufen des Editors
   legten weißes Papier über das PDF. */
.hf-insel.hf-pdfseite [data-zg-aktion="raster"] { display: none; }

/* Das ⋯ oben rechts: Knopf, daneben (eingebettet) Stand und Sync-Chip,
   darunter die Liste, senkrecht über der Seite (js/heft.js mehrSetzen —
   Überfahren, Klick, Tastatur). Die Liste scrollt, wenn das Fenster
   niedriger ist als sie. */
.hf-mehrwirt {
  position: absolute; top: 8px; right: 8px; bottom: 8px;
  display: flex; flex-direction: column; align-items: flex-end; pointer-events: none;
}
.hf-mehrkopf { display: flex; align-items: center; gap: 4px; pointer-events: auto; }
.hf-mehrkopf .hf-sync-wurzel, .hf-mehrkopf .hf-fluechtig { pointer-events: auto; }
.hf-knopf.hf-mehr-auf {
  min-width: 40px; height: 40px; font-size: var(--pp-fs-text); color: var(--pp-text);
  background: var(--pp-surface); border: 1px solid var(--pp-line); border-radius: 12px;
  box-shadow: 0 2px 6px rgba(0, 0, 0, .08), 0 10px 28px rgba(0, 0, 0, .14);
}
.hf-knopf.hf-mehr-auf[aria-expanded="true"] {
  background: var(--pp-accent-tint); color: var(--pp-accent-2); border-color: var(--pp-accent-line);
}
.hf-leiste {
  pointer-events: auto; flex: 0 1 auto; min-height: 0; overflow-x: hidden; overflow-y: auto;
  -webkit-overflow-scrolling: touch; overscroll-behavior: contain;
  display: flex; flex-direction: column; align-items: stretch; gap: 0;
  margin-top: 6px; padding: 4px 6px; min-width: 204px; box-sizing: border-box;
  background: var(--pp-surface); color: var(--pp-text);
  border: 1px solid var(--pp-line); border-radius: 12px; box-shadow: 0 6px 24px rgba(0, 0, 0, .22);
}
.hf-leiste[hidden] { display: none; }
.hf-gruppe {
  display: flex; flex-direction: column; align-items: stretch; gap: 2px;
  padding: 4px 0; border-bottom: 1px solid var(--pp-line);
}
/* b1015-A: display: flex schlug das hidden-Attribut — die KI-Gruppe
   (hf-kigruppe) und das ⋯ (hf-dokgruppe) standen auch „versteckt" da. */
.hf-gruppe[hidden] { display: none; }
.hf-gruppe:last-child { border-bottom: 0; }
/* Blättern und Zoom bleiben je EINE Reihe. */
.hf-gruppe.hf-reihe { flex-direction: row; }
.hf-gruppe.hf-reihe > .hf-knopf { flex: 1 1 0; }
.hf-leiste .hf-knopf { justify-content: flex-start; gap: 10px; padding: 0 10px; color: var(--pp-text); }
.hf-leiste .hf-reihe > .hf-knopf { justify-content: center; padding: 0 6px; }
.hf-knopf-lbl { font-size: var(--pp-fs-klein); line-height: var(--pp-lh-knapp); white-space: nowrap; }
.hf-knopf {
  display: inline-flex; align-items: center; justify-content: center; min-width: 32px; height: 32px;
  margin: 0; padding: 0 6px; font: inherit; font-size: var(--pp-fs-klein); color: var(--pp-text-2);
  background: transparent; border: 1px solid transparent; border-radius: 6px; cursor: pointer;
}
.hf-knopf:hover { background: var(--pp-surface-2); color: var(--pp-text); }
.hf-knopf:focus-visible { outline: 2px solid var(--pp-accent); outline-offset: 1px; }
/* Der EIN-Zustand ist eine FORM (Balken unten, Muster .zg-knopf). */
.hf-knopf[aria-pressed="true"] {
  background: var(--pp-accent-tint); color: var(--pp-accent-2);
  border-color: var(--pp-accent-line); box-shadow: inset 0 -2px 0 var(--pp-accent);
}
.hf-knopf:disabled { opacity: .45; cursor: default; background: transparent; }
.hf-zoomwert { min-width: 56px; font-family: var(--pp-mono); font-variant-numeric: tabular-nums; }
/* Nur für Screenreader (die Seitenzahl „Seite 2 / 5"): Sichtbar trägt
   die Seitenleiste dieselbe Auskunft. */
.hf-sr {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* ---------------- Reiter: die Dokumente des Hefts (r1-02) ----------------
   docs/HEFT-SEITEN-2026-09-25.md 1. Die Reihe wischt (eine Zeile, Bildlauf
   waagerecht); der offene Reiter trägt seinen Zustand als FORM (Balken
   oben, Fläche der Leiste darunter), nicht nur als Farbe. */
.hf-doks {
  flex: none; display: flex; align-items: flex-end; gap: 2px;
  padding: 4px 14px 0; background: var(--pp-surface-2); border-bottom: 1px solid var(--pp-line);
  overflow-x: auto; overflow-y: hidden; scrollbar-width: thin;
  -webkit-overflow-scrolling: touch; overscroll-behavior-x: contain;
}
/* F12 (r2-06): Mit einem Dokument klappt die Leiste ein — [hidden] muss
   gegen display:flex gewinnen (Falle .pp-inreq, 13.08.2026). Ihre zwei
   Wege stehen dann im ⋯ vorn in der Seitenleiste (.hf-dokgruppe). */
.hf-doks[hidden], .hf-dokgruppe[hidden] { display: none; }
.hf-dok-eins { font-size: var(--pp-fs-text); }
.hf-dok {
  flex: none; display: inline-flex; align-items: center; max-width: 30ch; margin-bottom: -1px;
  border: 1px solid transparent; border-bottom: 0; border-radius: 6px 6px 0 0;
}
.hf-dok.an { background: var(--pp-surface); border-color: var(--pp-line); box-shadow: inset 0 2px 0 var(--pp-accent); }
.hf-dok-knopf {
  display: inline-flex; align-items: center; gap: 6px; min-width: 0; min-height: 32px; margin: 0; padding: 0 10px;
  font: inherit; font-size: var(--pp-fs-klein); line-height: var(--pp-lh-knapp); color: var(--pp-text-2);
  background: none; border: 0; border-radius: 6px 6px 0 0; cursor: pointer;
}
.hf-dok-knopf .hf-ico { width: 16px; height: 16px; }
.hf-dok.an .hf-dok-knopf { color: var(--pp-text); font-weight: 600; }
.hf-dok-knopf:hover { color: var(--pp-text); }
.hf-dok-titel { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hf-dok-n { flex: none; font-family: var(--pp-mono); font-size: var(--pp-fs-mini); font-weight: 400; color: var(--pp-text-2); font-variant-numeric: tabular-nums; }
.hf-dok-mehr, .hf-dok-plus {
  display: inline-flex; align-items: center; justify-content: center; gap: 4px; margin: 0;
  font: inherit; font-size: var(--pp-fs-klein); line-height: var(--pp-lh-eng); color: var(--pp-text-2);
  background: transparent; border: 1px solid transparent; border-radius: 6px; cursor: pointer;
}
.hf-dok-mehr { flex: none; min-width: 28px; height: 28px; margin-right: 4px; padding: 0 4px; }
.hf-dok-plus { flex: none; min-height: 30px; margin: 0 0 2px 4px; padding: 0 10px; }
.hf-dok-plus .hf-ico { width: 16px; height: 16px; }
.hf-dok-mehr:hover, .hf-dok-plus:hover { background: var(--pp-surface); color: var(--pp-text); border-color: var(--pp-line); }
/* Das ⋯ steht an JEDEM Reiter, sichtbar am offenen; an den anderen erst
   unter dem Zeiger oder mit dem Fokus. `visibility` statt `display`: Der
   Platz bleibt reserviert, die Reiter rücken beim Wechsel nicht (gemessen
   35 px, docs/HEFT-SEITEN-2026-09-25.md 1), und ein verstecktes ⋯ ist
   weder klick- noch fokussierbar. */
.hf-dok:not(.an) .hf-dok-mehr { visibility: hidden; }
.hf-dok:not(.an):focus-within .hf-dok-mehr { visibility: visible; }
@media (hover: hover) { .hf-dok:not(.an):hover .hf-dok-mehr { visibility: visible; } }
.hf-dok-knopf:focus-visible, .hf-dok-mehr:focus-visible, .hf-dok-plus:focus-visible { outline: 2px solid var(--pp-accent); outline-offset: 1px; }

/* ---------------- Die Bühne ---------------- */
.hf-buehne {
  position: relative; flex: 1; min-height: 0; overflow: hidden;
  background: var(--pp-bg-2);
  touch-action: none; overscroll-behavior: contain;
  user-select: none; -webkit-user-select: none; -webkit-touch-callout: none;
}
.hf-buehne.hf-bewegen, .hf-buehne.hf-bewegen .zg-flaeche { cursor: grab; }
.hf-buehne.hf-schiebt, .hf-buehne.hf-schiebt .zg-flaeche { cursor: grabbing; }
.hf-welt { position: absolute; left: 0; top: 0; transform-origin: 0 0; }
/* Absolut, damit beim Scrollen mehrere Blätter untereinander liegen
   können (top setzt js/heft.js, blattGroesse). */
.hf-blatt {
  position: absolute; left: 0; top: 0; background: #fff;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .18), 0 8px 24px rgba(0, 0, 0, .12);
}
/* Bilder und Griffe (r1-02): Die Bilder liegen zwischen dem PDF und der
   Tinte, die Griffe darüber. Ohne z-index (siehe .hf-zg) — die Reihenfolge
   ist die des Dokuments. */
.hf-bilder, .hf-rahmen { position: absolute; left: 0; top: 0; width: 100%; height: 100%; pointer-events: none; }
.hf-bilder:empty, .hf-rahmen:empty { display: none; }
.hf-bild {
  position: absolute; display: block; max-width: none; margin: 0;
  user-select: none; -webkit-user-select: none; -webkit-user-drag: none; pointer-events: none;
}
/* Auf Papier mit einem Bild darauf verschwindet das weiße Papier der
   Zeichnung über dem Bild — Raster und Tinte bleiben (wie im Export). */
.hf-blatt.hf-mitbild .zg-svg { mix-blend-mode: multiply; }
/* W2 (21.10.2026, docs/W2-STIFT.md): ebenso auf einer PDF- oder Bild-Seite —
   die Tinte liegt mit „multiply" auf der Seite darunter, wie im Export
   (js/heft.js seiteRastern, tinteRastern). Der Marker färbt so nur das
   Papier, die Schrift darunter bleibt schwarz, auch wo WebKit die Mischung
   der SVG-Kinder nicht bis zur Leinwand trägt (die PDF-Seite ist eine
   eigene Ebene): Gemischt wird dann die ganze Tinte gegen die Seite. */
.hf-pdf:not([hidden]) ~ .hf-zg .zg-svg, .hf-bilder:not(:empty) ~ .hf-zg .zg-svg { mix-blend-mode: multiply; }
/* Rahmen und Griffe nur mit „Bewegen" — sonst schreibt der Stift durch
   das Bild hindurch aufs Blatt. */
.hf-bildrahmen {
  display: none; position: absolute; box-sizing: border-box;
  border: 2px dashed var(--pp-accent); pointer-events: auto; cursor: move;
}
.hf-buehne.hf-bewegen .hf-bildrahmen { display: block; }
.hf-bildrahmen.hf-zieht { border-style: solid; }
/* bf1022-H2 (docs/BF1022-H2.md): ein mit dem Auswahlwerkzeug GEWÄHLTES Foto —
   sein Rahmen steht auch ohne „Bewegen", durchgezogen und leicht gefüllt wie
   jede Auswahl im Heft; am Rahmen verschiebt man es. ✕, Drehen und der Griff
   gehören zu „Bewegen" — gelöscht wird über die Leiste daneben. */
.hf-bildrahmen.hf-gewaehlt { display: block; border-style: solid; background: color-mix(in srgb, var(--pp-accent) 10%, transparent); }
.hf-buehne:not(.hf-bewegen) .hf-bildrahmen.hf-gewaehlt .hf-bild-weg,
.hf-buehne:not(.hf-bewegen) .hf-bildrahmen.hf-gewaehlt .hf-bild-dreh,
.hf-buehne:not(.hf-bewegen) .hf-bildrahmen.hf-gewaehlt .hf-bild-griff { display: none; }
.hf-bild-weg {
  position: absolute; top: -14px; right: -14px; width: 28px; height: 28px; margin: 0; padding: 0;
  display: inline-flex; align-items: center; justify-content: center; cursor: pointer;
  color: var(--pp-text); background: var(--pp-surface); border: 1px solid var(--pp-line); border-radius: 50%;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .25);
}
.hf-bild-weg .hf-ico { width: 14px; height: 14px; }
.hf-bild-weg:focus-visible { outline: 2px solid var(--pp-accent); outline-offset: 1px; }
/* Drehen (F2): dieselbe Scheibe wie ✕, an der anderen oberen Ecke. */
.hf-bild-dreh {
  position: absolute; top: -14px; left: -14px; width: 28px; height: 28px; margin: 0; padding: 0;
  display: inline-flex; align-items: center; justify-content: center; cursor: pointer;
  color: var(--pp-text); background: var(--pp-surface); border: 1px solid var(--pp-line); border-radius: 50%;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .25);
}
.hf-bild-dreh .hf-ico { width: 14px; height: 14px; }
.hf-bild-dreh:focus-visible { outline: 2px solid var(--pp-accent); outline-offset: 1px; }
/* „Noch eins" (F3): ein Knopf mit Wort — die Serie soll man sehen. */
.hf-noch { width: auto; gap: 4px; padding: 0 10px; font-weight: 600; }
.hf-noch[hidden] { display: none; }
.hf-bild-griff {
  position: absolute; right: -8px; bottom: -8px; width: 16px; height: 16px; box-sizing: border-box;
  background: var(--pp-accent); border: 2px solid var(--pp-surface); border-radius: 4px; cursor: nwse-resize;
}
/* Der Dialog „Bild einfügen": zwei Wege als große Knöpfe. Der Rumpf eines
   Portal-Dialogs bringt keinen Seitenabstand mit — dieser bringt seinen. */
.hf-bildwahl { padding: 0 16px 4px; }
.hf-bildwahl-knoepfe { display: flex; flex-direction: column; gap: var(--pp-sp-2); }
.pp-btn.hf-bildwahl-knopf {
  display: flex; flex-direction: column; align-items: flex-start; gap: 2px; width: 100%;
  min-height: 56px; padding: 8px 12px; text-align: left; white-space: normal;
}
.hf-bildwahl-was { font-weight: 600; font-size: var(--pp-fs-text); line-height: var(--pp-lh-knapp); }
.hf-bildwahl-wie { font-size: var(--pp-fs-klein); line-height: var(--pp-lh-knapp); }
.hf-bildwahl-fuss { display: flex; justify-content: flex-end; margin-top: var(--pp-sp-3); }
.hf-pdf { position: absolute; left: 0; top: 0; width: 100%; height: 100%; display: block; }
.hf-pdf[hidden] { display: none; }
/* KEIN z-index: Sonst entstünde ein eigener Stapelkontext, und der
   Textmarker („multiply") färbte nur noch in sich statt über dem PDF. */
.hf-zg { position: relative; }
.hf-zg .zg-editor { gap: 0; }
.hf-zg .zg-flaeche { border: 0; border-radius: 0; background: transparent; }
.hf-laedt-ueber { position: absolute; left: 0; right: 0; top: 40%; text-align: center; }
.hf-fuss { flex: none; padding: 0 14px; background: var(--pp-surface); }
.hf-fuss .hf-meldung, .hf-zgstatus .zg-status { padding: 4px 0; }
.hf-zgstatus:empty { display: none; }

/* ---------------- Touch: eine wischende Reihe, 44 px ---------------- */
@media (hover: none), (max-width: 760px) {
  .hf-ansicht .zg-leiste {
    flex-wrap: nowrap; overflow-x: auto; overflow-y: hidden;
    -webkit-overflow-scrolling: touch; overscroll-behavior-x: contain;
  }
  .hf-ansicht .zg-gruppe { flex: none; flex-wrap: nowrap; }
}
@media (hover: none) {
  .hf-knopf { min-width: 44px; height: 44px; }
  /* Die Zoomzahl behält ihre 56 px (Politur 03.10.2026): Die Zeile
     darüber hob sie auf dem Finger auf 44 — gleiche Spezifität, später
     im Text —, und „100 %" passt nicht in 44 px. Sie steht NACH der
     44er Regel, sonst gewönne die wieder. */
  .hf-zoomwert { min-width: 56px; white-space: nowrap; }
  .hf-knopf.hf-mehr-auf { min-width: 44px; height: 44px; }
  .hf-dok-knopf, .hf-dok-plus { min-height: 44px; }
  .hf-dok-plus { min-width: 44px; }   /* ohne „Neu" war er 38 px breit (Abnahme 390 px) */
  .hf-dok-mehr { min-width: 44px; height: 44px; }
  .hf-bild-weg { width: 44px; height: 44px; top: -22px; right: -22px; }
  .hf-bild-dreh { width: 44px; height: 44px; top: -22px; left: -22px; }
  .hf-bild-griff::before { content: ""; position: absolute; left: -14px; top: -14px; right: -14px; bottom: -14px; }
  .hf-bildwahl-fuss .pp-btn { min-height: 44px; }
  .hf-kopf .pp-btn, .hf-neu-reihe .pp-btn, .hf-anker .pp-btn, .hf-leer-weg .pp-btn { min-height: 44px; }
  .hf-kopf > .pp-btn { min-width: 44px; justify-content: center; }
  .hf-titel { min-height: 44px; }
  .hf-link-auf, .hf-link-weg { min-height: 44px; }
  .hf-link-weg { min-width: 44px; justify-content: center; }
  .hf-zeile .pp-actions .pp-btn { min-width: 44px; min-height: 44px; }
}
/* Auf dem Telefon steht der Kopf in EINER Zeile: Zurück, Titel (gibt
   nach), Stand (kurz), Druck und Export als Symbol — Beschriftung in
   title/aria-label. Gemessen: Drei Zeilen Kopf ließen der Seite 450 von
   844 px (docs/abnahme/heft-0924/BERICHT.md). */
@media (max-width: 760px) {
  .hf-kopf { padding: 4px 8px; flex-wrap: nowrap; }
  .hf-kopf .hf-lbl, .hf-kopf-luft { display: none; }
  .hf-kopf .pp-btn .hf-ico { margin-right: 0; }
  .hf-kopf > .pp-btn { flex: none; }
  .hf-titel { flex: 1 1 auto; max-width: none; }
  /* MITSCHRIFT-R4 (p3 #12: „Üb…" bei 390 px): Der Titel darf auf dem
     Telefon in ZWEI Zeilen stehen — in derselben 44-px-Zeile des Kopfs,
     etwas kleiner; der Kurs gibt dafür auf ein Viertel der Breite nach. */
  .hf-kopf .hf-titel {
    white-space: normal; font-size: var(--pp-fs-klein); line-height: var(--pp-lh-knapp);
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; word-break: break-word;
  }
  .hf-kopf .hf-kurs-wirt { max-width: 25vw; }
  .hf-fluechtig { flex: none; }
  .hf-fluechtig .hf-lang { display: none; }
  .hf-fluechtig .hf-kurz { display: inline; }
  .hf-link { flex: 0 1 auto; }
  .hf-link-auf { max-width: 12ch; }
  .hf-doks { padding-left: 8px; padding-right: 8px; }
  .hf-dok-plus-lbl { display: none; }
  .hf-dok { max-width: 22ch; }
  /* UI1015-U3: Die Insel nimmt die Breite bis auf das ⋯ rechts — am
     Telefon wischt ihre Zeichenleiste (kompakt), die Seite läuft nie über.
     Die Randspalte steht hier UNTER der Bühne, sie nimmt rechts nichts weg. */
  .hf-schwebe { padding: 6px 56px 0 6px; }
  .hf-rand:not([hidden]) ~ .hf-schwebe { right: 0; }
  .hf-insel { margin-left: 0; }
  .hf-mehrwirt { top: 6px; right: 6px; bottom: 6px; }
  /* Die lockere Klemme (r1-02, docs/HEFT-SEITEN-2026-09-25.md 4): Auf dem
     Telefon liegt die Fußzeile (Meldung, Status des Editors) ÜBER der
     Bühne statt unter ihr — die Bühne reicht bis an den unteren Rand, und
     das Blatt rollt unter die Zeile, statt an ihr abgeschnitten zu werden.
     Ein z-index reicht; leer trägt die Zeile ohnehin keine Höhe. */
  .pp-page.hf-page.hf-ansicht { position: relative; }
  .hf-fuss { position: absolute; left: 0; right: 0; bottom: 0; z-index: 2; }
}

/* ---------------- Eingebettet im Arbeitsfenster (r2-09, 26.09.2026) ----------------
   docs/ARBEITSFENSTER-2026-09-26.md 2.4: dieselbe Ansicht im angedockten
   Fenster neben einer Aufgabe. Die HOEHE kommt aus dem Wirt statt aus
   100vh (die Kette Koerper → Slot → Wirt → Root gibt ganz nach, Muster
   .sbf-wirt; --hf-oben wird weiter gemessen, wirkt hier aber nicht —
   hoehere Spezifitaet), und die Leisten sind KOMPAKT wie auf dem Telefon:
   dieselben Regeln wie die Medienabfragen oben, nur mit einem zweiten
   Geltungsbereich. */
.pp-page.hf-page.hf-ansicht.hf-eingebettet { height: 100%; min-height: 0; }
.hf-eingebettet .zg-leiste {
  flex-wrap: nowrap; overflow-x: auto; overflow-y: hidden;
  -webkit-overflow-scrolling: touch; overscroll-behavior-x: contain;
}
.hf-eingebettet .zg-gruppe { flex: none; flex-wrap: nowrap; }
/* Die Spalte ist schmal: die Insel links, das ⋯ rechts daneben. */
.hf-eingebettet .hf-schwebe { padding: 6px 56px 0 6px; }
.hf-eingebettet .hf-insel { margin-left: 0; }
.hf-eingebettet .hf-mehrwirt { top: 6px; right: 6px; bottom: 6px; }
/* Kompakter Kopf im Dock (wa-2, 27.09.2026): Eingebettet gibt es keine
   .hf-kopf mehr — das ⋯ des Hefts steht als erste Gruppe in der Liste des
   ⋯ über der Seite, Stand und Sync daneben (seit UI1015-U3, js/heft.js
   schwebeHtml). Der Stand in der Kurzfassung, der
   Sync-Knopf nur als Punkt (das Wort steht in title/aria-label, sein ⋯
   geht — beide Wege stehen auch im Panel, dieselbe Regel wie auf dem
   Telefon). Gemessen (WebKit, iPad quer): Chrome über dem Blatt 227 → 174
   px, vier Zeilen → drei. docs/abnahme/stufe2-0927/BERICHT.md, wa-2. */
.hf-eingebettet .hf-fluechtig { flex: none; }
/* Trefferflächen im Dock: 44 px auf jedem groben Zeiger — nicht nur unter
   (hover: none) bzw. bis 1200 px Breite wie die Regeln der vollen Seite
   (ein iPad Pro quer ist breiter). */
@media (pointer: coarse) {
  .hf-eingebettet .hf-knopf { min-width: 44px; height: 44px; }
  .hf-eingebettet .hf-mehrkopf .hf-sync-knopf { min-width: 44px; height: 44px; }
}
.hf-eingebettet .hf-fluechtig .hf-lang { display: none; }
.hf-eingebettet .hf-fluechtig .hf-kurz { display: inline; }
.hf-eingebettet .hf-doks { padding-left: 8px; padding-right: 8px; }
.hf-eingebettet .hf-dok-plus-lbl { display: none; }
.hf-eingebettet .hf-dok { max-width: 22ch; }
/* Die Bühne braucht im Fenster eine Mindesthoehe, sonst faellt sie im
   gestapelten (unten) Fenster auf null. */
.hf-eingebettet .hf-buehne { min-height: 160px; }
/* Scrollhinweis der wischenden Leisten (MITSCHRIFT-R4, p4 #7 und p3 #12):
   Folgt rechts noch etwas (js/heft.js ueberlaufPruefen), blendet der Rand
   auf den letzten 32 px aus — ein halber Knopf am Rand sagte vorher nicht,
   dass die Leiste wischt. Am Ende angekommen, verschwindet die Blende. */
.hf-leiste.hf-ueber-rechts, .zg-leiste.hf-ueber-rechts {
  -webkit-mask-image: linear-gradient(to right, rgba(0, 0, 0, 1) calc(100% - 32px), rgba(0, 0, 0, .15));
  mask-image: linear-gradient(to right, rgba(0, 0, 0, 1) calc(100% - 32px), rgba(0, 0, 0, .15));
}
/* sim1016-R4: Die Zeichenleiste zeigt ihr Weiterrollen selbst — ein Rand
   mit Winkel (css/zeichnung.css .zg-rollt); die Blende darüber machte den
   Winkel wieder blass. */
.zg-leiste.hf-ueber-rechts.zg-rollt { -webkit-mask-image: none; mask-image: none; }

/* ---------------- Druck (PreppDruck.container, Klasse hfd) ----------------
   Je Seite ein Blatt. Das Bild ist schon gerastert (dieselben Raster wie
   der Export, ohne eigenen Streifen — die Fußzeile des Containers trägt
   das Wasserzeichen). */
.pp-druck.hfd .hfd-blatt { break-after: page; page-break-after: always; break-inside: avoid; }
.pp-druck.hfd .hfd-blatt:last-child { break-after: auto; page-break-after: auto; }
.pp-druck.hfd .hfd-seite { display: block; max-width: 100%; max-height: 262mm; width: auto; height: auto; margin: 0 auto; }

/* ---------------- Die Randspalte (Stufe 2, Paket 07-3) ----------------
   docs/HEFT-LIVE-2026-09-24.md. Bis Fokus Y3 (15.10.2026) stand hier auch
   der „Live"-Knopf der Kopfzeile samt Panel — den gibt es nicht mehr: Das
   Mitlesen schaltet und zeigt „Mitdenken" (js/vorlesung-live.js,
   css/vorlesung-live.css). Die Randspalte bleibt für VORHANDENE Notizen.
   Sie ist ein Geschwister der Bühne in .hf-mitte, NICHT ihr Kind: Die
   Bühne fängt jeden Zeiger ein (pointerdown in der Einfangphase,
   touch-action: none), ein Knopf darin bekäme keinen Klick und keine Liste
   ihr Wischen. */
.hf-mitte { flex: 1; min-height: 0; display: flex; }

.hf-rand {
  flex: none; width: 260px; min-height: 0; overflow-y: auto; -webkit-overflow-scrolling: touch;
  padding: var(--pp-sp-3) 14px; background: var(--pp-surface); border-left: 1px solid var(--pp-line);
  font-size: var(--pp-fs-klein); line-height: var(--pp-lh-text); color: var(--pp-text);
}
.hf-rand[hidden] { display: none; }
.hf-rand-kopf { font-weight: 600; margin-bottom: var(--pp-sp-2); }
.hf-rand-n {
  display: inline-block; min-width: 18px; padding: 0 5px; margin-left: 4px; text-align: center;
  font-family: var(--pp-mono); font-weight: 500; color: var(--pp-accent-2); background: var(--pp-accent-tint);
  border-radius: 9px;
}
.hf-notiz {
  position: relative; margin-bottom: var(--pp-sp-2); padding: var(--pp-sp-2) 30px var(--pp-sp-2) var(--pp-sp-3);
  background: var(--pp-warn-tint); border: 1px solid var(--pp-line); border-left: 3px solid var(--pp-warn);
  border-radius: 6px; overflow-wrap: anywhere;
}
.hf-notiz.neu { border-left-color: var(--pp-accent); }
/* Ein Hinweis zum nächsten Schritt ist kein Fehler: eigene Fläche und das
   Wort „Hinweis" vor der Zeit — nicht nur eine andere Farbe. */
.hf-notiz.hinweis { background: var(--pp-accent-tint); border-left-color: var(--pp-accent-line); }
.hf-notiz-art { font-family: var(--pp-sans); font-weight: 600; color: var(--pp-accent-2); }
.hf-notiz-zeit { font-family: var(--pp-mono); font-size: var(--pp-fs-mini); color: var(--pp-text-2); }
.hf-notiz-weg {
  position: absolute; right: 2px; top: 2px; width: 26px; height: 26px; margin: 0; padding: 0;
  font: inherit; font-size: var(--pp-fs-text); line-height: var(--pp-lh-eng); color: var(--pp-text-2);
  background: transparent; border: 1px solid transparent; border-radius: 6px; cursor: pointer;
}
.hf-notiz-weg:hover { background: var(--pp-surface-2); color: var(--pp-text); }
.hf-rand-leer { color: var(--pp-text-2); }
.hf-rand-andere { margin-top: var(--pp-sp-3); color: var(--pp-text-2); }
.hf-rand-sprung {
  display: inline-block; margin: 2px 2px 0 0; padding: 2px 8px; min-height: 26px;
  font: inherit; font-size: var(--pp-fs-klein); color: var(--pp-accent-2); background: var(--pp-accent-tint);
  border: 1px solid var(--pp-accent-line); border-radius: 6px; cursor: pointer;
}
@media (max-width: 760px) {
  .hf-mitte { flex-direction: column; }
  .hf-rand { width: auto; max-height: 34%; padding-left: 8px; padding-right: 8px; border-left: 0; border-top: 1px solid var(--pp-line); }
}
@media (hover: none) {
  .hf-notiz { padding-right: 48px; }
  .hf-notiz-weg { width: 44px; height: 44px; }
  .hf-rand-sprung { min-height: 44px; }
}

/* ---------------- Die Synchronisation (Stufe 2, Paket r2-05; R2 13.10.2026) --
   Seit R2 (docs/APP-R2-HEFT-KOPF-2026-10-13.md) steht im Kopf KEIN Sync-Knopf
   mehr, nur bei Bedarf ein CHIP (Wirt #hf-sync, js/heft-sync.js): Konflikt,
   Fehler, Pass abgelaufen, im Konto gelöscht — alle in der Warnfarbe, mit
   kurzem Wort und eckigem Punkt (Form, nicht nur Farbe). Die Trefferfläche
   ist 44 px hoch, auch wo der Chip selbst 30 px misst (::before). */
.hf-sync-wurzel { flex: 0 0 auto; position: relative; display: inline-flex; align-items: center; gap: 2px; }
.hf-sync-wurzel[hidden] { display: none; }
.hf-sync-knopf {
  position: relative; display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  box-sizing: border-box; height: 30px; min-width: 44px; margin: 0; padding: 0 10px;
  font-family: inherit; font-size: var(--pp-fs-klein); font-weight: 600; line-height: var(--pp-lh-eng);
  color: var(--pp-text); background: var(--pp-warn-tint); border: 1px solid var(--pp-warn); border-radius: 999px;
  cursor: pointer; white-space: nowrap;
}
.hf-sync-knopf::before { content: ""; position: absolute; left: 0; right: 0; top: 50%; height: 44px; transform: translateY(-50%); }
.hf-sync-knopf:hover { box-shadow: inset 0 -2px 0 var(--pp-warn); }
.hf-sync-knopf:focus-visible, .hf-sync-link:focus-visible { outline: 2px solid var(--pp-accent); outline-offset: 1px; }
.hf-sync-punkt { width: 8px; height: 8px; border-radius: 2px; background: var(--pp-warn); flex: none; box-sizing: border-box; }
/* Das Panel hängt IN der Wurzel (Muster .pp-timer-pop), rechtsbündig; läuft
   es am linken Rand aus dem Bild, schiebt js/heft-sync.js es zurück. */
.hf-sync-pop { position: absolute; top: 100%; right: 0; z-index: 120; padding-top: 8px; }
.hf-sync-pop[hidden] { display: none; }
.hf-sync {
  box-sizing: border-box; width: 320px; max-width: calc(100vw - 24px);
  display: flex; flex-direction: column; gap: var(--pp-sp-2); padding: 10px 12px;
  background: var(--pp-surface); border: 1px solid var(--pp-line-2); border-radius: 10px; box-shadow: var(--pp-lift);
  font-size: var(--pp-fs-klein); line-height: var(--pp-lh-knapp); color: var(--pp-text-2); text-align: left; white-space: normal;
}
.hf-sync-kopf { font-weight: 600; font-size: var(--pp-fs-text); color: var(--pp-text); }
.hf-sync-zeile { display: flex; align-items: center; flex-wrap: wrap; gap: var(--pp-sp-2); }
.hf-sync-satz { line-height: var(--pp-lh-text); color: var(--pp-text-2); }
.hf-sync .pp-btn:disabled { opacity: .5; cursor: default; }
/* Die Stand-Zeile bricht um statt abzuschneiden: abgeschnitten fehlte der
   Grund eines Stopps. */
.hf-sync-stand { min-width: 0; line-height: var(--pp-lh-text); overflow-wrap: anywhere; }
.hf-sync-stand:empty { display: none; }
.hf-sync-stand.fehler { color: var(--pp-err); }
.hf-sync-geraet { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 8px; overflow-wrap: anywhere; }
.hf-sync-geraet b { color: var(--pp-text); font-weight: 600; }
.hf-sync-liste { display: flex; flex-direction: column; gap: 6px; max-height: 40vh; overflow-y: auto; }
.hf-sync-liste:empty { display: none; }
/* D1: Was der Server verworfen, überschrieben oder als Konflikt abgelegt
   hat. Die Art steht als Rand links (eine Form), der Satz daneben sagt sie
   in Worten. */
.hf-sync-d1 {
  padding: 6px 8px; line-height: var(--pp-lh-text); color: var(--pp-text); overflow-wrap: anywhere;
  background: var(--pp-surface-2); border: 1px solid var(--pp-line); border-left: 3px solid var(--pp-text-3); border-radius: 6px;
}
.hf-sync-d1.konflikt { background: var(--pp-warn-tint); border-left-color: var(--pp-warn); }
.hf-sync-d1.verworfen, .hf-sync-d1.ueberschrieben, .hf-sync-d1.gross, .hf-sync-d1.unlesbar { border-left-color: var(--pp-err); }
.hf-sync-d1-knoepfe { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 4px; }
.hf-sync-link {
  display: inline-flex; align-items: center; min-height: 28px; margin: 0; padding: 2px 8px;
  font: inherit; font-size: var(--pp-fs-klein); line-height: var(--pp-lh-knapp); color: var(--pp-accent-2);
  background: var(--pp-accent-tint); border: 1px solid var(--pp-accent-line); border-radius: 6px; cursor: pointer;
}
.hf-sync-link.gefahr { color: var(--pp-err); background: transparent; border-color: var(--pp-line); }
.hf-sync-link[hidden] { display: none; }
.hf-sync-fuss { display: flex; flex-wrap: wrap; gap: 4px; padding-top: 6px; border-top: 1px solid var(--pp-line); }
/* Das Kästchen im Lösch-Dialog („auch aus meinem Konto"). */
.hf-sync-mit { display: flex; align-items: flex-start; gap: 8px; margin-top: var(--pp-sp-3); line-height: var(--pp-lh-text); color: var(--pp-text); cursor: pointer; }
.hf-sync-mit input { margin: 3px 0 0; flex: none; }

/* Eine Seite aus dem Konto, deren Tinte noch nicht hier ist: Platzhalter
   AUF DEM PAPIER (das Blatt bleibt in beiden Themes weiß — deshalb eine
   feste Farbe, kein Token: ein Token wäre im dunklen Theme hell auf weiß). */
.hf-blatt-laedt .hf-zg { position: absolute; left: 0; top: 0; width: 100%; height: 100%; }
.hf-seite-laedt {
  display: flex; align-items: center; justify-content: center; height: 100%; padding: 0 16px; box-sizing: border-box;
  font-size: var(--pp-fs-text); line-height: var(--pp-lh-text); color: #4f5661; text-align: center;
}
/* FX1019-V2 (docs/FX1019-V2.md, Jonas' Punkt 4): Der kleine Lade-Hinweis
   auf einem Blatt, dessen PDF oder Grundbild noch nicht gemalt ist — eine
   Pille oben auf dem Papier, zwischen PDF-Leinwand und Tinte, OHNE
   Zeiger-Ereignisse (schreiben geht weiter). Feste Farben wie
   .hf-seite-laedt: Das Blatt ist in beiden Themes weiß. Der Ring dreht nur
   mit Animationen (pp-anim am body, docs/ANIMATIONEN.md); ohne sie steht
   er still, mit sichtbarer Lücke — pixelgleich derselbe Ring. */
.hf-seite-lade {
  position: absolute; left: 50%; top: 7%; transform: translateX(-50%);
  display: inline-flex; align-items: center; gap: 8px; padding: 6px 12px; border-radius: 999px;
  background: rgba(255, 255, 255, .92); border: 1px solid rgba(0, 0, 0, .12); box-shadow: 0 1px 4px rgba(0, 0, 0, .12);
  font-size: var(--pp-fs-klein); line-height: var(--pp-lh-knapp); color: #4f5661; white-space: nowrap;
  pointer-events: none; user-select: none; -webkit-user-select: none;
}
.hf-seite-lade-ring {
  width: 14px; height: 14px; flex: none; border-radius: 50%; box-sizing: border-box;
  border: 2px solid rgba(79, 86, 97, .25); border-top-color: #4f5661;
}
.pp-anim .hf-seite-lade-ring { animation: hf-seite-lade-dreh .9s linear infinite; }
@keyframes hf-seite-lade-dreh { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .pp-anim .hf-seite-lade-ring { animation: none; } }

/* Die Liste: Hefte, die nur im Konto liegen. Dieselbe Zeile wie ein Heft
   hier, das Symbol ist eine Wolke. */
.hf-konto { margin-top: var(--pp-sp-4); }
.hf-konto-kopf { margin-bottom: var(--pp-sp-2); font-weight: 600; font-size: var(--pp-fs-text); color: var(--pp-text); }

/* Auf Touch 44 px hoch — dieselbe Abfrage wie der Live-Knopf, damit die
   Nachbarn gleich hoch bleiben. */
@media (max-width: 860px), (pointer: coarse) {
  .hf-sync-knopf { height: 44px; min-width: 44px; }
}
@media (hover: none) {
  .hf-sync .pp-btn, .hf-sync-link { min-height: 44px; }
  .hf-sync-mit { min-height: 44px; align-items: center; }
  .hf-sync-mit input { margin-top: 0; }
}
/* Auf dem Telefon steht der Kopf in EINER Zeile: der Chip etwas enger —
   sein Wort bleibt, es IST die Auskunft. */
@media (max-width: 760px) {
  .hf-sync-knopf { padding: 0 8px; }
}

/* ---------------- Die Seitenübersicht (a1014-P3, js/seitenleiste.js) ----
   Wie GoodNotes: Vorschaubilder in zwei Spalten, die Nummer darunter, die
   offene Seite umrandet. ANGEDOCKT eine Spalte links neben der Bühne
   (Geschwister in .hf-mitte, nicht ihr Kind — die Bühne fängt jeden
   Zeiger ein); als BLATT (Behälter < 640 px: Spalte der Mitschrift,
   Telefon) liegt sie über der Bühne. Die Komponente ist allgemein (.psl-*),
   das Heft gibt ihr nur den Platz (.hf-sl). Der offene Zustand ist eine
   FORM (Rahmen + Balken unter der Nummer), markiert eine zweite (Füllung
   + Ecken an Anfang und Ende) — nie nur eine Farbe. */
.hf-mitte { position: relative; }
.hf-knopf[aria-expanded="true"][data-hf-akt="seiten"] {
  background: var(--pp-accent-tint); color: var(--pp-accent-2);
  border-color: var(--pp-accent-line); box-shadow: inset 0 -2px 0 var(--pp-accent);
}
.psl[hidden] { display: none; }
.psl {
  display: flex; flex-direction: column; min-height: 0; box-sizing: border-box;
  background: var(--pp-surface); color: var(--pp-text); font-size: var(--pp-fs-klein);
}
.psl.psl-dock { flex: none; width: 216px; border-right: 1px solid var(--pp-line); }
.psl.psl-blatt { position: absolute; inset: 0; z-index: 6; box-shadow: 0 6px 24px rgba(0, 0, 0, .18); }
/* hz1020 (ab1020b S3): In der halben Spalte der Arbeitsumgebung (breite Lage) lässt
   das Blatt die Insel frei — es beginnt unter der Schwebe (Insel 42 px + Luft), statt
   das ganze Heft samt dem Knopf zu decken, der es öffnete. */
#vl-root.vl-breit .vl-heft-wirt .psl.psl-blatt { top: 56px; }
.psl-kopf {
  display: flex; align-items: center; gap: 6px; flex: none; padding: 6px 8px 6px 12px;
  border-bottom: 1px solid var(--pp-line);
}
.psl-titel { font-weight: 600; color: var(--pp-text-2); font-variant-numeric: tabular-nums; white-space: nowrap; }
.psl-luft { flex: 1; }
.psl-zu, .psl-fertig {
  display: inline-flex; align-items: center; justify-content: center; min-width: 30px; height: 30px; margin: 0;
  padding: 0 8px; font: inherit; font-size: var(--pp-fs-klein); color: var(--pp-text-2); background: transparent;
  border: 1px solid transparent; border-radius: 6px; cursor: pointer;
}
.psl-zu { font-size: var(--pp-fs-text); }
.psl-zu:hover, .psl-fertig:hover { background: var(--pp-surface-2); color: var(--pp-text); }
.psl-fertig { color: var(--pp-accent-2); font-weight: 600; border-color: var(--pp-accent-line); background: var(--pp-accent-tint); }
.psl-fertig[hidden] { display: none; }
.psl-zu:focus-visible, .psl-fertig:focus-visible, .psl-kachel:focus-visible { outline: 2px solid var(--pp-accent); outline-offset: 1px; }
.psl-hinweis {
  flex: none; padding: 6px 12px; color: var(--pp-text); background: var(--pp-accent-tint);
  border-bottom: 1px solid var(--pp-line); overflow-wrap: anywhere;
}
.psl-hinweis[hidden] { display: none; }
.psl-liste {
  flex: 1; min-height: 0; overflow-y: auto; -webkit-overflow-scrolling: touch; overscroll-behavior: contain;
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); align-content: start; gap: 12px 10px; padding: 12px;
}
.psl-blatt .psl-liste { grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); }
.psl-kachel {
  display: flex; flex-direction: column; align-items: stretch; gap: 4px; min-width: 0; margin: 0; padding: 3px;
  font: inherit; color: var(--pp-text-2); background: transparent; border: 2px solid transparent; border-radius: 8px;
  cursor: pointer; -webkit-user-select: none; user-select: none;
}
.psl-kachel:hover .psl-bild { border-color: var(--pp-text-2); }
.psl-bild {
  position: relative; display: block; width: 100%; overflow: hidden; box-sizing: border-box;
  /* Papier bleibt weiß — auch im dunklen Portal (wie das Blatt auf der Bühne). */
  background: #ffffff; border: 1px solid var(--pp-line); border-radius: 3px;
}
.psl-bild img { display: block; width: 100%; height: 100%; object-fit: contain; -webkit-user-drag: none; }
.psl-bild img[hidden] { display: none; }
.psl-nr {
  display: flex; align-items: center; justify-content: center; gap: 4px; min-height: 18px;
  font-family: var(--pp-mono); font-weight: 500; font-variant-numeric: tabular-nums; line-height: var(--pp-lh-eng);
}
.psl-marke {
  display: inline-block; padding: 0 4px; font-family: var(--pp-sans); font-size: var(--pp-fs-mini); font-weight: 600;
  color: var(--pp-warn); border: 1px solid var(--pp-warn); border-radius: 4px;
}
/* Paket G (17.10.2026): das ＋ hinter der letzten Seite, wie GoodNotes —
   eine leere Kachel in Miniaturgröße. Gestrichelt und ohne Papierweiß,
   damit sie nie für eine leere Seite gehalten wird; der Rand in der
   Feldfarbe (≥ 3:1, WCAG 1.4.11). Das Überfahren nur, wo es eins gibt —
   WebKit hält :hover nach einem Tipp fest. */
.psl-plus {
  display: flex; flex-direction: column; align-items: stretch; gap: 4px; min-width: 0; margin: 0; padding: 3px;
  font: inherit; color: var(--pp-text-2); background: transparent; border: 2px solid transparent; border-radius: 8px;
  cursor: pointer; -webkit-user-select: none; user-select: none;
}
.psl-plus[hidden] { display: none; }
.psl-plus .psl-plus-bild {
  display: flex; align-items: center; justify-content: center;
  background: transparent; border: 2px dashed var(--pp-line-feld); border-radius: 6px;
}
.psl-plus-zeichen { font-size: var(--pp-fs-titel); font-weight: 300; line-height: var(--pp-lh-eng); color: var(--pp-text-2); }
@media (hover: hover) {
  .psl-plus:hover .psl-plus-bild { border-color: var(--pp-accent); background: var(--pp-accent-tint); }
  .psl-plus:hover .psl-plus-zeichen { color: var(--pp-accent-2); }
}
.psl-plus:focus-visible { outline: 2px solid var(--pp-accent); outline-offset: 1px; }
/* hm1020 (20.10.2026): das Seitenmenü — Kachel und ⌄ sind Geschwister in
   einer Zelle (ein Knopf darf nicht in einem Knopf stehen). Das ⌄ sitzt in
   der Zeile der Nummer rechts, wie in GoodNotes; am Finger 32 px (das lange
   Drücken ist dort der zweite Weg). Im Markier-Modus ruht es. Langes Drücken
   auf dem Vorschaubild zeigt in WebKit sonst das System-Bildmenü. */
.psl-zelle { position: relative; display: flex; flex-direction: column; min-width: 0; }
.psl-zelle > .psl-kachel { flex: 1 1 auto; }
.psl-mit-menue .psl-kachel { -webkit-touch-callout: none; }
.psl-mit-menue .psl-nr { padding: 0 24px; }
.psl-mehr {
  position: absolute; right: 3px; bottom: 3px; display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 22px; margin: 0; padding: 0; font: inherit; font-size: var(--pp-fs-text); line-height: var(--pp-lh-eng);
  color: var(--pp-text-2); background: transparent; border: 1px solid transparent; border-radius: 6px; cursor: pointer;
}
.psl-mehr > span { transform: translateY(-3px); }
@media (hover: hover) { .psl-mehr:hover { background: var(--pp-surface-2); color: var(--pp-text); border-color: var(--pp-line); } }
.psl-mehr:focus-visible { outline: 2px solid var(--pp-accent); outline-offset: 1px; }
.psl-mehr[aria-expanded="true"], .psl-zelle.pp-ctx-offen .psl-mehr { background: var(--pp-accent-tint); color: var(--pp-accent-2); border-color: var(--pp-accent-line); }
.psl-zelle.pp-ctx-offen .psl-kachel .psl-bild { border-color: var(--pp-accent); }
.psl-menue-ruht .psl-mehr { display: none; }
@media (hover: none), (pointer: coarse) {
  .psl-mehr { width: 32px; height: 32px; right: 1px; bottom: 0; }
  .psl-mit-menue .psl-nr { padding: 0 32px; min-height: 28px; }
}
.psl-kachel[aria-current="page"] { border-color: var(--pp-accent); background: var(--pp-accent-tint); }
.psl-kachel[aria-current="page"] .psl-nr { color: var(--pp-accent-2); font-weight: 600; box-shadow: inset 0 -2px 0 var(--pp-accent); }
/* Markier-Modus: der Bereich mit Rahmen und Schleier, Anfang und Ende mit
   einer Ecke. Dass die Liste unter dem Finger dann nicht rollt, setzt die
   Komponente selbst, NUR solange markiert wird (js/seitenleiste.js
   markZeigen) — im Stylesheet gilt touch-action: none allein der Bühne
   (verify-heft.js 15.1). Ein Zug an den Rand rollt die Liste mit. */
.psl-zieht .psl-liste { cursor: grabbing; }
.psl-kachel.markiert .psl-bild { outline: 3px solid var(--pp-accent); outline-offset: -3px; }
.psl-kachel.markiert .psl-bild::after {
  content: ""; position: absolute; inset: 0; background: var(--pp-accent); opacity: .16; pointer-events: none;
}
.psl-kachel.markiert .psl-nr { color: var(--pp-accent-2); font-weight: 600; }
.psl-kachel.anfang .psl-bild::before, .psl-kachel.ende .psl-bild::before {
  content: ""; position: absolute; z-index: 1; width: 0; height: 0; border: 9px solid transparent; pointer-events: none;
}
.psl-kachel.anfang .psl-bild::before { left: 0; top: 0; border-left-color: var(--pp-accent); border-top-color: var(--pp-accent); }
.psl-kachel.ende .psl-bild::before { right: 0; bottom: 0; border-right-color: var(--pp-accent); border-bottom-color: var(--pp-accent); }
@media (hover: none) {
  .psl-zu, .psl-fertig { min-width: 44px; height: 44px; }
}

/* ---------------- a1014-G5c: das gemeinsame Heft der Lerngruppe ----------------
   docs/abnahme/a1014-g5c/BERICHT.md. Die Zeiger der anderen stehen in ihrer
   Kürzel-Farbe auf dem Blatt (Prozent der Blattmaße, also zoomfest), die
   Leiste der Anwesenden oben rechts; ein Nur-Leser (Pass ruht) sieht alles,
   zeichnet aber nicht (Zeichenfläche ohne Zeiger-Ereignisse). */
.hg-zeiger {
  position: absolute; z-index: 3; pointer-events: none;
  transform: translate(-50%, -50%);
  min-width: 22px; height: 22px; padding: 0 5px; box-sizing: border-box;
  border-radius: 11px; border: 2px solid #fff;
  color: #fff; font: 600 12px/18px var(--pp-sans, system-ui, sans-serif);   /* a1014-fix-lv LV-10: 12 px */
  text-align: center; box-shadow: 0 1px 3px rgba(0, 0, 0, .3);
  transition: left .12s linear, top .12s linear;
}
.hg-anwesend {
  position: absolute; right: 12px; top: 8px; z-index: 6;
  display: flex; align-items: center; gap: 4px; pointer-events: none;
}
.hg-anwesend:empty { display: none; }
.hg-kuerzel {
  display: inline-block; min-width: 24px; height: 24px; padding: 0 5px; box-sizing: border-box;
  border-radius: 12px; border: 2px solid #fff; color: #fff;
  font: 600 12px/20px var(--pp-sans, system-ui, sans-serif); text-align: center;   /* LV-10: 12 px */
  box-shadow: 0 1px 3px rgba(0, 0, 0, .25);
}
/* b1015-A (Jonas: „Der grüne Punkt da soll entfernt werden"): kein
   Statuspunkt mehr — offline steht als Wort da (js/heft-gemeinsam.js). */
.hg-offline-hinweis {
  padding: 2px 8px; border: 1px solid var(--pp-line); border-radius: 999px; background: var(--pp-surface);
  color: var(--pp-text-2); font: 500 var(--pp-fs-mini)/var(--pp-lh-knapp) var(--pp-sans, system-ui, sans-serif); white-space: nowrap;
}
.hg-nurlesen-hinweis { font: 500 var(--pp-fs-mini)/1 var(--pp-sans, system-ui, sans-serif); color: var(--pp-text-3); margin-left: 4px; }
/* lg1019-P6 (Jonas: „nirgends angezeigt, dass noch ein Nutzer in der Datei
   ist"): Kürzel UND Name („mit JA Jonas Test Account") auf eigener Fläche,
   damit die Zeile über jeder Tinte lesbar bleibt — Markup aus
   PreppLive.anwesendLeisteHtml (js/live.js), dieselbe Leiste wie die Fläche. */
.hg-anwesend:has(.hg-person) {
  padding: 3px 6px 3px 8px; border: 1px solid var(--pp-line); border-radius: 999px; background: var(--pp-surface);
  box-shadow: 0 1px 3px rgba(0, 0, 0, .12); max-width: min(70vw, 520px); flex-wrap: wrap;
}
.hg-mit { font: 500 var(--pp-fs-mini)/1 var(--pp-sans, system-ui, sans-serif); color: var(--pp-text-2); margin-right: 2px; }
.hg-person { display: inline-flex; align-items: center; gap: 5px; }
.hg-name { font: 500 var(--pp-fs-mini)/1 var(--pp-sans, system-ui, sans-serif); color: var(--pp-text); white-space: nowrap; }
@media (max-width: 600px) { .hg-name { display: none; } }   /* am Telefon nur das Kürzel */
.hg-nurlesen .hf-zg { pointer-events: none; }
/* K3-P7 (17.10.2026): der ENTSTEHENDE Strich eines anderen — eine Vorschau-
   Ebene je Blatt im Blattmaß (viewBox der Seite, deshalb zoomfest), über der
   Zeichnung, ohne Zeiger-Ereignisse; die fertige Tinte löst sie ab
   (js/heft-gemeinsam.js Regel 9). Mit „multiply" wie die eigene Tinte
   (W2): Der z-index macht die Ebene zu einem eigenen Stapel, in dem die
   Marker sonst nur in sich mischten und die Schrift darunter verblasste. */
.hg-fremd { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 2; pointer-events: none; overflow: visible; mix-blend-mode: multiply; }
@media (max-width: 600px) { .hg-anwesend { top: 4px; right: 6px; } }

/* UI1015-U3: Im Lesemodus der Arbeitsumgebung ruhen die Leisten des Hefts
   (css/vorlesung.css .vl-lesen) — mit ihnen das ⋯, das sonst eine leere
   Liste öffnete. */
.vl-lesen .hf-mehrwirt { display: none; }
